微信支付需要三个参数(APP_ID,商户号,商户KEY),自己去微信申请,此处略;
注意:以下参数有删减,只关心支付流程
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1
// APP_ID 替换为你的应用从官方网站申请到的合法appId
public static final String APP_ID = "";
//商户号
public static final String mch_id = "";
// API密钥,商户KEY
public static final String API_KEY= "";第一步:
服务器没接口的情况下:要获取prepay_id,
关键就是生成sign签名参数,按照流程一步步走
服务器有接口的情况下:跳过此步骤,直接看第二步
1.填写必填参数用来生成sign,然后保留此HashMap,因为生成sign后要把sign作为参数
添加到此HashMap,下面会讲到
hashMap.put("appid",AppConstants.APP_ID);
hashMap.put("mch_id",AppConstants.mch_id);
hashMap.put("nonce_str","5K826H16CSI8ZNMTM67VS");
hashMap.put("body","123456");
hashMap.put("out_trade_no","1708191226221");
hashMap.put("total_fee","1");
hashMap.put("spbill_create_ip",ipString);
hashMap.put("notify_url","https://www.baidu.com");
hashMap.put("trade_type","APP");
2.先按照参数名ASCII字典序排序,相当无此处开头字母为a的appid是最开始,
接着是body,顺序参考如下图:
3.然后拼接之后,最后加上拼接上商户key,如下:
appid=wx414c07f&body=123456&mch_id=17422&nonce_str=5K8264ILTTM67VS
¬ify_url=https://www.baidu.com&out_trade_no=17081226221
&spbill_create_ip=192.168.1.164&total_fee=1&trade_type=APP
&key=ZKAyLicSPBfMtB
4.MD5加密。且转换为大写
sign=FEA6EE6BFAA.....省略
5.得到sign之后,执行和第1点同样的步骤,只是多加了一个参数sign,
作为获取prepay_id的参数最终hashmap。
hashMap.put("appid",AppConstants.APP_ID);
hashMap.put("mch_id",AppConstants.mch_id);
hashMap.put("nonce_str","5K826H16CSI8ZNMTM67VS");
hashMap.put("body","123456");
hashMap.put("out_trade_no","1708191226221");
hashMap.put("total_fee","1");
hashMap.put("spbill_create_ip",ipString);
hashMap.put("notify_url","https://www.baidu.com");
hashMap.put("trade_type","APP");
hashMap.put("sign","FEA6EE6BFAA.....");
6.hashMap遍历拼接然后XML转译
List<String> hashlist=new ArrayList<>();
hashlist.add("appid");
hashlist.add("mch_id");
hashlist.add("nonce_str");
hashlist.add("body");
hashlist.add("out_trade_no");
hashlist.add("total_fee");
hashlist.add("spbill_create_ip");
hashlist.add("notify_url");
hashlist.add("trade_type");
hashlist.add("sign");
Collections.sort(hashlist, new SpellComparator());
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < hashlist.size(); i++) {
for (String key : params.keySet()) {
if (hashlist.get(i).equals(key)){
sb.append("<"+key+">");
sb.append(params.get(key));
sb.append("</"+key+">");
}
}
}
sb.append("</xml>");
Log.e("orion",sb.toString());
7.调用微信统一下单接口,获取prepay_id,如下:
此处我是直接用网上MyHttpClient和SSLSocketFactoryEx去获取统一下单接口的,
把转译的XML字符串,
之后为:
<xml><appid>wx48c6f</appid><body>123456</body>
<mch_id>142</mch_id><nonce_str>5K8264TM67VS</nonce_str><notify_url>https://www.baidu.com</notify_url>
<out_trade_no>171226221</out_trade_no>
<sign>FEA6E859BFAA5</sign><spbill_create_ip>192.168.1.164
</spbill_create_ip><total_fee>1</total_fee><trade_type>APP
</trade_type></xml>
作为参数请求。
因为是https,成功时候返回的是byte[]数组转换成XML就是如下
成功之后返回:
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx47078c6f]]></appid>
<mch_id><![CDATA[17242]]></mch_id>
<nonce_str><![CDATA[Mn5Ott5Xm]]></nonce_str>
<sign><![CDATA[4E523B88863B172CC41]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx2017c0086505460]]></prepay_id>
<trade_type><![CDATA[APP]]></trade_type>
</xml>
--------------------------------------此处将几点可能遇到的问题:
<xml><return_code><![CDATA[FAIL]]></return_code><return_msg>
<![CDATA[签名错误]]></return_msg></xml>
或者sign签名长度错误就是签名流程没走对
又或者微信支付提交的金额是不能带小数点的,且是以分为单位,
total_fee=1就是一分钱
<xml><return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[invalid total_fee]]></return_msg>
</xml>
------------------------------------------------------------
第二步,生成参数,调起支付
提示:有接口直接把接口获取的参数填到下面,签名还是要的
reqMap.put("appid",APP_ID);
reqMap.put("prepayid",prepay_id);
reqMap.put("partnerid",mch_id);
reqMap.put("package","prepay_id="+
prepay_id_xml.get("prepay_id"));
reqMap.put("noncestr",getRandomString(32));
reqMap.put("timestamp",String.valueOf(genTimeStamp()));
然后把这些参数拼接起来生成sign,和第一步中第4点有点不同,
不用转换成大写不用执行toUpperCase()
然后在调起微信支付的地方弹框提示
ToastUtil.showShort(context,String.valueOf(payRequest.checkArgs()));
api.sendReq(payRequest);
为true的话说明成功。
此处可能出现的问题:
----------------------------问题一:要么就是提示商户号重复
ToastUtil.showShort(context,payRequest.toString());
修改了订单号和商品描述,可能重复提交了,然后打包重试就可以了
--------------------------问题二:要么就是payRequest.checkArgs()虽然为true,
但还是没有调起微信,也没有支付界面,
然后加载一下就过去了返回支付失败
这个问题我的解决办法是先把微信启动然后在启动app,微信启动后再回到App去支付
如果可以调起支付页,以后每次app支付都能调起微信支付。或者重启设备之后或者切换微信账号之后,
换个订单号重新打包安装,每次都能调起支付界面,
---------------------------------------------------------------------------
也可以先去微信支付接口调试出去输入参数调试,微信支付接口调试网址:
https://pay.weixin.qq.com/wiki/tools/signverify/
自己去研究下,填写必填参数后可直接到第一步的第3点,不过不建议直接跳,
因为之前的步骤始终还是要走的。