微信支付实现过程

微信支付实现过程:

 

1:首先是企业注册微信公众平台;

2:需要认证,然后开通微信支付;如图

 

3:进入这里来注册商户;  每一个小程序对应一个商户

 

 4: 商户和小程序或者公众号做邦定,

 

 5:根据开发需要 ,进行开发配置:

 

 

 ------------------------------------------------

 

以上准备工作做完后可进行开发,邦定成功后如图显示

 小程序配置

 

 

 接下来开始配置代码:

这里我只介绍小程序的支付配置:

小程序相对较为简单,关键是接下来的参数需要配置正确其余就ok了;

整体思路:

小程序发送一个支付请求,后端进行支付处理,返回5个参数,然后小程序发起支付输入密码,支付成功;

 

1: 小程发送请求 ,后端下单 ,返回5个参数

 

5个参数搞清楚了一切好办:

 

appid=wx5c022XXXXXXXX 小程序的appid
secret=3165b49d0772fdf28bd20 小程序的secret
key= 这个key就是上面商户配置中,帐户中心->API安全-> 设置密钥,,这个在你写程序的时候往往会出现解密不成功,或其他签名错误时,重新设置一下这个密钥,
mch_id=15236 绑定的商户号
body=支付收款名称
notify_url =https://wx.ing.com,这里配置小程序的配置里;



开始后端处理支付代码:

//CommonSdo我自己定义的返回类
 public CommonSdo<Map<String,Object>> wxpay(String openid, //这是openid ,根据自己业务来传参
                                    Long oid, //这是我们的 订单id 根据自己业务来传参
                                    HttpServletRequest request){
        if (null==openid){
            return CommonSdo.error("登陆过期,请重新登陆");
        }
        //客户下订单
        Order order = findOrderById(oid).getItem();  //获取小程序端客户下的订单
    
        //微信支付开始///////////////////////////////////////////////////////////////////////////////try {
                       //生成的随机字符串
            String nonce_str =getRandomStringByLength(32);
            //商品名称
            String body = "工作室";
            //获取客户端的ip地址
            String spbill_create_ip = getIpAddr(request);
            //组装参数,用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<String, String>();
            packageParams.put("appid", apppid);    //小程序的appid
            packageParams.put("mch_id", mch_id);   //绑定的商户号
            packageParams.put("nonce_str", nonce_str);  //生成的随机字符串
            packageParams.put("body", body);  //商品名称
            packageParams.put("out_trade_no",order.getCode());      //商户订单号,这个订单号注意不要重复,否则会提示已支付等问题
            packageParams.put("total_fee",orderPrice);              //支付金额,这边需要转成字符串类型,否则后面的签名会失败,以分为单位
            packageParams.put("spbill_create_ip", spbill_create_ip);//
            packageParams.put("notify_url",notify_url);//支付成功后的回调地址
            packageParams.put("trade_type", "JSAPI");//支付方式
            packageParams.put("openid", openid);

            // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
            String prestr = PayUtil.createLinkString(packageParams);

            //MD5运算生成签名,这里是第一次签名,用于调用统一下单接口
            String mysign = PayUtil.sign(prestr,key,"utf-8").toUpperCase();

            //拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去
            String xml = "<xml>" + "<appid>"+apppid+"</appid>"
                    + "<body><![CDATA[" + body + "]]></body>"
                    + "<mch_id>"+mch_id+"</mch_id>"
                    + "<nonce_str>"+nonce_str + "</nonce_str>"
                    + "<notify_url>"+notify_url+"</notify_url>"
                    + "<openid>"+openid+"</openid>"
                    + "<out_trade_no>"+order.getCode()+"</out_trade_no>"
                    + "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"
                    + "<total_fee>"+orderPrice+"</total_fee>"
                    + "<trade_type>"+"JSAPI"+"</trade_type>"
                    + "<sign>"+mysign+"</sign>"
                    + "</xml>";

            System.out.println("调试模式_统一下单接口 请求XML数据:" + xml);

            //调用统一下单接口,并接受返回的结果
            String result = PayUtil.httpRequest(
                    "https://api.mch.weixin.qq.com/pay/unifiedorder",
                    "POST", xml);

            System.out.println("调试模式_统一下单接口 返回XML数据:" + result);
            ////////////////////////////////////////////////////////////////////////////////

            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);

            String return_code = (String) map.get("return_code");//返回状态码

            Map<String, Object> response = new HashMap<String, Object>();//返回给小程序端需要的参数
            if (return_code.equals("SUCCESS")) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                response.put("nonceStr", nonce_str);
                response.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
                //拼接签名需要的参数
                String stringSignTemp = "appId=" + apppid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名,这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, key, "utf-8").toUpperCase();

                response.put("paySign", paySign);
            }

            response.put("appid", apppid);
            //////////////////////////////////////微信支付结束/////////////////////////////////
            //更改订单状态
            order.setState(Order.STATE_PAY);
            orderRepository.save(order);
            ///////////////////////////////////////////////

            return CommonSdo.success(response);   //CommonSdo我自己定义的返回类
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CommonSdo.error("支付异常,未能支付成功");
    }

    /**
     * StringUtils工具类方法
     * 获取一定长度的随机字符串,范围0-9,a-z
     *
     * @param length:指定字符串长度
     * @return 一定长度的随机字符串
     */
    public static String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * IpUtils工具类方法
     * 获取真实的ip地址
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            //多次反向代理后会有多个ip值,第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

2:

官方小程序支付方法,然后小程序拿到返回的以下参数,即可发起支付

  wx.requestPayment({
    timeStamp: " ",
    nonceStr: " ",
    package: " ",
    signType: 'MD5',
    paySign: " ",
    success: function (res) {
    
       
  })

 

posted @ 2019-01-16 13:57  ldp.im  阅读(669)  评论(0编辑  收藏  举报