小程序微信支付实践案例-JAVA
微信支付接入总让我产生一种很容易的幻觉,但自己又不知道从何下手。平时每次去买东西,点击支付后拉起来的支付界面,我很好奇,想自己玩一下。
如果你从来没有过微信支付相关实践经验,你肯定会去看微信官方文档,然后看了好几遍还会一脸懵逼,反正我是这样的…
以下是我查阅微信支付官方文档和网上查找资料后做的总结:
先强调一下,必须要先申请到商户相关资料,如果没有申请条件(需要营业执照),还是别瞎折腾了…
申请入口:微信支付商户注册
准备商户相关资料,须包含以下:
mchId (商户号)由微信生成
mchKey (API秘钥)调V2版本的接口才需要
apiV3Key (APIV3秘钥)V3版本接口才需要,可以两者都设置
certSerialNo (证书序列化)
证书文件,一共3份
apiclient_cert.p12
apiclient_cert.pem
apiclient_key.pem
appId (注意是小程序的应用ID) 在小程序后台-开发管理-开发设置页面查看
Java后端
有了以上资料,接下来就是接口调用了,可以直接使用官方提供的SDK,也可以使用第三方的,我是使用第三方的,依赖以下jar包:
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.1.0</version>
</dependency>
public static void main(String[] args) {
WxPayConfig wxPayConfig = new WxPayConfig();
wxPayConfig.setMchId("1623324432");
wxPayConfig.setAppId("wxaxxxxxxxxxxx");
wxPayConfig.setMchKey("1245adfsadghgdfhfg");
wxPayConfig.setApiV3Key("Imdaskldkladklaaskllads");
wxPayConfig.setCertSerialNo("ASDFADF132534");
wxPayConfig.setKeyPath("C:\Users\LENOVO\Desktop\wx_pay\apiclient_cert.p12");
wxPayConfig.setPrivateCertPath("C:\Users\LENOVO\Desktop\wx_pay\apiclient_cert.pem");
wxPayConfig.setPrivateKeyPath("C:\Users\LENOVO\Desktop\wx_pay\apiclient_key.pem");
// 小程序支付
wxPayConfig.setTradeType(WxPayConstants.TradeType.JSAPI);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(wxPayConfig); //微信配置信息
// 官方接口文档地址- https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_1.shtml
String url = "/v3/pay/transactions/jsapi";
try {
JSONObject jsonObject = WxpayV3Util.unifiedOrderV3(url, param(), wxPayService);
logger.info("支付返回:{}", jsonObject);
} catch (WxPayException e) {
e.printStackTrace();
}
}
private static JSONObject param() {
String payOrderId = "12345678903423534539";
// 微信统一下单请求对象
JSONObject reqJSON = new JSONObject();
reqJSON.put("out_trade_no", payOrderId);
reqJSON.put("description", "我是一个商品");
// 订单失效时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,示例值:2018-06-08T10:34:56+08:00
// reqJSON.put("time_expire", String.format("%sT%s+08:00", DateUtil.format(orderPay.getExpiredTime(), DatePattern.NORM_DATE_FORMAT), DateUtil.format(orderPay.getExpiredTime(), DatePattern.NORM_TIME_FORMAT)));
reqJSON.put("notify_url", "https://www.baidu.com");
JSONObject amount = new JSONObject();
amount.put("total", 888888);
amount.put("currency", "CNY");
reqJSON.put("amount", amount);
JSONObject sceneInfo = new JSONObject();
sceneInfo.put("payer_client_ip", "172.130.100.39");
reqJSON.put("scene_info", sceneInfo);
reqJSON.put("appid", "wxaxxxxxxxxxxx");
reqJSON.put("mchid", "1623324432");
JSONObject payer = new JSONObject();
payer.put("openid", "o6Kjkafkldajkfdskjfjkdfkjx-bfmdfmd5");
reqJSON.put("payer", payer);
return reqJSON;
}
WxpayV3Util.java
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
public static JSONObject unifiedOrderV3(String reqUrl, JSONObject reqJSON, WxPayService wxPayService) throws WxPayException {
String response = wxPayService.postV3(PAY_BASE_URL + reqUrl, reqJSON.toJSONString());
return JSONObject.parseObject(getPayInfo_(response, wxPayService.getConfig()));
}
public static String getPayInfo_(String response, WxPayConfig wxPayConfig) throws WxPayException {
try {
JSONObject resJSON = JSON.parseObject(response);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
String nonceStr = SignUtils.genRandomStr();
String prepayId = resJSON.getString("prepay_id");
Map<String, String> payInfo = new HashMap<>(8);
String appid = wxPayConfig.getAppId();
payInfo.put("appId", appid);
payInfo.put("timeStamp", timestamp);
payInfo.put("nonceStr", nonceStr);
payInfo.put("package", "prepay_id=" + prepayId);
payInfo.put("signType", "RSA");
String beforeSign = String.format("%sn%sn%sn%sn", appid, timestamp, nonceStr, "prepay_id=" + prepayId);
payInfo.put("paySign", SignUtils.sign(beforeSign, PemUtils.loadPrivateKey(new FileInputStream(wxPayConfig.getPrivateKeyPath()))));
// 签名以后在增加prepayId参数
payInfo.put("prepayId", prepayId);
return JSON.toJSONString(payInfo);
} catch (Exception e) {
throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e);
}
}
支付返回结果示例:
支付返回:{"timeStamp":"1669104769","package":"prepay_id=wxxxxxxxxxxxxxxxxxxxxx45f0000","paySign":"dK0jZZU5WkUS+DPwwt/asasas/meVi38HP68erz9kaAseZHYubkzrii+asa+C2VqQ+SshjWG/0oM/asa+asas+asas/y93SP8VCWU71Jw+asas+asa+asas==","appId":"wxaxxxxxxxxxxx","signType":"RSA","prepayId":"wxxxxxxxxxxxxxxxxxxxxx45f0000","nonceStr":"rlaiAJ9hgGrPzNCevzb7gN5D3W2R9BNw"}
小程序端
唤起微信支付界面接口,就是这一个接口,其实真的很容易对吧。
wx.requestPayment(
{
"timeStamp":"",
"nonceStr": "",
"package": "",
"signType": "RSA",
"paySign": "",
"success":function(res){},
"fail":function(res){},
"complete":function(res){}
})
将后台返回的支付结果参数赋值到对应的位置即可调起微信支付界面了。
效果展示如下
值得注意的地方:
-
openid 这个参数必须是在当前小程序下的openid,因为同一个用户在不同小程序下是不一样的,可以通过授权登录小程序获取到,也可以通过微信小程序提供的接口换取(https://api.weixin.qq.com/sns/jscode2session?appid=wxaxxxxxxxxxxx&secret=222&js_code=‘+code +’&grant_type=authorization_code)
-
微信开发者工具中这个AppId要和接口保持一致,要不然调用wx.requestPayment接口会报:requestPayment:fail no permission