这一篇开始对微信支付细节进行解释和开发
1.获取openid,这个比较简单,上一篇已经讲到,通过appid,appsecret请求微信接口获取,具体看https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_4
2.设置测试授权目录,这个目录(也就是请求地址)就是你调用支付请求的地址。比如我调用支付的地址是http://********/user/userPay.do,那么测试授权目录就填写http://**********/user/即可,要注意大小写要完全一致
3.获取微信版本号https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_5,这个步骤就是用来验证用户的微信版本支不支持微信支付功能
4.获取预支付回话标识prepay_id,获取prepay_id,就是通过https协议,用POST方式,向微信统一下单接口https://api.mch.weixin.qq.com/pay/unifiedorder发送xml格式请求,返回数据也是xml格式;
a.这是微信官方文档所要求的请求参数列表
注意看参数列表,参数名称都为小写字母,而且有些参数是必填,有些是非必填的。
要注意的第一个参数是:签名(sign),签名的获取就是对其他所有参数进行处理后的结果,具体操作如下
第一步,先把所有参数放到一个map中(要十分注意,这里的参数名全是小写!小写!小写)
<span style="font-family:SimSun;"><span style="font-size:18px;">Map map = new HashMap();
map.put("appid",appid);
map.put("mch_id",mch_id);
map.put("nonce_str",noncestr);
map.put("body","test");
map.put("out_trade_no",out_trade_no);
map.put("total_fee","1");
map.put("spbill_create_ip",add);
map.put("notify_url",notify_url);
map.put("trade_type","JSAPI");
//trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识</span>
<span style="white-space:pre"> </span> <span style="font-size:18px;">map.put("openid",openid);</span></span>
第二步,在工具类中新建一个获取sign的方法
<span style="font-family:SimSun;font-size:18px;">public static String getSign(Map<String,Object> map){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(entry.getValue()!=""){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();</span>
<span style="font-family:SimSun;font-size:18px;"><span style="white-space:pre"> </span><span style="background-color: rgb(255, 204, 153);">//这里的key就是在微信支付商户平台中的账户设置--API安全--设置秘钥中设置</span>
result += "key=" + Constant.key;
result = MD5.MD5Encode(result).toUpperCase();
return result;
}</span>
这样就可以获得参数sign;
第二个要注意的参数是商户订单号,其实这个倒没什么难度的,官方文档的解释是:商户系统内部的订单号,32个字符内、可包含字母。我自己的做法是用10位的时间戳再加上22位的随机字符串。
第三个要注意的参数是open_id,当参数trade_type为JSAPI时,open_id必填,很多人也是忽略了这一点,导致了签名错误!!
b.参数了解清楚和获取后,就可以构造xml格式数据请求微信统一下单接口https://api.mch.weixin.qq.com/pay/unifiedorder,必须是通过https协议,以POST方式请求
String xml="<xml>"+
"<appid>"+appid+"</appid>"+
"<mch_id>"+mch_id+"</mch_id>"+
"<nonce_str>"+noncestr+"</nonce_str>"+
"<body><![CDATA["+"test"+"]]></body>"+
"<out_trade_no>"+out_trade_no+"</out_trade_no>"+
//金额,这里写的1 分到时修改
"<total_fee>"+1+"</total_fee>"+
"<spbill_create_ip>"+add+"</spbill_create_ip>"+
"<notify_url>"+notify_url+"</notify_url>"+
"<trade_type>"+"JSAPI"+"</trade_type>"+
"<openid>"+openid+"</openid>"+
"<sign>"+signature+"</sign>"+
"</xml>";
如果请求的数据正确的话,就会出现xml返回数据,其中就有我们需要的prepay_id,若是没有成功返回数据,肯定是参数错误、参数名大小写问题,或者请求的方法不对,回头细心检查一下。(官方文档也有列举出错误代码,可以对应不同的错误码进行检查https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
(腾讯还自动识别了一个OK的表情,有点萌萌的)
好啦,这样第一个难题就解决了。得到所需的prepay_id。
5.现在就可以进入网页调用支付接口的步骤了。这是官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
问题来了,一定要千万注意这里的变量名,第二个单词的首字母变成了大写,就是这么坑,不注意的话,等一下生成签名就会报错!!!
公众号id,时间戳,随机字符串,签名方式都不是难题,package的值就是我们上面获取的prepay_id,提交格式如:prepay_id=***,签名paysign的值,就是把对应的参数名和参数放到map里,通过上面的获取签名的方法来获得签名。
这些参数都是我们在后台获得,然后传到前端调用,调用微信支付接口的方法,官方文档已经给出来了:
如果参数计算正确的话,将会出现支付窗口
大功告成,但是很多人在这里返回的接口是get_brand_wcpay_request:fail,如果出现这个错误,基本是就是参数错误或者支付测试目录填写有误!
第一次编辑,有点乱,大家将就着看吧。