微信支付流程指引

来源:互联网 发布:金薇内衣网络传销吗 编辑:程序博客网 时间:2024/04/30 04:41

微信支付需要三个参数(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

&notify_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点,不过不建议直接跳,

因为之前的步骤始终还是要走的。



如果踩坑,自行百度,流程走通,参数搞对,耐心一步步去执行

记录到此

本文参考:http://blog.csdn.net/qq_25821067/article/details/55253613