ASP.NET Core 2.0 使用支付寶PC網(wǎng)站支付實(shí)現(xiàn)代碼
前言
最近在使用ASP.NET Core來進(jìn)行開發(fā),剛好有個接入支付寶支付的需求,百度了一下沒找到相關(guān)的資料,看了官方的SDK以及Demo都還是.NET Framework的,所以就先根據(jù)官方SDK的源碼,用.NET Standard 2.0 實(shí)現(xiàn)了支付寶服務(wù)端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET CORE 2.0。為了使用方便,已上傳至Nuget可以直接使用。
支付寶有比較多的支付產(chǎn)品,比如當(dāng)面付、APP支付、手機(jī)網(wǎng)站支付、電腦網(wǎng)站支付等,本次講的是電腦網(wǎng)站支付。
如果你沒有時間閱讀文章,可以直接從github獲取Demo原來進(jìn)行查看,非常簡單。github: https://github.com/stulzq/Alipay.Demo.PCPayment
創(chuàng)建項(xiàng)目
新建一個ASP.NET Core 2.0 MVC項(xiàng)目
配置
由于我在開發(fā)的時候支付接口并沒有申請下來,所以使用的是支付寶沙箱環(huán)境來進(jìn)行開發(fā)的。
支付寶沙箱環(huán)境介紹:螞蟻沙箱環(huán)境(Beta)是協(xié)助開發(fā)者進(jìn)行接口功能開發(fā)及主要功能聯(lián)調(diào)的輔助環(huán)境。沙箱環(huán)境模擬了開放平臺部分產(chǎn)品的主要功能和主要邏輯,在開發(fā)者應(yīng)用上線審核前,開發(fā)者可以根據(jù)自身需求,先在沙箱環(huán)境中了解、組合和調(diào)試各種開放接口,進(jìn)行開發(fā)調(diào)通工作,從而幫助開發(fā)者在應(yīng)用上線審核完成后,能更快速、更順利的進(jìn)行線上調(diào)試和驗(yàn)收工作。
如果在簽約或創(chuàng)建應(yīng)用前想要進(jìn)行集成測試,可以使用沙箱環(huán)境。
沙箱環(huán)境支持使用個人賬號或企業(yè)賬號登陸。
沙箱環(huán)境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
1.生成密鑰
下載支付寶官方提供的密鑰生成工具來進(jìn)行生成,詳細(xì)介紹:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1
2.設(shè)置應(yīng)用公鑰
我們生成密鑰之后,需要到支付寶后臺設(shè)置應(yīng)用公鑰,就是我們生成的公鑰。
設(shè)置之后,支付寶會給我們一個支付寶公鑰,保存這個支付寶公鑰
這個支付寶公鑰和我們自己生成的公鑰是不一樣的,我們在配置SDK時用的公鑰就是支付寶公鑰
3.配置SDK
新建一個Config
類,在里面存儲我們的配置。
public class Config{ // 應(yīng)用ID,您的APPID public static string AppId = ""; // 支付寶網(wǎng)關(guān) public static string Gatewayurl = ""; // 商戶私鑰,您的原始格式RSA私鑰 public static string PrivateKey = ""; // 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應(yīng)APPID下的支付寶公鑰。 public static string AlipayPublicKey = ""; // 簽名方式 public static string SignType = "RSA2"; // 編碼格式 public static string CharSet = "UTF-8";}
應(yīng)用ID和支付寶網(wǎng)關(guān)都可以在支付寶后臺查看。
商戶私鑰即我們自己生成的私鑰,公鑰就是支付寶公鑰這里一定要注意,別用錯了。這里的公鑰私鑰直接填寫字符串即可。
簽名方式推薦使用RSA2
,使用RSA2,支付寶會用SHA256withRsa算法進(jìn)行接口調(diào)用時的驗(yàn)簽(不限制密鑰長度)。
編碼格式,如果我們是直接配置的字符串(公鑰、私鑰),那么就是我們代碼的編碼,如果使用的是文件(公鑰、私鑰),那么就是文件的編碼。
完成配置如下:
添加SDK
官方SDK的源碼(.NET Framework),用.NET Standard 2.0 實(shí)現(xiàn)的支付寶服務(wù)端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET Core 2.0。
通過Nuget安裝:Install-Package Alipay.AopSdk.Core
支付
添加一個控制器 PayController
/// 發(fā)起支付請求/// </summary>/// <param name="tradeno">外部訂單號,商戶網(wǎng)站訂單系統(tǒng)中唯一的訂單號</param>/// <param name="subject">訂單名稱</param>/// <param name="totalAmout">付款金額</param>/// <param name="itemBody">商品描述</param>/// <returns></returns>[HttpPost] public void PayRequest(string tradeno,string subject,string totalAmout,string itemBody){ DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0", Config.SignType, Config.AlipayPublicKey, Config.CharSet, false); // 組裝業(yè)務(wù)參數(shù)model AlipayTradePagePayModel model = new AlipayTradePagePayModel(); model.Body = itemBody; model.Subject = subject; model.TotalAmount = totalAmout; model.OutTradeNo = tradeno; model.ProductCode = "FAST_INSTANT_TRADE_PAY"; AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 設(shè)置同步回調(diào)地址 request.SetReturnUrl("http://localhost:5000/Pay/Callback"); // 設(shè)置異步通知接收地址 request.SetNotifyUrl(""); // 將業(yè)務(wù)model載入到request request.SetBizModel(model); var response = client.SdkExecute(request); Console.WriteLine($"訂單支付發(fā)起成功,訂單號:{tradeno}"); //跳轉(zhuǎn)支付寶支付 Response.Redirect(Config.Gatewayurl + "?" + response.Body);}
運(yùn)行:
圖1
圖2
圖3
支付異步回調(diào)通知
支付寶同步回調(diào)通知(支付成功后跳轉(zhuǎn)到商戶網(wǎng)站),是不可靠的,所以這里必須使用異步通知來獲取支付結(jié)果,異步通知即支付寶主動請求我們提供的地址,我們根據(jù)請求數(shù)據(jù)來校驗(yàn),獲取支付結(jié)果。
/// <summary>/// 支付異步回調(diào)通知 需配置域名 因?yàn)槭侵Ц秾氈鲃觩ost請求這個action 所以要通過域名訪問或者公網(wǎng)ip/// </summary>public async void Notify(){ /* 實(shí)際驗(yàn)證過程建議商戶添加以下校驗(yàn)。 1、商戶需要驗(yàn)證該通知數(shù)據(jù)中的out_trade_no是否為商戶系統(tǒng)中創(chuàng)建的訂單號, 2、判斷total_amount是否確實(shí)為該訂單的實(shí)際金額(即商戶訂單創(chuàng)建時的金額), 3、校驗(yàn)通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據(jù)的對應(yīng)的操作方(有的時候,一個商戶可能有多個seller_id/seller_email) 4、驗(yàn)證app_id是否為該商戶本身。 */ Dictionary<string, string> sArray = GetRequestPost(); if (sArray.Count != 0) { bool flag = AlipaySignature.RSACheckV1(sArray, Config.AlipayPublicKey,Config.CharSet, Config.SignType, false); if (flag) { //交易狀態(tài) //判斷該筆訂單是否在商戶網(wǎng)站中已經(jīng)做過處理 //如果沒有做過處理,根據(jù)訂單號(out_trade_no)在商戶網(wǎng)站的訂單系統(tǒng)中查到該筆訂單的詳細(xì),并執(zhí)行商戶的業(yè)務(wù)程序 //請務(wù)必判斷請求時的total_amount與通知時獲取的total_fee為一致的 //如果有做過處理,不執(zhí)行商戶的業(yè)務(wù)程序 //注意: //退款日期超過可退款期限后(如三個月可退款),支付寶系統(tǒng)發(fā)送該交易狀態(tài)通知 Console.WriteLine(Request.Form["trade_status"]); await Response.WriteAsync("success"); } else { await Response.WriteAsync("fail"); } }}
同步回調(diào)
同步回調(diào)即支付成功跳轉(zhuǎn)回商戶網(wǎng)站
運(yùn)行:
/// <summary>/// 支付同步回調(diào)/// </summary>[HttpGet]public IActionResult Callback(){ /* 實(shí)際驗(yàn)證過程建議商戶添加以下校驗(yàn)。 1、商戶需要驗(yàn)證該通知數(shù)據(jù)中的out_trade_no是否為商戶系統(tǒng)中創(chuàng)建的訂單號, 2、判斷total_amount是否確實(shí)為該訂單的實(shí)際金額(即商戶訂單創(chuàng)建時的金額), 3、校驗(yàn)通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據(jù)的對應(yīng)的操作方(有的時候,一個商戶可能有多個seller_id/seller_email) 4、驗(yàn)證app_id是否為該商戶本身。 */ Dictionary<string, string> sArray = GetRequestGet(); if (sArray.Count != 0) { bool flag = AlipaySignature.RSACheckV1(sArray, Config.AlipayPublicKey, Config.CharSet, Config.SignType, false); if (flag) { Console.WriteLine($"同步驗(yàn)證通過,訂單號:{sArray["out_trade_no"]}"); ViewData["PayResult"] = "同步驗(yàn)證通過"; } else { Console.WriteLine($"同步驗(yàn)證失敗,訂單號:{sArray["out_trade_no"]}"); ViewData["PayResult"] = "同步驗(yàn)證失敗"; } } return View(); }
訂單查詢
查詢訂單當(dāng)前狀態(tài):已付款、未付款等等。
運(yùn)行:
訂單退款
[HttpPost]public JsonResult Query(string tradeno, string alipayTradeNo){ DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0", Config.SignType, Config.AlipayPublicKey, Config.CharSet, false); AlipayTradeQueryModel model = new AlipayTradeQueryModel(); model.OutTradeNo = tradeno; model.TradeNo = alipayTradeNo; AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); request.SetBizModel(model); var response = client.Execute(request); return Json(response.Body);}
退回該訂單金額。
運(yùn)行:
/// <summary> /// 訂單退款 /// </summary>/// <param name="tradeno">商戶訂單號</param>/// <param name="alipayTradeNo">支付寶交易號</param>/// <param name="refundAmount">退款金額</param>/// <param name="refundReason">退款原因</param>/// <param name="refundNo">退款單號</param>/// <returns></returns>[HttpPost]public JsonResult Refund(string tradeno,string alipayTradeNo,string refundAmount,string refundReason,string refundNo){ DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0", Config.SignType, Config.AlipayPublicKey, Config.CharSet, false); AlipayTradeRefundModel model = new AlipayTradeRefundModel(); model.OutTradeNo = tradeno; model.TradeNo = alipayTradeNo; model.RefundAmount = refundAmount; model.RefundReason = refundReason; model.OutRequestNo = refundNo; AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); request.SetBizModel(model); var response = client.Execute(request); return Json(response.Body);}
退款查詢
查詢退款信息。
運(yùn)行:
/// <summary> /// 退款查詢 /// </summary> /// <param name="tradeno">商戶訂單號</param> /// <param name="alipayTradeNo">支付寶交易號</param> /// <param name="refundNo">退款單號</param> /// <returns></returns> [HttpPost] public JsonResult RefundQuery(string tradeno,string alipayTradeNo,string refundNo) { DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0", Config.SignType, Config.AlipayPublicKey, Config.CharSet, false); if (string.IsNullOrEmpty(refundNo)) { refundNo = tradeno; } AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel(); model.OutTradeNo = tradeno; model.TradeNo = alipayTradeNo; model.OutRequestNo = refundNo; AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest(); request.SetBizModel(model); var response = client.Execute(request); return Json(response.Body); }
訂單關(guān)閉
對一定時間以后沒有進(jìn)行付款的訂單進(jìn)行關(guān)閉,訂單狀態(tài)需為:待付款,已完成支付的訂單無法關(guān)閉。
運(yùn)行:
/// <summary> /// 關(guān)閉訂單 /// </summary> /// <param name="tradeno">商戶訂單號</param> /// <param name="alipayTradeNo">支付寶交易號</param> /// <returns></returns> [HttpPost] public JsonResult OrderClose(string tradeno, string alipayTradeNo) { DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0", Config.SignType, Config.AlipayPublicKey, Config.CharSet, false); AlipayTradeCloseModel model = new AlipayTradeCloseModel(); model.OutTradeNo = tradeno; model.TradeNo = alipayTradeNo; AlipayTradeCloseRequest request = new AlipayTradeCloseRequest(); request.SetBizModel(model); var response = client.Execute(request); return Json(response.Body); }
地址集合支付寶API文檔支付寶沙箱環(huán)境支付寶密鑰生成工具支付寶服務(wù)端SDK源碼支付寶服務(wù)端SDK Nuget
最重要的:
本文Demo:https://github.com/stulzq/Alipay.Demo.PCPayment
- .Net Core3 用Windows 桌面應(yīng)用開發(fā)Asp.Net Core網(wǎng)站
- 如何利用IIS調(diào)試ASP.NET網(wǎng)站程序詳解
- 利用IIS調(diào)試ASP.NET網(wǎng)站程序的完整步驟
- asp.net core下給網(wǎng)站做安全設(shè)置的方法詳解
- IIS部署asp.net mvc網(wǎng)站的方法
- CodeFirst從零開始搭建Asp.Net Core2.0網(wǎng)站
- 詳解ASP.NET Core 網(wǎng)站在Docker中運(yùn)行
- ASP.NET網(wǎng)站第一次訪問慢的解決方法
- 如何使用ASP.NET創(chuàng)建網(wǎng)站并設(shè)計web頁面
相關(guān)文章
ASP.NET之Excel下載模板、導(dǎo)入、導(dǎo)出操作
這篇文章主要介紹了ASP.NET之Excel下載模板、導(dǎo)入、導(dǎo)出操作的相關(guān)資料,需要的朋友可以參考下2016-07-07得到真實(shí)外網(wǎng)IP、IP所在國家、省份、地區(qū)(小偷程序)
通過正則抓取IP顯示網(wǎng)站中的數(shù)據(jù),并篩選出所需要的內(nèi)容即可。2011-11-11.NET中 關(guān)于臟讀 不可重復(fù)讀與幻讀的代碼示例
本篇文章小編將為大家介紹,.NET中 關(guān)于臟讀 不可重復(fù)讀與幻讀的代碼示例,有需要的朋友可以參考一下2013-04-04C# javaScript函數(shù)的相互調(diào)用
如何在JavaScript訪問C#函數(shù),如何在C#中訪問JavaScript的已有變量等實(shí)現(xiàn)方法2008-12-12ASP.NET?Core?實(shí)現(xiàn)自動刷新JWT?Token
這篇文章主要介紹了ASP.NET?Core?實(shí)現(xiàn)自動刷新JWT?Token,通過增加??refresh_token??,客戶端使用refresh_token去主動刷新JWT?Token,下文具體操作過程需要的小伙伴可以參考一下2022-04-04.NET 下運(yùn)用策略模式(組合行為和實(shí)體的一種模式)
我簡單的理解策略模式就是把行為(方法)單獨(dú)的抽象出來,并采用組合(Has-a)的方式,來組合行為和實(shí)體的一種模式比如,.NET中對數(shù)組排序的Sort的方法就是一個策略模式的實(shí)現(xiàn)模板2012-12-12Asp.Mvc?2.0實(shí)現(xiàn)用戶注冊實(shí)例講解(1)
這篇文章主要介紹了Asp.Mvc?2.0如何實(shí)現(xiàn)用戶注冊,實(shí)例講解很細(xì)致,注冊功能是每個網(wǎng)站必不可少的組成部分,感興趣的的朋友可以參考下2015-08-08ASP.NET沒有魔法_ASP.NET MVC 模型驗(yàn)證方法
下面小編就為大家分享一篇ASP.NET沒有魔法_ASP.NET MVC 模型驗(yàn)證方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02