C#開發微信門戶及應用(32)--微信支付接入和API封裝使用

在微信的應用上,微信支付是一個比較有用的部分,但也是比較複雜的技術要點,在微商大行其道的年代,本身的商店沒有增長微信支付好像也說不過去,微信支付旨在爲廣大微信用戶及商戶提供更優質的支付服務,微信的支付和安全系統由騰訊財付通提供支持。本文主要介紹如何在微信公衆號上實現微信支付的接入、微信支付API的封裝,以及API的調用,實現咱們一些常見的業務調用。html

一、開通微信支付並配置

微信支付是須要微信公衆號的認證基礎,也就是隻對認證的公衆號開放,微信認證須要簽署相關的資料,而且進行對帳認證,通常會有電話聯繫確認相關的信息的。前端

在微信支付API開始使用前,咱們通常須要在後臺進行必定的配置,如咱們須要配置公衆號支付的受權目錄,測試白名單等信息,以及掃碼支持的回調處理地址(這個實如今後面再講),以下所示。api

在使用API以前,咱們要知道微信一些關鍵的操做,如退款、撤銷訂單等操做是須要證書的,並且常規的支付操做,咱們也須要商戶號、商戶支付祕鑰等信息,這些證書和祕鑰信息,是咱們從微信支付的商戶平臺上獲取的,咱們微信支付開通並審覈經過後,咱們就能夠登陸商戶平臺進行相關的操做了。安全

首先咱們須要在開發的電腦上安裝證書。服務器

而後須要設置API的祕鑰微信

最後在【API安全】項目上下載證書供咱們開發環境使用。app

 

二、微信支付API的介紹

微信支付配置相關的參數,並得到證書、API祕鑰、商戶號等信息後,咱們能夠開始瞭解微信支付的API的具體使用了,咱們須要先把API封裝爲C#的類庫進行使用,這樣才能在各類應用裏面方便調用。函數

微信支付分爲有多種方式,如掃碼支付、公衆號支付、JSAPI支付、APP支付等方面,不過核心的API都差很少,基本上都覆蓋了下面截圖的幾個API,只是有部分的接口差別。post

咱們能夠從其中掃碼支付開始瞭解,這個是對二維碼進行掃碼支付的場景,分爲了模式一和模式二兩種方式。測試

掃碼支付可分爲兩種模式,商戶根據支付場景選擇相應模式。

【模式一】:商戶後臺系統根據微信支付規則連接生成二維碼,連接中帶固定參數productid(可定義爲產品標識或訂單號)。用戶掃碼後,微信支付系統將productid和用戶惟一標識(openid)回調商戶後臺系統(須要設置支付回調URL),商戶後臺系統根據productid生成支付交易,最後微信支付系統發起用戶支付流程。

【模式二】:商戶後臺系統調用微信支付【統一下單API】生成預付交易,將接口返回的連接生成二維碼,用戶掃碼後輸入密碼完成支付交易。注意:該模式的預付單有效期爲2小時,過時後沒法支付。

根據掃碼支付的API說明,咱們能夠分別對這些接口(如統一下單、查詢訂單、關閉訂單、申請退款、查詢退款、下載對帳單等接口進行逐一封裝,以方便咱們的開發使用。

模式一和模式二,都須要使用到了統一下單的接口,而後生成相應的二維碼給客戶掃碼支付使用。

那麼咱們先來看看統一下單的接口說明,以瞭解它的具體使用。

1)應用場景

除被掃支付場景之外,商戶系統先調用該接口在微信支付服務後臺生成預支付交易單,返回正確的預支付交易回話標識後再按掃碼、JSAPI、APP等不一樣場景生成交易串調起支付。

2)接口連接

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

3)是否須要證書

不須要

4)請求參數

請求參數看似不少,大概分爲兩部分,一部分是系統必須的固定參數,一部分是業務所需的參數。

系統必須的固定參數以下所示。

一部分是業務參數,業務參數以下所示,主要是記錄訂單的相關產品ID、說明、費用等等

微信支付接口的調用和公衆號其餘接口調用不太同樣,這裏所有是採用XML進行交換的,感受沒有JSON那麼方便靈活,以下所示是統一下單的接口提交數據。

 

而後返回的數據也是XML的,以下面例子代碼所示,並且其中的字段內容還不太肯定,所以按官網的建議,使用字典集合來存儲返回的數據對象。

 

三、微信支付APIC#封裝和調用

根據上面的描述,咱們大概瞭解了微信支付API 的大概說明,根據這些信息,咱們能夠對它進行C#代碼的封裝了,對於代碼的封裝,咱們關鍵點在其中第一個,若是順利封裝好第一個接口,那麼後面的根據通用的方式,就很容易繼續處理這些接口了。

例如,咱們能夠定義好微信支付的API接口定義,以下所示。

    /// <summary>
    /// 微信支付接口
    /// </summary>
    public interface ITenPayApi
    {      
        /// <summary>
        /// 生成掃描支付模式一URL
        /// </summary>
        /// <param name="productId">商品ID</param>
        /// <returns></returns>
        string GetPrePayUrl(string productId);

        /// <summary>
        /// 生成直接支付url,支付url有效期爲2小時,模式二
        /// </summary>
        /// <param name="info">商品訂單數據</param>
        /// <returns></returns>
        string GetPayUrl(WxPayOrderData info);

        /// <summary>
        /// 統一下單。(不須要證書,默認不須要)
        /// 除被掃支付場景之外,商戶系統先調用該接口在微信支付服務後臺生成預支付交易單,
        /// 返回正確的預支付交易回話標識後再按掃碼、JSAPI、APP等不一樣場景生成交易串調起支付。
        /// </summary>
        /// <param name="info">商品訂單數據</param>
        WxPayData UnifiedOrder(WxPayOrderData info);

        .............

其中的接口方法的輸入參數咱們定義一個實體類 WxPayOrderData 來存儲一些業務參數,這些參數根據第二點的接口說明進行定義,代碼以下所示

    /// <summary>
    /// 統一下單的商品訂單信息
    /// </summary>
    public class WxPayOrderData
    {
        /// <summary>
        /// 商品ID, trade_type=NATIVE,此參數必傳
        /// </summary>
        public string product_id { get; set; }
        /// <summary>
        /// 商品或支付單簡要描述
        /// </summary>
        public string body { get; set; }
        /// <summary>
        /// 訂單總金額,單位爲分
        /// </summary>
        public int total_fee { get; set; }
        /// <summary>
        /// 商品標記,代金券或立減優惠功能的參數,說明詳見代金券或立減優惠
        /// </summary>
        public string goods_tag { get; set; }

        /// <summary>
        /// 交易類型,默認爲:NATIVE。
        /// JSAPI--公衆號支付、NATIVE--原生掃碼支付、APP--app支付
        /// </summary>
        public string trade_type { get; set; }

        /// <summary>
        /// 商品名稱明細列表
        /// </summary>
        public string detail { get; set; }
        /// <summary>
        /// 附加數據
        /// 在查詢API和支付通知中原樣返回,該字段主要用於商戶攜帶訂單的自定義數據
        /// </summary>
        public string attach { get; set; }
        /// <summary>
        /// 用戶標識
        /// trade_type=JSAPI,此參數必傳,用戶在商戶appid下的惟一標識。
        /// </summary>
        public string openid { get; set; }

        public WxPayOrderData()
        {
            this.trade_type = "NATIVE";
        }
    }

而後咱們定義一個接口返回的類WxPayData,它用來存儲返回的對象信息的,這個類在官網例子裏面有說明,其裏面內置一個排序過的字典對象進行存儲數據,部分代碼以下所示,我對它進行了相關的修改,以方便在構造函數裏面初始化一些必備的參數(固定參數)。

    public class WxPayData
    {
        //採用排序的Dictionary的好處是方便對數據包進行簽名,不用再簽名以前再作一次排序
        private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();
        
        /// <summary>
        /// 默認構造函數
        /// 若是initDefault爲true,則自動填入字段(appid,mch_id,time_stamp,nonce_str,out_trade_no,)
        /// </summary>
        public WxPayData(bool initDefault = false)
        {
            if(initDefault)
            {
                Init();
            }
        }

        /// <summary>
        /// 對象初始化後,自動填入字段(appid,mch_id,time_stamp,nonce_str,out_trade_no,)
        /// </summary>
        public void Init()
        {
            //初始化幾個參數
            this.SetValue("appid", WxPayConfig.APPID);//公衆賬號id
            this.SetValue("mch_id", WxPayConfig.MCHID);//商戶號
            this.SetValue("nonce_str", GenerateNonceStr());//隨機字符串
            this.SetValue("out_trade_no", GenerateOutTradeNo(WxPayConfig.MCHID));//隨機字符串

        }

而後咱們根據上面的數據定義,能夠實現統一下單的函數內容,主要是把輸入參數轉換爲咱們須要的字典參數集合,以下代碼所示。

        /// <summary>
        /// 統一下單。(不須要證書,默認不須要)
        /// 除被掃支付場景之外,商戶系統先調用該接口在微信支付服務後臺生成預支付交易單,
        /// 返回正確的預支付交易回話標識後再按掃碼、JSAPI、APP等不一樣場景生成交易串調起支付。
        /// </summary>
        /// <param name="info">商品訂單數據</param>
        public WxPayData UnifiedOrder(WxPayOrderData info)
        {
            WxPayData data = new WxPayData(true);
            data.SetValue("product_id", info.product_id);//商品ID
            data.SetValue("openid", info.openid);//商品ID

            //其餘信息
            data.SetValue("body", info.body);//商品描述
            data.SetValue("attach", info.attach);//附加數據
            data.SetValue("total_fee", info.total_fee);//總金額
            data.SetValue("goods_tag", info.goods_tag);//商品標記
            data.SetValue("trade_type", info.trade_type);//交易類型

            //默認構建
            data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始時間
            data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易結束時間

          ..............

最後的數據交換邏輯,咱們經過對URL進行POST提交XML數據給它獲取返回結果就能夠了,以下所示。

            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            return GetPostResult(data, url);

其中上面的函數的代碼邏輯以下所示,主要是把返回的結果再還原爲XML對象類WxPayData。

        /// <summary>
        /// 通用的獲取結果函數
        /// </summary>
        private WxPayData GetPostResult(WxPayData data, string url)
        {
            string xml = data.ToXml();
            string response = helper.GetHtml(url, xml, true);

            WxPayData result = new WxPayData();
            result.FromXml(response);
            return result;
        }   

對於掃碼操做的模式二,直接生成一種二維碼,不須要後臺進行回調的,那麼它的實現邏輯只須要對上面代碼進行封裝就能夠了,如先構建二維碼的函數代碼以下所示。

        /// <summary>
        /// 生成直接支付url,支付url有效期爲2小時,模式二
        /// </summary>
        /// <param name="info">商品訂單數據</param>
        /// <returns></returns>
        public string GetPayUrl(WxPayOrderData info)
        {
            WxPayData result = UnifiedOrder(info);//調用統一下單接口
            return result.GetString("code_url");//得到統一下單接口返回的二維碼連接
        }

如在Winform界面裏面,調用生成二維碼的代碼以下所示,主要邏輯就是構建好二維碼,而後顯示在界面上。

        private void btnGetPayUrl_Click(object sender, EventArgs e)
        {
            //測試掃碼模式二的生成二維碼方式
            WxPayOrderData data = new WxPayOrderData()
            {
                product_id = "123456789",
                body = "測試支付-模式二",
                attach = "愛奇迪技術支持",
                detail = "測試掃碼支付-模式二",
                total_fee = 1,
                goods_tag = "test1"
            };

            var url = api.GetPayUrl(data);
            var image = api.GenerateQRImage(url);

            this.imgGetPayUrl.Image = image;
            this.imgGetPayUrl.SizeMode = PictureBoxSizeMode.StretchImage;
        }

另外對於模式一,它在前端傳入一個簡單的產品ID,生成二維碼,當用戶掃碼的時候,微信後臺會調用商戶平臺(咱們服務器)的回調處理方法,這個回調方法會調用統一下單的API進行生成支付交易,過程有點複雜,咱們來看看,咱們的實現代碼以下所示。

        /// <summary>
        /// 生成掃描支付模式一URL
        /// </summary>
        /// <param name="productId">商品ID</param>
        /// <returns></returns>
        public string GetPrePayUrl(string productId)
        {
            WxPayData data = new WxPayData(true);
            data.SetValue("product_id", productId);//商品ID     
            data.SetValue("time_stamp", data.GenerateTimeStamp());//隨機字符串         
            data.SetValue("sign", data.MakeSign());//簽名

            string str = data.ToUrlParams();//轉換爲URL串
            string url = "weixin://wxpay/bizpayurl?" + str;

            return url;
        }

它的調用代碼生成二維碼操做以下所示。

        private void btnGetPrePayUrl_Click(object sender, EventArgs e)
        {
            var productId = "12345678";
            var url = api.GetPrePayUrl(productId);
            var image = api.GenerateQRImage(url);

            this.imgGetPrePayUrl.Image = image;
            this.imgGetPayUrl.SizeMode = PictureBoxSizeMode.StretchImage;
        }

咱們在第一小節裏面介紹了,須要在微信後臺配置掃碼的回調函數,以下所示。

這樣咱們還須要添加一個頁面aspx、或者通常處理程序ashx的方式來實現掃碼的回調過程。具體的邏輯也就是在這個頁面裏面獲取到提交過來的參數,而後調用統一下單處理後,進行數據返回便可,代碼邏輯以下所示。

 

四、在頁面上進行掃碼處理

前面的例子,我介紹了Winfrom的掃碼例子,不少時候,咱們的應用多是基於Web的,那麼它的實現是如何的呢,下面我繼續介紹一下。

首先咱們在本身的業務Web後臺系統裏面,添加兩個頁面,主要是用來生成二維碼在頁面上進行展現的,以下所示。

最終咱們在NativePayPage.aspx頁面上展現咱們的二維碼,方便用戶進行掃碼支付處理,頁面的代碼很簡單,咱們只須要在前端頁面放置兩個圖片控件,圖片內容經過MakeQRCode.aspx頁面進行生成就能夠了。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="content-type" content="text/html;image/gif;charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1" /> 
    <title>微信支付樣例-掃碼支付</title>
</head>
<body>
    <div style="margin-left: 10px;color:#00CD00;font-size:30px;font-weight: bolder;">掃碼支付模式一</div><br/>
    <asp:Image ID="Image1" runat="server" style="width:200px;height:200px;"/>
    <br/><br/><br/>
    <div style="margin-left: 10px;color:#00CD00;font-size:30px;font-weight: bolder;">掃碼支付模式二</div><br/>
    <asp:Image ID="Image2" runat="server" style="width:200px;height:200px;"/>
    
</body>
</html>

頁面後臺的代碼就是綁定二維碼的過程,代碼以下所示,和Winform的代碼相似操做。

        protected void Page_Load(object sender, EventArgs e)
        {
            TenPayApi api = new TenPayApi();

            var productId = "123456789";
            //生成掃碼支付模式一url
            string url1 = api.GetPrePayUrl(productId);

            //生成掃碼支付模式二url
            WxPayOrderData info = new WxPayOrderData()
            {
                product_id = "123456789",
                body = "測試支付-模式二",
                attach = "愛奇迪技術支持",
                detail = "測試掃碼支付-模式二",
                total_fee = 1,
                goods_tag = "test1"
            };
            string url2 = api.GetPayUrl(info);

            //將url生成二維碼圖片
            Image1.ImageUrl = "MakeQRCode.aspx?data=" + HttpUtility.UrlEncode(url1);
            Image2.ImageUrl = "MakeQRCode.aspx?data=" + HttpUtility.UrlEncode(url2);
        }

實現後的頁面效果以下所示。

實現並預覽效果,肯定是咱們所需的頁面後,咱們能夠發佈在公衆號的菜單鏈接上進行測試使用了。

打開微信公衆號-廣州愛奇迪,咱們能夠看到對應的菜單發生改變,而且看到進入微信支付的菜單能夠進行支付了。

    

 

以上就是微信支付的掃碼過程的一個實現,微信支付還包括不少其餘API接口,後面有機會能夠繼續進行介紹。微信支付的接口實現雖然相對其餘微信接口比較複雜一些,可是咱們一旦完成幾個案例,後面的就相對比較容易的了,由於它的調用方式基本上比較一致,很相似。

 

若是對這個《C#開發微信門戶及應用》系列感興趣,能夠關注個人其餘文章,系列隨筆以下所示:

C#開發微信門戶及應用(36)--微信卡劵管理的封裝操做

C#開發微信門戶及應用(35)--微信支付之企業付款封裝操做

C#開發微信門戶及應用(34)--微信裂變紅包

C#開發微信門戶及應用(33)--微信現金紅包的封裝及使用

C#開發微信門戶及應用(32)--微信支付接入和API封裝使用

C#開發微信門戶及應用(31)--微信語義理解接口的實現和處理

C#開發微信門戶及應用(30)--消息的羣發處理和預覽功能

C#開發微信門戶及應用(28)--微信「搖一搖·周邊」功能的使用和接口的實現

C#開發微信門戶及應用(27)-公衆號模板消息管理 

C#開發微信門戶及應用(26)-公衆號微信素材管理

C#開發微信門戶及應用(25)-微信企業號的客戶端管理功能

C#開發微信門戶及應用(24)-微信小店貨架信息管理

C#開發微信門戶及應用(23)-微信小店商品管理接口的封裝和測試

C#開發微信門戶及應用(22)-微信小店的開發和使用

C#開發微信門戶及應用(21)-微信企業號的消息和事件的接收處理及解密 

C#開發微信門戶及應用(20)-微信企業號的菜單管理

C#開發微信門戶及應用(19)-微信企業號的消息發送(文本、圖片、文件、語音、視頻、圖文消息等)

C#開發微信門戶及應用(18)-微信企業號的通信錄管理開發之成員管理

C#開發微信門戶及應用(17)-微信企業號的通信錄管理開發之部門管理

C#開發微信門戶及應用(16)-微信企業號的配置和使用

C#開發微信門戶及應用(15)-微信菜單增長掃一掃、發圖片、發地理位置功能

C#開發微信門戶及應用(14)-在微信菜單中採用重定向獲取用戶數據

C#開發微信門戶及應用(13)-使用地理位置擴展相關應用

C#開發微信門戶及應用(12)-使用語音處理

C#開發微信門戶及應用(11)--微信菜單的多種表現方式介紹

C#開發微信門戶及應用(10)--在管理系統中同步微信用戶分組信息

C#開發微信門戶及應用(9)-微信門戶菜單管理及提交到微信服務器

C#開發微信門戶及應用(8)-微信門戶應用管理系統功能介紹

C#開發微信門戶及應用(7)-微信多客服功能及開發集成

C#開發微信門戶及應用(6)--微信門戶菜單的管理操做

C#開發微信門戶及應用(5)--用戶分組信息管理

C#開發微信門戶及應用(4)--關注用戶列表及詳細信息管理

C#開發微信門戶及應用(3)--文本消息和圖文消息的應答

C#開發微信門戶及應用(2)--微信消息的處理和應答

C#開發微信門戶及應用(1)--開始使用微信接口

相關文章
相關標籤/搜索