1、前言
“小魏呀,這個微信支付還要多久?”,“快了快了老板,就等著最后一步了,,,”,“搞快點哈,就等著上線呢”,“.........”
因公司業務需要微信支付,以前沒弄過花了幾天時間寫了一個微信v3的JSAPI支付,我滴個乖乖,差點今年小孩的奶粉就沒了,還好弄出來了,在這里面各種踩坑,在這里記錄一下,我開發的是微信公眾號上面拉起微信支付,后臺是Core3.1的介面,前端用的是Vue,后面是部署在CentOS上面的
2、寫代碼之前的準備
你必須要有一個非個人性質的公眾號(服務號),還有一個微信商戶號,服務號申請地址,微信商戶號申請地址,具體的根據網站申請中按人家要求來就行了,個人建議把申請下來的公眾號里面的appid 、appsecret,微信商戶平臺,商戶號等資料保存在資料庫中,
3、公眾號、商戶號配置
1)、公眾號JS安全域名
登錄公眾號在左手邊選單:公眾號設定---->功能設定------>JS安全域名----->設定,在里面可以連寫5個域名下載檔案上傳到服務器上面 域名要經過ICP備案,可以訪問到上面說的那個檔案就可以了,
core3.1Api 發布后你放根目錄是訪問不到的,在configure里面加上訪問靜態檔案 app.UseStaticFiles();然后在根目錄建一個檔案夾wwwroot 吧域名驗證需要的txt檔案丟進去 我是這么搞點,暫時沒有想到其他騷操作
這里有人要問了 這個設定了是干嘛的,以前我也不知道是干嘛的哈哈,總有一顆好奇的心想知道,現在想想個人理解這個JS安全域名就是一個驗證的機制吧,這里設定了加上微信服務號也有一個類似的,后面就可以呼叫JSAPI支付了,

2)、
這個緊接著在JS安全域名后面 跟著設定一下就可以了 我部署在CentOS上面 看一下檔案夾目錄,還有一個檔案夾里面是是p12檔案 后面會提到

這個網頁授權意思就是后面要獲取到用戶的OpenId的時候 要通過這個域名授權,我們就能獲取到用戶的資訊,授權登錄這些配置,后面圖上還有一個HHhhjZj的檔案這個是商戶號上面設定的,
3)、微信商戶號設定
在微信商戶平臺上面選擇產品中心---->開發配置,這里面設定支付目錄,我這里是設定的一個 ,我也不是申請商戶號的人 也沒有這個權限 ,上面的界面跟上面兩步驟差不多就不啰嗦了,

4)、微信商戶號的key,V3key設定
這里不再重復 參考微信開發檔案 微信JSAPI開發接入前準備 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_1.shtml 慢慢來哦,設定秘鑰 我倒是自己想著(阿貓阿狗888666)AMAG66688這種來拼夠32位就可以了哈哈,
4、Core3.1后端代碼 詳解
前面這些弄好了只算搭好了環境 下面開始擼碼,微信支付的邏輯就是,獲取用戶的OpenId------->統一下單獲取payId-------------->拉起微信支付------------>支付回呼介面寫邏輯
下面官網的

參考檔案 JSAPI支付
1)、封裝微信請求類
這里我單獨封裝了一個微信支付的請求類,因為呼叫v3支付必須要符合APIV3介面規則 ,具體的在微信官方檔案看
using App.Common.Base; using Microsoft.AspNetCore.Hosting; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; namespace App.Common.HttpHelper { /// <summary> /// 請求類封裝 別忘了 呼叫的時候添加 services.AddHttpClient() 呼叫都要加引數,物體類回傳沒有超時時間 /// 容器要添加 /// </summary> public class HttpClientFactoryHelper { private readonly IHttpClientFactory _httpClientFactory; private IWebHostEnvironment _webHostEnvironment; public HttpClientFactoryHelper(IHttpClientFactory httpClientFactory, IWebHostEnvironment webHostEnvironment) { _httpClientFactory = httpClientFactory; _webHostEnvironment = webHostEnvironment; } public void SaveLog(string text) { string thisTime = DateTime.Now.ToString("yyyyMMdd"); var path = _webHostEnvironment.ContentRootPath + $"/ApiInterfaceErrorLog/";//絕對路徑 string dirPath = Path.Combine(path, thisTime + "/");//絕對徑路 儲存檔案路徑的檔案夾 if (!Directory.Exists(dirPath))//查看檔案夾是否存在 Directory.CreateDirectory(dirPath); string splitLine = "============================下一條=============================="; string timeNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); using StreamWriter file = new StreamWriter(dirPath + thisTime + ".txt", true); file.WriteLine(timeNow+text); file.WriteLine(splitLine); } #region //微信支付請求 /// <summary> /// 微信請求Post /// </summary> /// <param name="url">地址</param> /// <param name="requestString">引數</param> /// <param name="privateKey">私有秘鑰 p12檔案</param> /// <param name="merchantId">商戶號</param> /// <param name="serialNo">商戶證書號</param> /// <returns></returns> public async Task<string> WeChatPostAsync(string url,string requestString, string privateKey, string merchantId, string serialNo) { try { var client = _httpClientFactory.CreateClient(); var requestContent = new StringContent(requestString); requestContent.Headers.ContentType.MediaType = "application/json"; var auth = BuildAuthAsync(url, requestString, privateKey, merchantId, serialNo,"POST"); string value = https://www.cnblogs.com/w5942066/p/$"WECHATPAY2-SHA256-RSA2048 {auth}"; client.DefaultRequestHeaders.Add("Authorization", value); client.DefaultRequestHeaders.Add("Accept", "application/json"); client.DefaultRequestHeaders.Add("User-Agent", "WOW64"); client.Timeout = TimeSpan.FromSeconds(60); var response = await client.PostAsync(url, requestContent); if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsStringAsync(); return result; } else { return $"介面【{url}】請求錯誤,錯誤代碼{response.StatusCode},錯誤原因{response.ReasonPhrase}具體的話========================================\n{JsonConvert.SerializeObject(response)}"; } } catch(Exception ex) { SaveLog($"介面【{DateTime.Now +url}】請求錯誤,錯誤代碼{ex.Message}具體=============================================/n{ex.StackTrace}"); return ex.Message + ex.StackTrace; } } /// <summary> /// 微信請求 /// </summary> /// <param name="url">地址</param> /// <param name="requestString">引數</param> /// <param name="privateKey">私有秘鑰 p12檔案</param> /// <param name="merchantId">商戶號</param> /// <param name="serialNo">商戶證書號</param> /// <param name="method">Get或者Post</param> /// <returns></returns> public async Task<string> WeChatGetAsync(string url, string privateKey, string merchantId, string serialNo) { try { var client = _httpClientFactory.CreateClient(); var auth = BuildAuthAsync(url, "", privateKey, merchantId, serialNo,"GET"); string value = https://www.cnblogs.com/w5942066/p/$"WECHATPAY2-SHA256-RSA2048 {auth}"; client.DefaultRequestHeaders.Add("Authorization", value); client.DefaultRequestHeaders.Add("Accept", "*/*"); client.DefaultRequestHeaders.Add("User-Agent", "WOW64"); client.Timeout = TimeSpan.FromSeconds(60); var response = await client.GetAsync(url); if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsStringAsync(); return result; } else { return $"介面【{url}】請求錯誤,錯誤代碼{response.StatusCode},錯誤原因{response.ReasonPhrase}"; } } catch (Exception ex) { SaveLog($"介面【{DateTime.Now + url}】請求錯誤,錯誤代碼{ex.Message}具體=============================================/n{ex.StackTrace}"); return ex.Message+ ex.StackTrace; } } protected string BuildAuthAsync(string url,string jsonParame ,string privateKey, string merchantId,string serialNo,string method="") { string body = jsonParame; var uri = new Uri(url); var urlPath = uri.PathAndQuery; var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); string nonce = Path.GetRandomFileName(); string message = $"{method}\n{urlPath}\n{timestamp}\n{nonce}\n{body}\n"; //string signature = Sign(message, privateKey); var path = _webHostEnvironment.WebRootPath + "/arsjkll/apiclient_cert.p12"; string signature = Sign(message,path, "1601849569"); return $"mchid=\"{merchantId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{serialNo}\",signature=\"{signature}\""; } /// <summary> /// 簽名(CentOs 不支持 換了下面的) /// </summary> /// <param name="message">簽名內容</param> /// <param name="privateKey">秘鑰</param> /// <returns></returns> public string Sign(string message,string privateKey) { byte[] keyData =https://www.cnblogs.com/w5942066/p/ Convert.FromBase64String(privateKey); using CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob); using RSACng rsa = new RSACng(cngKey); byte[] data =https://www.cnblogs.com/w5942066/p/ System.Text.Encoding.UTF8.GetBytes(message); return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); } /// <summary> /// 獲取簽名證書私鑰 /// </summary> /// <param name="priKeyFile">證書檔案路徑</param> /// <param name="keyPwd">密碼</param> /// <returns></returns> private static RSA GetPrivateKey(string priKeyFile, string keyPwd) { var pc = new X509Certificate2(priKeyFile, keyPwd, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); return (RSA)pc.PrivateKey; } /// <summary> //// <summary> /// 根據證書簽名資料 后面要做成配置在資料庫中 /// </summary> /// <param name="data">要簽名的資料</param> /// <param name="certPah">證書路徑</param> /// <param name="certPwd">密碼</param> /// <returns></returns> public string Sign(string data, string certPah, string certPwd) { var rsa = GetPrivateKey(certPah, certPwd); var rsaClear = new RSACryptoServiceProvider(); var paras = rsa.ExportParameters(true); rsaClear.ImportParameters(paras); var signData =https://www.cnblogs.com/w5942066/p/ rsa.SignData(Encoding.UTF8.GetBytes(data), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signData); } #endregion } public class CustomerHttpException : Exception { public CustomerHttpException() : base() { } public CustomerHttpException(string message) : base(message) { } } public class ReturnData { /// <summary> /// 回傳碼 /// </summary> public int Code { get; set; } /// <summary> /// 訊息 /// </summary> public string Msg { get; set; } /// <summary> /// 是否成功 /// </summary> public bool IsSuccess { get; set; } /// <summary> /// 回傳資料 /// </summary> public object Data { get; set; } /// <summary> /// 成功默認 /// </summary> /// <param name="data"></param> /// <param name="msg"></param> public static ReturnData ToSuccess(object data, string msg = "sussess") { var result = new ReturnData { Code = (int)HttpStatusCode.OK, IsSuccess = true, Msg = msg, Data = data }; return result; } public static ReturnData ToFail(string msg) { var result = new ReturnData { Code = (int)HttpStatusCode.BadRequest, IsSuccess = false, Msg = msg }; return result; } /// <summary> /// 例外 /// </summary> /// <param name="msg"></param> /// <param name="data"></param> public static ReturnData ToError(Exception ex, object data = https://www.cnblogs.com/w5942066/p/null) { var result = new ReturnData { Code = (int)HttpStatusCode.InternalServerError, IsSuccess = false, Msg = "例外" + ex.Message, Data = data }; return result; } /// <summary> /// 未經授權 /// </summary> /// <param name="data"></param> public static ReturnData ToNoToken(object data = https://www.cnblogs.com/w5942066/p/null) { var result = new ReturnData { Code = (int)HttpStatusCode.Forbidden, IsSuccess = false, Msg = "未經授權不能訪問", Data = data }; return result; } public static ReturnData Instance(object data, string msg, int code) { var result = new ReturnData { Code = code, IsSuccess = false, Msg = msg, Data = data }; return result; } } }
Sign簽名官方給的只能在IIS上面運行 那是通過直接用私鑰簽名,我在CentOS上面不行

以前在IIS上面也是 但是這個只要配置IIS應用程式池,把加載用戶組態檔改成true就可以了,CentOS上面就不行了,后來我還是把p12檔案放在了跟驗證域名的那個位置,通過讀取檔案獲取私鑰,這個問題搞了我2天,,,不能跨平臺,或者是我配置不對,后面有時間在研究,
2)、獲取用戶的OpenId
在用戶統一下單的時候需要用戶的OpenId就是這個用戶在這個公眾號下面的一個身份號碼,關沒關注獲取了就不會變,所以我就是沒呼叫統一下單之前就獲取了保存在資料庫中,統一下單的時候直接呼叫就可以了 參考連接 公眾號網頁授權
private const string AuthorUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?"; private const string Oauth = "https://api.weixin.qq.com/sns/oauth2/access_token?"; private const string GetUserInfo = "https://api.weixin.qq.com/sns/userinfo?"; public string GetAuthorizeUrl(string appId, string redirectUrl, string state = "state", string scope = "snsapi_userinfo", string responseType = "code") { redirectUrl = HttpUtility.UrlEncode(redirectUrl, System.Text.Encoding.UTF8); object[] args = new object[] { appId, redirectUrl, responseType, scope, state }; return string.Format(AuthorUrl + "appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}#wechat_redirect", args); } private string GetOpenIdUrl(string appId, string secret, string code, string grantType = "authorization_code") { object[] args = new object[] { appId, secret, code, grantType }; string requestUri = string.Format(Oauth + "appid={0}&secret={1}&code={2}&grant_type={3}", args); return requestUri; } public GetOpenIdDto GetOpenid(string appId, string secret, string code, string grantType = "authorization_code") { string requestUri = GetOpenIdUrl(appId, secret, code, grantType); var responseStr = _httpClientFactoryHelper.GetAsync(requestUri, null, 120).Result; var obj = JsonConvert.DeserializeObject<GetOpenIdDto>(responseStr); var getUserInfoUrl = GetUserInfo + $"access_token={obj.Access_Token}&openid={obj.OpenId}&lang=zh_CN"; var responseUser = _httpClientFactoryHelper.GetAsync(getUserInfoUrl, null, 120).Result; SaveLog("OpenDetails", responseUser); var objUser = JsonConvert.DeserializeObject<GetOpenIdDto>(responseUser); return objUser; }
上面GetOpenId就是下面Api這里呼叫的
下面的介面地址就是/api/WeChatPay/SaveHospPatirntOpenId
/// <summary> /// 儲存用戶所在公眾號下面的OpenId /// </summary> /// <param name="hospCode">醫院|公眾號編碼</param> /// <param name="userId">用戶Id(登錄的那個)</param> /// <param name="code">微信服務器回傳的code不用填</param> /// <returns>跳轉的returnUrl</returns> [HttpGet] public IActionResult SaveHospPatirntOpenId(string hospCode, int userId, string code = "") { var modelOpenId = _weChatPayService.IsSaveHospPatientOpenId(hospCode, userId); var model = _weChatPayService.GetHospInfo(hospCode); var modelNew = _weChatPayService.GetHospNewInfo(hospCode); // var path = _configuration.GetValue<string>("ReturnUrl"); var returnUrl = $"http://打碼/#/subSite?hospCode={model.HospCode}&hospId={modelNew.Id}"; //var returnUrl = HttpUtility.UrlEncode(returnUrltarget, System.Text.Encoding.UTF8); if (modelOpenId != null) return Redirect(returnUrl); else { if (string.IsNullOrEmpty(code)) { var redirectUrl = _weChatPayService.GetAuthorizeUrl(model.WxAppid, $"http://打碼/WeChatPay/SaveHospPatirntOpenId?hospCode={hospCode}&userId={userId}"); return Redirect(redirectUrl); } else { //根據code和微信引數得到openid var openIdModel = _weChatPayService.GetOpenid(model.WxAppid, model.WxAppsecret, code); //業務處理保存到資料庫 var modelOId=_weChatPayService.HospPatirntOpenIdSaveAsync(hospCode, userId, openIdModel).Result; return Redirect(returnUrl); } } }
我這里的邏輯就是獲取過了直接資料庫獲取沒有獲取過的微信授權獲取,這里 如果用戶沒有授權實際上這個介面要訪問2次的 第一次code沒有值,第二次微信授權后通過redirect_uri帶著code回來就獲取到了用戶的OpenId資訊,
3)、統一下單
var path = RequestUrl.TRANSACTIONS;//https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi var timeOut = DateTime.Now.AddMinutes(10); var address = $"{model.Address}/api/WeChatPay/NotifySuccess";//這個是微信支付狀態回傳發到你的介面上的地址 var reqDto = new { appid = model.WxAppid, mchid = model.WxMchid, description = req.Desc, out_trade_no = troNo, //time_expire = timeOut, attach = regOrderModel.RegId.ToString(), notify_url = address, amount = new { total = req.Total, currency = "CNY" }, payer = new { openid = modelOpenId.OpenId } }; var reqJson = JsonConvert.SerializeObject(reqDto); var ret = _httpClientFactoryHelper.WeChatPostAsync(path, reqJson, model.PrivateKey, model.WxMchid, model.CardNo).Result; var result = JsonConvert.DeserializeObject<JsApiResult>(ret); if (!string.IsNullOrEmpty(result.Prepay_Id)) { //時間戳 DateTimeOffset dto = new DateTimeOffset(DateTime.Now); var unixTime = dto.ToUnixTimeSeconds().ToString(); //亂數 var nonMun = Guid.NewGuid().ToString("N").Substring(0, 30); var pck = "prepay_id=" + result.Prepay_Id; //簽名 string message = $"{model.WxAppid}\n{unixTime}\n{nonMun}\n{pck}\n"; var pathfile = _webHostEnvironment.WebRootPath + "/arsjkll/apiclient_cert.p12"; string keyRsa = _httpClientFactoryHelper.Sign(message, pathfile, "密碼咯"); //var keyRsa = _httpClientFactoryHelper.Sign(message, model.PrivateKey); //構建JSAPI拉取支付的引數 匿名引數 var requestParam = new { appId = model.WxAppid, timeStamp = unixTime, nonceStr = nonMun, package = pck, signType = "RSA", paySign = keyRsa }; return Result.ToSuccess(requestParam); } else { return Result.ToFail("prepay_id獲取失敗+++++++" + ret); }
上面統一下單獲取到prepay_id在構造JSAPI拉取微信支付的引數回傳到前端,簽名上面有代碼就不貼了,
4)、支付回呼介面
public Result NotifySuccess(NotifyDto ret) { SaveLog("NotifyParame", JsonConvert.SerializeObject(ret)); //ResourceASC if (ret.Event_type == "TRANSACTION.SUCCESS")//支付成功 { //解密資料報文 var dataJson = AesGcmHelper.AesGcmDecrypt(ret.Resource.Associated_data, ret.Resource.Nonce, ret.Resource.Ciphertext); //轉換物件接受 var data = https://www.cnblogs.com/w5942066/p/JsonConvert.DeserializeObject(dataJson); //獲取當前訂單記錄物體 //自己的業務邏輯 } else { SaveLog("NotifyFaile", JsonConvert.SerializeObject(ret)); } return Result.ToSuccess(""); }
/// <summary> /// 支付結果回呼接收引數 /// </summary> public class NotifyDto { /// <summary> /// 通知ID通知的唯一ID /// 示例值:EV-2018022511223320873 /// </summary> public string Id { get; set; } /// <summary> /// 通知創建時間 通知創建的時間,遵循rfc3339標準格式,格式為YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出現在字串中,表示time元素的開頭,HH:mm:ss.表示時分秒,TIMEZONE表示時區(+08:00表示東八區時間,領先UTC 8小時,即北京時間),例如:2015-05-20T13:29:35+08:00表示北京時間2015年05月20日13點29分35秒, /// 示例值:2015-05-20T13:29:35+08:00 /// </summary> public string Create_time { get; set; } /// <summary> /// 通知型別 通知的型別,支付成功通知的型別為TRANSACTION.SUCCESS /// 示例值:TRANSACTION.SUCCESS /// </summary> public string Event_type { get; set; } /// <summary> /// 通知資料型別 通知的資源資料型別,支付成功通知為encrypt-resource /// 示例值:encrypt-resource /// </summary> public string Resource_type { get; set; } /// <summary> /// 通知資料 通知資源資料 /// json格式,見示例 /// </summary> public Resource Resource { get; set; } /// <summary> /// 回呼摘要 /// 示例值:支付成功 /// </summary> public string Summary { get; set; } }
解密類
public class AesGcmHelper { private static string ALGORITHM = "AES/GCM/NoPadding"; private static int TAG_LENGTH_BIT = 128; private static int NONCE_LENGTH_BYTE = 12; private static string AES_KEY = "v3秘鑰"; public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext) { GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine()); AeadParameters aeadParameters = new AeadParameters( new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)), 128, Encoding.UTF8.GetBytes(nonce), Encoding.UTF8.GetBytes(associatedData)); gcmBlockCipher.Init(false, aeadParameters); byte[] data =https://www.cnblogs.com/w5942066/p/ Convert.FromBase64String(ciphertext); byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)]; int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0); gcmBlockCipher.DoFinal(plaintext, length); return Encoding.UTF8.GetString(plaintext); } }
支付回傳的我保存了日志分享出來看看

之前一直沒有調通,花了一天時間 找到了原因 統一下單的時候 里面不是謠傳一個引數 支付金錢 total 我攜程decmial型別了賦值 ,注意這里一定要int 單位是分數,支付提示 (系統繁忙、請稍后再試),一般這個錯誤就是引數不對,型別一定要跟官網對應起來
5)、Vue前端呼叫拉起支付
<template> <div> <van-nav-bar left-text="回傳" left-arrow @click-left="clickLeft" title="支付訂單" /> <div class="figure"> <div>支付金額</div> <div class="money"> ¥ <span>{{ total }}</span> </div> <div style="font-size: 14px"> 請在 <van-count-down :time="countDownTime" format="mm分ss秒" style="display: inline" @finish="countDownFinish" /> 內支付完成,超時后訂單自動取消 </div> </div> <van-radio-group v-model="radio"> <van-cell-group> <van-cell v-for="el in payType" @click="chkCheck(el)"> <template #right-icon> <svg class="icon" aria-hidden="true"> <use :xlink:href="el.icon"></use> </svg> <span style="width: 80px; margin-left: 15px">{{ el.title }}</span> <van-radio style="margin-left: 60%" :name="el.name" /> </template> </van-cell> </van-cell-group> </van-radio-group> <div style="margin: 16px"> <van-button round block type="info" native-type="submit" @click="onSubmit" :disabled="!btnIsable" > {{ btnText }} </van-button> </div> </div> </template> <script> export default { data() { return { // cardNo: '', // desc: '', // hospCode: '', // pointId: '',//號點Id total: '',//支付費用 countDownTime: 5 * 60 * 1000,//支付剩余毫秒數 radio: '1', appId: '', timeStamp: '', nonceStr: '', package: '', signType: '', paySign: '', btnText: '立即支付', btnIsable: true,//支付按鈕是否可用,true:可用 false:不可用 payType: [{ icon: '#icon-weixinzhifu', title: '微信支付', name: '1', }], } }, methods: { onSubmit() { let vm = this; let obj = { "appId": vm.appId,//公眾號名稱 "timeStamp": vm.timeStamp,//時間戳,自1970年以來的秒數 "nonceStr": vm.nonceStr,//隨機串 "package": vm.package, "signType": vm.signType, "paySign": vm.paySign //簽名 }; function onBridgeReady() { WeixinJSBridge.invoke('getBrandWCPayRequest', obj, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { // 使用以上方式判斷前端回傳,微信團隊鄭重提示: //res.err_msg將在用戶支付成功后回傳ok,但并不保證它絕對可靠, vm.btnIsable = false; vm.closePage('支付成功');//后期跳轉到掛號記錄頁面 } }); } if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { onBridgeReady(); } }, chkCheck: (el) => { return el.name; }, countDownFinish() { //倒計時結束銷號,不提交支付 this.btnIsable = false; this.closePage('支付超時'); }, clickLeft() { this.$dialog.confirm({ title: '提示', message: '支付尚未完成,是否繼續支付', }) .then(() => { // on confirm }) .catch(() => { this.$router.go(-1); }); }, getBaseData() { // 獲得支付資訊 let vm = this; let p = vm.$route.params; if (JSON.stringify(p) != "{}") { this.appId = p.appId; this.total = p.fee; this.nonceStr = p.nonceStr; this.package = p.package; this.paySign = p.paySign; this.countDownTime = p.paymentDeadline - vm.$moment().valueOf(); this.signType = p.signType; this.timeStamp = p.timeStamp; } else { this.closePage('無效請求'); } }, closePage(text, num = 5, route = 'home') { this.btnIsable = false; let lock = setInterval(() => { num--; this.btnText = `${text},${num}秒后關閉`; if (num == 0) { clearInterval(lock); this.$router.push({ path: route }); } }, 1000); }, }, mounted() { this.getBaseData(); } } </script> <style> .figure { background: #fff; text-align: center; margin: 10px auto; padding: 10px 0; color: gray; } .money { color: orange; font-size: 16px; margin: 15px auto; } .money span { font-size: 36px; } </style>
5、總結
紙上得來終覺淺,看著微信官網的,v3支付只有 爪哇 跟 派森 的sdk ,NET的還是自己來,里面的各種術語花里花哨的感覺 哈哈,可能是現在的我心里太多的浮躁了,還是要慢慢靜下心來看,本文出處魏楊楊博客園
原文鏈接我自己貼上https://www.cnblogs.com/w5942066/p/14313946.html
做個內心陽光的人,不憂傷,不心急,堅強、向上,靠近陽光,成為更好的自己,你不需要別人過多的稱贊,因為你自己知道自己有多好,內心的強大,永遠勝過外表的浮華,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/251288.html
標籤:.NET Core
