微信服务号 微信支付开发

微信支付,需要通过微信支付验证 
目前,支付仅限服务号, 
做微信支付开发,主要看开发文档 
统一下单, 
订单查询 
退款等

1.发起支付,都是通过h5发起的,首先获取prepay_id

发起支付,需要统一下单的prepay_id

SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", ConfigUtil.APPID);

        parameters.put("mch_id", ConfigUtil.MCH_ID);
        parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
        parameters.put("body", bodyorder);
        parameters.put("out_trade_no", outTradeNo);// 用户订单号
        parameters.put("total_fee", totalfee);// 标价金额(分)
        // parameters.put("spbill_create_ip",IpAddressUtil.getIpAddr(request));
        parameters.put("spbill_create_ip", "192.168.1.1");// 电脑测试
        // parameters.put("spbill_create_ip",NetworkUtil.getIpAddress(request));
        parameters.put("notify_url", ConfigUtil.NOTIFY_URL);
        parameters.put("trade_type", "JSAPI");
        parameters.put("openid", openId);
        String sign = PayCommonUtil.createSign("UTF-8", parameters);
        parameters.put("sign", sign);
        String requestXML = PayCommonUtil.getRequestXml(parameters);

        String result = CommonUtil.httpsRequestR2s(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
        System.out.println("第一弹数据" + result + "ip地址" + NetworkUtil.getIpAddress(request));

 数据为

第一弹数据
  <xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
  <appid><![CDATA[wx06e68e38fcef451d]]></appid>
  <mch_id><![CDATA[1427607202]]></mch_id>
  <nonce_str><![CDATA[vOK9ll6ZylQAOiRV]]></nonce_str>
  <sign><![CDATA[4D7F2D8D55377493503F8BB9E2F94C8B]]></sign>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <prepay_id><![CDATA[wx20170105120958d7d94506790707606719]]></prepay_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
  </xml>

 

2.拿到prepay_id后,就可以发起支付

支付,需要设置测试路径和真实路径, 

发起支付,将参数转为json,在放到respond里,然后h5页面从request里取

SortedMap<Object, Object> params = new TreeMap<Object, Object>();
        params.put("appId", ConfigUtil.APPID);
        params.put("timeStamp", Long.toString(new Date().getTime()));
        params.put("nonceStr", PayCommonUtil.CreateNoncestr());
        System.out.println("订单id" + map.get("prepay_id"));
        params.put("package", "prepay_id=" + map.get("prepay_id"));
        params.put("signType", ConfigUtil.SIGN_TYPE);
        String paySign = PayCommonUtil.createSign("UTF-8", params);
        // params.put("packageValue", "prepay_id="+map.get("prepay_id"));
        // //这里用packageValue是预防package是关键字在js获取值出错
        params.put("paySign", paySign); // paySign的生成规则和Sign的生成规则一致
        String json = JSONObject.fromObject(params).toString();
        System.out.println("第二弹数据" + json);
        try {

            response.setContentType("text/html" + ";charset=UTF-8");

            response.setHeader("Pragma", "No-cache");

            response.setHeader("Cache-Control", "no-cache");

            response.setDateHeader("Expires", 0);

            response.getWriter().write(json);

            response.getWriter().flush();

        } catch (IOException e) {

            e.printStackTrace();

        }
    }

 上传,支付的html页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>微信支付</title>
</head>
<body>
<!-- <form action="weiChatPayServlet" method="post" >
    <input type="button" value="确认支付" name="ajaxLoadId" id="test1"/>
</form> -->
<div> 
<p> 苏牌皮草</p>
<p> 库存18件</p>
<p> 原价:8888元</p>
<p> 现价:5000</p>
<p> <button id="test"> 我要购买</button></p>

</div>
<script src="js/jquery.min.js"></script>
<script src="js/jweixin-1.0.0.js"></script>
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
function checkWeiXinVersion(){
     var wechatInfo = navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i) ;  
    if( !wechatInfo ) {  
        alert("本活动仅支持微信") ;  
    } else if ( wechatInfo[1] < "5.0" ) {  
        alert("本活动仅支持微信5.0以上版本") ;  
    }  
}
function onBridgeReady(obj){
   WeixinJSBridge.invoke('getBrandWCPayRequest',{
       "appId":obj.appId,                  //公众号名称,由商户传入
       "timeStamp":obj.timeStamp,          //时间戳,自 1970 年以来的秒数
       "nonceStr":obj.nonceStr,         //随机串
       "package" : obj.package,      //<span style="font-family:微软雅黑;">商品包信息</span>
       "signType" : obj.signType,        //微信签名方式:
       "paySign" : obj.paySign           //微信签名
   },function(res){
       alert(res.err_msg);
       if(res.err_msg == "get_brand_wcpay_request:ok" ) {
           window.location.href="http://weixin.xiaowanban.com/WXZ/weichatPay.html"; 
         alert("f成功");
       }else{
           alert("fail");
           window.location.href="http://weixin.xiaowanban.com/WXZ/signup.html";
           //<span style="font-family:微软雅黑;">当失败后,继续跳转该支付页面让用户可以继续付款,贴别注意不能直接调转jsp,</span><span style="font-size:10.5pt">不然会报</span><span style="font-size:12.0pt"> system:access_denied。</span>
       }
   }); 
    }
    var basePath ="weiChatPayServlet";

    $("#test").one("click",function(){
        $.ajax({
            type:"POST",
            url:basePath    
            //<span style="font-family:微软雅黑;">ajax调用微信统一接口获取prepayId</span>
        }).done(function(data){
            alert("数据"+data);
            console.log("数据为"+data);
       var obj = eval('(' + data + ')');
            //var obj =eval("("+data+")");//转换为json对象
           /*  if(parseInt(obj.agent)<5){
                alert("您的微信版本低于5.0无法使用微信支付");
                return;
            } */
          /*   //配置微信
            wx.config({
           debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
           appId: obj.appId, // 必填,公众号的唯一标识
           timestamp:obj.timeStamp , // 必填,生成签名的时间戳
           nonceStr: obj.nonceStr, // 必填,生成签名的随机串
           signature: obj.signature,// 必填,签名,见附录1
           jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 
       });*/
            checkWeiXinVersion();
       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(obj);
        }  



        });
    });

</script>
</body>
</html>

 支付后,可以登录商户平台查看支付状态 

3.支付后要查询自己的订单

在支付时,我会默认存一下,商家生成的订单(商户订单号),一个openid下n那个订单, 
商户订单号,要求唯一性,为了测试,我获取的时间戳,但是商用,最好用每秒100000次不同的订单号,自己可以搜 
我拿到自己的数据库的商户号后,就去掉订单查询

扫描二维码关注公众号,回复: 239384 查看本文章
private String checkOrder(String outTradeNo){
        SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
        parameters.put("appid", ConfigUtil.APPID);
        parameters.put("mch_id", ConfigUtil.MCH_ID);
        parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
        parameters.put("out_trade_no", outTradeNo);//用户订单号
        parameters.put("sign_type", ConfigUtil.SIGN_TYPE);
        String sign = PayCommonUtil.createSign("UTF-8", parameters);
        parameters.put("sign", sign);
        String requestXML = PayCommonUtil.getRequestXml(parameters);
        String result=null ;
    Map<String, String> map = null;
         result =CommonUtil.httpsRequestR2s(ConfigUtil.CHECK_ORDER_URL, "POST", requestXML);
                try {
                    map = XMLUtil.doXMLParse(result);
                } catch (JDOMException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (map!=null) {
                    String returnCode=  map.get("return_code");
                    String resultCode=  map.get("result_code"); 
                    if (returnCode.equals("SUCCESS")&&resultCode.equals("SUCCESS")){
//                      System.out.println("returnCode结果为"+returnCode+"resultCode结果"+resultCode);
//                      System.out.println("支付状态"+map.get("trade_state"));
                        return map.get("trade_state");
                    }else {
                        return "noArrivePay";//为发起支付,没有到输入密码处直接退出
                    }
                }else{
                    return null;
                }




    }

 直要查到为支付成功,就修改数据库,支付状态

4.微信支付退款,直接看pai,涉及到证书的

测试退款时,也可以自己登陆商户平台退款; 

退款的servlet主要代码

SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", ConfigUtil.APPID);
        parameters.put("mch_id", ConfigUtil.MCH_ID);
        parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
        parameters.put("out_trade_no", outTradeNo);// 用户订单号
        parameters.put("out_refund_no", outRefundno);// 商户退款单号
        parameters.put("total_fee", totalFee);// 订单金额
        parameters.put("refund_fee", refundFee);// 退款金额
        parameters.put("op_user_id", ConfigUtil.MCH_ID);// 操作员id
        parameters.put("sign_type", ConfigUtil.SIGN_TYPE);
        String sign = PayCommonUtil.createSign("UTF-8", parameters);
        parameters.put("sign", sign);
        String requestXML = PayCommonUtil.getRequestXml(parameters);
        String result = null;
        Map<String, String> map = null;
        result = CommonUtil.httpsRequestR2s(ConfigUtil.REFUND_URL, "POST", requestXML);
        try {
            map = XMLUtil.doXMLParse(result);
        } catch (JDOMException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // 退款微信证书相关
        KeyStore keyStore = null;
        FileInputStream instream=null;
        try {
            keyStore = KeyStore.getInstance("PKCS12");
            instream = new FileInputStream(new File("D:/10016225.p12"));
            keyStore.load(instream, "10016225".toCharArray());

        } catch (KeyStoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CertificateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            instream.close();
        }






        // Trust own CA and all self-signed certs
        SSLContext sslcontext=null;
        try {

            sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "10016225".toCharArray()).build();
        } catch (KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (KeyStoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {

            HttpGet httpget = new HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");

            System.out.println("executing request" + httpget.getRequestLine());

            CloseableHttpResponse responseSJT = httpclient.execute(httpget);
            try {
                HttpEntity entity = responseSJT.getEntity();

                System.out.println("----------------------------------------");
                System.out.println(responseSJT.getStatusLine());
                if (entity != null) {
                    System.out.println("Response content length: " + entity.getContentLength());
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                    String text;
                    while ((text = bufferedReader.readLine()) != null) {
                        System.out.println(text);
                    }

                }
                EntityUtils.consume(entity);
            } finally {
                responseSJT.close();
            }
        } finally {
            httpclient.close();
        }
    }

 退款成功图片 

退款成功的数据

退款成功返回
executing requestPOST https://api.mch.weixin.qq.com/secapi/pay/refund HTTP/1.1
----------------------------------------
HTTP/1.1 200 OK
Response content length: 850
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx06e68e38fcef451d]]></appid>
<mch_id><![CDATA[1427607202]]></mch_id>
<nonce_str><![CDATA[tR8oByXN60Xc1C9M]]></nonce_str>
<sign><![CDATA[4F9FD6304C7CF37F0DD9B194AA7C6B8A]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[4007112001201701115967786227]]></transaction_id>
<out_trade_no><![CDATA[1484126688291]]></out_trade_no>
<out_refund_no><![CDATA[20170113161502599000]]></out_refund_no>
<refund_id><![CDATA[2007112001201701130741391621]]></refund_id>
<refund_channel><![CDATA[]]></refund_channel>
<refund_fee>100</refund_fee>
<coupon_refund_fee>0</coupon_refund_fee>
<total_fee>100</total_fee>
<cash_fee>100</cash_fee>
<coupon_refund_count>0</coupon_refund_count>
<cash_refund_fee>100</cash_refund_fee>
</xml>

 

5.说一下,支付的api准备配置

5.1微信支付需要验证 
这里写图片描述 
5.2微信支付,设置秘钥 
这里写图片描述 
设置秘钥时,会提醒你,是否安装证书,就是微信验证,发给你的邮件里附件里的cert 
这里写图片描述

6.微信授权,获取openid,网页授权的东西,是最基本的,也要知道

这里写图片描述 
网页授权,获取用户信息 
这里写图片描述

猜你喜欢

转载自kissuyoyo.iteye.com/blog/2357174