.NETCore中微信支付之公眾號(hào)、H5支付的示例分析-創(chuàng)新互聯(lián)

小編給大家分享一下.NET Core中微信支付之公眾號(hào)、H5支付的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

10余年的衢江網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)營(yíng)銷(xiāo)推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整衢江建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“衢江網(wǎng)站設(shè)計(jì)”,“衢江網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

準(zhǔn)備篇

公眾號(hào)或者服務(wù)號(hào)(并開(kāi)通微信支付功能)、商戶平臺(tái)中開(kāi)通JSAPI支付、H5支付。

配置篇

公眾號(hào)或者服務(wù)號(hào)中 -------開(kāi)發(fā)-------開(kāi)發(fā)者工具---------web開(kāi)發(fā)者工具-------綁定為開(kāi)發(fā)者

公眾號(hào)或者服務(wù)號(hào)中 -------公眾號(hào)設(shè)置--------功能設(shè)置   :填寫(xiě)業(yè)務(wù)域名、JS安全域名、網(wǎng)頁(yè)授權(quán)域名 示例:pay.one.com

商戶平臺(tái)中--------產(chǎn)品中心-------開(kāi)發(fā)配置------JSAPI支付授權(quán)目錄填寫(xiě):http://pay.one.com/    http://pay.one.com/WeChatPay/PubPay/-----H5支付填寫(xiě):pay.one.com

.NET Core中微信支付之公眾號(hào)、H5支付的示例分析

.NET Core中微信支付之公眾號(hào)、H5支付的示例分析

.NET Core中微信支付之公眾號(hào)、H5支付的示例分析

若對(duì)配置還有疑問(wèn),可參考官方文檔:

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

開(kāi)發(fā)篇

JSAPI支付

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

首先 使用Nuget安裝payment:

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

建一個(gè)Model: WeChatPayPubPayViewModel

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:

//微信支付請(qǐng)求客戶端(用于處理請(qǐng)求與響應(yīng))
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>
    /// 公眾號(hào)支付
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public IActionResult PubPay()
    {
      WeChatPayPubPayViewModel payModel=new WeChatPayPubPayViewModel()
      {
        Body = "微信公眾號(hào)支付測(cè)試",
        OutTradeNo = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
        TotalFee = 1,//分 單位
        SpbillCreateIp = "127.0.0.1",
        NotifyUrl = "http://pay.one.com/notify/wechatpay/unifiedorder",
        TradeType = "JSAPI",
        OpenId = "" //此處需進(jìn)行授權(quán) 獲取OpenId
      };
      return View(payModel);
    }

    /// <summary>
    /// 公眾號(hào)支付
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<IActionResult> PubPay(WeChatPayPubPayViewModel viewModel)
    {
      if(string.IsNullOrEmpty(viewModel.OpenId))
      {
        ViewData["response"] = "請(qǐng)返回上級(jí)重新進(jìn)入此頁(yè)面以獲取新數(shù)據(jù)";
        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 //此處需進(jìn)行授權(quán) 獲取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);
        // 將參數(shù)(parameter)給 公眾號(hào)前端 讓他在微信內(nèi)H5調(diào)起支付(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();
    }

注意:公眾號(hào)或者微信內(nèi)支付,需要授權(quán)獲取到用戶的OpenId。所以,此處我們還需要進(jìn)行微信授權(quán),而授權(quán)方式有兩種,一種是靜默授權(quán)、一種是需要用戶同意,區(qū)別是 靜默授權(quán)只能拿到Openid,而經(jīng)用戶同意后可拿到 微信頭像、昵稱(chēng)、性別等其他信息。

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

頁(yè)面:

@using Newtonsoft.Json
@model WeChatPayPubPayViewModel
@{
  ViewData["Title"] = "公眾號(hào)支付-統(tǒng)一下單";
}
<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">提交請(qǐng)求</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/oauth3/authorize?appid=@ViewBaig.AppId&redirect_uri=' + encodeURIComponent(local)+'&response_type=code&scope=snsapi_base&state=a#wechat_redirect';
    });
  
  });

</script>

此時(shí):PayBack Action如下:

 [HttpGet]
    public async Task<IActionResult> PayBack()
    {
      var code = Request.Query["code"];
      var state = Request.Query["state"];
      OAuthToken tokenModel = new OAuthToken();
      //通過(guò)code換取token
      if (!string.IsNullOrEmpty(code))
      {
        _logger.LogWarning("授權(quán)成功");
        ViewBag.Code = code;
        tokenModel = OauthApi.GetAuthToken(code, wechatAppId);
      }

      var request = new WeChatPayUnifiedOrderRequest
      {
        Body = "微信公眾號(hào)支付測(cè)試",
        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 //此處需進(jìn)行授權(quán) 獲取OpenId
      };
      var response = await _client.ExecuteAsync(request);
      _logger.LogWarning($"統(tǒng)一下單接口返回:{response.ReturnCode}");

      if (response.ReturnCode == "SUCCESS" && response.ResultCode == "SUCCESS")
      {
        var req = new WeChatPayH5CallPaymentRequest
        {
          Package = "prepay_id=" + response.PrepayId
        };
        var parameter = await _client.ExecuteAsync(req);
        // 將參數(shù)(parameter)給 公眾號(hào)前端 讓他在微信內(nèi)H5調(diào)起支付(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6)
        ViewData["parameter"] = JsonConvert.SerializeObject(parameter);
        _logger.LogWarning($"統(tǒng)一下單成功,即將調(diào)起微信支付:{ViewData["parameter"].ToString()}");
        ViewData["response"] = response.Body;
        return View();
      }
      ViewData["response"] = response.Body;

      
      return View();
    }

其中:OAuthToken是網(wǎng)頁(yè)授權(quán) 返回的實(shí)體:

/// 獲取網(wǎng)頁(yè)授權(quán)token時(shí),返回的實(shí)體
  /// </summary>
  public class OAuthToken : BaseRes
  {
    /// <summary>
    /// 網(wǎng)頁(yè)授權(quán)接口調(diào)用憑證。注意:此access_token與基礎(chǔ)支持的access_token不同
    /// </summary>
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
    private int _expiresIn;
    /// <summary>
    /// access_token接口調(diào)用憑證超時(shí)時(shí)間,單位(秒)
    /// </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>
    /// 用戶標(biāo)識(shí)。請(qǐng)注意,在未關(guān)注公眾號(hào)時(shí),用戶訪問(wèn)公眾號(hào)的網(wǎng)頁(yè),也會(huì)產(chǎn)生一個(gè)用戶和公眾號(hào)的openid
    /// </summary>
    [JsonProperty("openid")]
    public string Openid { get; set; }
    /// <summary>
    /// 用戶授權(quán)的作用域,使用逗號(hào)(,)分隔
    /// </summary>
    [JsonProperty("scope")]
    public string Scope { get; set; }
    [JsonProperty("expires_time")]
    public DateTime ExpiresTime { get; set; }
    /// <summary>
    /// 只有在用戶將公眾號(hào)綁定到微信開(kāi)放平臺(tái)賬號(hào)后,才會(huì)出現(xiàn)該字段
    /// </summary>
    [JsonProperty("unionid")]
    public string Unionid { get; set; }
  }

最后 貼一下支付成功后的回調(diào)函數(shù):

[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>
    /// 統(tǒng)一下單支付結(jié)果通知
    /// </summary>
    /// <returns></returns>
    [Route("unifiedorder")]
    [HttpPost]
    public async Task<IActionResult> Unifiedorder()
    {
      try
      {
        _logger.LogWarning($"進(jìn)入回調(diào)");
        var payconfig = OpenApi.GetPayConfig();
        var notify = await _client.ExecuteAsync<WeChatPayUnifiedOrderNotify>(Request);
        _logger.LogWarning($"返回狀態(tài)碼:{notify.ReturnCode}");

        if (notify.ReturnCode == "SUCCESS")
        {
          _logger.LogWarning($"業(yè)務(wù)結(jié)果碼:{notify.ResultCode}");

          if (notify.ResultCode == "SUCCESS")
          {
            _logger.LogWarning($"支付方式:{notify.TradeType}");
            _logger.LogWarning($"商戶訂單號(hào):{notify.OutTradeNo}");
            _logger.LogWarning($"微信支付訂單號(hào):{notify.TransactionId}");
            _logger.LogWarning($"支付金額:{notify.TotalFee}");
            return WeChatPayNotifyResult.Success;
          }
        }
        return NoContent();
      }
      catch(Exception ex)
      {
        _logger.LogWarning($"回調(diào)失?。簕ex.Message}");
        return NoContent();
      }
    }
}

然后測(cè)試一下支付,查看服務(wù)器Log如下:

.NET Core中微信支付之公眾號(hào)、H5支付的示例分析

H5支付

H5支付是指再除開(kāi)微信瀏覽器以外的移動(dòng)端瀏覽器上進(jìn)行微信回復(fù)操作。

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

1:客戶端IP問(wèn)題:H5支付的時(shí)候,微信支付系統(tǒng)會(huì)根據(jù)客戶端調(diào)起的當(dāng)前Ip 作為支付Ip,若發(fā)現(xiàn) 發(fā)起支付請(qǐng)求時(shí),ip有問(wèn)題,則會(huì)支付失敗,或者提示系統(tǒng)繁忙。這里貼一下我獲取IP的代碼:

Utils.GetUserIp(_accessor.HttpContext);//頁(yè)面上調(diào)用


    /// <summary>
    /// 穿過(guò)代理服務(wù)器獲取真實(shí)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類(lèi)型應(yīng)該是:MWEB

3:若調(diào)起微信支付成功后,默認(rèn)回調(diào)到支付首頁(yè),若需要設(shè)置回調(diào)頁(yè)面,則可以再URl中拼接:

  /// <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為拉起微信支付收銀臺(tái)的中間頁(yè)面,可通過(guò)訪問(wèn)該url來(lái)拉起微信客戶端,完成支付,mweb_url的有效期為5分鐘。
      if (response.MwebUrl == null)
      {
        ViewData["response"] = response.ReturnMsg;
        return View();
      }
      return Redirect(response.MwebUrl);
    }

.NET Core中微信支付之公眾號(hào)、H5支付的示例分析

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

4:支付結(jié)果通知:

注意:

1、同樣的通知可能會(huì)多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復(fù)的通知。

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

3、在訂單狀態(tài)不明或者沒(méi)有收到微信支付結(jié)果通知的情況下,建議商戶主動(dòng)調(diào)用微信支付【 查詢訂單API 】確認(rèn)訂單狀態(tài)。

特別提醒:

1、商戶系統(tǒng)對(duì)于支付結(jié)果通知的內(nèi)容一定要做 簽名驗(yàn)證,并校驗(yàn)返回的訂單金額是否與商戶側(cè)的訂單金額一致 ,防止數(shù)據(jù)泄漏導(dǎo)致出現(xiàn)“假通知”,造成資金損失。

2、當(dāng)收到通知進(jìn)行處理時(shí),首先檢查對(duì)應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過(guò),如果沒(méi)有處理過(guò)再進(jìn)行處理,如果處理過(guò)直接返回結(jié)果成功。在對(duì)業(yè)務(wù)數(shù)據(jù)進(jìn)行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。

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

.NET Core中微信支付之公眾號(hào)、H5支付的示例分析

看完了這篇文章,相信你對(duì)“.NET Core中微信支付之公眾號(hào)、H5支付的示例分析”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

當(dāng)前名稱(chēng):.NETCore中微信支付之公眾號(hào)、H5支付的示例分析-創(chuàng)新互聯(lián)
分享鏈接:http://muchs.cn/article24/dsjdje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航網(wǎng)站內(nèi)鏈、標(biāo)簽優(yōu)化、網(wǎng)頁(yè)設(shè)計(jì)公司、用戶體驗(yàn)、Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作