微信小程式支付

来源:https://www.cnblogs.com/haoxiaozhang/archive/2019/09/27/11594523.html
-Advertisement-
Play Games

微信小程式支付 1、背景 因業務需要接入微信支付功能(客戶端是微信小程式),因公司伺服器版本較低,服務端採用.Net Framework 版本(並採用盛派微信SDK) 2、文檔地址 1)小程式支付:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api. ...


微信小程式支付

1、背景

  因業務需要接入微信支付功能(客戶端是微信小程式),因公司伺服器版本較低,服務端採用.Net Framework 版本(並採用盛派微信SDK)

2、文檔地址

  1)小程式支付:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1

  2)小程式調起支付API:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5

  3)支付下單:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

  4)發起微信支付:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html

  5)盛派SDK:http://sdk.weixin.senparc.com/

3、代碼實現

  小程式支付的交互圖如下:

  

  3.1 服務端實現

   1)引入包:

    

   2)註冊:在 Global.asmx 里進行註冊

  /* 
             * CO2NET 全局註冊開始
             * 建議按照以下順序進行註冊
             */

            /*
             * CO2NET 是從 Senparc.Weixin 分離的底層公共基礎模塊,經過了長達 6 年的迭代優化。
             * 關於 CO2NET 在所有項目中的通用設置可參考 CO2NET 的 Sample:
             * https://github.com/Senparc/Senparc.CO2NET/blob/master/Sample/Senparc.CO2NET.Sample.netcore/Startup.cs
             */


            //設置全局 Debug 狀態
            var isGLobalDebug = true;
            //全局設置參數,將被儲存到 Senparc.CO2NET.Config.SenparcSetting
            var senparcSetting = SenparcSetting.BuildFromWebConfig(isGLobalDebug);
            //也可以通過這種方法在程式任意位置設置全局 Debug 狀態:
            //Senparc.CO2NET.Config.IsDebug = isGLobalDebug;


            //CO2NET 全局註冊,必須!!
            IRegisterService register = RegisterService.Start(senparcSetting).UseSenparcGlobal();

            #region  全局緩存配置(按需)

            #region 配置和使用 Redis          -- DPBMARK Redis

            //配置全局使用Redis緩存(按需,獨立)
            var redisConfigurationStr = senparcSetting.Cache_Redis_Configuration;
            var useRedis = !string.IsNullOrEmpty(redisConfigurationStr) && redisConfigurationStr != "Redis配置";
            if (useRedis)//這裡為了方便不同環境的開發者進行配置,做成了判斷的方式,實際開發環境一般是確定的,這裡的if條件可以忽略
            {
                /* 說明:
                 * 1、Redis 的連接字元串信息會從 Config.SenparcSetting.Cache_Redis_Configuration 自動獲取並註冊,如不需要修改,下方方法可以忽略
                /* 2、如需手動修改,可以通過下方 SetConfigurationOption 方法手動設置 Redis 鏈接信息(僅修改配置,不立即啟用)
                 */
                Senparc.CO2NET.Cache.Redis.Register.SetConfigurationOption(redisConfigurationStr);

                //以下會立即將全局緩存設置為 Redis
                Senparc.CO2NET.Cache.Redis.Register.UseKeyValueRedisNow();//鍵值對緩存策略(推薦)
                //Senparc.CO2NET.Cache.Redis.Register.UseHashRedisNow();//HashSet儲存格式的緩存策略

                //也可以通過以下方式自定義當前需要啟用的緩存策略
                //CacheStrategyFactory.RegisterObjectCacheStrategy(() => RedisObjectCacheStrategy.Instance);//鍵值對
                //CacheStrategyFactory.RegisterObjectCacheStrategy(() => RedisHashSetObjectCacheStrategy.Instance);//HashSet
            }
            //如果這裡不進行Redis緩存啟用,則目前還是預設使用記憶體緩存 

            #endregion                        // DPBMARK_END

            #region 配置和使用 Memcached      -- DPBMARK Memcached

            //配置Memcached緩存(按需,獨立)
            var memcachedConfigurationStr = senparcSetting.Cache_Memcached_Configuration;
            var useMemcached = !string.IsNullOrEmpty(memcachedConfigurationStr) && memcachedConfigurationStr != "Memcached配置";

            if (useMemcached) //這裡為了方便不同環境的開發者進行配置,做成了判斷的方式,實際開發環境一般是確定的,這裡的if條件可以忽略
            {
                /* 說明:
                * 1、Memcached 的連接字元串信息會從 Config.SenparcSetting.Cache_Memcached_Configuration 自動獲取並註冊,如不需要修改,下方方法可以忽略
               /* 2、如需手動修改,可以通過下方 SetConfigurationOption 方法手動設置 Memcached 鏈接信息(僅修改配置,不立即啟用)
                */
                Senparc.CO2NET.Cache.Memcached.Register.SetConfigurationOption(memcachedConfigurationStr);

                //以下會立即將全局緩存設置為 Memcached
                Senparc.CO2NET.Cache.Memcached.Register.UseMemcachedNow();

                //也可以通過以下方式自定義當前需要啟用的緩存策略
                CacheStrategyFactory.RegisterObjectCacheStrategy(() => MemcachedObjectCacheStrategy.Instance);
            }

            #endregion                        //  DPBMARK_END

            #endregion

            #region 註冊日誌(按需,建議)

            register.RegisterTraceLog(ConfigWeixinTraceLog);//配置TraceLog

            #endregion


            /* 微信配置開始
             * 建議按照以下順序進行註冊
             */

            //設置微信 Debug 狀態
            var isWeixinDebug = true;
            //全局設置參數,將被儲存到 Senparc.Weixin.Config.SenparcWeixinSetting
            var senparcWeixinSetting = SenparcWeixinSetting.BuildFromWebConfig(isWeixinDebug);
            //也可以通過這種方法在程式任意位置設置微信的 Debug 狀態:
            //Senparc.Weixin.Config.IsDebug = isWeixinDebug;

            //微信全局註冊,必須!!
            register.UseSenparcWeixin(senparcWeixinSetting, senparcSetting)


            #region 註冊公眾號或小程式(按需)

                //註冊公眾號(可註冊多個)                                                -- DPBMARK MP
                .RegisterMpAccount(senparcWeixinSetting, "【盛派網路小助手】公眾號")// DPBMARK_END


                //註冊多個公眾號或小程式(可註冊多個)                                        -- DPBMARK MiniProgram
                .RegisterWxOpenAccount(senparcWeixinSetting, "小程式名稱")// DPBMARK_END

                //除此以外,仍然可以在程式任意地方註冊公眾號或小程式:
                //AccessTokenContainer.Register(appId, appSecret, name);//命名空間:Senparc.Weixin.MP.Containers
            #endregion

                                    // DPBMARK_END

            #region 註冊微信支付(按需)        -- DPBMARK TenPay

                //註冊舊微信支付版本(V2)(可註冊多個)
                .RegisterTenpayOld(senparcWeixinSetting, "標記名稱")//這裡的 name 和第一個 RegisterMpAccount() 中的一致,會被記錄到同一個 SenparcWeixinSettingItem 對象中

                //註冊最新微信支付版本(V3)(可註冊多個)
                .RegisterTenpayV3(senparcWeixinSetting, "標記名稱")//記錄到同一個 SenparcWeixinSettingItem 對象中

            #endregion                          // DPBMARK_END

                                 // DPBMARK_END

            ;

            /* 微信配置結束 */
/// <summary>
        /// 配置微信跟蹤日誌
        /// </summary>
        private void ConfigWeixinTraceLog()
        {
            //Senparc.CO2NET.Config.IsDebug = false;

            //這裡設為Debug狀態時,/App_Data/WeixinTraceLog/目錄下會生成日誌文件記錄所有的API請求日誌,正式發佈版本建議關閉
            Senparc.Weixin.WeixinTrace.SendCustomLog("系統日誌", "系統啟動");//只在Senparc.Weixin.Config.IsDebug = true的情況下生效

            //自定義日誌記錄回調
            Senparc.Weixin.WeixinTrace.OnLogFunc = () =>
            {
                //加入每次觸發Log後需要執行的代碼
            };

            //當發生基於WeixinException的異常時觸發
            Senparc.Weixin.WeixinTrace.OnWeixinExceptionFunc = ex =>
            {
                //加入每次觸發WeixinExceptionLog後需要執行的代碼

                //發送模板消息給管理員
                var eventService = new EventService();
                eventService.ConfigOnWeixinExceptionFunc(ex);
            };
        }

 

   3)統一下單:

  *** 因實際代碼設計隱私問題,因此剔除了,如有問題請聯繫我。

        public async Task<ActionResult> GetWxOpenPrepayid(string sessionId,string cost)
        {
            
            try
            {
                var sessionBag = SessionContainer.GetSession(sessionId);
                var openId = sessionBag.OpenId;

                //生成訂單10位序列號,此處用時間和隨機數生成,商戶根據自己調整,保證唯一
                var sp_billno = string.Format("{0}{1}{2}", "商戶號" /*10位*/, SystemTime.Now.ToString("yyyyMMddHHmmss"),
                        TenPayV3Util.BuildRandomStr(6));

                var timeStamp = TenPayV3Util.GetTimestamp();
                var nonceStr = TenPayV3Util.GetNoncestr();
                var price = Convert.ToInt32(Convert.ToDecimal(cost) * 100);//單位:分
              
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(
                    "小程式AppId", "小程式商戶號", body, sp_billno,
                    price, "127.0.0.1", "回調地址", TenPayV3Type.JSAPI, openId, "小程式商戶key", nonceStr, attach: "附加數據");

                var result = TenPayV3.Unifiedorder(xmlDataInfo);//調用統一訂單介面

                //  WeixinTrace.SendCustomLog("統一訂單介面調用結束", "請求:" + xmlDataInfo.ToJson() + "\r\n\r\n返回結果:" + result.ToJson());

                var packageStr = "prepay_id=" + result.prepay_id;

                //var cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();
                //cacheStrategy.Set($"WxOpenUnifiedorderRequestData-{openId}", xmlDataInfo, TimeSpan.FromDays(4));//3天內可以發送模板消息
                //cacheStrategy.Set($"WxOpenUnifiedorderResultData-{openId}", result, TimeSpan.FromDays(4));//3天內可以發送模板消息
                return ToSuccess(data: new
                {
                    result.prepay_id,
                    appId = "小程式AppId",
                    timeStamp,
                    nonceStr,
                    tradeId = sp_billno,
                    package = packageStr,
                    //signType = "MD5",
                    paySign = TenPayV3.GetJsPaySign("小程式AppId", timeStamp, nonceStr, packageStr, "小程式支付key")
                });
            }
            catch (Exception ex)
            {
                return ToError(msg: ex.Message);
            }

*** 這個介面 在什麼地方用呢(A:在小程式客戶端調用微信支付的時候需要用到【而且是必須的】,也就是下午的 小程式客戶端調用:wx.requestPayment 的時候)

  4)回調地址(支付結果通知):

 

  *** 需要註意的地方已 標出了。(值得註意的就是這個地址必須是外網能訪問到的)

  代碼實現:

  public ActionResult InquiryNotify()
        {
            try
            {
                var resHandler = new ResponseHandler(null);
                var return_code = resHandler.GetParameter("return_code");

                var return_msg = resHandler.GetParameter("return_msg");
                if (return_code != "SUCCESS") return PayResultNotify();
                var attach = resHandler.GetParameter("attach");
                if (string.IsNullOrEmpty(attach)) return PayResultNotify();

                //這裡請簽名驗證,並校驗返回的訂單金額是否與商戶側的訂單金額一致

                var cost = resHandler.GetParameter("total_fee");//金額
                var tradeId = resHandler.GetParameter("out_trade_no");//商戶訂單號
                //驗證支付狀態與金額
       
              //業務邏輯處理,採用非同步回調
                return PayResultNotify("SUCCESS", "OK");
            }
            catch (Exception ex)
            {        
                return PayResultNotify();
            }
        }

 private ActionResult PayResultNotify(string returnCode = "FAIL", string returnMsg = "wrong")
        {
            var xml = $@"<xml>
                       <return_code><![CDATA[{returnCode}]]></return_code>
                       <return_msg><![CDATA[{returnMsg}]]></return_msg>
                       </xml>";
            return Content(xml, "text/xml");
        }

  3.2、客戶端實現(小程式)

  

/**
   * 支付
   */
  bindPay: function(e) {
    let that = this
    let url = wx.getStorageSync(config.domainName)
    url += '服務端介面地址'
    let data = {
      sessionId: wx.getStorageSync(config.sessionId),
      cost: "支付金額",
    }
    wxRequest.getRequest(url, data).then((res) => {
      if (res.data.success) {
        let payInfo = res.data.data
        wx.requestPayment({
          timeStamp: payInfo.timeStamp,
          nonceStr: payInfo.nonceStr,
          package: payInfo.package,
          paySign: payInfo.paySign,
          signType: 'MD5',
          success: function(res) {
          /*這裡一定要註意,這裡的方法有可能會不執行(支付完成後 用戶在不點擊 支付完成頁面底部的“完成”按鈕時 這裡的方法是不會執行到的,因此這裡請不要寫業務邏輯代碼)*/
            that.queryPayResult(payInfo.tradeId)
          },
          fail: function(res) {
        /*用戶取消支付後 會執行這裡的方面*/ that.payCancel(payInfo.tradeId) } }) }
else { app.showToast(res.data.msg) } }) }

  至此,小程式的支付就完成了。感謝 盛派網路 對微信相關介面的封裝,用起來很方便

說明:

    1:如有疑問,可以與我取得聯繫

    2:已官方文檔為主,很有可能過些時間後文檔及SDK會發生變化

    3:官方文檔已在上文中給出

    4:文章首發於公眾號

    5:服務端使用的小程式包是盛派的SDK(https://weixin.senparc.com)GitHub:https://github.com/Senparc/WeiXinMPSDK

    6:.Net Core 類似,有何疑問也可以與我取得聯繫

  如果對您有幫助,點個推薦唄!

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 群里看到有人詢問:誰會用python將微信音頻文件尾碼m4a格式轉成mp3格式,毫不猶豫回了句:我會。然後就私下聊起來了 解決方法介紹如下: 工具:windows系統,python2.7,轉換庫ffmpeg 安裝ffmpeg庫:下載對應電腦系統版本 https://ffmpeg.zeranoe.co ...
  • 1. 概覽 在編寫 Spring Boot 應用程式時, "將配置屬性映射到 Java bean 上" 是非常有用的。但是,記錄這些屬性的最好方法是什麼呢? 在本教程中,我們將探討 "Spring Boot Configuration Processor" 和 "關聯的 JSON 元數據文件" ,該 ...
  • 本文導讀: 微服務技術架構選型介紹 k8s 容器化部署架構方案 Eureka 註冊中心問題場景 問題解決手段及原理剖析 閱讀本文建議先瞭解: 1. 註冊中心基本原理 2. K8s(Kuberneters)基本概念 我們的微服務目前都是在伺服器上部署的,也是基於 Docker 來部署的。 運維部門基於 ...
  • Flask中的CBV以及正則表達式 一.CBV 二.正則表達式 ...
  • 一.request 二.response ...
  • .Net Core中間件官網:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.0 ASP.Net請求管道: 請求最終會由一個具體的HttpHandler處理(page/as ...
  • 好久沒有寫文章了,最近在用.net core3.0,一些開發中問題順便記錄; 1.首先nuget引入 Autofac Autofac.Extensions.DependencyInjection 2.修改Program.cs 添加.UseServiceProviderFactory(new Auto ...
  • --近期有一個需要運用多線程的項目,會有併發概率,所以寫了一份代碼,可能有寫地方還不完善,後續有需求在改 1 /// <summary> 2 /// 併發對象 3 /// </summary> 4 public class MeterAsyncQueue 5 { 6 public MeterAsyn... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...