最近公司项目需要整合微信支付Native版本(网页扫码支付),不同的支付实操也大同小异,修改部分参数即可,看了下微信支付的官方文档,已经推出了更加方便安全V3支付接口,目前为了快速集成,先奉上V1版本的接入完整示例:
- 首先是要拿到开发所需要的配置项(appId 微信商户绑定的公众号ID、mchId 商户号 、partnerKey 商户秘钥-微信商户后台-Api安全设置自行设置,需要用户自行牢记该秘钥且不要泄露)
- 添加项目依赖
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-WxPay</artifactId>
<version>2.7.2</version>
</dependency>
- 添加微信配置
@Bean
public WxPayApiConfig wxPayApiConfig() {
WxPayApiConfig wxPayApiConfig = new WxPayApiConfig();
wxPayApiConfig.setAppId(app_id);
wxPayApiConfig.setMchId(mch_id);
wxPayApiConfig.setDomain(domain);
wxPayApiConfig.setPartnerKey(partnerKey);
WxPayApiConfigKit.putApiConfig(wxPayApiConfig);
return wxPayApiConfig;
}
IJPay中微信配置绑定线程私有对象ThreadLocal,详情可阅读com.ijpay.wxpay.WxPayApiConfigKit的源码,如果我们项目中只用到了一个微信支付实体,我们就在加载配置的地方调用WxPayApiConfigKit.putApiConfig(wxPayApiConfig); 使其成为我们所有线程的默认微信支付配置。
当我们调用WxPayApiConfigKit.getWxPayApiConfig();时,就会获取到我们先前设置的Config对象
- 微信统一下单
对接过微信支付的朋友都应该清楚,微信提供了一个统一下单的接口,IJPay也帮助我们省略了很多代码,微信Native支付下单示例:
/**
* 系统内部下单接口
*
* @param orderCode 订单号
* @param goodsName 订单描述
* @param amount 订单金额
*/
public static String createOrder(String orderCode, String goodsName, BigDecimal amount) {
WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
Map<String, String> params = UnifiedOrderModel
.builder()
.appid(wxPayApiConfig.getAppId())
.mch_id(wxPayApiConfig.getMchId())
.nonce_str(WxPayKit.generateStr())
.out_trade_no(orderCode)
.total_fee(formatAmount(amount))
.spbill_create_ip("8.8.8.8")
.notify_url(wxPayApiConfig.getDomain()+"/api/order/callback")
.body(goodsName)
.trade_type(TradeType.NATIVE.getTradeType())
.build()
.createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
String xmlResult = WxPayApi.pushOrder(false, params);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
log.debug("统一下单返回:\n {}", result);
if (!WxPayKit.codeIsOk(result.get("result_code"))) {
throw new MyOrderException("创建订单失败,请稍后重试");
}
return result.get("code_url"); // 获取到的是微信支付二维码链接 生成二维码扫码即可
}
注意:
1.微信支付中的total_fee 总金额字段 单位为分 需要将BigDecimal对象转成分为单位
eg: return String.valueOf(amount.multiply(new BigDecimal(100)).intValue());
2.notify_url 为微信支付通知回调地址,不允许携带查询参数 (eg:?key=wx)
3,.示范例子为Native支付,其他类型的支付需要的必传参数查看微信支付官方文档,逐个添加即可,例如小程序支付需要提供openId
- 根据上述步骤应该可以正常下单,最后还差支付回调就基本大功告成啦:
/**
* 订单回调地址
*/
@RequestMapping("callback")
public String callback(HttpServletRequest request) {
String data = HttpKit.readData(request);
Map<String, String> result = WxPayKit.xmlToMap(data);
boolean verifyNotify = WxPayKit
.verifyNotify(result, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey());
if (!verifyNotify) {
log.warn("接收到验证不通过订单回调:{}", data);
return "fail";
}
log.debug("微信支付回调:\n {}", result);
if (WxPayKit.codeIsOk(result.get("return_code"))) {
String orderCode = result.get("out_trade_no");
log.debug("收到订单号为:{} 的支付回调通知", orderCode);
//todo 这里编写完成支付的逻辑
}
return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}
注意:微信支付回调一定要校验是否由微信服务器发起的
boolean verifyNotify = WxPayKit
.verifyNotify(result, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey());
这里就是微信商户秘钥需要保密的一大原因,如果泄露,可以被人为的伪造微信的回调,
如果真的泄密了,也不要太慌,微信支付是支持订单查询的,具体接口查看微信支付文档,获取到微信支付回调后,主动去查询该订单的支付状态为最安全保险的做法!
暂时收工,如果对V3有需求,后续再补充V3支付的集成。