微信jsapi支付下单对于java开发来说只需要调用官方文档的“统一下单”接口,然后将返回的xml字符串转成Map返回给前台,而前端需要获取返回的参数唤起支付
一、JSAPI下单所需参数
- appid:公众号appid
- secret: 公众号secret
- mch_id:商户号
- paternerKey:商户秘钥
二、支付授权目录以及授权域名
参考官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3
三、开发流程
1.获取openid
参考官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
2.下载官方sdk
下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
主要是用其中的WXPayUtil工具类中的一些方法
3.支付下单接口开发
统一下单官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
3.1 必填参数取值
其中的必填参数有:
- appid APPID (已有)
- mch_id 商户ID (已有)
- nonce_str:随机字符串用WXPayUtil中的generateNonceStr()即可,就是生成UUID的方法
- sign 签名:用WXPayUtil中的generateSignature
/**
* 生成签名
*
* @param data 待签名数据
* @param key API密钥
* @return 签名
*/
public static String generateSignature(final Map<String, String> data, String key) throws Exception {
return generateSignature(data, key, SignType.MD5);
}
- body 所支付的名称
- out_trade_no 咱们自己所提供的订单号,需要唯一
- total_fee
支付金额 单位:分
这个地方一定要注意
/**
* 元转换成分
*
* @param amount
* @return
*/
public static String getMoney(String amount) {
if (amount == null) {
return "";
}
// 金额转化为分为单位
String currency = amount.replaceAll("\\$|\\¥|\\,", ""); //处理包含, ¥ 或者$的金额
int index = currency.indexOf(".");
int length = currency.length();
Long amLong = 0l;
if (index == -1) {
amLong = Long.valueOf(currency + "00");
} else if (length - index >= 3) {
amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
} else if (length - index == 2) {
amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
} else {
amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
}
return amLong.toString();
}
- spbill_create_ip IP地址
//获取请求ip地址
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getRemoteAddr();
}
if(ip.indexOf(",")!=-1){
String[] ips = ip.split(",");
ip = ips[0].trim();
}
- notify_url 回调地址,一定要公网可以访问,通过回调接口根据参数以及自己系统的业务逻辑修改订单状态
- trade_type 支付类型 JSAPI
- openid 支付人的微信公众号对应的唯一标识
3.2 请求微信统一下单接口
此处用到post请求的方法,请求微信"统一下单接口https://api.mch.weixin.qq.com/pay/unifiedorder
接口返回结果:
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
请求下单接口最重要的就是获取参数prepay_id,然后将前端所需参数以map形式返回,这个地方有一个需要注意一下,前端需要一个字段名为package的参数,因为package是java的关键字,所以最好以Map返回
3.3 JSAPI调起支付
前端所需参数描述:
前端示例
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"wx2421b1c4370ec43b", //公众号ID,由商户传入
"timeStamp":"1395712654", //时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5", //微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(