微信支付对接
前期准备工作
去官方申请账号并申请相关支付功能,并且生成对应的公钥与私钥。
一、如果对接微信支付
微信支付不用于支付宝支付,在传参上没有支付宝那么的傻瓜方式,需要我们自己按照他的要求拼装参数。
二、开始对接
1.申请交易
引入微信支付SDK
<!-- 微信支付sdk -->
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-pay -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>4.1.0</version>
</dependency>
创建调用工具类
public class ApiURLConsts {
/***
* 统一下单
*/
public static final String UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
/***
* 订单查询
*/
public static final String ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
}
下文中 OpenTM.XXXX 这个方法是我系统内自己的方法用来获取数据库中配置好的 Appid 商户号之类的,这个大家换成自己的就行。
@Override
public JSONObject getWXPayOrderInfoNative(OrderEntity entity){
if (null != entity && PsopConstant.OrderStatus.INIT.equals(entity.getStatus())) {
long money4wx = Long.valueOf(entity.getPrice());
String openId="";
Optional<MemberEntity> memberEntity = memberDao.findById(entity.getMemberId());
if (memberEntity.isPresent()){
openId = memberEntity.get().getOpenId();
}
SortedMap<String, String> params = new TreeMap<String, String>();
params.put("mch_id", OpenTM.getWXpayMchid());
params.put("appid", OpenTM.getWXpayAppid());
params.put("device_info","WEB");
params.put("nonce_str", RandomStringUtils.randomAlphanumeric(20));
params.put("body", "充值备注");
params.put("out_trade_no", entity.getId() + "");
params.put("total_fee", money4wx + "00");// 单位 分
params.put("spbill_create_ip", OpenTM.getWXPayIP());
params.put("notify_url", OpenTM.getWXpayNotifyUrl());
params.put("trade_type", "NATIVE");
// params.put("openid", openId);
//交易结束时间:订单产生多久后不支付订单失效,请求支付必传参数prepay_id只有两小时的有效期
//Date endDate = DateUtil.getDateAfterHours(1);
//String time_expire = DateUtil.getDateStr("yyyyMMddHHmmss", endDate);
// params.put("time_expire",time_expire);
params.put("sign", WechatPayUtil.createSign("UTF-8", params));
String requestXML = WechatPayUtil.getRequestXml(params);
logger.info(requestXML);
String result = WechatPayUtil.httpsRequest(ApiURLConsts.UNIFIEDORDER, "POST", requestXML);
logger.info(result);
/**统一下单接口返回正常的prepay_id(预支付交易会话标识),再按签名规范重新生成签名后,将数据传输给APP。
参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
**/
//调起支付接口
try {
Map<String, String> map = XMLUtil.doXMLParse(result);
logger.info(JSONHelper.bean2JSONStr(map));
SortedMap<String, String> parameterMap2 = new TreeMap<String, String>();
parameterMap2.put("appId", OpenTM.getWXpayAppid());
parameterMap2.put("nonceStr", RandomStringUtils.randomAlphanumeric(20));
parameterMap2.put("package", "prepay_id=" + map.get("prepay_id"));
parameterMap2.put("signType", "MD5");
parameterMap2.put("timeStamp", (System.currentTimeMillis() + "").substring(0, 10));
parameterMap2.put("code_url", map.get("code_url"));
//parameterMap2.put("partnerid", OpenTM.getWXpayMchid());
//parameterMap2.put("prepayid", map.get("prepay_id"));
//本来生成的时间戳是13位,但是ios必须是10位,所以截取了一下
String sign2 = WechatPayUtil.createSign("UTF-8", parameterMap2);
parameterMap2.put("paySign", sign2);
return JSONHelper.map2JSONObj(parameterMap2);
} catch (Exception e) {
logger.error("读取微信返回结果异常");
logger.error(e.getLocalizedMessage());
}
}
return JSONHelper.success("");
}
以上是相关业务代码,需要注意的是微信传入钱的单位是以分位单位,传入 1 元支付 0.01 元,由于我们的最小充值单位是1元而且都是整数,所以我这里直接补了 00 前端就不做任何处理了。
2.微信回调方法
如果支付成功,微信官方会回调这个接口,带上相关支付信息。解析request获得对应的Map信息然后处理对应的业务即可。
@RequestMapping(value = "wechat/notify.json")
public void notify(HttpServletRequest request) {
logger.info("微信支付回调参数");
SortedMap<String, String> wxparams = new TreeMap<String, String>();
try {
String string = WechatPayUtil.inputStream2String(request.getInputStream(), "UTF-8");
Map<String, String> map = XMLUtil.doXMLParse(string);
wxparams.putAll(map);
} catch (Exception e) {
logger.error(e.getLocalizedMessage());
}
if (null == wxparams || wxparams.size() == 0) {
logger.error("微信支付通知回调参数处理失败");
WebUtil.ajaxOutXml(WechatPayUtil.setXML("FAIL", "参数格式校验错误"));
return;
}
//1.验证签名
boolean isWxpaySign = WechatPayUtil.isTenpaySign("utf-8", wxparams);
if (!isWxpaySign) {
logger.error("微信签名验证失败");
WebUtil.ajaxOutXml(WechatPayUtil.setXML("FAIL", "签名验证失败"));
return;
}
//2.验证appid
if (!OpenTM.getWXpayAppid().equals(wxparams.get("appid"))) {
logger.error("appid 错误");
WebUtil.ajaxOutXml(WechatPayUtil.setXML("FAIL", "应用ID错误"));
return;
}
//3.验证商户ID
if (!OpenTM.getWXpayMchid().equals(wxparams.get("mch_id"))) {
logger.error("mch_id 错误");
WebUtil.ajaxOutXml(WechatPayUtil.setXML("FAIL", "商户ID错误"));
return;
}
if ("SUCCESS".equals(wxparams.get("return_code")) && "SUCCESS".equals(wxparams.get("result_code"))) {
logger.info("全部验证通过,处理自己的逻辑");
//paymentService.saveWXpayNotify(wxparams);
logger.info("微信支付回调只需要处理自己的逻辑,一切OK");
try {
String orderIdStr = wxparams.get("out_trade_no");
String wxpayOrderIdStr = wxparams.get("transaction_id");
String totalFee = wxparams.get("total_fee");
logger.info("orderIdStr:{} wxpayOrderIdStr:{} totalFee:{} ", orderIdStr, wxpayOrderIdStr, totalFee);
orderService.execReceiveWXPayNotify(orderIdStr, wxpayOrderIdStr, totalFee);
} catch (Exception e) {
e.printStackTrace();
}
WebUtil.ajaxOutXml(WechatPayUtil.setXML("SUCCESS", "处理成功"));
return;
} else {
//记录通知信息
WebUtil.ajaxOutXml(WechatPayUtil.setXML("SUCCESS", "处理成功"));
return;
}
}
总结
以上就是微信支付的相关代码,希望对大家有所帮助。