【轉】ASP.NET Core 2.0 使用支付寶PC網站支付

ASP.NET Core 2.0 使用支付寶PC網站支付

【轉載】原文地址:https://www.cnblogs.com/stulzq/p/7606164.html

前言

最近在使用ASP.NET Core來進行開發,剛好有個接入支付寶支付的需求,百度了一下沒找到相關的資料,看了官方的SDK以及Demo都還是.NET Framework的,所以就先根據官方SDK的源碼,用.NET Standard 2.0 實現了支付寶服務端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET CORE 2.0。爲了使用方便,已上傳至Nuget可以直接使用。

支付寶有比較多的支付產品,比如當面付、APP支付、手機網站支付、電腦網站支付等,本次講的是電腦網站支付。

如果你沒有時間閱讀文章,可以直接從github獲取Demo原來進行查看,非常簡單。github: https://github.com/stulzq/Alipay.Demo.PCPayment

創建項目

新建一個ASP.NET Core 2.0 MVC項目

配置

由於我在開發的時候支付接口並沒有申請下來,所以使用的是支付寶沙箱環境來進行開發的。

支付寶沙箱環境介紹:螞蟻沙箱環境(Beta)是協助開發者進行接口功能開發及主要功能聯調的輔助環境。沙箱環境模擬了開放平臺部分產品的主要功能和主要邏輯,在開發者應用上線審覈前,開發者可以根據自身需求,先在沙箱環境中瞭解、組合和調試各種開放接口,進行開發調通工作,從而幫助開發者在應用上線審覈完成後,能更快速、更順利的進行線上調試和驗收工作。
如果在簽約或創建應用前想要進行集成測試,可以使用沙箱環境。
沙箱環境支持使用個人賬號或企業賬號登陸。

沙箱環境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info

1.生成密鑰

這裏所使用的RSA密鑰標準爲PKCS1,需要特別注意。

可以下載我寫的密鑰生成器:https://github.com/dotnetcore/Alipay.AopSdk.Core/tree/dev/tool

運行可以直接生成長度爲2048標準爲PKCS1的公鑰和私鑰。

或者使用下載支付寶官方提供的密鑰生成工具來進行生,詳細介紹:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1

2.設置應用公鑰

我們生成密鑰之後,需要到支付寶後臺設置應用公鑰,就是我們生成的公鑰。

設置之後,支付寶會給我們一個支付寶公鑰,保存這個支付寶公鑰

這個支付寶公鑰和我們自己生成的公鑰是不一樣的,我們在配置SDK時用的公鑰就是支付寶公鑰

3.配置SDK

新建一個Config類,在裏面存儲我們的配置。

public class Config
{
	// 應用ID,您的APPID
	public static string AppId = "";

	// 支付寶網關
	public static string Gatewayurl = "";

	// 商戶私鑰,您的原始格式RSA私鑰
	public static string PrivateKey = "";

	// 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
	public static string AlipayPublicKey = "";

	// 簽名方式
	public static string SignType = "RSA2";

	// 編碼格式
	public static string CharSet = "UTF-8";
}
  • 應用ID和支付寶網關都可以在支付寶後臺查看。

  • 商戶私鑰即我們自己生成的私鑰,公鑰就是支付寶公鑰這裏一定要注意,別用錯了。這裏的公鑰私鑰直接填寫字符串即可。

  • 簽名方式推薦使用RSA2,使用RSA2,支付寶會用SHA256withRsa算法進行接口調用時的驗籤(不限制密鑰長度)。

  • 編碼格式,如果我們是直接配置的字符串(公鑰、私鑰),那麼就是我們代碼的編碼,如果使用的是文件(公鑰、私鑰),那麼就是文件的編碼。

  • 完成配置如下:

添加SDK

官方SDK的源碼(.NET Framework),用.NET Standard 2.0 實現的支付寶服務端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET Core 2.0。
通過Nuget安裝:Install-Package Alipay.AopSdk.Core

支付

添加一個控制器 PayController

/// 發起支付請求
/// </summary>
/// <param name="tradeno">外部訂單號,商戶網站訂單系統中唯一的訂單號</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);

	// 組裝業務參數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();
	// 設置同步回調地址
	request.SetReturnUrl("http://localhost:5000/Pay/Callback");
	// 設置異步通知接收地址
	request.SetNotifyUrl("");
	// 將業務model載入到request
	request.SetBizModel(model);

	var response = client.SdkExecute(request);
	Console.WriteLine($"訂單支付發起成功,訂單號:{tradeno}");
	//跳轉支付寶支付
	Response.Redirect(Config.Gatewayurl + "?" + response.Body);
}

運行:

  • 圖1

  • 圖2

  • 圖3

支付異步回調通知

支付寶同步回調通知(支付成功後跳轉到商戶網站),是不可靠的,所以這裏必須使用異步通知來獲取支付結果,異步通知即支付寶主動請求我們提供的地址,我們根據請求數據來校驗,獲取支付結果。

/// <summary>
/// 支付異步回調通知 需配置域名 因爲是支付寶主動post請求這個action 所以要通過域名訪問或者公網ip
/// </summary>
public async void Notify()
{
	/* 實際驗證過程建議商戶添加以下校驗。
	1、商戶需要驗證該通知數據中的out_trade_no是否爲商戶系統中創建的訂單號,
	2、判斷total_amount是否確實爲該訂單的實際金額(即商戶訂單創建時的金額),
	3、校驗通知中的seller_id(或者seller_email) 是否爲out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)
	4、驗證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)
		{
			//交易狀態
			//判斷該筆訂單是否在商戶網站中已經做過處理
			//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
			//請務必判斷請求時的total_amount與通知時獲取的total_fee爲一致的
			//如果有做過處理,不執行商戶的業務程序

			//注意:
			//退款日期超過可退款期限後(如三個月可退款),支付寶系統發送該交易狀態通知
			Console.WriteLine(Request.Form["trade_status"]);

			await Response.WriteAsync("success");
		}
		else
		{
			await Response.WriteAsync("fail");
		}
	}
}

同步回調

同步回調即支付成功跳轉回商戶網站

運行:

/// <summary>
/// 支付同步回調
/// </summary>
[HttpGet]
public  IActionResult Callback()
{
	/* 實際驗證過程建議商戶添加以下校驗。
	1、商戶需要驗證該通知數據中的out_trade_no是否爲商戶系統中創建的訂單號,
	2、判斷total_amount是否確實爲該訂單的實際金額(即商戶訂單創建時的金額),
	3、校驗通知中的seller_id(或者seller_email) 是否爲out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)
	4、驗證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($"同步驗證通過,訂單號:{sArray["out_trade_no"]}");
			ViewData["PayResult"] = "同步驗證通過";
		}
		else
		{
			Console.WriteLine($"同步驗證失敗,訂單號:{sArray["out_trade_no"]}");
			ViewData["PayResult"] = "同步驗證失敗";
		}
	}
	return View();
}

訂單查詢

查詢訂單當前狀態:已付款、未付款等等。

運行:

[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);
}

訂單退款

退回該訂單金額。

運行:

/// <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);
}

退款查詢

查詢退款信息。

運行:

/// <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);
}

訂單關閉

對一定時間以後沒有進行付款的訂單進行關閉,訂單狀態需爲:待付款,已完成支付的訂單無法關閉。

運行:

/// <summary>
/// 關閉訂單
/// </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);
}

地址集合

最重要的:

本文Demo:https://github.com/stulzq/Alipay.Demo.PCPayment

 

原文作者:曉晨Master(李志強)

聲明:原創博客請在轉載時保留原文鏈接(https://www.cnblogs.com/stulzq/p/7606164.html)或者在文章開頭加上原文博客地址(https://www.cnblogs.com/stulzq/),凡是轉載文章,不能設置打賞功能,如有特殊需求請與原文作者聯繫!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章