1. 程式人生 > >微信公眾號開發之微信支付開發

微信公眾號開發之微信支付開發

微信公眾號開發對接,開發文件也有蠻多坑,所以一路的血淚教訓,這次先針對微信支付整理一下支付的踩坑全過程,開發時間緊現在整理出來,既是對此段時間的學習總結,也希望對遇到同樣問題的童鞋可以有參考價值。

1. 微信掃碼支付

認證微信服務號,申請開通微信支付功能,獲取到微信支付商戶號,然後可以進行開發

模式一開發前,商戶必須在公眾平臺後臺設定支付回撥URL。URL實現的功能:接收使用者掃碼後微信支付系統回撥的productid和openid。先根據規則生成支付二維碼,使用者掃碼獲取openid呼叫微信支付的統一下單接口生成預支付id,使用者支付。

模式二流程相比模式一更為簡單,不依賴設定的回撥支付URL。商戶後臺系統先呼叫微信支付的統一下單介面,微信後臺系統返回連結引數code_url,

商戶後臺系統將code_url值生成二維碼圖片,使用者使用微信客戶端掃碼後發起支付。注意:code_url有效期為2小時,過期後掃碼不能再發起支付。

所以這次的掃碼支付採用了簡單點的模式二

先呼叫統一下單介面https://api.mch.weixin.qq.com/pay/unifiedorder

1) 引數

private String appid = "";//微信支付分配的公眾賬號ID(企業號corpid即為此appId)

    private String mch_id = "";//微信支付分配的商戶號(申請通過之後郵件裡收到的商戶號

    private String nonce_str = "";//隨機字串,不長於32 位

    private String sign = "";//根據API給的簽名規則進行簽名

    private String body = "";//要支付的商品的描述資訊

    private String attach = "";//支付訂單裡面可以填的附加資料

    private String out_trade_no = "";//商戶系統內部的訂單號

    private int total_fee = 0;//訂單總金額,單位為“分”,只能整數

    private String spbill_create_ip = "";//訂單生成的機器IP

    private String time_start = "";//訂單生成時間, 格式為yyyyMMddHHmmss

    private String goods_tag = "";//商品標記,微信平臺配置的商品標記,用於優惠券或者滿減使用

    private String trade_type = "NATIVE";//JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付,統一下單介面trade_type的傳參可參考這裡

    private String notify_url = “”;//回撥url 非同步接收微信支付結果通知的回撥地址,通知url必須為外網可訪問的url,不能攜帶引數

    private String detail = "name";

    private String openid = "";//JSAPI 一定要傳 (下面的微信公眾號支付一定要傳的

2) 簽名生成演算法

public static String getSign(Map<String,Object> map){
    ArrayList<String> list = new ArrayList<String>();
    for(Map.Entry<String,Object> entry:map.entrySet()){
        if(entry.getKey().equals("sign")) {
            continue;
        }
        if (entry.getValue() != "") {
            list.add(entry.getKey() + "=" + entry.getValue() + "&");
        }
    }
    int size = list.size();
    String [] arrayToSort = list.toArray(new String[size]);
    Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < size; i ++) {
        sb.append(arrayToSort[i]);
    }
    String result = sb.toString();
    result += "key=" + WxpayConfig.getKey();
    result = MD5.MD5Encode(result).toUpperCase();
    return result;
}

隨機字串生成

public static String getRandomStringByLength(int length) {// length<=32
    String base = "abcdefghijklmnopqrstuvwxyz0123456789";
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < length; i++) {
        int number = random.nextInt(base.length());
        sb.append(base.charAt(number));
    }
    return sb.toString();
}

3) 回撥處理

public String wxpaymentCallBack(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws Exception {
        String returnXML = "";
        try {
            //獲取HTTP請求的輸入流InputStream is = httpRequest.getInputStream();
            //HTTP請求輸入流建立一個BufferedReader物件BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            //讀取HTTP請求內容String buffer = null;
            StringBuffer sb = new StringBuffer();
            while ((buffer = br.readLine()) != null) {
                sb.append(buffer);
            }
            br.close();
            ScanPayResDTO scanPayResDto = (ScanPayResDTO) Util.getObjectFromXML(sb.toString(), ScanPayResDTO.class);
            System.out.println("微信回撥:"+scanPayResDto.getReturn_code()+",訂單號:"+scanPayResDto.getOut_trade_no());
            //商戶系統對於支付結果通知的內容一定要做簽名驗證,並校驗返回的訂單金額是否與商戶側的訂單金額一致,防止資料洩漏導致出現假通知,造成資金損失。if (scanPayResDto.getReturn_code().equals("SUCCESS")) {
                if (scanPayResDto.getSign() != null && scanPayResDto.getOut_trade_no() != null) {Map<String, Object> reqData= xmlToMap(sb.toString());
                    System.out.println("微信返回的簽名:"+scanPayResDto.getSign());
                    String sign = Signature.getSign(reqData);
                    System.out.println("系統生成的簽名:"+sign);
                    if (scanPayResDto.getSign().equals(sign)) {//簽名一樣處理訂單資訊logger.info("【支付成功】");                       if(memberService.existOrderSnInRedis(scanPayResDto.getOut_trade_no())){
                           return returnXML("SUCCESS");
                        }
                        Charge charge = new Charge();
                        charge.setOrderNo(scanPayResDto.getOut_trade_no());//訂單號charge.setTransactionNo(scanPayResDto.getTransaction_id());//交易號orderPaymentService.paymentCallBackAsyn(charge);returnXML = returnXML("SUCCESS");
                    } else {
                        logger.info("【簽名失敗】");
                        returnXML = returnXML("FAIL");
                    }
                }
            } else {
                returnXML = returnXML("FAIL");
                logger.info("【支付失敗】");
            }
        } catch (Exception e) {
            returnXML = returnXML("FAIL");
        }
        return returnXML;
    }

    private String returnXML(String return_code) {
        return "<xml><return_code><![CDATA["+ return_code
          + "]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    }

微信支付結果的通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒

注意:同樣的通知可能會多次傳送給商戶系統。商戶系統必須能夠正確處理重複的通知。

推薦的做法是,當收到通知進行處理時,首先檢查對應業務資料的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,如果處理過直接返回結果成功。在對業務資料進行狀態檢查和處理之前,要採用資料鎖進行併發控制,以避免函式重入造成的資料混亂。

特別提醒:商戶系統對於支付結果通知的內容一定要做簽名驗證,並校驗返回的訂單金額是否與商戶側的訂單金額一致,防止資料洩漏導致出現“假通知”,造成資金損失。

2. 微信公眾號支付

公眾號支付需要先在公眾號設定支付目錄(請確保實際支付時的請求目錄與後臺配置的目錄一致,否則將無法成功喚起微信支付)和授權域名(開發公眾號支付時,在統一下單介面中要求必傳使用者openid,而獲取openid則需要您在公眾平臺設定獲取openid的域名)。設定參考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3

伺服器端先呼叫統一下單介面,獲取到prepay_id,再根據簽名演算法(直接呼叫上方掃碼支付的簽名演算法)生成paySign(參與簽名的引數有appId, timeStamp, nonceStr, package, signType,注意 大小寫,時間戳要轉成秒

public Map<String, Object> createWxSDPaySign(String prepay_id) {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("appId", WxpayConfig.getAppid());
    map.put("timeStamp", System.currentTimeMillis()/1000);
    map.put("nonceStr", RandomStringGenerator.getRandomStringByLength(32));
    map.put("package", "prepay_id=" + prepay_id);
    map.put("signType", "MD5");
    String sign = Signature.getSign(map);
    map.put("paySign", sign);
    return map;
}

注意微信內建物件在其他瀏覽器中無效,即微信公眾號支付只能在微信內部開啟付款

列表中引數名區分大小,大小寫錯誤簽名驗證會失敗。其中:低版本的timestamp欄位名s小寫,新版的timeStamp欄位名S大寫

wx.chooseWXPay({
    timestamp: 0, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp欄位均為小寫。但最新版的支付後臺生成簽名使用的timeStamp欄位名需大寫其中的S字元    nonceStr: '', // 支付簽名隨機串,不長於 32     package: '', // 統一支付介面返回的prepay_id引數值,提交格式如:prepay_id=***    signType: '', // 簽名方式,預設為'SHA1',使用新版支付需傳入'MD5'    paySign: '', // 支付簽名    success: function (res) { // 支付成功後的回撥函式    }
    });

WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
           "appId":"wx2421b1c4370ec43b",     //公眾號名稱,由商戶傳入           "timeStamp":"1395712654",         //時間戳,自1970年以來的秒數           "nonceStr":"e61463f8efa94090b1f366cccfbbb444"//隨機串           "package":"prepay_id=u802345jgfjsdfgsdg888",     
           "signType":"MD5",         //微信簽名方式:           "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名       },
       function(res){     
           if(res.err_msg == "get_brand_wcpay_request:ok" ) {}            }
   ); 

3. 微信支付--優惠券 紅包支付--回撥簽名驗證問題

還要注意一個問題 支付回撥通知返回的資料最好用Map接收,再進行簽名校驗,因為如果有獎勵金或者優惠券等引數,可能接收的物件沒有寫全而導致驗籤失敗,踩坑教訓,所以後面簽名用Map了,微信官方jdk一開始也是物件,後面也改了,都是用的map接收,還有一個原因就是引數命名,如下圖的引數名是不確定幾個的,所以還是map最方便

 

相關推薦

[Python爬蟲] 十五:Selenium +phantomjs根據公眾抓取文章

頭部 drive lac 過程 標題 操作 函數 軟件測試 init   借助搜索微信搜索引擎進行抓取   抓取過程   1、首先在搜狗的微信搜索頁面測試一下,這樣能夠讓我們的思路更加清晰        在搜索引擎上使用微信公眾號英文名進行“搜公眾號&r

公眾接入排序問題小記

發  微信公眾號作為強大的自媒體工具,對接一下是很正常的了。不過這不是本文的方向,本文的方向公眾號接入的排序問題。   最近接了一個重構的小專案,需要將原有的php的公眾號後臺系統,轉換為java系統。當然,也很簡單的了。      不過,在接入的時候,遇到有一個有趣的問題,可以分享下。   大家知道

公眾 基於PHP 拼團活動開發一 模板搭建

已測試號為例;使用者發起拼團活動(為團長),回覆給他帶有活動id與其openid的二維碼圖片,轉發給他人,已關注的掃碼之後儲存其openid,未關注的在關注之後儲存openid(防止重複參與)(團員),然後自動回覆團員自己活動資訊的二維碼。 1.微信公眾號後臺配置好 伺服器

【 專欄 】- 基於公眾的公益眾籌專案開發

基於微信公眾號的公益眾籌專案開發 筆者結合專案逐步講解微信公眾號開發,微信Api和JSSDK使用,多公眾號支援、微信支付、發紅包。涉及SpringMVC、MyBatise、AJAX跨域,Redis、MySql、Angalarjs+

JeeSite 4.0 公眾牛牛房卡網站開發環境部署執行除錯

環境要求1、微信公眾號牛牛房卡網站開發(Q1687054422) 下載2、Eclipse IDE for Java EE Mars 2 (4.5.2) 下載3、Apache Maven 3.3+ 下載4、MySql 5.7+ 下載匯入到Eclipse1、檢出JeeSite4原

公眾介面介面資訊配置(一)

微信公眾號地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index配置url和token<?php/**  * wechat php test  *

公眾與APP第三方登錄賬號打通

class 微信服務號 成功 信用 lock 通用 管理中心 post 公眾 一個項目同時開發了APP和微信服務號,需要做到APP和微信服務號的賬號互通同步,也就是說一個賬號在2個地方都可以用,當然這個前提是保證你公司自己的服務器的數據庫用的是同一套。 為保證用戶數據的唯

開發微公眾小技巧(授權跳轉)

出發微信公眾號 先pick一個小技巧 開發過公眾號的朋友們知道流程,在使用者點選登入後,會在url上返回code...等值,這時候要取code值傳給後端同學,然後跳轉到我們的主頁面,大多數的朋友都是這種流程 window.location.href = 'url' // 但是呢,這樣會有

普通js使用ajax,公眾授權(網頁授權)

微信授權的整個流程: 引導使用者進入授權頁面同意授權,獲取code 通過code換取網頁授權access_token(與基礎支援中的access_token不同) 如果需要,開發者可以重新整理網頁授權access_token,避免過期 通過網頁授權access_tok

vue腳手架,公眾授權(網頁授權)

如果使用者在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取使用者基本資訊,進而實現業務邏輯。 首先我做了一個H5小專案,然後申請公眾號,然後在【自定義選單】中輸入想填寫的,公眾號選單名稱,以及頁面地址: 然後,我們在我們的前端頁面寫呼叫伺服器介面,得到授權。當然

公眾使用:公眾平臺企業一次釋出多條圖文訊息的方法

       作為微信公眾號的維護人員來說,不僅要知道微信公眾號的基本功能,還要知道微信公平臺的法律法規,釋出文章的規則等常識。今天就來說說微信公眾號怎麼一次同時釋出多條圖文文章訊息。       話又說回來了,微信公眾平臺在不斷的改版中前進,我們公司的微信公眾號是企業號,一

個人公眾功能猜想:便捷:實現(一)

想了幾天也搞了幾天,其實就是面試耽誤了時間人又突然不想做,就幾天沒寫後續的部落格,(詳情請參考上一篇部落格),今天這個部落格就是對上一篇部落格的後續說明還有之後的話具體每一步實現都會寫部落格記錄一下.現在的話就是給自己猜想這個微信公眾號起了一個名字嘛,就叫微便捷,畢竟是自己的

用python wxpy管理公眾,並利用獲取自己的開源資料。

之前瞭解到itchat 乃至於 wxpy時 是利用tuling聊天機器人的介面。呼叫介面並儲存雙方的問答結果可以作為自己的問答詞庫的一個數據庫累計。這些資料可以用於自己訓練。 而最近希望獲取一些語音資源,用於卷積神經網路的訓練。。     首先wxpy是itchat的升級版,通

公眾開發網頁授權(獲取用戶息)

還需要 開發文檔 app err 通過 casb ddt 省份 sse   這次暑假留在學校參與工作室的項目,對微信公眾號比較感興趣,所以參與這方面的學習研究。 昨天完成了關於網頁授權,獲取用戶信息方面的功能,所以乘熱打鐵,寫上一篇。實現本篇涉及的 功能,還需要完成一些基礎

C#公眾開發接收事件推送與消息排重的方法

data push con 這樣的 etime ali 推薦 系列 是否 本文實例講述了C#微信公眾號開發之接收事件推送與消息排重的方法。分享給大家供大家參考。具體分析如下: 微信服務器在5秒內收不到響應會斷掉連接,並且重新發起請求,總共重試三次。這樣的話,問題就來了。有

公眾開發-回調的所有類型

mage 下回 nco ble sgi msg www 系統拍照 sel 眾所周知,微信公眾號配置後臺開發時,微信會在一些情況下回調我們配置的服務器地址,比如www.***.com/wechat_callback 盡管調用情況不同,調用的都是這一個接口,只是攜帶的參數不同,

php公眾開發三公牛牛房卡平臺搭建使用php7要註意的地方

mar shadow 公眾號開發 jpg oss 文檔 微信公眾號開發 dem proc 開啟微信公眾號開發三公牛牛房卡平臺搭建網站(h5.fanshubbs.com聯系Q1687054422),從微信開發文檔中下載demo 如下載php示例代碼 示例代碼中是使用“$GL

php篇二 公眾開發

mps timestamp brush ack article time curl lB -m 博主提示玩微信公眾號必須要有自己的服務器,其次有自己的微信公眾平臺,將自己的token保存在開發者模式中,將代碼上傳到服務器中,並且保存在開發者模式中。代碼類似如下 <?

利用NATAPP隧道解決公眾開發本地調試難題

需要 alt clas 公眾號開發 help 服務器 -a amd64 驗證 一、問題 眾所周知,微信公眾號開發需要公網的有效域名和80端口,本機當然互聯網是訪問不了的。那麽我們難道去一個公網的服務器去開發嗎?那樣是不是太土了。 答案當然是,NO 當然我們在做微信支付

公眾開發傳送模板訊息

在我們做微信公眾號開發時,傳送模板訊息往往是必不可少的功能。今天我們就來說說吧! 1、申請模板訊息 首先我們應該知道,模板訊息是需要申請的。這個申請就其本身來說是很easy的(我前一天晚上申請的,顯示需要2--3個工作日,結果第二天早上就發現已經開通了,所以說騰訊官方還是比較給力的哈)。