MZERO微信支付流程的梳理

根据项目代码分析微信支付的具体流程

项目中的一个包含支付逻辑的Activity

RechargeActivity(里面包含使用微信支付完成积分充值的逻辑)

在具体的支付逻辑在onClick这个点击事件中,下面具体来看这个点击事件中所做的内容:

以上这些只需要注意下面这行代码:

    MyWxPayUtils.Pay(UiUtils.getContext(), Params, Url_pay);
  • 参数1:上下文
  • 参数2: 下单需要提交的参数
    (这个参数的内容参考 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1)

  • 参数3: 用户生成并返回”正确的预支付交易回话标识”的Servlet

以上是调用部分,下面具体看MyWxPayUtils这个工具类:

/**
 * 进行微信支付的工具类
 * 
 * @author king
 * 
 */
public class MyWxPayUtils {

    public static Context mContext = null;
    public static WXPay wxPay = null;

    // 调用该方法进行支付
    public static void Pay(Context context, Map Params,
            String URL) {
        mContext = context;
        String ip = getIpAddress(context); //获取本机的Ip地址
        Params.put("ip", ip);
        // 1.首先进行请求服务器,上传本次微信支付的订单详情,并获取预支付Id
        HttpHelper httpHelper = new HttpHelper(context, URL, Params,
                new Handler() {
                    @Override
                    public void handleMessage(Message msg) {

                        wxPay = new WXPay(); // 封装从服务器获取的用于支付的参数

                        String json_wx = (String) msg.obj;
                        try {
                            JSONObject jsonObject = new JSONObject(json_wx);
                            wxPay.setPrepay_id(jsonObject
                                    .getString("prepay_id"));
                            wxPay.setSign(jsonObject.getString("sign"));
                            wxPay.setOut_trade_no(jsonObject
                                    .getString("out_trade_no"));
                        } catch (JSONException e) {
                            Log.i("MyWxPayUtils", "json解析异常");
                            e.printStackTrace();
                        }

                        // 2.调用微信支付的逻辑

                        IWXAPI wxapi = WXAPIFactory.createWXAPI(mContext,
                                WxPay.appid);

                        wxapi.registerApp(WxPay.appid); //进行注册

                        PayReq payRequest = new PayReq();

                        payRequest.appId = WxPay.appid; // 应用id
                        payRequest.partnerId = WxPay.partnerid; // 商户id
                        payRequest.prepayId = wxPay.getPrepay_id();// 预支付订单ID
                        payRequest.packageValue = WxPay.packageValue;// 扩展字段
                        payRequest.nonceStr = WxPayUtils.genNonceStr(); // 随机字符串
                        payRequest.timeStamp = WxPayUtils.genTimeStamp(); // 时间戳

                        // 二次签名
                        List signParams = new LinkedList();

                        signParams.add(new BasicNameValuePair("appid",
                                payRequest.appId));
                        signParams.add(new BasicNameValuePair("noncestr",
                                payRequest.nonceStr));
                        signParams.add(new BasicNameValuePair("package",
                                payRequest.packageValue));
                        /** 注意二次签名这里不再是mch_id,变成了prepayid; */
                        signParams.add(new BasicNameValuePair("partnerid",
                                payRequest.partnerId));
                        signParams.add(new BasicNameValuePair("prepayid",
                                payRequest.prepayId));
                        signParams.add(new BasicNameValuePair("timestamp",
                                payRequest.timeStamp));

                        payRequest.sign = genAppSign(signParams); // 签名

                        wxapi.sendReq(payRequest); //开始调用微信支付

                        Log.i("Test", "Sign:\n" + payRequest.sign);

                    }
                });

        // 2.通过handler告知要进行调用微信支付了

    }

    private static String getIpAddress(Context context) {
        // 获取wifi服务
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        // 判断wifi是否开启
        if (!wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(true);
        }
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        int ipAddress = wifiInfo.getIpAddress();
        String intToIp = intToIp(ipAddress);

        Log.i("Test", "本机IP:"+intToIp);

        return intToIp;
    }

    /**
     * 在app端生成签名
     * @param params
     * @return
     */
    private static String genAppSign(List params) {
        StringBuilder str = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            str.append(params.get(i).getName());
            str.append('=');
            str.append(params.get(i).getValue());
            str.append('&');
        }
        str.append("key=");
        str.append(WxPay.API_KEY);

        String appSign = MD5.getMessageDigest(str.toString().getBytes())
                .toUpperCase();
        Log.e("orion", appSign);
        return appSign;
    }

    // 将获取到的ip转换成字符串
    public static String intToIp(int i) {

        return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF)
                + "." + (i >> 24 & 0xFF);
    }

}

WxPayRetrunServlet.Java(用于生成并返回预支付id)


/**
 * 返回给客户端预支付id
 * @author 春水碧于天
 *
 */
public class WxPayRetrunServlet extends HttpServlet {


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String spbill_create_ip =request.getParameter("ip"); //获取终端的IP地址
        System.out.println("终端ip:"+spbill_create_ip);
        String encode = TenpayUtil.getCharacterEncoding(request, response);
        System.out.println("编码:"+encode);

        String body = request.getParameter("body"); //商品描述
        String total_fee = request.getParameter("total_fee"); //消费的金额
        //获取当前具体的日期
        Calendar calendar=Calendar.getInstance();
        int year=calendar.get(Calendar.YEAR);
        int month=calendar.get(Calendar.MONTH)+1;
        int day=calendar.get(Calendar.DAY_OF_MONTH);
        int hour=calendar.get(Calendar.HOUR_OF_DAY);
        int minute=calendar.get(Calendar.MINUTE);
        int second=calendar.get(Calendar.SECOND);   
        String currentDateTime=year+"-"+month+"-"+day+" "+hour+":"+minute+":"+second;       

                //---------------生成订单号 开始------------------------
                //当前时间 yyyyMMddHHmmss
                String currTime = TenpayUtil.getCurrTime();
                //8位日期
                String strTime = currTime.substring(8, currTime.length());
                //四位随机数
                String strRandom = TenpayUtil.buildRandom(4) + "";
                //10位序列号,可以自行调整。
                String strReq = strTime + strRandom;
                //订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行
                String out_trade_no = strReq;
                //---------------生成订单号 结束------------------------
                //  
                PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);//获取prepayid的请求类
                ClientRequestHandler clientHandler = new ClientRequestHandler(request, response);//返回客户端支付参数的请求类
                String noncestr = WXUtil.getNonceStr();
                    String timestamp = WXUtil.getTimeStamp();
                    ////设置获取prepayid支付参数
                    prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID); //应用id
                    prepayReqHandler.setParameter("mch_id", ConstantUtil.PARTNER); //商户号
                    prepayReqHandler.setParameter("nonce_str", noncestr);//随机字符串
                    prepayReqHandler.setParameter("body", body);//商品描述
                    prepayReqHandler.setParameter("out_trade_no", out_trade_no);//商户订单号
                    prepayReqHandler.setParameter("total_fee",total_fee);//总金额
                    prepayReqHandler.setParameter("spbill_create_ip", spbill_create_ip);//终端IP
                    prepayReqHandler.setParameter("notify_url", ConstantUtil.TOKENURL);//通知地址
                    prepayReqHandler.setParameter("trade_type", "APP");//指定支付方式
                    WXPay wxPay = new WXPay(); //用于封装传回客户端的调用微信支付所需的参数
                    wxPay.setOut_trade_no(out_trade_no); //订单号
                    //生成获取预支付签名
                    String sign = prepayReqHandler.createMD5Sign();
                    wxPay.setSign(sign);
                    System.out.println("签名:"+sign);
                    prepayReqHandler.setParameter("sign",sign);
                    String gateUrl = ConstantUtil.GATEURL ;
                    prepayReqHandler.setGateUrl(gateUrl);
                    String prepayid = null;
                    try{
                    //获取prepayId
                        prepayid = prepayReqHandler.sendPrepay();

                        wxPay.setPrepay_id(prepayid);

                        System.out.println("预支付签名:"+prepayid);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                Gson gson = new Gson();
                String json_wxpay = gson.toJson(wxPay);
                response.getWriter().write(json_wxpay);
    }

}

对MyWxPayUtils和WxPayRetrunServlet之间的一个交互流程进行一个简要的梳理:

  1. 当调用MyWxPayUtils.pay()方法进行支付的时候,首先携带由调用者传递过来的Params(提交的参数参考 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1,需要注意的是客户端仅需要提供body,detail,total_fell等不涉及用户安全的参数,一些涉及到安全的参数全部在服务端进行配置 )去请求WxPayRetrunServlet,用于获取Android客户端调用起微信支付所必须的prepayId。

    Android客户端调用起来微信支付所需要的必须参数如下:

    注意红框中圈出来的部分,prepayId 这个就是前面请求WxPayRetrunServlet获取到的,也是是否能够调用起来微信支付的关键。

    那么sign这个参数该如何获得?

    需要根据微信官方文档给出的签名算法,对字段名为appid,partnerid,prepayid,noncestr,timestamp,package进行二次签名得到sign这个参数。

  2. 下面关注WxPayRetrunServlet是如何获取prepayId的,看下面的图中的标记:

  3. 以上两个步骤完成后,下面关注Android客户端是如何调用起微信支付的。

    1. 先向微信注册APPId:

      IWXAPI wxapi = WXAPIFactory.createWXAPI(mContext,WxPay.appid);
      wxapi.registerApp(WxPay.appid); //进行注册
      
    2. 调起支付:

      wxapi.sendReq(payRequest); //开始调用微信支付
      

    payRequest为第一步中封装的那些调用微信支付的必要参数

    不出意外的话到这里微信支付就可以正常被调起了

Android客户端中支付结果的回调

当调起微信支付的支付界面后,我们不能确定用户一定支付成功,有可能用户直接点击了返回不再进行支付,因此对于这种情况,需要给用户一个界面的提示。具体的步骤如下:

  1. 创建一个名为WXPayEntryActivity的类(需要在当前项目包的根路径下创建,而且包名必须和前面给出的包名一致,不然无法回调!)

一定要注意,不要踩坑!

  1. 接着实现 IWXAPIEventHandler 这个接口,并注册支付结果的回调用。
api = WXAPIFactory.createWXAPI(this, WxPay.appid);  
appidapi.handleIntent(getIntent(), this);

3.支付的结果会回调给onResp方法
“`
@Override
public void onResp(BaseResp resp){

}

“`
根据BaseResp对象中封装的code进行判断即可

你可能感兴趣的:(Java,微信,支付)