Commit 7d78af1a authored by zhuxiao's avatar zhuxiao
Browse files

完善微信支付V3接口回调

parent f087fd89
...@@ -16,24 +16,19 @@ ...@@ -16,24 +16,19 @@
package com.jeequan.jeepay.pay.channel.wxpay; package com.jeequan.jeepay.pay.channel.wxpay;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.auth.AutoUpdateCertificatesVerifier;
import com.github.binarywang.wxpay.v3.auth.PrivateKeySigner;
import com.github.binarywang.wxpay.v3.auth.WxPayCredentials;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import com.jeequan.jeepay.core.constants.CS; import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException; import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.exception.ResponseException; import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.pay.channel.AbstractChannelNoticeService; import com.jeequan.jeepay.pay.channel.AbstractChannelNoticeService;
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.pay.service.ConfigContextService; import com.jeequan.jeepay.pay.service.ConfigContextService;
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
import com.jeequan.jeepay.service.impl.PayOrderService; import com.jeequan.jeepay.service.impl.PayOrderService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
...@@ -44,10 +39,7 @@ import org.springframework.http.ResponseEntity; ...@@ -44,10 +39,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
/* /*
* 微信回调 * 微信回调
...@@ -87,22 +79,10 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService { ...@@ -87,22 +79,10 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService {
throw new BizException("获取商户信息失败"); throw new BizException("获取商户信息失败");
} }
// 验签 // 验签 && 获取订单回调数据
if (!verifyNotifySign(request, mchAppConfigContext)) { WxPayOrderNotifyV3Result.DecryptNotifyResult result = parseOrderNotifyV3Result(request, mchAppConfigContext);
throw new BizException("验签失败");
}
// 获取加密信息
JSONObject params = getReqParamJSON();
JSONObject resource = params.getJSONObject("resource");
String cipherText = resource.getString("cipherText");
String associatedData = resource.getString("associatedData");
String nonce = resource.getString("nonce");
// 解密 return MutablePair.of(result.getOutTradeNo(), result);
String result = AesUtils.decryptToString(associatedData, nonce, cipherText, mchAppConfigContext.getWxServiceWrapper().getWxPayService().getConfig().getApiV3Key());
JSONObject decryptJSON = JSONObject.parseObject(result);
return MutablePair.of(decryptJSON.getString("out_trade_no"), decryptJSON);
} else { // V2接口回调 } else { // V2接口回调
String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding()); String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
...@@ -141,12 +121,12 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService { ...@@ -141,12 +121,12 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService {
}else if (CS.PAY_IF_VERSION.WX_V3.equals(mchAppConfigContext.getWxServiceWrapper().getApiVersion())) { // V3 }else if (CS.PAY_IF_VERSION.WX_V3.equals(mchAppConfigContext.getWxServiceWrapper().getApiVersion())) { // V3
// 获取回调参数 // 获取回调参数
JSONObject resultJSON = (JSONObject) params; WxPayOrderNotifyV3Result.DecryptNotifyResult result = (WxPayOrderNotifyV3Result.DecryptNotifyResult) params;
// 验证参数 // 验证参数
verifyWxPayParams(resultJSON, payOrder); verifyWxPayParams(result, payOrder);
String channelState = resultJSON.getString("trade_state"); String channelState = result.getTradeState();
if ("SUCCESS".equals(channelState)) { if ("SUCCESS".equals(channelState)) {
channelResult.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS); channelResult.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
}else if("CLOSED".equals(channelState) }else if("CLOSED".equals(channelState)
...@@ -155,10 +135,10 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService { ...@@ -155,10 +135,10 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService {
channelResult.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); //支付失败 channelResult.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL); //支付失败
} }
channelResult.setChannelOrderId(resultJSON.getString("transaction_id")); //渠道订单号 channelResult.setChannelOrderId(result.getTransactionId()); //渠道订单号
JSONObject payer = resultJSON.getJSONObject("payer"); WxPayOrderNotifyV3Result.Payer payer = result.getPayer();
if (payer != null) { if (payer != null) {
channelResult.setChannelUserId(StringUtils.isNotBlank(payer.getString("openid")) ? payer.getString("openid") : payer.getString("sp_openid")); //支付用户ID channelResult.setChannelUserId(payer.getOpenid()); //支付用户ID
} }
}else { }else {
...@@ -203,38 +183,30 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService { ...@@ -203,38 +183,30 @@ public class WxpayChannelNoticeService extends AbstractChannelNoticeService {
* @param mchAppConfigContext 商户配置 * @param mchAppConfigContext 商户配置
* @return true:校验通过 false:校验不通过 * @return true:校验通过 false:校验不通过
*/ */
private boolean verifyNotifySign(HttpServletRequest request, MchAppConfigContext mchAppConfigContext) throws Exception { private WxPayOrderNotifyV3Result.DecryptNotifyResult parseOrderNotifyV3Result(HttpServletRequest request, MchAppConfigContext mchAppConfigContext) throws Exception {
SignatureHeader header = new SignatureHeader(); SignatureHeader header = new SignatureHeader();
header.setTimeStamp(request.getHeader("Wechatpay-Timestamp")); header.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
header.setNonce(request.getHeader("Wechatpay-Nonce")); header.setNonce(request.getHeader("Wechatpay-Nonce"));
header.setSerialNo(request.getHeader("Wechatpay-Serial")); header.setSerial(request.getHeader("Wechatpay-Serial"));
header.setSigned(request.getHeader("Wechatpay-Signature")); header.setSignature(request.getHeader("Wechatpay-Signature"));
String beforeSign = String.format("%s\n%s\n%s\n", // 获取加密信息
header.getTimeStamp(), JSONObject params = getReqParamJSON();
header.getNonce(),
getReqParamJSON().toJSONString()); WxPayOrderNotifyV3Result result = mchAppConfigContext.getWxServiceWrapper().getWxPayService().parseOrderNotifyV3Result(params.toJSONString(), header);
WxPayConfig wxPayConfig = mchAppConfigContext.getWxServiceWrapper().getWxPayService().getConfig(); return result.getResult();
// 自动获取微信平台证书
PrivateKey privateKey = PemUtils.loadPrivateKey(new FileInputStream(wxPayConfig.getPrivateKeyPath()));
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WxPayCredentials(wxPayConfig.getMchId(), new PrivateKeySigner(wxPayConfig.getCertSerialNo(), privateKey)),
wxPayConfig.getApiV3Key().getBytes("utf-8"));
return verifier.verify(header.getSerialNo(),
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
} }
/** /**
* V3接口验证微信支付通知参数 * V3接口验证微信支付通知参数
* @return * @return
*/ */
public void verifyWxPayParams(JSONObject result, PayOrder payOrder) { public void verifyWxPayParams(WxPayOrderNotifyV3Result.DecryptNotifyResult result, PayOrder payOrder) {
try { try {
// 核对金额 // 核对金额
Integer total_fee = result.getInteger("total"); // 总金额 Integer total_fee = result.getAmount().getTotal(); // 总金额
long wxPayAmt = new BigDecimal(total_fee).longValue(); long wxPayAmt = new BigDecimal(total_fee).longValue();
long dbPayAmt = payOrder.getAmount().longValue(); long dbPayAmt = payOrder.getAmount().longValue();
if (dbPayAmt != wxPayAmt) { if (dbPayAmt != wxPayAmt) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment