废话不多说,直接上代码,微信的小程序,公众号支付都大差不差,自行看文档修改参数即可。
maven依赖:
com.github.wxpay
wxpay-sdk
0.0.3
application.yml中配置微信相关参数:
wx:
app:
appId: wxdee12345681703e8
mchId: 1512345671
key: 86799C8812345675C82F3FE33FFE7EE3
notifyUrl: https://test.shuai.com/wxPayCallback
引入wxpay依赖后需要实现里面的微信配置类,将上面的微信相关的信息写进去:
package com.bcn.yeyks.apppay.service.impl;
import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.InputStream;
/**
* @Author fuchangshuai
* @date 2019/3/13 5:29 PM
*/
@Service
public class WXPayConfigImpl implements WXPayConfig {
@Value("${wx.app.appId}")
String appID;
@Value("${wx.app.key}")
String key;
@Value("${wx.app.mchId}")
String mchID;
@Override
public String getAppID()
{
return appID;
}
@Override
public String getMchID()
{
return mchID;
}
@Override
public String getKey()
{
return key;
}
@Override
public InputStream getCertStream()
{
return this.getClass().getResourceAsStream("/apiclient_cert.p12");
}
@Override
public int getHttpConnectTimeoutMs()
{
return 2000;
}
@Override
public int getHttpReadTimeoutMs()
{
return 10000;
}
}
微信支付类:
package com.bcn.yeyks.apppay.service.impl;
import com.alibaba.fastjson.JSON;
import com.bcn.yeyks.apppay.service.WXAppPayService;
import com.bcn.yeyks.exception.ServiceException;
import com.bcn.yeyks.model.RefundRequestNo;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Author fuchangshuai
* @date 2019/3/4 2:34 PM
*/
@Service
@Slf4j
public class WXAppPayServiceImpl implements WXAppPayService {
@Autowired
private WXPayConfig wxPayConfig;
@Value("${wx.app.key}")
String key;
@Value("${wx.app.notifyUrl}")
String notify_url;
@Value("${wx.app.vipNotifyUrl}")
String vip_notify_url;
@Value("${wx.app.appId}")
String appId;
@Value("${wx.app.mchId}")
String mch_id;
@Override
public String pay(Integer totalFee, String orderNo, String ip) {
log.info("微信app支付");
Map map = wxPay(orderNo, totalFee, ip);
return JSON.toJSONString(map);
}
@Override
public Boolean refund(Integer refundFee, Integer totalFee, String orderNo) {
log.info("微信退款");
return wxRefund(refundFee, totalFee, orderNo);
}
private Map wxPay(String orderNO, Integer payAmount, String ip) {
try {
Map map = new LinkedHashMap<>();
String body = "订单支付";
String nonce_str = WXPayUtil.generateNonceStr();
String total_fee = String.valueOf(payAmount);
map.put("body", body);
map.put("nonce_str", nonce_str);
map.put("out_trade_no", orderNO);
map.put("total_fee", total_fee);
map.put("spbill_create_ip", ip);
map.put("notify_url", notify_url);
map.put("trade_type", "APP");
WXPay pay = new WXPay(wxPayConfig);
Map returnMap = pay.unifiedOrder(map);
Map resultMap = new LinkedHashMap<>();
resultMap.put("appid", appId);
resultMap.put("noncestr", nonce_str);
resultMap.put("package", "Sign=WXPay");
resultMap.put("partnerid", mch_id);
resultMap.put("prepayid", returnMap.get("prepay_id"));
resultMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
StringBuilder result = new StringBuilder();
for (Map.Entry entry : resultMap.entrySet()) {
result.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
result.append("key=").append(key);
resultMap.put("sign", DigestUtils.md5Hex(result.toString()).toUpperCase());
return resultMap;
} catch (Exception e) {
log.info("微信支付失败{}", Arrays.toString(e.getStackTrace()));
throw new ServiceException("微信支付异常");
}
}
private Boolean wxRefund(Integer refundFee, Integer totalFee, String orderNo) {
try {
String outRequestNo = orderNo + RefundRequestNo.outNo;
String refundAmount = String.valueOf(refundFee);
String totalAmount = String.valueOf(totalFee);
Map map = new LinkedHashMap<>();
String nonce_str = WXPayUtil.generateNonceStr();
map.put("nonce_str", nonce_str);
map.put("out_trade_no", orderNo);
map.put("out_refund_no", outRequestNo);
map.put("total_fee", totalAmount);
map.put("refund_fee", refundAmount);
WXPay pay = new WXPay(wxPayConfig);
Map resutlMap = pay.refund(map);
String resultCode = resutlMap.get("result_code") == null ? "FAIL" : resutlMap.get("result_code");
String resultRefundFee = resutlMap.get("refund_fee") == null ? "FAIL" : resutlMap.get("refund_fee");
if ("SUCCESS".equals(resultCode) && resultRefundFee.equals(refundAmount)) {
return true;
}
} catch (Exception e) {
log.info("微信退款失败{}", Arrays.toString(e.getStackTrace()));
return false;
}
return false;
}
}
微信支付返回的回调类:
package com.bcn.yeyks.apppay.controller;
import com.bcn.yeyks.dal.domain.OrderInfo;
import com.bcn.yeyks.dal.domain.VipOrder;
import com.bcn.yeyks.exception.ServiceException;
import com.bcn.yeyks.service.OrderService;
import com.bcn.yeyks.service.VipOrderService;
import com.bcn.yeyks.wxpay.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Author fuchangshuai
* @date 2019/3/11 1:48 PM
*/
@RestController
@Slf4j
public class WxPayCallbackController {
@Autowired
private OrderService orderService;
@Autowired
private VipOrderService vipOrderService;
private ExecutorService executorService = Executors.newFixedThreadPool(20);
@RequestMapping(value = "/wxPayCallback", method = RequestMethod.POST)
public String wxPayCallback(HttpServletRequest request) {
log.info("微信支付回调");
try {
// 读取参数
// 解析xml成map
Map map = WXPayUtil.xmlToMap(getParam(request));
log.info("微信支付回调返回的信息{}", map);
check(map);//该处读者自行校验(验证订单号,付款金额等是否正确)
String orderNo = map.get("out_trade_no");
String resultCode = map.get("result_code");
// 另起线程处理业务
log.info("另起线程处理业务");
executorService.execute(() -> {
// 支付成功
if (resultCode.equals("SUCCESS")) {
log.info("支付成功");
// TODO 自己的业务逻辑
} else {
log.info("支付失败");
// TODO 自己的业务逻辑
}
});
if (resultCode.equals("SUCCESS")) {
return setXml("SUCCESS", "OK");
} else {
return setXml("fail", "付款失败");
}
} catch (ServiceException e) {
log.info("微信支付回调发生异常{}", e.getMessage());
return setXml("fail", "付款失败");
} catch (Exception e) {
log.info("微信支付回调发生异常{}", e.getLocalizedMessage());
return setXml("fail", "付款失败");
}
}
private String getParam(HttpServletRequest request) throws IOException {
// 读取参数
InputStream inputStream;
StringBuilder sb = new StringBuilder();
inputStream = request.getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
inputStream.close();
return sb.toString();
}
private void check(Map params) throws ServiceException {
String outTradeNo = params.get("out_trade_no");
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
OrderInfo order = orderService.selectOrderByOrderNo(outTradeNo);
if (order == null) {
throw new ServiceException("out_trade_no错误");
}
// 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
Integer totalAmount = Integer.valueOf(params.get("total_fee"));
log.info("totalAmount{}", totalAmount);
if (!totalAmount.equals(order.getSnapshotTotalFee())) {
throw new ServiceException("total_amount错误");
}
}
// 通过xml发给微信消息
private static String setXml(String return_code, String return_msg) {
SortedMap parameters = new TreeMap<>();
parameters.put("return_code", return_code);
parameters.put("return_msg", return_msg);
try {
return WXPayUtil.mapToXml(parameters);
} catch (Exception e) {
log.error("返回微信消息时map转xml失败");
return "" + " ";
}
}
}
到这里微信支付已经完成,按照上面的步骤,完全可以实现微信的app支付,下一篇将介绍支付宝的app支付