微信支付
备注:本次支付接入的是微信支付v2.0版本,其中所有的请求格式均为XML。
如有需求可直接参阅官方文档 https://pay.weixin.qq.com/wiki/doc/api/index.html
官网支付demo地址(v2.0): https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
微信支付V3.0版本是基于JSON格式的API。
个人支付案例git地址[微信支付/支付宝支付/华为支付/苹果支付/小米支付]:https://gitee.com/wazk2008/demo-pay
1.下单支付(跳转微信进行支付)
微信接口名称: 统一下单
微信接口地址: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
个人支付代码demo
@RestController
@RequestMapping(value = "/pay")
@Slf4j
public class PayController {
@Autowired
private WechatService wechatService;
@PostMapping(value = "/wechat")
public Result<PayWechatResponse> payWechat (@RequestBody PayWechatRequest payWechatRequest) {
try {
log.info("微信支付接口开始执行,请求参数:{}", JSON.toJSONString(payWechatRequest));
PayWechatResponse payWechatResponse = wechatService.pay(payWechatRequest);
log.info("微信支付接口执行成功,请求参数:{},响应参数:{}", JSON.toJSONString(payWechatRequest), JSON.toJSON(payWechatResponse));
return Result.getSuccess(payWechatResponse);
} catch (ResponseException e) {
log.error("微信支付接口执行失败1,请求参数:{},异常原因:{}", JSON.toJSONString(payWechatRequest), e.getMessage());
e.printStackTrace();
return Result.getFail(e);
} catch (Exception e) {
log.error("微信支付接口执行失败2,请求参数:{},异常原因:{}", JSON.toJSONString(payWechatRequest), e.getMessage());
e.printStackTrace();
return Result.getFail(ResultCode.INTERNAL_SERVER_ERROR);
}
}
}
@Service
@Slf4j
public class WechatService {
@Autowired
private WechatConfig wechatConfig;
@Autowired
private Map<String, WechatAppConfig> wechatApps;
@Autowired
private HttpXmlRequest httpXmlRequest;
public PayWechatResponse pay (PayWechatRequest payWechatRequest) throws Exception {
// 这里可以写各种校验
// 校验appid是否合法
String appid = payWechatRequest.getAppid();
WechatAppConfig wechatApp = wechatApps.get(appid);
if (Objects.isNull(wechatApp)) {
throw new ResponseException(ResultCode.WECHAT_PAY_APPID_ERROR);
}
// 校验支付方式tradeType是否合法
String tradeType = payWechatRequest.getTradeType();
boolean isContainTradeType = wechatApp.getTradeType().contains(tradeType);
if (!isContainTradeType) {
throw new ResponseException(ResultCode.WECHAT_PAY_TRADE_TYPE_NAME_ERROR);
}
// todo 校验该比订单的支付金额是否合法
// todo 校验该笔订单的状态是否为待支付
// 获取请求微信的xml参数
String xml = getPayValidRequestXml(payWechatRequest);
String responseXml = httpXmlRequest.postXml(wechatConfig.getUnifiedOrderUrl(), xml);
Map<String, String> map = WXPayUtil.xmlToMap(responseXml);
// 返回状态码==SUCCESS && 业务结果==SUCCESS 表示退款申请成功
if (WechatConstant.SUCCESS.equals(map.get(WechatConstant.RETURN_CODE)) && WechatConstant.SUCCESS.equals(map.get(WechatConstant.RESULT_CODE))) {
// todo 这里可以保存用户微信支付的唤醒记录
WechatTradeTypeEnum wechatTradeTypeEnum = WechatTradeTypeEnum.valueOf(payWechatRequest.getTradeType());
return generatePayWechatResponse(wechatTradeTypeEnum, appid, map);
}
throw new ResponseException(ResultCode.WECHAT_PAY_ERROR);
}
// 获取请求微信的xml参数
private String getPayValidRequestXml (PayWechatRequest payWechatRequest) throws Exception {
// 获取请求微信的xml对应的map
Map<String, String> payXmlMap = getPayXmlMap(payWechatRequest);
// 校验生成的签名
boolean signatureValid = WXPayUtil.isSignatureValid(payXmlMap, wechatApps.get(payWechatRequest.getAppid()).getAppSecret());
if (!signatureValid) {
throw new ResponseException(ResultCode.WECHAT_PAY_SIGNATURE_VALID_ERROR);
}
//
return WXPayUtil.mapToXml(payXmlMap);
}
private Map<String, String> getPayXmlMap (PayWechatRequest payWechatRequest) {
Map<String, String> reqData = new HashMap<>();
String appid = payWechatRequest.getAppid();
WechatAppConfig wechatApp = wechatApps.get(appid);
reqData.put(WechatConstant.APPID, appid);
reqData.put(WechatConstant.MCH_ID, wechatApp.getMchId());
reqData.put(WechatConstant.NONCE_STR , WXPayUtil.generateNonceStr());
reqData.put(WechatConstant.BODY , payWechatRequest.getBody());
reqData.put(WechatConstant.OUT_TRADE_NO , payWechatRequest.getOrderNo());
reqData.put(WechatConstant.TOTAL_FEE , payWechatRequest.getFee());
reqData.put(WechatConstant.SPBILL_CREATE_IP , payWechatRequest.getSpbillCreateIp());
reqData.put(WechatConstant.NOTIFY_URL , wechatConfig.getUnifiedOrderCallbackUrl());
reqData.put(WechatConstant.TRADE_TYPE , payWechatRequest.getTradeType());
if (WechatTradeTypeEnum.JSAPI.name().equals(payWechatRequest.getTradeType())) {
reqData.put(WechatConstant.OPENID , payWechatRequest.getOpenid());
}
if (WechatConstant.MD5.equals(wechatApp.getSignType())) {
reqData.put(WechatConstant.SIGN_TYPE, WechatConstant.MD5);
}
else if (WechatConstant.HMACSHA256.equals(wechatApp.getSignType())) {
reqData.put(WechatConstant.SIGN_TYPE, WechatConstant.HMACSHA256);
} else {
throw new ResponseException(ResultCode.WECHAT_CONFIG_SIGN_TYPE_ERROR);
}
try {
reqData.put(WechatConstant.SIGN, WXPayUtil.generateSignature(reqData, wechatApp.getAppSecret(), WechatSignTypeEnum.valueOf(wechatApp.getSignType())));
} catch (Exception e) {
log.error("微信支付生成签名错误");
e.printStackTrace();
throw new ResponseException(ResultCode.WECHAT_PAY_GENERATE_SIGN_ERROR);
}
return reqData;
}
private PayWechatResponse generatePayWechatResponse(WechatTradeTypeEnum wechatTradeTypeEnum, String appid, Map<String, String> map) throws Exception {
PayWechatResponse payWechatResponse = new PayWechatResponse();
switch (wechatTradeTypeEnum) {
case APP:
payWechatResponse.setAppResponse(generatePayWechatAppResponse(appid, map));
break;
case JSAPI:
payWechatResponse.setJsapiResponse(generatePayWechatJsapiResponse(appid, map));
break;
case NATIVE:
break;
case MWEB:
break;
default:
break;
}
return payWechatResponse;
}
private PayWechatJsapiResponse generatePayWechatJsapiResponse (String appid, Map<String, String> map) throws Exception{
// 对于微信返回的参数再签名
Map<String, String> pkg = new HashMap<>();
pkg.put("appId", appid);
pkg.put("timeStamp", String.valueOf(System.currentTimeMillis()/1000));
pkg.put("nonceStr", WXPayUtil.generateNonceStr());
pkg.put("package", "prepay_id=" + map

本文档详细介绍了如何在Java环境中集成微信支付V2.0版本,包括下单支付、支付回调处理和退款操作。示例代码展示了如何创建XML请求和响应,校验签名,以及处理微信支付接口的调用。此外,还提供了微信支付回调的处理逻辑和退款接口的实现。整个流程涵盖了订单支付、退款和回调验证的关键步骤。
最低0.47元/天 解锁文章
1075

被折叠的 条评论
为什么被折叠?



