微信公衆號支付開發,但願能幫到你們

文檔真的很重要,不論是寫仍是看的人都應該認真點php

本文主要寫給公衆平臺h5支付開發者html

真的,區分大小寫,注意前面的參數就不多會出現問題了。前端

除了博客園,這篇文章的內容也放在這裏本身的blog 【http://mimeay.cc/】web

1、技術棧

  • 語言:Node
  • web框架 Express
  • 開發過程當中依賴的模塊
    1. express-xml-bodyparser 用於解析客戶端post過來的xml格式的數據
    2. jstoxml 用於將js對象轉換成xml
    3. xml2js 用戶將xml轉換js對象

 

2、微信開發之旅

 

  1. 註冊商戶平臺

     這一步不設計開發。。。不詳說。ajax

  2. 支付目錄設置

     微信公衆平臺-> 微信支付-> 開發配置,見微信官方圖,具體細節見圖片數據庫

alt

  3. 統一下單

    接口地址 :https://api.mch.weixin.qq.com/pay/unifiedorderexpress

必須提交的參數json

appid 公衆平臺的appid
 attach 自定義消息
 body 商品類別【商品信息均可以】
 mch_id 商戶平臺的帳號
 nonce_str 隨機字符串,不超過32位
 notify_url 微信生成prepay_id後,會發送請求到所設置的回調地址
 out_trade_no 商戶自定義生成的訂單號,要保證不能重複
 spbill_create_ip 客戶端的ip地址
 total_fee 支付的金額,以分爲單位
 trade_type 交易類型 取值有JSAPI,NATIVE,APP ,由於是在h5頁面觸發支付,我選擇了 JSAPI,要根據實際需求選擇

根據項目,須要提交的參數後端

openid 標示用戶的id 【下面會貼相關連接】,若是是h5支付開發就必定要傳

    以上提交參數要注意區分大小寫【若是有大寫的話】,針對幾個參數說明一下 openid :用戶受權後,微信會在你設置的受權回調域名後拼接code參數,經過這個code的值,而後經過code換取網頁受權accesstoken。    api

    openid。請注意,這裏須要經過網頁受權獲取
    mch_id :註冊商戶平臺後,微信會把商戶號和密碼發到指定的郵箱,這裏用到商戶帳號而已

  4.代碼

看代碼啦

    後端代碼

    爲了展現,我把內容整合成在一塊兒,實際開發並無寫在一塊兒

  let config = {
    appid : '這裏是appid',
    mch_id : '商戶平臺帳號'
    notify_url : 'http://mimeay.cc/pay/receive',
    key : '在商戶平臺設置的'
 }

 let util = {
  createNonceStr () {
    return Math.random().toString(36).substr(2, 15);
  },
  createTimestamp  () {
    return parseInt(new Date().getTime() / 1000) + '';
  },
  raw (args) {
    let keys = Object.keys(args);
    keys = keys.sort()
    let newArgs = {};
    keys.forEach(function (key) {
      newArgs[key] = args[key];
    });
    let string = '';
    for (let k in newArgs) {
      string += '&' + k + '=' + newArgs[k];
    }
    string = string.substr(1);
    return string;
  },
  paySign (data,key) {
    let stringA,stringSignTemp,sign;
    stringA = module.exports.raw(data);
    stringSignTemp = stringA +'&key=' + key;
    sign = md5(stringSignTemp).toUpperCase();
    return sign;
  },
  post_request_xml(url,data){
    // 這裏返回響應的內容
  }
 }

    生成 prepay_id

unified_order ({openid,ip,out_trade_no,total_fee,category = '記念品',trade_type = 'JSAPI',device_info = 'WEB',attach = '網上商城'}){  
    let baseUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    let nonce_str = util.createNonceStr();
    // ip 能夠從請求對象取
    // openid 經過客戶端傳遞
    // out_trade_no 請求統一下單前先生成【無論用戶最終是否完成支付】
    // total_fee 支付金額,單位爲分,經過商品的id從數據庫獲取價格並轉化成分【前端傳遞金額不可靠】
    // 其餘參數不傳則默認
    let data = {
      appid : config.appid,
      attach : attach,
      body : '公司名-' + category,
      mch_id : config.mch_id,
      nonce_str: nonce_str,
      notify_url : config.notify_url,
      openid : openid,
      out_trade_no : out_trade_no,
      spbill_create_ip : ip,
      total_fee:total_fee,
      trade_type : trade_type,
      device_info : device_info
    };
    let sign  = util.paySign(data,config.key);
    data['sign'] = sign;
    let xmlData = {
      xml : data
    }
    //jstoxml.toXML 是把js轉換成xml的一個方法來的
    let xml = jstoxml.toXML(xmlData);
    // post_request_xml 
    return util.post_request_xml(baseUrl,xml).then((result)=>{
      const {sign,prepay_id,return_code,return_msg} = result;
      if(return_code == 'FAIL'){
        return {
          return_code,
          return_msg
        }
      }else{
        return {
          return_code,
          return_msg,
          prepay_id : prepay_id
        }
      }
    })
  }

    結合prepay_id生成客戶端支付請求的參數,這裏的 appId, timeStamp, nonceStr, package, signType嚴格區分大小寫,我一開始沒注意,把參數都小寫了,結果致使客戶端簽名失敗

wx_pay_sign (prepay_id){
    let baseUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    let nonce_str,data,sign,timestamp,xmlData,xml,_package;
    nonce_str = util.createNonceStr();
    timestamp = util.createTimestamp();
    _package = 'prepay_id=' + prepay_id;
    //這裏的參數要區分大小寫
    data  = {
      appId : config.appId,
      timeStamp : timestamp,
      nonceStr : nonce_str,
      package : _package,
      signType : 'MD5'
    }
    // appId, timeStamp, nonceStr, package, signType
    sign  = util.paySign(data,config.key);
    data['paySign'] = sign;
    return data;
  }

 

    到此,後端統一下單作的事情告一段落


    前端代碼

    還記得wx_pay_sign函數作的事情嗎,假設咱們經過接口請求,拿到了wx_pay_sign返回的值

$.ajax({
  url : 'xxxxxxx',
  type : 'post',
  data : {
    openid : '經過受權拿到的openid'
  },
  success (json){
   const {code,data,msg} = json;
   if(code == 0){
     wx.chooseWXPay({
       timestamp: data.timeStamp, // 支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符
       nonceStr: data.nonceStr, // 支付簽名隨機串,不長於 32 位
       package: data.package, // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)
       signType: data.signType, // 簽名方式,默認爲'SHA1',使用新版支付需傳入'MD5'
       paySign: data.paySign, // 支付簽名
       success: function (res) {
         // 支付成功後的回調函數
       }
    });
   }
  }
})

 

  5. 服務端可能出現的問題
  • XML格式錯誤 :若是出現錯誤,能夠在發送請求前打印在本地看下 ,格式通常以下(只展現格式,不表明這就是請求發送的參數):
  <xml>
     <appid>xxxxx</appid> 
  </xml>

 

  • 簽名錯誤: 通常會出現這個問題,多是參數值爲空,以下狀況【appid爲空】就會致使簽名失敗(只展現格式,不表明這就是請求發送的參數)
 <xml>
     <appid></appid>
     <mch_id>23123123</mch_id> 
 </xml>

 

  6. 客戶端調試可能出現的問題
  • 支付簽名失敗 :正常來講是 appId, timeStamp, nonceStr, package, signType 簽名的時候出現問題,一有多是沒有區分大小寫,要麼就是參數的值設置錯誤,參與簽名的時候key必定要正確,若是沒有的話,能夠在商戶平臺設置
  7. 部分參考地址

三  聯繫我

   由於是爲了展現給你們看,因此對代碼有所修改,可能會出現錯誤,請你們理解。你們若是在作微信h5支付開發過程當中有遇到問題,可加我qq【200909050】,我盡本身能力幫忙。

相關文章
相關標籤/搜索