zoukankan      html  css  js  c++  java
  • 【JAVA笔记】JAVA后端实现统一扫码支付:微信篇

    最近做完了一个项目,正好没事做,产品经理就给我安排了一个任务。
     
    做一个像收钱吧这样可以统一扫码收钱的功能。
     
    一开始并不知道是怎么实现的,咨询了好几个朋友,才知道大概的业务流程:先是开一个网页用来判断支付平台,是微信还是支付宝,判断过后就好办了,直接照搬微信支付和支付宝的官方文档。不过微信的文档感觉有点坑,得多花点心思。
     
    现在讲讲怎么实现微信支付网页支付,也就是公众号支付:
     
    1.判断支付平台,在判断是微信平台时,必须使用window.location打开网页,使用其他方法在IOS版微信无法打开网页,至少现在的新版微信无法打开。对应的连接是请求获取code的链接。第2步会讲到。
    复制代码
    <html>
    <head>
      <title>判断客户平台</title>
      <basefont face="微软雅黑" size="2" />
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
      <meta name="exporter-version" content="Evernote Windows/303244 (zh-CN, DDL); Windows/6.1.7601 Service Pack 1 (Win64);"/>
    <script type="text/javascript" src="jquery-3.1.1.min.js"></script>
      <style>
        body, td {
          font-family: 微软雅黑;
          font-size: 10pt;
        }
      </style>
    </head>
    <body>
    <script type="text/javascript"> 
    

    window.onload = function(){
    if(isWeiXin()){
    window.location
    ='http://www.xxoo.com/InterfaceAPI/code';
    }
    else if(isZFB()){
    alert(
    '支付宝即将开放....');
    //var p = document.getElementsByTagName('p');
    //
    p[0].innerHTML = window.navigator.userAgent;
    }else{
    alert(
    '请使用微信或者支付宝App扫码');
    }
    }
    function isWeiXin(){
    var ua = window.navigator.userAgent.toLowerCase();
    if(ua.match(/MicroMessenger/i) 'micromessenger'){
    return true;
    }
    else{
    return false;
    }
    }
    function isZFB(){
    var ua = window.navigator.userAgent.toLowerCase();
    if(ua.match(/AlipayClient/i) 'alipayclient'){
    return true;
    }
    else{
    return false;
    }
    }
    </script>
    </body></html>

    复制代码

    2.这里是获取code,回调地址必须使用URLEncoder的utf-8编码,这里最终只获取openid,需要获取UserInfo其他信息的自行测试,只需要修改一下 scope 的参数,

    复制代码
    @RequestMapping({ "code" })
        public void getCode(HttpServletRequest request, HttpServletResponse response) {
            try {
                //回调地址
                String redirect_uri = URLEncoder.encode(
                        "http://www.xxoo.com/InterfaceAPI/openid?codeID=7837283",
                        "utf-8");
                String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="
                        + WechatConfig.APP_ID
                        + "&redirect_uri="
                        + redirect_uri
                        + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
                response.sendRedirect(url);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    复制代码

    3.里面有一个codeid的参数,不要在意这个,是用来测试用的。这里只需要openid,下面是使用get方法获取json返回结果,获取到openid后,重定向到支付页面。

    复制代码
    @RequestMapping({ "openid" })
        public void getOpenid(String codeID, String code,
                HttpServletResponse response) {
            try {
                String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                        + WechatConfig.APP_ID
                        + "&secret="
                        + WechatConfig.APP_SECRET
                        + "&code="
                        + code
                        + "&grant_type=authorization_code";
                if (code != null) {
                    String json = WebUtils.get(requestUrl, null);
                    WechatResult result = new Gson().fromJson(json,
                            WechatResult.class);
                    OPEN_ID = result.getOpenid();
                    System.out.println("====OPEN_ID====" + OPEN_ID);
                    response.sendRedirect("http://www.xxoo.com/InterfaceAPI/pay.html");
                }
    
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {
            e.printStackTrace();
        }
    }</span></pre>
    
    复制代码

    4.在前端支付页面输入要支付的金额,提交到后台

    复制代码
    $.ajax({
    
                type: </span>"POST"<span style="color: #000000">,
                dataType: </span>"html"<span style="color: #000000">,
                url: </span>"http://www.xxoo.com/InterfaceAPI/weixinPay"<span style="color: #000000">,
                data: </span>"value="+<span style="color: #000000">self.input.value,
                timeout:</span>10000<span style="color: #000000">, 
                cache: </span><span style="color: #0000ff">true</span><span style="color: #000000">,
                async: </span><span style="color: #0000ff">true</span><span style="color: #000000">,
                error: function(data){
                        </span><span style="color: #008000">//</span><span style="color: #008000">alert(data+"---value--&gt;"+self.input.value);</span>
                },    },});</pre>
    
    复制代码

    5.后端获取金额然后在后端统一下单,公众号支付有两个地方不一样,一是支付类型要改为 JSAPI,二是需要获取openid

    复制代码
        @RequestMapping({ "weixinPay" })
        public void weixinPay(HttpServletRequest request,
                HttpServletResponse response) {
            String value = request.getParameter("value");
            WechatTradeTest wechat = new WechatTradeTest();
            String json = wechat.testunifiedOrder(Integer.valueOf(value), OPEN_ID);
        //这里返回json到前端
            write(json, response);
        }
    复制代码

    6.统一下单成功后返回的结果例子:

    复制代码
    <xml>
       <return_code><![CDATA[SUCCESS]]></return_code>
       <return_msg><![CDATA[OK]]></return_msg>
       <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
       <mch_id><![CDATA[10000100]]></mch_id>
       <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
       <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
       <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
       <result_code><![CDATA[SUCCESS]]></result_code>
       <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
       <trade_type><![CDATA[JSAPI]]></trade_type>
    </xml>
    复制代码

    7.返回的参数需要重新签名并返回到前端,签名方法与统一下单时的签名是一样的!签名时必须要带上微信商户返回是以Json格式返回到前端。

    复制代码
    public String testunifiedOrder(int fee,String openid) {
            WechatUnifiedOrder request = new WechatUnifiedOrder();
            request.setBody("测试商品");
            request.setDetail("一个好商品");
            request.setGoods_tag("测试");
            request.setOut_trade_no(System.currentTimeMillis() + "");
            request.setFee_type("CNY");
            request.setTotal_fee(1);
            request.setSpbill_create_ip("192.168.88.26");
            request.setTime_start(System.currentTimeMillis() + "");
            request.setOpenid(openid);
            //下单成功后返回
            WechatUnifiedOrder.Response response = WechatConfig.getInstance()
                    .unifiedOrder(request);
            response.setTime_start(request.getTime_start());
            WeichatData data = new WeichatData();
            data.setAppId(response.getAppid());
            data.setTimeStamp(request.getTime_start());
            data.setNonceStr(response.getNonce_str());
            data.setPrepay_id(response.getPrepay_id());
            data.setSignType("MD5");
            TreeMap<String, String> requestMap = new TreeMap<String, String>();
            requestMap.put("appId", response.getAppid());
            requestMap.put("timeStamp", response.getTime_start());
            requestMap.put("nonceStr", response.getNonce_str());
            requestMap.put("package", "prepay_id="+response.getPrepay_id());
            requestMap.put("signType","MD5");
            data.setPaySign(sign(requestMap).toUpperCase());
            return new Gson().toJson(data);
        }
    复制代码

    8.前端需要解析json,获取对应的值,唤醒微信支付

    复制代码
     success: function(data){
                        if(data!=null){
                            var obj=eval("("+data+")");
                            appId = obj["appId"];
                            //timeStamp = new Date().getTime();
                            timeStamp = obj["timeStamp"];
                            nonceStr = obj["nonceStr"];
                            package = obj["prepay_id"];
                            paySign = obj["paySign"];
                        if (typeof WeixinJSBridge == "undefined"){
                               if( document.addEventListener ){
                                   document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
                               }else if (document.attachEvent){
                                   document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                                document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
                               }
                        }else{
                               onBridgeReady();
                        }
                    }else{
                        alert("支付失败");
                    }
            },
    复制代码
    复制代码
        //微信回调
            function onBridgeReady(){
       WeixinJSBridge.invoke(
           'getBrandWCPayRequest', {
               "appId" :appId,
               "timeStamp":timeStamp,
               "nonceStr" :nonceStr,
               "package" :"prepay_id="+package,
               "signType" :"MD5",
               "paySign" : paySign
           },
           function(res){     
               if(res.err_msg == "get_brand_wcpay_request:ok" ) {
    
           }</span><span style="color: #0000ff">else</span><span style="color: #000000"> {
    
           }
       }
    

    );

    复制代码

    到这里基本成功了,同时感谢一位网友的文章:http://blog.csdn.net/u012706811/article/details/52988782。

  • 相关阅读:
    You are not late! You are not early!
    在同一个服务器(同一个IP)为不同域名绑定的免费SSL证书
    Vue.js Is Good, but Is It Better Than Angular or React?
    It was not possible to find any compatible framework version
    VS增加插件 Supercharger破解教程
    Git使用ssh key
    Disconnected: No supported authentication methods available (server sent: publickey)
    VS 2013打开.edmx文件时报类型转换异常
    asp.net MVC4 框架揭秘 读书笔记系列3
    asp.net MVC4 框架揭秘 读书笔记系列2
  • 原文地址:https://www.cnblogs.com/jpfss/p/9957534.html
Copyright © 2011-2022 走看看