文章出處

返回目錄

談談transactionId和out_trade_no

前一篇微信JSApi支付~坑和如何填坑文章反映不錯,所以又寫了個后篇,呵呵。

每個第三方在線支付系統中都會有至少兩類訂單號,其一為支付系統的訂單號,我們稱為transactionId,其二為商戶平臺的訂單號,我們通常稱為out_trade_no,這兩個號一般用來對賬,在第三方支付平臺你可以通過這兩個訂單號來查詢訂單的狀態,而在商戶自己的網站后臺,也可以查詢它的狀態,一般地,transactionId由支付系統生成,并在回調時轉回給商戶;而out_trade_no一般在商戶平臺生成,自己可以設計自己的規則,然后把這個ID轉到第三方支付平臺,在支付成功后,第三方同樣把這個號轉回來,我們通過這個號進行商戶系統的其它操作。

看一下第三方支付的流程圖

對第三方支付的封裝

封裝要求通用,對任何一個項目都可以靈活的使用它,這是最重要的,要想實現松耦合,需要記住委托的概念,我們在訂單回調時,定義一個訂單所要數據的實體,然后以這個實體做為參數,定義一個委托,當然你完全可以使用.net為我們提供的Action,Func等通用的委托對象,這在大叔框架里通常被看到,也是大叔的常客!

下面是微信支付的封裝,可以看到業務代碼只寫自己業務,而不處理任務微信API相關的東西

        /// <summary>
        /// 返回鏈接串
        /// </summary>
        /// <returns></returns>
        public string Get()
        {
            int money = 10;
            string orderID = "Lind0001";
            Logger.LoggerFactory.Instance.Logger_Info("發送訂單號" + orderID);

            return JsApiImplement.Send(money, orderID);
        }

        //微信回調
        public void Notify()
        {
            JsApiImplement.Notify((model) =>
            {
                Logger.LoggerFactory.Instance.Logger_Info("回調訂單號" + model.Out_Trade_No);

                //更新領域訂單狀態,用戶賬戶數據,流水等
            });
        }

微信回調實體是大叔自己定義的,應該可以滿足大部分業務的需要了,主要用于回調業務層的方法

    /// <summary>
    /// 微信回調數據模型
    /// </summary>
    public class NotifyModel
    {
        /// <summary>
        /// 當次交易存儲到微信平臺的訂單號
        /// </summary>
        public string Transaction_Id { get; set; }
        /// <summary>
        /// 系統本身生成的訂單號
        /// </summary>
        public string Out_Trade_No { get; set; }
        /// <summary>
        /// 對應當前公眾號的用戶OpenId
        /// </summary>
        public string OpenId { get; set; }
        /// <summary>
        /// 微信用戶唯一標識
        /// </summary>
        public string UniqueId { get; set; }
    }

而對于方法回調JsApiImplement.Notify方法,我們在底層進行了封裝,對外公開一個委托,這個委托實現了方法的回調,當執行到微信核心業務時,回調業務層的方法即可。

        /// <summary>
        /// JsApi微信回調
        /// </summary>
        public static void Notify(Action<NotifyModel> action)
        {
            var context = System.Web.HttpContext.Current;
            ResultNotify resultNotify = new ResultNotify(context);
            resultNotify.ProcessNotify(action);
        }

其實,我在看微信API時,也發現了不少問題,感覺他們的.net開發人員功力不夠,或者說代碼不是很嚴謹,但一些公用基類,應該聲明為abstract,一般必須要子類實現的方法,應該聲明為abstract,但它們都沒有這樣做,感覺很奇怪,哈哈,下面是我對微信Notify

類的修改,加了一些應該加的,去了一些應該去的,感覺舒服多了!

   /// <summary>
    /// 回調處理基類
    /// 主要負責接收微信支付后臺發送過來的數據,對數據進行簽名驗證
    /// 子類在此類基礎上進行派生并重寫自己的回調處理過程
    /// </summary>
    public abstract class Notify
    {
        public HttpContext page { get; set; }
        public Notify(HttpContext page)
        {
            this.page = page;
        }

        /// <summary>
        /// 接收從微信支付后臺發送過來的數據并驗證簽名
        /// </summary>
        /// <returns>微信支付后臺返回的數據</returns>
        public WxPayData GetNotifyData()
        {
            //接收從微信后臺POST過來的數據
            System.IO.Stream s = page.Request.InputStream;
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            while ((count = s.Read(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            s.Flush();
            s.Close();
            s.Dispose();

            Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString());

            //轉換數據格式并驗證簽名
            WxPayData data = new WxPayData();
            try
            {
                data.FromXml(builder.ToString());
            }
            catch (WxPayException ex)
            {
                //若簽名錯誤,則立即返回結果給微信支付后臺
                WxPayData res = new WxPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", ex.Message);
                Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml());
                page.Response.Write(res.ToXml());
                page.Response.End();
            }

            Log.Info(this.GetType().ToString(), "Check sign success");
            return data;
        }

        //派生類自已必須重寫這個方法
        public abstract void ProcessNotify(Action<NotifyModel> action);

    }

對于第三方支付就說到這樣,希望大家自己也對一些東西進行封裝,方便其它項目中直接使用它們!

微信JSApi支付~坑和如何填坑

返回目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()