Android 微信支付走过的坑

1.微信支付步骤:

 1. 在微信开发平台创建app,获取appid,之后申请微信支付
 2. 下载微信支付的sdk到项目中
 3. 看微信支付文档集成微信支付

2.微信支付所需要的材料:

 1. 商户id(申请微信支付成功后,会发到你的邮箱中)
 2. appid
 3. apikey(微信商户平台-->账户设置-->API安全-->密钥设置)

3.微信支付开发过程:

  1. 根据文档进行微信注册(看文档)
  2. 调用统一下单接口(https://api.mch.weixin.qq.com/pay/unifiedorder)生成订单(这个步骤可以交给后台,从后台的接口中获取需要的数据)。
    首先准备一些工具类和方法:
    方法都是在这里找到的。表示感谢
    http://www.open-open.com/lib/view/open1479350904960.html
    回调的界面空白解决方法。表示感谢
    http://www.jianshu.com/p/463b064968b2
    md5类(百度的)
public class MD5 {

    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()));
            else
                resultString = 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" };
}

创建微信支付所需要的sign方法

   /**
     * 
     * @param charactEncoding
     * @param param
     * @param key 是apikey
     * @return
     */
    public static  String CreateSign(String charactEncoding, SortedMap<Object, Object> param, String key){
        StringBuilder sb = new StringBuilder();
        Set es = param.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key="+key);
        Utils.LogI("sb:"+sb.toString());
        String sign = MD5.MD5Encode(sb.toString(), charactEncoding).toUpperCase();
        Utils.LogI("sign:"+sign);
        return sign;
    }

因为微信同意下单所需要的数据是xml,所以需要转化xml的方法

public static String xmlString (SortedMap<Object, Object> param){
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        Set es = param.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()){

            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            sb.append("<").append(k).append(">");
            sb.append(v);
            sb.append("</").append(k).append(">");
        }
        sb.append("</xml>");
        Utils.LogI("xml:"+sb.toString());
        return sb.toString();
    }

工具类或方法准备的差不多了。进行请求吧

 private void paymentWX() {
        PayBean pb = new PayBean();
        pb.setAppid(appId);// appid;
        pb.setBody("这是怎么了来");
        pb.setMach_id(partnerId);// 商户id
        pb.setNonce_str("5K8264ILTKCH16CQ2502SI8ZNMTM67VS");// 随机字符串
        pb.setNotify_url("http://www.peita.net");
        pb.setOut_trade_no("20150806125348");// 订单编号
        pb.setTotal_fee(1);// 总金额
        pb.setTrade_type("APP");// 支付类型
        pb.setSpbill_create_ip("192.168.1.1");// ip



      //微信签名需要(https://pay.weixin.qq.com/wiki/doc/api/app/app.php?        chapter=4_3) 
        SortedMap<Object, Object> param = new TreeMap<Object, Object>();// 可以根据键升序排列
        param.put("appid",申请的appid);
        param.put("body","这个东东很棒");// 商品描述
        param.put("mch_id",申请的商户id);
        param.put("nonce_str","5K8264ILTKCH16CQ2502SI8ZNMTM67VS");//随机字符串
        param.put("notify_url",所通知的url);// 这个url必须能直接访问
        param.put("out_trade_no",订单号);// 不能重复
        param.put("total_fee",1));// 商品总金额
        param.put("trade_type","APP");// 交易类型
        param.put("spbill_create_ip","192.168.1.1");// 用户实际ip
        // 调用获取微信签名的方法,
        String  sign = CreateSign("UTF-8", param, key);
        param.put("sign", sign);
        // 调用转化xml的方法
        String xmlStr = xmlString(param);
        // 进行网络请求,我使用的是xutils
        goRequestion(xmlStr );
    }
    public void goRequestion(String str){
        RequestParams params = new RequestParams();
        params.setBodyEntity(new StringEntity(str,"UTF-8"));
        // 微信的同一下单接口
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        http.send(HttpMethod.POST, url, params, new RequestCallBack<String>() {
            @Override
            public void onSuccess(ResponseInfo<String> responseInfo) {
                // 解析xml获取数据
                Utils.LogI("onSuccess"+responseInfo.result);
            }

            @Override
            public void onFailure(HttpException e, String s) {
                Utils.LogI("onFailure"+s);
            }
        });
    }

注意。注意。注意,第二步完全可以让后台来操作,下面的步骤才是android所需要的调起微信支付页面
1.根据官方文档创建一个包名为:xx.xx.xx.wxapi,在包里创建一个为WXPayEntryActivity类(包名或类名不一致会造成无法回调),用于调用微信支付界面的回调,这个类在微信支付的deom中有,直接拿过来用就可以。最主要的是在这个类中的这个方法做回调界面处理

   @Override
    public void onResp(BaseResp resp) {
        if(resp.getType()==ConstantsAPI.COMMAND_PAY_BY_WX){
            switch (resp.errCode){
                case 0:// 支付界面成功
                    break;
                case -1:// 支付界面调起失败
                    break;
                case -2:// 用户取消支付
                    break;
            }
            finish();
        }
    }

我在这里把WXPayEntryActivity的主题设为了透明,

  android:theme="@android:style/Theme.Translucent"

坑: 我的初衷不是把他设为透明的。我刚开始想在这个activity的界面做一些处理。例如。在activity中有个textview,在支付成功之后。我就让textview显示支付成功,失败,支付失败。。但是不知道怎么回事就是不显示。并且保证走到了回调时间里面,也走到了case里面。所以我就让他透明了。

2.调起微信支付的界面
通过第二步获取所需要的参数,因为我第二步是服务器做的,所以我直接从服务器获取的。如果第二步是Android客户端做的。你就解析返回的xml数据,之后拿到数据。

 // 解析微信的数据,并且调用微信支付
    private void parserWx(JSONObject object) {
        try {
            String appid = object.getString("appid");// appid
            String partnerId = object.getString("mch_id");// 商户id
            String prepayId = object.getString("prepay_id");//预支付交易会话ID
            String nonceStr = object.getString("nonce_str");// 随机字符串
            String sign = object.getString("sign");// 签名
            PayReq parReq = new PayReq();

            // 需要第二次签名,不然调起微信支付界面为空白,返回的errCode为-1
            String time = String.valueOf(getTimeSteamp());
            SortedMap<Object, Object> param = new TreeMap<Object, Object>();// 能排序
            param.put("appid",appid);
            param.put("partnerid",partnerId);
            param.put("prepayid",prepayId);
            param.put("package","Sign=WXPay");
            param.put("noncestr",nonceStr);
            param.put("timestamp",String.valueOf(getTimeSteamp()));

            parReq.appId = appid;
            parReq.partnerId = partnerId;
            parReq.prepayId = prepayId;
            parReq.nonceStr = nonceStr;
            parReq.timeStamp = time;
            parReq.packageValue = "Sign=WXPay";
            // 二次签名
            String agin_sign = WxUtils.CreateSign("UTF-8", param, key);
            parReq.sign = agin_sign;
            boolean flag = msgApi.sendReq(parReq);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    // 获取时间戳
    public long getTimeSteamp(){
        return System.currentTimeMillis()/1000;
    }

注意,注意,注意,如果你在调起微信支付界面的回调方法中返回的是-1.
请检测:可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
如果你没有发现异常那你就要看看你有没有进行二次签名了。把第二次请求的参数在进行一次签名。不需要服务器返回的签名。我在这里挣扎了一个下午。。坑啊!!
最后步骤就是支付成功的查询了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值