廢話不多說,直接上代碼,微信的小程序,公衆號支付都大差不差,自行看文檔修改參數即可。
maven依賴:
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
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<String, String> 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<String, String> wxPay(String orderNO, Integer payAmount, String ip) {
try {
Map<String, String> 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<String, String> returnMap = pay.unifiedOrder(map);
Map<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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 "<xml><return_code><![CDATA[" + return_code + "]]>" + "</return_code><return_msg><![CDATA[" + return_msg
+ "]]></return_msg></xml>";
}
}
}
到這裏微信支付已經完成,按照上面的步驟,完全可以實現微信的app支付,下一篇將介紹支付寶的app支付