Android 实现微信支付那些事

来源:互联网 发布:淘宝店铺收藏 编辑:程序博客网 时间:2024/05/14 07:38

各位博友们好,这是鄙人写的第一篇技术博客(前面一篇都是代码截图,不方便使用,所以重新写了一遍),有写的不好的地方请提出来,仅供参考,不喜勿喷!关于微信支付,接触过的Android朋友们应该都深有感触,无数个坑等你着来填,你准备好了吗?

第一步,当然是去微信开放平台中创建应用,创建成功后可以拿到AppID、AppSecret和商户号PartnerId。开通微信支付能力,登录商户平台设置秘钥(32位)

签名工具下载地址: 
https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk 
设置成功后可以在开放平台应用详情中查看。这个秘钥就是后面我们要用到的ApiKey。 
第二步,集成libammsdk.jar后,前面的把AppID注册到微信就不说了,接下来最重要的是调用官方文档中的接口https://api.mch.weixin.qq.com/pay/unifiedorder拿到PrepayId,这也是微信支付中最大的坑之一: 

再者,参数中有一个非常重要的sign签名的生成,具体怎么生成官方说的是比较详细,但是要注意一点是参数的顺序一定要一致,我就在这里浪费了很多时间,代码如下:

            List<NameValuePair> packageParams = new LinkedList<>();            packageParams.add(new NameValuePair("appid", appId));            packageParams.add(new NameValuePair("body", body));            packageParams.add(new NameValuePair("mch_id", mchId));            packageParams.add(new NameValuePair("nonce_str", nonceStr));            packageParams.add(new NameValuePair("notify_url", notifyURL));            packageParams.add(new NameValuePair("out_trade_no", orderNumber));            packageParams.add(new NameValuePair("spbill_create_ip", ip));            packageParams.add(new NameValuePair("total_fee", payAmt));            packageParams.add(new NameValuePair("trade_type", tradeType));            String packageValue = createServerSign(packageParams);

最后,要注意文档中有个注解容易忽视,调用上面接口时所传的参数必须是XML格式,如果你传json,那不好意思,报错。具体格式仅供参考: 

                xml = "<xml>" + "<appid>" + appId + "</appid>"                    + "<mch_id>" + mchId + "</mch_id>"                    + "<nonce_str>" + nonceStr + "</nonce_str>"                    + "<sign>" + packageValue + "</sign>"                    + "<body><![CDATA[" + body + "]]></body>"                    + "<out_trade_no>" + orderNumber + "</out_trade_no>"                    + "<attach>" + "" + "</attach>"                    + "<total_fee>" + payAmt + "</total_fee>"                    + "<spbill_create_ip>" + ip + "</spbill_create_ip>"                    + "<notify_url>" + notifyURL + "</notify_url>"                    + "<trade_type>" + tradeType + "</trade_type>"                    + "<openid>" + "" + "</openid>" + "</xml>";

补充一下签名的方法,签名这边需要用到ApiKey:

    //签名    private String createServerSign(List<NameValuePair> params) {        StringBuffer sb = new StringBuffer();        for (int i = 0; i < params.size(); i++) {            String k = params.get(i).getName();            String v = params.get(i).getValue();            if (null != v && !"".equals(v) && !"sign".equals(k)                    && !"key".equals(k)) {                sb.append(k + "=" + v + "&");            }        }        sb.append("key=" + Const.API_KEY);        String appSign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();        return appSign;    }

MD5工具类:

public class MD5Util {private static String byteArrayToHexString(byte b[]) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++)resultSb.append(byteToHexString(b[i]));return resultSb.toString();}private static String byteToHexString(byte b) {int n = b;if (n < 0)n += 256;int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}public static String MD5Encode(String origin, String charsetname) {String resultString = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))resultString = byteArrayToHexString(md.digest(resultString.getBytes()));elseresultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));} catch (Exception exception) {}return resultString;}private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };}


第三步,上一步返回的数据也是xml格式,解析时会用到jdom.jar这个包,具体代码就不列了,拿到PrepayId后就可以调用微信支付,这里还需要二次签名,签名的方法同上,下面是调用微信支付的代码:

String timestamp = String.valueOf(genTimeStamp());                String appId = Const.APP_ID;                String mchId = Const.PARTNER_ID;                String packageValue = "Sign=WXPay";                String sign = "";                List<NameValuePair> signParams = new LinkedList<>();                signParams.add(new NameValuePair("appid", appId));                signParams.add(new NameValuePair("noncestr", nonceStr));                signParams.add(new NameValuePair("package", packageValue));                signParams.add(new NameValuePair("partnerid", mchId));                signParams.add(new NameValuePair("prepayid", prepayId));                signParams.add(new NameValuePair("timestamp", timestamp));                sign = createServerSign(signParams);                if (!api.isWXAppInstalled()) {                    showToast(getString(R.string.pay_wx));                    return;                }                if (!api.isWXAppSupportAPI()) {                    showToast(getString(R.string.check_pay));                    return;                }                PayReq req = new PayReq();                req.appId = appId;                req.partnerId = mchId;                req.prepayId = prepayId;                req.nonceStr = nonceStr;                req.timeStamp = timestamp;                req.packageValue = packageValue;                req.sign = sign;                req.extData = "app data";                api.sendReq(req);

最后,回调支付结果通知WXPayEntryActivity这个类,必须是在包名.wxapi.WXPayEntryActivity之下,清单中别忘记注册了,具体如下:

 <activity            android:name=".wxapi.WXPayEntryActivity"            android:exported="true"            android:launchMode="singleTop"            android:noHistory="true">            <intent-filter>                <action android:name="android.intent.action.VIEW" />                <category android:name="android.intent.category.DEFAULT" />                <data android:scheme="wx3e8d4bdfabaf9856" />            </intent-filter>        </activity>

谢谢大家观看!希望能有所帮助





1 0
原创粉丝点击