微信公眾號支付分為三類
以下主要介紹公眾號H5授權支付
首先看一下微信支付的業務邏輯
大部分微信支付邏輯在于服務器和微信服務器之間的信息驗證,對于SPringMVC框架開發,可以使用ajax來進行業務處理,H5頁面相應立刻購買按鈕事件,傳遞下單信息,服務器收到信息后整合統一下單信息,發往微信服務器獲取預支付碼,返回H5頁面調起支付驗證,通過H5微信支付框架JSAPI異步獲取支付結果
邏輯開發前階段:設計統一下單實體類,設計隨機數算法、簽名算法、實體類XML格式轉換算法等工具類(建議用微信SDK下的WXPayUtil),HTTP請求實現類
第一步:獲取訂單信息,轉換微信統一訂單
微信統一訂單
接口鏈接
URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder
請求參數
appid? 微信支付分配的公眾賬號ID(企業號corpid即為此appId) 例:wxd678efh567hg6787
mch_id? 微信支付分配的商戶號? 例:1230000109
device_info? 自定義參數,可以為終端設備號(門店號或收銀設備ID),PC網頁或公眾號內支付可以傳"WEB"? 例:WEB 或 013467007045764
nonce_str? 隨機字符串,長度要求在32位以內。推薦隨機數生成算法? 例:5K8264ILTKCH16CQ2502SI8ZNMTM67VS
body? 商品簡單描述,該字段請按照規范傳遞? 例:騰訊充值中心-QQ會員充值
sign? 通過簽名算法計算得出的簽名值,詳見下面簽名生成算法? 例:C380BEC2BFD727A4B6845133519F3AD6
sign_type? 簽名類型,默認為MD5,支持HMAC-SHA256和MD5? 例:MD5
out_trade_no? 商戶系統內部訂單號,要求32個字符內,只能是數字、大小寫字母_-|*@ ,且在同一個商戶號下唯一? 例:20150806125346
fee_type? 符合ISO 4217標準的三位字母代碼,默認人民幣:CNY? 例:CNY
total_fee? 訂單總金額,單位為分? 例:88
time_start? 訂單生成時間,格式為yyyyMMddHHmmss,如2009年12月25日9點10分10秒表示為20091225091010? 例:20091225091010
notify_url? 異步接收微信支付結果通知的回調地址,通知url必須為外網可訪問的url,不能攜帶參數? 例:http://www.weixin.qq.com/wxpay/pay.php
trade_type? 取值如下:JSAPI,NATIVE,APP等? 例:JSAPI
openid? 用戶標識,trade_type=JSAPI時(即公眾號支付),此參數必傳,此參數為微信用戶在商戶對應appid下的唯一標識。openid如何獲取請參考獲取微信openId? 例:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
微信支付參數眾多,在此不統一舉例,詳情參考微信官方文檔
appid為申請微信公眾號時獲取到的公眾號id,mch_id為申請微信支付時獲取的商戶號id,device_info由于我們主要開發公眾號支付此值為WEB,sign_type為簽名類型本文主要使用MD5,trade_type為交易類型公眾號指定為JSAPI,fee_type 人民幣默認CNY。
body 需要根據實際業務訂單信息來拼接,用于微信支付時顯示支付商品內容
nonce_str 為隨機字符串用于刷新sign簽名,保證每次簽名都是異于其他簽名,隨機字符串算法推薦使用微信工具包中的工具類WXPayUtil.generateNonceStr()獲取,也可使用java隨機生成UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
out_trade_no 商戶訂單號用于識別支付訂單,唯一,避免商品重疊導致支付失敗
total_fee? 訂單總金額,單位為分,88為0.88元,建議使用int類型
time_start? 訂單時間,建議使用H5調起支付時的系統時間System.currentTimeMillis()/1000;,時間單位:秒
notify_url? 為支付成功后回調路徑,也可以再H5頁面中后續控制
了解完參數情況,根據業務需要創建統一訂單的實體類,方便后續調用
當用戶點擊立即購買的按鈕時,我們將業務邏輯中的訂單信息轉換成微信統一訂單,在服務器端獲取統一訂單信息
第二步:驗證訂單信息獲取預支付id(prepay_id)
獲取預支付id需要將統一訂單信息打包發給微信服務器驗證,驗證通過后會返回相關數據包
URL地址? https://api.mch.weixin.qq.com/pay/unifiedorder
將統一下單信息轉成XML格式,推薦使用WXPayUtil.generateSignedXml(map, payKey)已經封裝簽名算法
String xml = WXPayUtil.generateSignedXml(map, payKey);? ? ? ?
String response = new HttpConnection().post(unifiedOrderUrl, xml);
MapresponseMap = WXPayUtil.xmlToMap(response);
String prepay_id = responseMap.get("prepay_id");
簽名算法
第一步,設所有發送或者接收到的數據為集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特別注意以下重要規則:
◆ 參數名ASCII碼從小到大排序(字典序);
◆ 如果參數的值為空不參與簽名;
◆ 參數名區分大小寫;
◆ 驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值作校驗。
◆ 微信接口可能增加字段,驗證簽名時必須支持增加的擴展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并對stringSignTemp進行MD5運算,再將得到的字符串所有字符轉換為大寫,得到sign值signValue。
◆ key設置路徑:微信商戶平臺(pay.weixin.qq.com)-->賬戶設置-->API安全-->密鑰設置
舉例:
第一步:對參數按照key=value的格式,并按照參數名ASCII字典序排序如下:
第二步:拼接API密鑰:
最終得到最終發送的數據:
發送XML數據包時,注意參數除必填項以外,可不封裝不必需參數,請勿參數傳空值,會報參數值錯誤
XML數據包需包含用戶openId及API秘鑰(申請認證微信支付時設置的API密碼)
成功獲取到prepay_id后進行微信支付H5調起支付驗證
第三步:H5網頁調起支付API
服務器后臺封裝微信支付信息數據,ajax返回數據,H5起調微信支付JSAPI,使用WeixinJSBridge.invoke發起支付驗證
參數
appId? 公眾號id
timeStamp? 時間戳
nonceStr? 隨機字符串
package? 預支付碼,格式:prepay_id=Re6s********89HS
signType? 微信簽名類型,MD5
paySign? 微信簽名,詳情參照簽名算法
返回結果
根據不同返回值處理不同的邏輯
最后貼一張官方文檔的說明圖,解釋下appid,mch_id,API密鑰,Appsecret區別