怎麼串接綠界金流?以 Angular & .NET 實作
文章目錄
如何串接綠界金流?以 Angular 、 .NET 實作網站結帳付款功能。
綠界金流串接流程
- 使用者按下結帳按鈕。
- Angular將使用者結帳商品資訊傳送至.NET。
- .Net以結帳商品資訊產生請求綠界付款頁面所需的參數回傳給Angular。
- Angular接收參數後,向綠界發送請求,以產生綠界付款訂單。
- 綠界顯示付款頁面給使用者。
- 使用者付款完成。
- 綠界發送付款結果通知給.NET。
- .NET接收通知,更新資料庫,導回指定頁面。
一、準備綠界商店串接資料
在 appsettings.json 中配置綠界商店資訊。
"ECPay": {
"MerchantID": "3002607",
"HashKey": "pwFHCqoQZGmho4w6",
"HashIV": "EkRm7iFT261dpevs"
}
依賴注入綠界商店資訊。
private readonly string _baseUrl;
private readonly string _hashKey;
private readonly string _hashIV;
private readonly string _merchantId;
private readonly ICartService _cartService;
public ECPayService(IConfiguration config)
{
_baseUrl = config["urls"] ?? throw new Exception("urls is null.");
_hashKey = config["ECPay:HashKey"] ?? throw new Exception("ECPay:HashKey is null.");
_hashIV = config["ECPay:HashIV"] ?? throw new Exception("ECPay:HashIV is null.");
_merchantId = config["ECPay:MerchantID"] ?? throw new Exception("ECPay:MerchantID is null.");
}
二、建立綠界檢查碼機制
private string GetCheckMacValue(Dictionary<string, string?> dix)
{
var param = dix.Keys.OrderBy(x => x)
.Where(key => dix[key] != null)
.Select(key => key + "=" + dix[key]).ToList();
var checkValue = string.Join("&", param);
checkValue = $"HashKey={_hashKey}&{checkValue}&HashIV={_hashIV}";
checkValue = HttpUtility.UrlEncode(checkValue).ToLower();
checkValue = GetSHA256(checkValue);
return checkValue.ToUpper();
}
private static string GetSHA256(string value)
{
var result = new StringBuilder();
using SHA256 sha256 = SHA256.Create();
byte[] inputBytes = Encoding.UTF8.GetBytes(value);
byte[] hashBytes = sha256.ComputeHash(inputBytes);
for (int i = 0; i < hashBytes.Length; i++)
{
result.Append(hashBytes[i].ToString("X2"));
}
return result.ToString();
}
三、產生綠界付款頁面所需參數
將購物車產品資訊傳送到後端,以後端產生付款頁面所需參數。
public Dictionary<string, string> GetTradeOrder(ECPayTradeData data)
{
var order = new Dictionary<string, string>
{
{ "MerchantID", _merchantId },
{ "MerchantTradeNo", data.MerchantTradeNo },
{ "MerchantTradeDate", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") },
{ "PaymentType", "aio" },
{ "TotalAmount", $"{data.TotalAmount}" },
{ "TradeDesc", data.TradeDesc },
{ "ItemName", data.ItemName },
{ "ReturnURL", $"{_baseUrl}/api/ECPay" },
{ "OrderResultURL", $"{_baseUrl}/api/ECPay/Redirect" },
{ "ChoosePayment", "ALL" },
{ "IgnorePayment", "TWQR#CVS#BARCODE#ApplePay#BNPL" },
{ "EncryptType", "1" },
{ "CustomField1", data.CartProductIds }
};
order["CheckMacValue"] = GetCheckMacValue(order!);
return order;
}
ChoosePayment
:指定付款方式。綠界提供的付款方式:
- Credit:信用卡及銀聯卡(需申請開通)
- TWQR :歐付寶TWQR行動支付(需申請開通)
- WebATM:網路ATM
- ATM:自動櫃員機
- CVS:超商代碼
- BARCODE:超商條碼
- ApplePay: Apple Pay(僅支援手機支付)
- BNPL:裕富無卡分期(需申請開通)
- ALL:不指定付款方式,由綠界顯示付款方式選擇頁面。
IgnorePayment
:隱藏不需要的付款方式(以#
分隔)。- 指定2個以上的付款方式,需將
ChoosePayment
設定為ALL
,再以IgnorePayment
隱藏不需要的付款方式。
- 指定2個以上的付款方式,需將
MerchantTradeNo
:自定義不可重複的訂單編號。ReturnURL
:指定POST端點接收綠界回傳的付款結果通知。- 不支援中文網址。
- 避免指定port。
- 須對外開放。可參考建立對外臨時網址。
OrderResultURL
:指定POST端點以導向特定前端畫面。
四、產生綠界付款頁面
前端接收來自後端產生的綠界付款頁面參數,以 form 表單 post 方法發送請求至綠界,以產生綠界付款頁面。
<form #payForm method="post" action="https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5">
@for (item of data | keyvalue; let last = $last; track $index) {
<input type="hidden" [name]="formatKey(item.key)" [value]="item.value">
@if (last) {
{{ payForm.submit() }}
}
}
</form>
@Component({
selector: 'pay',
standalone: true,
imports: [KeyValuePipe],
templateUrl: './pay.component.html',
styleUrl: './pay.component.css'
})
export class PayComponent {
@Input() data?: {};
formatKey(str: string): string {
if (str.length > 0) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
return str;
}
}
五、接收付款通知
綠界會將付款結果以POST方式回傳到ReturnURL
。
建立後端端點,以接收付款通知。驗證檢查碼正確,確認訂單付款完成,才新增訂單。
[HttpPost]
public async Task<string> OnPayResult([FromForm] IFormCollection result)
{
try
{
// 驗證檢查碼
var data = _service.HandlePayResult(result);
var order = new Order()
{
MerchantTradeNo = data["MerchantTradeNo"]!,
TradeNo = data["TradeNo"]!,
TradeAmt = int.Parse(data["TradeAmt"]!),
TradeStatus = data["RtnCode"]!,
PaymentDate = data["PaymentDate"]!,
PaymentType = data["PaymentType"]!
};
// 付款完成才將訂單寫入資料庫
if(order.TradeStatus == "1")
{
var cartProductIds = data["CustomField1"]!.Split(",").ToList();
await _orderService.CreateOrderAsync(order, cartProductIds);
}
}
catch (Exception ex)
{
Log.Error(ex.Message);
}
return "1|OK";
}
六、付款完成自動導回指定前端畫面
綠界會將付款結果以POST方式回傳到OrderResultURL
。
建立後端端點接收付款結果,以Redirect導向至特定URL。
[HttpPost("Redirect")]
public IActionResult OrderResultURL([FromForm] IFormCollection result)
{
try
{
return Redirect($"http://localhost:4200/order/{result["MerchantTradeNo"]}");
}
catch(Exception ex)
{
Log.Error(ex.Message);
return Redirect($"http://localhost:4200/cart");
}
}
七、測試金流
綠界一般信用卡
- 測試卡號 : 4311-9522-2222-2222
- 安全碼 : 222
進入綠界測試用的特店管理後台以「模擬付款」按鈕測試付款通知。
- 特店後台登入帳號:stagetest3
- 特店後台登入密碼:test1234
- 特店統一編號:00000000
附錄、建立對外臨時網址
註冊並登入ngrok,取得
authtoken
。執行
ngrok.exe
連結帳戶。
配置 ngrok ,設定
TOKEN
以連結帳戶。ngrok config add-authtoken <TOKEN>
在
%HOMEPATH%\AppData\Local\ngrok\ngrok.yml
檔案中可見以下配置。version: "2" authtoken: <TOKEN>
對外開放內部網址。
對外開放後端,輸入
port
以建立對外臨時網址。ngrok http <port>