微信小程序-統一下單、微信支付(Java後臺)

 

一、首先分享 微信統一下單接口: php

      https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 html

        微信接口 簽名 對比網址:前端

      https://pay.weixin.qq.com/wiki/tools/signverify/算法

        微信小程序 微信支付 網址:sql

      https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-pay.html#wxrequestpaymentobject小程序

 

二、微信小程序端 代碼示例:微信小程序

 1   payment:function(event){
 2     var that = this;
 3     console.log('去支付按鈕點擊事件')
 4     wx.request({
 5       url: 'http://192.168.8.50:8080/matouwang/wechat/wechatAppletGolf/createUnifiedOrder',
 6       method: 'POST', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
 7       // 當method 爲POST 時 設置如下 的header 
 8       header: { 'content-type': 'application/x-www-form-urlencoded' },
 9       data: {
10         amount: teamMoney,
11         openid: openId
12       },
13       success: function (res) {
14         if (res.data.prepayId != ''){
15           console.log('微信統一下單接口調用成功 數據包:' + res.data.prepayId);
16           console.log('微信統一下單接口調用成功 訂單號:' + res.data.outTradeNo);
17           console.log('調用微信支付接口以前先生成簽名')
18           //保存訂單號信息
19           var outTradeNo = res.data.outTradeNo;
20           wx.request({
21             url: 'http://192.168.8.50:8080/matouwang/wechat/wechatAppletGolf/generateSignature',
22             method: 'POST', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
23             // 當method 爲POST 時 設置如下 的header 
24             header: { 'content-type': 'application/x-www-form-urlencoded' },
25             data: {
26               prepayId: res.data.prepayId
27             },
28             success: function (paryResult) {
29               if (paryResult.data.sign != '') {
30                 console.log('微信支付接口以前先生成簽名成功')
31                 console.log('簽名:' + paryResult.data.sign)
32                 console.log('隨機串:' + paryResult.data.nonceStr)
33                 console.log('時間戳:' + paryResult.data.timeStamp)
34                 //這個applyId必定要大寫 並且簽名的參數和調用方法的參數值必定要統一
35                 wx.requestPayment({
36                   'appId': '',
37                   'timeStamp': paryResult.data.timeStamp,
38                   'nonceStr': paryResult.data.nonceStr,
39                   'package': paryResult.data.package,
40                   'signType': 'MD5',
41                   'paySign': paryResult.data.sign,
42                   'success': function (paymentRes) {
43                     console.log(paymentRes)
44                     that.setData({
45                       notPay: true,
46                       paySuccess: false,
47                       teamNotPay: true,
48                       button:true,
49                       outTradeNo: outTradeNo,
50                       payDate:new Date()
51                     })
52                   },
53                   'fail': function (error) {
54                     console.log(error)
55                   }
56                 })
57               } else {
58                 console.log('微信支付接口以前先生成簽名失敗')
59               }
60             }
61           })
62         }
63       }
64     });
65   },

三、分享微信 統一下單 後臺代碼示例:api

  1     @Override
  2     public JSONObject createUnifiedOrder(HttpServletRequest request,HttpServletResponse response) {
  3         logger.info("微信 統一下單 接口調用");
  4         //設置最終返回對象
  5         JSONObject resultJson = new JSONObject();
  6         //建立條件
  7         Criteria criteria = new Criteria();
  8     
  9         //接受參數(金額)
 10         String amount = request.getParameter("amount");
 11         //接受參數(openid)
 12         String openid = request.getParameter("openid");
 13         //接口調用總金額單位爲分換算一下(測試金額改爲1,單位爲分則是0.01,根據本身業務場景判斷是轉換成float類型仍是int類型)
 14         //String amountFen = Integer.valueOf((Integer.parseInt(amount)*100)).toString();
 15         //String amountFen = Float.valueOf((Float.parseFloat(amount)*100)).toString();
 16         String amountFen = "1";
 17         //建立hashmap(用戶得到簽名)
 18         SortedMap<String, String> paraMap = new TreeMap<String, String>();
 19         //設置body變量 (支付成功顯示在微信支付 商品詳情中)
 20         String body = "啦啦啦測試";
 21         //設置隨機字符串
 22         String nonceStr = Utils.getUUIDString().replaceAll("-", "");
 23         //設置商戶訂單號
 24         String outTradeNo = Utils.getUUIDString().replaceAll("-", "");
 25         
 26         
 27         //設置請求參數(小程序ID)
 28         paraMap.put("appid", APPLYID);
 29         //設置請求參數(商戶號)
 30         paraMap.put("mch_id", MCHID);
 31         //設置請求參數(隨機字符串)
 32         paraMap.put("nonce_str", nonceStr);
 33         //設置請求參數(商品描述)
 34         paraMap.put("body", body);
 35         //設置請求參數(商戶訂單號)
 36         paraMap.put("out_trade_no", outTradeNo);
 37         //設置請求參數(總金額)
 38         paraMap.put("total_fee", amountFen);
 39         //設置請求參數(終端IP)
 40         paraMap.put("spbill_create_ip", WebUtils.getIpAddress(request, response));
 41         //設置請求參數(通知地址)
 42         paraMap.put("notify_url", WebUtils.getBasePath()+"wechat/wechatAppletGolf/payCallback");
 43         //設置請求參數(交易類型)
 44         paraMap.put("trade_type", "JSAPI");
 45         //設置請求參數(openid)(在接口文檔中 該參數 是否必填項 可是必定要注意 若是交易類型設置成'JSAPI'則必須傳入openid)
 46         paraMap.put("openid", openid);
 47         //調用邏輯傳入參數按照字段名的 ASCII 碼從小到大排序(字典序)
 48         String stringA = formatUrlMap(paraMap, false, false);
 49         //第二步,在stringA最後拼接上key獲得stringSignTemp字符串,並對stringSignTemp進行MD5運算,再將獲得的字符串全部字符轉換爲大寫,獲得sign值signValue。(簽名)
 50         String sign = MD5Util.MD5(stringA+"&key="+KEY).toUpperCase();
 51         //將參數 編寫XML格式
 52         StringBuffer paramBuffer = new StringBuffer();
 53         paramBuffer.append("<xml>");
 54         paramBuffer.append("<appid>"+APPLYID+"</appid>");
 55         paramBuffer.append("<mch_id>"+MCHID+"</mch_id>");
 56         paramBuffer.append("<nonce_str>"+paraMap.get("nonce_str")+"</nonce_str>");
 57         paramBuffer.append("<sign>"+sign+"</sign>");
 58         paramBuffer.append("<body>"+body+"</body>");
 59         paramBuffer.append("<out_trade_no>"+paraMap.get("out_trade_no")+"</out_trade_no>");
 60         paramBuffer.append("<total_fee>"+paraMap.get("total_fee")+"</total_fee>");
 61         paramBuffer.append("<spbill_create_ip>"+paraMap.get("spbill_create_ip")+"</spbill_create_ip>");
 62         paramBuffer.append("<notify_url>"+paraMap.get("notify_url")+"</notify_url>");
 63         paramBuffer.append("<trade_type>"+paraMap.get("trade_type")+"</trade_type>");
 64         paramBuffer.append("<openid>"+paraMap.get("openid")+"</openid>");
 65         paramBuffer.append("</xml>");
 66         
 67         try {
 68             //發送請求(POST)(得到數據包ID)(這有個注意的地方 若是不轉碼成ISO8859-1則會告訴你body不是UTF8編碼 就算你改爲UTF8編碼也同樣很差使 因此修改爲ISO8859-1)
 69             Map<String,String> map = doXMLParse(getRemotePortData(URL, new String(paramBuffer.toString().getBytes(), "ISO8859-1")));
 70             //應該建立 支付表數據
 71             if(map!=null){
 72                 //清空
 73                 criteria.clear();
 74                 //設置openId條件
 75                 criteria.put("openId", openid);
 76                 //獲取數據
 77                 List<WechatAppletGolfPayInfo> payInfoList = appletGolfPayInfoMapper.selectByExample(criteria);
 78                 //若是等於空 則證實是第一次支付
 79                 if(CollectionUtils.isEmpty(payInfoList)){
 80                     //建立支付信息對象
 81                     WechatAppletGolfPayInfo appletGolfPayInfo = new  WechatAppletGolfPayInfo();
 82                     //設置主鍵
 83                     appletGolfPayInfo.setPayId(outTradeNo);
 84                     //設置openid
 85                     appletGolfPayInfo.setOpenId(openid);
 86                     //設置金額
 87                     appletGolfPayInfo.setAmount(Long.valueOf(amount));
 88                     //設置支付狀態
 89                     appletGolfPayInfo.setPayStatus("0");
 90                     //插入Dao
 91                     int sqlRow = appletGolfPayInfoMapper.insert(appletGolfPayInfo);
 92                     //判斷
 93                     if(sqlRow == 1){
 94                         logger.info("微信 統一下單 接口調用成功 而且新增支付信息成功");
 95                         resultJson.put("prepayId", map.get("prepay_id"));
 96                         resultJson.put("outTradeNo", paraMap.get("out_trade_no"));
 97                         return resultJson;
 98                     }
 99                 }else{
100                     //判斷 是否等於一條
101                     if(payInfoList.size() == 1){
102                         //獲取 須要更新數據
103                         WechatAppletGolfPayInfo wechatAppletGolfPayInfo = payInfoList.get(0);
104                         //更新 該條的 金額
105                         wechatAppletGolfPayInfo.setAmount(Long.valueOf(amount));
106                         //更新Dao
107                         int sqlRow = appletGolfPayInfoMapper.updateByPrimaryKey(wechatAppletGolfPayInfo);
108                         //判斷
109                         if(sqlRow == 1){
110                             logger.info("微信 統一下單 接口調用成功 修改支付信息成功");
111                             resultJson.put("prepayId", map.get("prepay_id"));
112                             resultJson.put("outTradeNo", paraMap.get("out_trade_no"));
113                             return resultJson;
114                         }
115                     }
116                 }
117             }
118             //將 數據包ID 返回
119             
120             System.out.println(map);
121         } catch (UnsupportedEncodingException e) {
122             logger.info("微信 統一下單 異常:"+e.getMessage());
123             e.printStackTrace();
124         } catch (Exception e) {
125             logger.info("微信 統一下單 異常:"+e.getMessage());
126             e.printStackTrace();
127         }
128         logger.info("微信 統一下單 失敗");
129         return resultJson;
130     }

四、生成 微信支付 簽名後臺 代碼示例:數組

 1     @Override
 2     public JSONObject generateSignature(HttpServletRequest request,
 3             HttpServletResponse response) {
 4         logger.info("微信 支付接口生成簽名 方法開始");
 5         //實例化返回對象
 6         JSONObject resultJson = new JSONObject();
 7         
 8         //得到參數(微信統一下單接口生成的prepay_id )
 9         String prepayId = request.getParameter("prepayId");
10         //建立 時間戳
11         String timeStamp = Long.valueOf(System.currentTimeMillis()).toString();
12         //建立 隨機串
13         String nonceStr = Utils.getUUIDString().replaceAll("-", "");
14         //建立 MD5
15         String signType = "MD5";
16         
17         //建立hashmap(用戶得到簽名)
18         SortedMap<String, String> paraMap = new TreeMap<String, String>();
19         //設置(小程序ID)(這塊必定要是大寫)
20         paraMap.put("appId", APPLYID);
21         //設置(時間戳)
22         paraMap.put("timeStamp", timeStamp);
23         //設置(隨機串)
24         paraMap.put("nonceStr", nonceStr);
25         //設置(數據包)
26         paraMap.put("package", "prepay_id="+prepayId);
27         //設置(簽名方式)
28         paraMap.put("signType", signType);
29         
30         
31         //調用邏輯傳入參數按照字段名的 ASCII 碼從小到大排序(字典序)
32         String stringA = formatUrlMap(paraMap, false, false);
33         //第二步,在stringA最後拼接上key獲得stringSignTemp字符串,並對stringSignTemp進行MD5運算,再將獲得的字符串全部字符轉換爲大寫,獲得sign值signValue。(簽名)
34         String sign = MD5Util.MD5(stringA+"&key="+KEY).toUpperCase();
35         
36         if(StringUtils.isNotBlank(sign)){
37             //返回簽名信息
38             resultJson.put("sign", sign);
39             //返回隨機串(這個隨機串是新建立的)
40             resultJson.put("nonceStr", nonceStr);
41             //返回時間戳
42             resultJson.put("timeStamp", timeStamp);
43             //返回數據包
44             resultJson.put("package", "prepay_id="+prepayId);
45             
46             logger.info("微信 支付接口生成簽名 設置返回值");
47         }
48         logger.info("微信 支付接口生成簽名 方法結束");
49         return resultJson;
50     }

五、簽名算法 將key Value 字典排序 代碼示例:緩存

 1     /** 
 2      *  
 3      * 方法用途: 對全部傳入參數按照字段名的 ASCII 碼從小到大排序(字典序),而且生成url參數串<br> 
 4      * 實現步驟: <br> 
 5      *  
 6      * @param paraMap   要排序的Map對象 
 7      * @param urlEncode   是否須要URLENCODE 
 8      * @param keyToLower    是否須要將Key轉換爲全小寫 
 9      *            true:key轉化成小寫,false:不轉化 
10      * @return 
11      */  
12     private static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower){  
13         String buff = "";  
14         Map<String, String> tmpMap = paraMap;  
15         try  
16         {  
17             List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());  
18             // 對全部傳入參數按照字段名的 ASCII 碼從小到大排序(字典序)  
19             Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>()  
20             {  
21                 @Override  
22                 public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2)  
23                 {  
24                     return (o1.getKey()).toString().compareTo(o2.getKey());  
25                 }  
26             });  
27             // 構造URL 鍵值對的格式  
28             StringBuilder buf = new StringBuilder();  
29             for (Map.Entry<String, String> item : infoIds)  
30             {  
31                 if (StringUtils.isNotBlank(item.getKey()))  
32                 {  
33                     String key = item.getKey();  
34                     String val = item.getValue();  
35                     if (urlEncode)  
36                     {  
37                         val = URLEncoder.encode(val, "utf-8");  
38                     }  
39                     if (keyToLower)  
40                     {  
41                         buf.append(key.toLowerCase() + "=" + val);  
42                     } else  
43                     {  
44                         buf.append(key + "=" + val);  
45                     }  
46                     buf.append("&");  
47                 }  
48    
49             }  
50             buff = buf.toString();  
51             if (buff.isEmpty() == false)  
52             {  
53                 buff = buff.substring(0, buff.length() - 1);  
54             }  
55         } catch (Exception e)  
56         {  
57            return null;  
58         }  
59         return buff;  
60     }  

六、發送遠程請求 得到數據 代碼示例:

 1     
 2     /**
 3      * 方法名: getRemotePortData
 4      * 描述: 發送遠程請求 得到代碼示例
 5      * 參數:  @param urls 訪問路徑
 6      * 參數:  @param param 訪問參數-字符串拼接格式, 例:port_d=10002&port_g=10007&country_a=
 7      * 建立人: Xia ZhengWei
 8      * 建立時間: 2017年3月6日 下午3:20:32
 9      * 版本號: v1.0   
10      * 返回類型: String
11     */
12     private String getRemotePortData(String urls, String param){
13         logger.info("港距查詢抓取數據----開始抓取外網港距數據");
14         try {
15             URL url = new URL(urls);
16             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
17             // 設置鏈接超時時間
18             conn.setConnectTimeout(30000);
19             // 設置讀取超時時間
20             conn.setReadTimeout(30000);
21             conn.setRequestMethod("POST");
22             if(StringUtil.isNotBlank(param)) {
23                 conn.setRequestProperty("Origin", "https://sirius.searates.com");// 主要參數
24                 conn.setRequestProperty("Referer", "https://sirius.searates.com/cn/port?A=ChIJP1j2OhRahjURNsllbOuKc3Y&D=567&G=16959&shipment=1&container=20st&weight=1&product=0&request=&weightcargo=1&");
25                 conn.setRequestProperty("X-Requested-With", "XMLHttpRequest");// 主要參數
26             }
27             // 須要輸出
28             conn.setDoInput(true);
29             // 須要輸入
30             conn.setDoOutput(true);
31             // 設置是否使用緩存
32             conn.setUseCaches(false);
33             // 設置請求屬性
34             conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
35             conn.setRequestProperty("Connection", "Keep-Alive");// 維持長鏈接
36             conn.setRequestProperty("Charset", "UTF-8");
37             
38             if(StringUtil.isNotBlank(param)) {
39                 // 創建輸入流,向指向的URL傳入參數
40                 DataOutputStream dos=new DataOutputStream(conn.getOutputStream());
41                 dos.writeBytes(param);
42                 dos.flush();
43                 dos.close();
44             }
45             // 輸出返回結果
46             InputStream input = conn.getInputStream();
47             int resLen =0;
48             byte[] res = new byte[1024];
49             StringBuilder sb=new StringBuilder();
50             while((resLen=input.read(res))!=-1){
51                 sb.append(new String(res, 0, resLen));
52             }
53             return sb.toString();
54         } catch (MalformedURLException e) {
55             e.printStackTrace();
56             logger.info("港距查詢抓取數據----抓取外網港距數據發生異常:" + e.getMessage());
57         } catch (IOException e) {
58             e.printStackTrace();
59             logger.info("港距查詢抓取數據----抓取外網港距數據發生異常:" + e.getMessage());
60         }
61         logger.info("港距查詢抓取數據----抓取外網港距數據失敗, 返回空字符串");
62         return "";
63     }

七、XML 轉換成 map 對象 代碼示例:

 1     /**
 2      * 解析xml,返回第一級元素鍵值對。若是第一級元素有子節點,則此節點的值是子節點的xml數據。
 3      * @param strxml
 4      * @return
 5      * @throws JDOMException
 6      * @throws IOException
 7      */
 8     @SuppressWarnings("rawtypes")
 9     private Map<String,String> doXMLParse(String strxml) throws Exception {
10         if(null == strxml || "".equals(strxml)) {
11             return null;
12         }
13         
14         Map<String,String> m = new HashMap<String,String>();
15         InputStream in = String2Inputstream(strxml);
16         SAXBuilder builder = new SAXBuilder();
17         Document doc = builder.build(in);
18         Element root = doc.getRootElement();
19         List list = root.getChildren();
20         Iterator it = list.iterator();
21         while(it.hasNext()) {
22             Element e = (Element) it.next();
23             String k = e.getName();
24             String v = "";
25             List children = e.getChildren();
26             if(children.isEmpty()) {
27                 v = e.getTextNormalize();
28             } else {
29                 v = getChildrenText(children);
30             }
31             
32             m.put(k, v);
33         }
34         
35         //關閉流
36         in.close();
37         
38         return m;
39     }
40     
41     private  InputStream String2Inputstream(String str) {
42         return new ByteArrayInputStream(str.getBytes());
43     }
44     
45     /**
46      * 獲取子結點的xml
47      * @param children
48      * @return String
49      */
50     @SuppressWarnings("rawtypes")
51     private static String getChildrenText(List children) {
52         StringBuffer sb = new StringBuffer();
53         if(!children.isEmpty()) {
54             Iterator it = children.iterator();
55             while(it.hasNext()) {
56                 Element e = (Element) it.next();
57                 String name = e.getName();
58                 String value = e.getTextNormalize();
59                 List list = e.getChildren();
60                 sb.append("<" + name + ">");
61                 if(!list.isEmpty()) {
62                     sb.append(getChildrenText(list));
63                 }
64                 sb.append(value);
65                 sb.append("</" + name + ">");
66             }
67         }
68         
69         return sb.toString();
70     }

八、獲取本機IP

    /**
     * @Title: getIpAddress
     * @Description: 獲取客戶端真實IP地址
     * @author yihj
     * @param @param request
     * @param @param response
     * @param @return    參數
     * @return String    返回類型
     * @throws
     */
    public static String getIpAddress(HttpServletRequest request) {
        // 避免反向代理不能獲取真實地址, 取X-Forwarded-For中第一個非unknown的有效IP字符串
        String ip = request.getHeader("x-forwarded-for");
       if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
           ip = request.getHeader("Proxy-Client-IP");
       }
       if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
           ip = request.getHeader("WL-Proxy-Client-IP");
       }
       if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
           ip = request.getRemoteAddr();
       }
        return ip;
    }

九、通知地址 回調服務器 支付結果(這個回調 若是不返回給微信服務器 是否成功回調標示 則會一直回調8次 一直到返回成功標示位置) 代碼示例:

 1     @Override
 2     public void payCallback(HttpServletRequest request,HttpServletResponse response) {
 3         logger.info("微信回調接口方法 start");
 4         logger.info("微信回調接口 操做邏輯 start");
 5         String inputLine = "";
 6         String notityXml = "";
 7         try {
 8             while((inputLine = request.getReader().readLine()) != null){
 9                 notityXml += inputLine;
10             }
11             //關閉流
12             request.getReader().close();
13             logger.info("微信回調內容信息:"+notityXml);
14             //解析成Map
15             Map<String,String> map = doXMLParse(notityXml);
16             //判斷 支付是否成功
17             if("SUCCESS".equals(map.get("result_code"))){
18                 logger.info("微信回調返回是否支付成功:是");
19                 //得到 返回的商戶訂單號
20                 String outTradeNo = map.get("out_trade_no");
21                 logger.info("微信回調返回商戶訂單號:"+outTradeNo);
22                 //訪問DB
23                 WechatAppletGolfPayInfo payInfo = appletGolfPayInfoMapper.selectByPrimaryKey(outTradeNo);
24                 logger.info("微信回調 根據訂單號查詢訂單狀態:"+payInfo.getPayStatus());
25                 if("0".equals(payInfo.getPayStatus())){
26                     //修改支付狀態
27                     payInfo.setPayStatus("1");
28                     //更新Bean
29                     int sqlRow = appletGolfPayInfoMapper.updateByPrimaryKey(payInfo);
30                     //判斷 是否更新成功
31                     if(sqlRow == 1){
32                         logger.info("微信回調  訂單號:"+outTradeNo +",修改狀態成功");
33                         //封裝 返回值
34                         StringBuffer buffer = new StringBuffer();
35                         buffer.append("<xml>");
36                         buffer.append("<return_code>SUCCESS</return_code>");
37                         buffer.append("<return_msg>OK</return_msg>");
38                         buffer.append("</xml>");
39                         
40                         //給微信服務器返回 成功標示 不然會一直詢問 我們服務器 是否回調成功
41                         PrintWriter writer = response.getWriter();
42                         //返回
43                         writer.print(buffer.toString());
44                     }
45                 }
46             }
47         } catch (IOException e) {
48             e.printStackTrace();
49         } catch (Exception e) {
50             e.printStackTrace();
51         }
52     }    

十、MD5 算法:

    /**
     * @Title: encodeByMD5
     * @Description: 對字符串進行MD5編碼
     * @author yihj
     * @param @param originString
     * @param @return    參數
     * @return String    返回類型
     * @throws
     */
    public static String MD5(String originString){
        if (originString!=null) {
            try {
                //建立具備指定算法名稱的信息摘要
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                //使用指定的字節數組對摘要進行最後更新,而後完成摘要計算
                byte[] results = md5.digest(originString.getBytes());
                //將獲得的字節數組變成字符串返回
                String result = byteArrayToHexString(results);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

十一、注意事項:

  1)、全部的簽名和發送微信服務器的數據必須一致 包括Key的大小寫 不然簽名失敗

  2)、微信小程序 前端調用 接口的時候 文檔上並無寫appId參數 該參數必定要穿 而且是大寫

  3)、交易類型 爲 JSAPI 的時候 則必須傳入openid

  4)、body格式問題 寫的是UTF-8 實際要的格式則是ISO8859-1 並且單獨對body進行設置好像很差使 因此必須所有都改爲該格式

  5)、生成簽名 最後加上key的那塊 加的格式是 &key = KEY 這種 並且不是直接 + key 這個地方須要注意一下 我碰了個坑 文檔沒看仔細

  6)、數據包ID 格式 不是 value直接設置成 數據包ID就能夠 前面須要加 "prepay_id="

  7)、最後一點強調 生成簽名的數據和發送服務器的數據 必須保持一致 

  8)、appid 是公衆號的appid

  9)、mch_id 這是商戶平臺的id

  10)、key 這是設置的 商戶平臺支付密鑰

 

十一、歡迎你們 發表問題 一塊兒學習 嘿嘿 

相關文章
相關標籤/搜索