一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - .NET Core之微信支付之公眾號、H5支付詳解

.NET Core之微信支付之公眾號、H5支付詳解

2020-06-09 16:16瀟十一郎 ASP.NET教程

這篇文章主要介紹了.NET Core之微信支付之公眾號、H5支付篇,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

本篇主要記錄微信支付公眾號H5支付全過程。

準備篇

公眾號或者服務號(并開通微信支付功能)、商戶平臺中開通JSAPI支付、H5支付。

配置篇

公眾號或者服務號中 -------開發-------開發者工具---------web開發者工具-------綁定為開發者

公眾號或者服務號中 -------公眾號設置--------功能設置   :填寫業務域名、JS安全域名、網頁授權域名 示例:pay.one.com

商戶平臺中--------產品中心-------開發配置------JSAPI支付授權目錄填寫:http://pay.one.com/    http://pay.one.com/WeChatPay/PubPay/-----H5支付填寫:pay.one.com

.NET Core之微信支付之公眾號、H5支付詳解

.NET Core之微信支付之公眾號、H5支付詳解

.NET Core之微信支付之公眾號、H5支付詳解

若對配置還有疑問,可參考官方文檔:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

開發篇

JSAPI支付

本Demo是基于Payment 的SDK開發。具體詳情可參考: https://github.com/Essensoft/Payment

首先 使用Nuget安裝payment:

Install-Package  :Essensoft.AspNetCore.Payment.WeChatPay -Version 2.3.2

建一個Model: WeChatPayPubPayViewModel

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class WeChatPayPubPayViewModel
  {
    [Required]
    [Display(Name = "out_trade_no")]
    public string OutTradeNo { get; set; }
 
    [Required]
    [Display(Name = "body")]
    public string Body { get; set; }
 
    [Required]
    [Display(Name = "total_fee")]
    public int TotalFee { get; set; }
 
    [Required]
    [Display(Name = "spbill_create_ip")]
    public string SpbillCreateIp { get; set; }
 
    [Required]
    [Display(Name = "notify_url")]
    public string NotifyUrl { get; set; }
 
    [Required]
    [Display(Name = "trade_type")]
    public string TradeType { get; set; }
 
    [Required]
    [Display(Name = "openid")]
    public string OpenId { get; set; }
  }

WeChatPayController:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//微信支付請求客戶端(用于處理請求與響應)
private readonly IWeChatPayClient _client;
private readonly ILogger<WeChatPayController> _logger;
 
 private IHttpContextAccessor _accessor;
 
public WeChatPayController(IWeChatPayClient client, IHttpContextAccessor accessor, ILogger<WeChatPayController> logger)
    {
      _client = client;
      _accessor = accessor;
      _logger = logger;
    }
    /// <summary>
    /// 公眾號支付
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public IActionResult PubPay()
    {
      WeChatPayPubPayViewModel payModel=new WeChatPayPubPayViewModel()
      {
        Body = "微信公眾號支付測試",
        OutTradeNo = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
        TotalFee = 1,//分 單位
        SpbillCreateIp = "127.0.0.1",
        NotifyUrl = "http://pay.one.com/notify/wechatpay/unifiedorder",
        TradeType = "JSAPI",
        OpenId = "" //此處需進行授權 獲取OpenId
      };
      return View(payModel);
    }
 
    /// <summary>
    /// 公眾號支付
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<IActionResult> PubPay(WeChatPayPubPayViewModel viewModel)
    {
      if(string.IsNullOrEmpty(viewModel.OpenId))
      {
        ViewData["response"] = "請返回上級重新進入此頁面以獲取最新數據";
        return View();
      }
 
      var request = new WeChatPayUnifiedOrderRequest
      {
        Body = viewModel.Body,
        OutTradeNo = viewModel.OutTradeNo,
        TotalFee = viewModel.TotalFee,
        SpbillCreateIp = viewModel.SpbillCreateIp,
        NotifyUrl = viewModel.NotifyUrl,
        TradeType = viewModel.TradeType,
        OpenId = viewModel.OpenId //此處需進行授權 獲取OpenId
      };
      var response = await _client.ExecuteAsync(request);if (response.ReturnCode == "SUCCESS" && response.ResultCode == "SUCCESS")
      {
        var req = new WeChatPayH5CallPaymentRequest
        {
          Package = "prepay_id=" + response.PrepayId
        };
        var parameter = await _client.ExecuteAsync(req);
        // 將參數(parameter)給 公眾號前端 讓他在微信內H5調起支付(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6)
        ViewData["parameter"] = JsonConvert.SerializeObject(parameter);
        ViewData["response"] = response.Body;
        return View();
      }
      ViewData["response"] = response.Body;
      return View();
    }

注意:公眾號或者微信內支付,需要授權獲取到用戶的OpenId。所以,此處我們還需要進行微信授權,而授權方式有兩種,一種是靜默授權、一種是需要用戶同意,區別是 靜默授權只能拿到Openid,而經用戶同意后可拿到 微信頭像、昵稱、性別等其他信息。

具體可參閱文檔: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

頁面:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
@using Newtonsoft.Json
@model WeChatPayPubPayViewModel
@{
  ViewData["Title"] = "公眾號支付-統一下單";
}
<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item"><a asp-controller="WeChatPay" asp-action="Index">微信支付</a></li>
    <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
  </ol>
</nav>
<br />
<div class="card">
  <div class="card-body">
    <form asp-controller="WeChatPay" asp-action="PubPay">
      <div asp-validation-summary="All" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="OutTradeNo"></label>
        <input type="text" class="form-control" asp-for="OutTradeNo" value="@Model?.OutTradeNo" />
      </div>
      <div class="form-group">
        <label asp-for="Body"></label>
        <input type="text" class="form-control" asp-for="Body" value="@Model?.Body" />
      </div>
      <div class="form-group">
        <label asp-for="TotalFee"></label>
        <input type="text" class="form-control" asp-for="TotalFee" value="@Model?.TotalFee" />
      </div>
      <div class="form-group">
        <label asp-for="SpbillCreateIp"></label>
        <input type="text" class="form-control" asp-for="SpbillCreateIp" value="@Model?.SpbillCreateIp" />
      </div>
      <div class="form-group">
        <label asp-for="NotifyUrl"></label>
        <input type="text" class="form-control" asp-for="NotifyUrl" value="@Model?.NotifyUrl" />
      </div>
      <div class="form-group">
        <label asp-for="TradeType"></label>
        <input type="text" class="form-control" asp-for="TradeType" value="@Model?.TradeType" />
      </div>
      <div class="form-group">
        <label asp-for="OpenId"></label>
        <input type="text" class="form-control" asp-for="OpenId" value="@Model?.OpenId" />
      </div>
      <button type="submit" class="btn btn-primary">提交請求</button>
      <button type="button" class="btn btn-success" id="PayNow">立即支付</button>
    </form>
    <hr />
    <form class="form-horizontal">
      <div class="form-group">
        <label>Response:</label>
        <textarea class="form-control" rows="10">@ViewData["response"]</textarea>
      </div>
      <div class="form-group">
        <label>Parameter:</label>
        <textarea class="form-control" rows="3">@ViewData["parameter"]</textarea>
      </div>
    </form>
  </div>
</div>
@section Scripts {
  @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script type="text/javascript">
  $(function () {
    $("#PayNow").on('click', function () {
      const local = "http://pay.one.com/WeChatPay/PayBack/";
       window.location.href ='https://open.weixin.qq.com/connect/oauth2/[email protected]&redirect_uri=' + encodeURIComponent(local)+'&response_type=code&scope=snsapi_base&state=a#wechat_redirect';
    });
  
  });
 
</script>

此時:PayBack Action如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[HttpGet]
   public async Task<IActionResult> PayBack()
   {
     var code = Request.Query["code"];
     var state = Request.Query["state"];
     OAuthToken tokenModel = new OAuthToken();
     //通過code換取token
     if (!string.IsNullOrEmpty(code))
     {
       _logger.LogWarning("授權成功");
       ViewBag.Code = code;
       tokenModel = OauthApi.GetAuthToken(code, wechatAppId);
     }
 
     var request = new WeChatPayUnifiedOrderRequest
     {
       Body = "微信公眾號支付測試",
       OutTradeNo = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
       TotalFee = 1,//分 單位
       SpbillCreateIp = "127.0.0.1",
       NotifyUrl = "http://pay.one.com/notify/wechatpay/unifiedorder",
       TradeType = "JSAPI",
       OpenId = tokenModel.Openid //此處需進行授權 獲取OpenId
     };
     var response = await _client.ExecuteAsync(request);
     _logger.LogWarning($"統一下單接口返回:{response.ReturnCode}");
 
     if (response.ReturnCode == "SUCCESS" && response.ResultCode == "SUCCESS")
     {
       var req = new WeChatPayH5CallPaymentRequest
       {
         Package = "prepay_id=" + response.PrepayId
       };
       var parameter = await _client.ExecuteAsync(req);
       // 將參數(parameter)給 公眾號前端 讓他在微信內H5調起支付(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6)
       ViewData["parameter"] = JsonConvert.SerializeObject(parameter);
       _logger.LogWarning($"統一下單成功,即將調起微信支付:{ViewData["parameter"].ToString()}");
       ViewData["response"] = response.Body;
       return View();
     }
     ViewData["response"] = response.Body;
 
     
     return View();
   }

其中:OAuthToken是網頁授權 返回的實體:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/// 獲取網頁授權token時,返回的實體
  /// </summary>
  public class OAuthToken : BaseRes
  {
    /// <summary>
    /// 網頁授權接口調用憑證。注意:此access_token與基礎支持的access_token不同
    /// </summary>
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
    private int _expiresIn;
    /// <summary>
    /// access_token接口調用憑證超時時間,單位(秒)
    /// </summary>
    [JsonProperty("expires_in")]
    public int ExpiresIn
    {
      get { return _expiresIn; }
      set
      {
        ExpiresTime = DateTime.Now.AddSeconds(value);
        _expiresIn = value;
      }
    }
    /// <summary>
    /// 用于刷新access_token
    /// </summary>
    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }
    /// <summary>
    /// 用戶唯一標識。請注意,在未關注公眾號時,用戶訪問公眾號的網頁,也會產生一個用戶和公眾號唯一的openid
    /// </summary>
    [JsonProperty("openid")]
    public string Openid { get; set; }
    /// <summary>
    /// 用戶授權的作用域,使用逗號(,)分隔
    /// </summary>
    [JsonProperty("scope")]
    public string Scope { get; set; }
    [JsonProperty("expires_time")]
    public DateTime ExpiresTime { get; set; }
    /// <summary>
    /// 只有在用戶將公眾號綁定到微信開放平臺賬號后,才會出現該字段
    /// </summary>
    [JsonProperty("unionid")]
    public string Unionid { get; set; }
  }

最后 貼一下支付成功后的回調函數:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[Route("notify/wechatpay")]
  public class WeChatPayNotifyController : Controller
  {
    private readonly IWeChatPayNotifyClient _client;
    private readonly ILogger<WeChatPayNotifyController> _logger;
    public WeChatPayNotifyController(IWeChatPayNotifyClient client,ILogger<WeChatPayNotifyController> logger)
    {
      _client = client;
      _logger = logger;
    }
 
    /// <summary>
    /// 統一下單支付結果通知
    /// </summary>
    /// <returns></returns>
    [Route("unifiedorder")]
    [HttpPost]
    public async Task<IActionResult> Unifiedorder()
    {
      try
      {
        _logger.LogWarning($"進入回調");
        var payconfig = OpenApi.GetPayConfig();
        var notify = await _client.ExecuteAsync<WeChatPayUnifiedOrderNotify>(Request);
        _logger.LogWarning($"返回狀態碼:{notify.ReturnCode}");
 
        if (notify.ReturnCode == "SUCCESS")
        {
          _logger.LogWarning($"業務結果碼:{notify.ResultCode}");
 
          if (notify.ResultCode == "SUCCESS")
          {
            _logger.LogWarning($"支付方式:{notify.TradeType}");
            _logger.LogWarning($"商戶訂單號:{notify.OutTradeNo}");
            _logger.LogWarning($"微信支付訂單號:{notify.TransactionId}");
            _logger.LogWarning($"支付金額:{notify.TotalFee}");
            return WeChatPayNotifyResult.Success;
          }
        }
        return NoContent();
      }
      catch(Exception ex)
      {
        _logger.LogWarning($"回調失?。簕ex.Message}");
        return NoContent();
      }
    }
}

然后測試一下支付,查看服務器Log如下:

.NET Core之微信支付之公眾號、H5支付詳解

H5支付

H5支付是指再除開微信瀏覽器以外的移動端瀏覽器上進行微信回復操作。

和上面步驟大體一致,有幾個地方需要注意

1:客戶端IP問題:H5支付的時候,微信支付系統會根據客戶端調起的當前Ip 作為支付Ip,若發現 發起支付請求時,ip有問題,則會支付失敗,或者提示系統繁忙。這里貼一下我獲取IP的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Utils.GetUserIp(_accessor.HttpContext);//頁面上調用
 
 
    /// <summary>
    /// 穿過代理服務器獲取真實IP
    /// </summary>
    /// <returns></returns>
    public static string GetUserIp(this HttpContext context)
    {
      var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
      if (string.IsNullOrEmpty(ip))
      {
        ip = context.Connection.RemoteIpAddress.ToString();
      }
      return ip;
      
    }

2:TradeType類型應該是:MWEB

3:若調起微信支付成功后,默認回調到支付首頁,若需要設置回調頁面,則可以再URl中拼接:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/// <summary>
  /// H5支付
  /// </summary>
  /// <param name="viewModel"></param>
  /// <returns></returns>
  [HttpPost]
  public async Task<IActionResult> H5Pay(WeChatPayH5PayViewModel viewModel)
  {
    var request = new WeChatPayUnifiedOrderRequest
    {
      Body = viewModel.Body,
      OutTradeNo = viewModel.OutTradeNo,
      TotalFee = viewModel.TotalFee,
      SpbillCreateIp = viewModel.SpbillCreateIp,
      NotifyUrl = viewModel.NotifyUrl,
      TradeType = viewModel.TradeType
    };
    var response = await _client.ExecuteAsync(request);
 
    // mweb_url為拉起微信支付收銀臺的中間頁面,可通過訪問該url來拉起微信客戶端,完成支付,mweb_url的有效期為5分鐘。
    if (response.MwebUrl == null)
    {
      ViewData["response"] = response.ReturnMsg;
      return View();
    }
    return Redirect(response.MwebUrl);
  }

.NET Core之微信支付之公眾號、H5支付詳解

更多詳細可參考文檔: https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4

4:支付結果通知:

注意:

1、同樣的通知可能會多次發送給商戶系統。商戶系統必須能夠正確處理重復的通知。

2、后臺通知交互時,如果微信收到商戶的應答不符合規范或超時,微信會判定本次通知失敗,重新發送通知,直到成功為止(在通知一直不成功的情況下,微信總共會發起10次通知,通知頻率為15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 總計 24h4m),但微信不保證通知最終一定能成功。

3、在訂單狀態不明或者沒有收到微信支付結果通知的情況下,建議商戶主動調用微信支付【 查詢訂單API 】確認訂單狀態。

特別提醒:

1、商戶系統對于支付結果通知的內容一定要做 簽名驗證,并校驗返回的訂單金額是否與商戶側的訂單金額一致 ,防止數據泄漏導致出現“假通知”,造成資金損失。

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

最后可以測試下H5支付,查看返回的Log:

.NET Core之微信支付之公眾號、H5支付詳解

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/zhangxiaoyong/p/10588241.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久精品无码一区二区日韩av | 女同xx美女放 | 日本大片网 | 91免费精品国自产拍在线不卡 | 亚洲另类中文字幕 | 男人机机桶女人机机 | 污影院 | 亚洲精品国产精品国自产观看 | 韩日理论片 | 96av视频在线观看 | 啊哈~嗯哼~用力cao我小说 | 免费一级欧美片在线观免看 | 精品无码久久久久久久久 | 小小水蜜桃视频高清在线观看免费 | japonensis中国东北老人 | 日韩在线视频免费观看 | 亚洲一区二区福利视频 | 日本视频二区 | 欧美a级在线观看 | 精品国产福利片在线观看 | 热99re国产久热在线 | 青青青国产视频 | 二区三区视频 | 亚洲国产精品嫩草影院久久 | 国产成人免费在线观看 | 双性太子| 丰满岳乱妇在线观看视频国产 | 99热热99| 欧美一卡2卡三卡4卡5卡免费观看 | 国产日韩欧美视频 | 欧美久久久久久久一区二区三区 | 日本免费在线 | japanese超丰满人妖 | 白丝美女用胸伺候主人 | 双夫1v2| 114级毛片免费观看 1024亚洲天堂 | 欧美日韩精彩视频 | 欧美精品综合一区二区三区 | 亚洲男人的天堂网 | 美女撒尿毛片免费看 | 高清国产欧美一v精品 |