[C#] 綠界站內付2.0 - 參數加密與解密

一般串接金流時,如果要傳遞資料都需要將資料進行加解密,而最近因案子需求有接觸到綠界站內付 2.0,所以在此紀錄如何用 C# 編寫綠界站內付 2.0 加解密的程式。

綠界站內付 2.0

「站內付 2.0」是綠界在今年(2021)年初推出的全新廠商付款串接規格,付款頁面改用嵌入式以減少跳轉畫面(如下圖),提供流暢的交易體驗,詳情可看綠界的官網服務介紹

站內付2.0 示意圖

資料如何加解密?

站內付 2.0 的介接方式可以去官網的「串接規格下載」,下載相關的技術文件。根據文件上的說明(如下圖)可知道須透過 JSON 格式編碼、URL 編碼及 AES 加密演算法,這 3 個階段來進行參數加解密。

站內付2.0 參數加密方式

以下將先個別介紹 3 個階段該如何處理,而於最後整合在一起。

AES 加密演算法

AES(Advanced Encryption Standard)又稱 Rijndael 加密法,是對稱金鑰加密中流行的演算法之一。

AesCryptoServiceProvider

針對 AES 加密演算法可透過 AesCryptoServiceProvider 類別來處理,這是微軟提供有關於 AES 的實作類別,用於執行對稱加密和解密。

加解密程式範例

跟據綠界所需的 AES 設定,建立一個用於處理 AES 加解密的類別,程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class AESEncryption
{
/// <summary>
/// 加密
/// </summary>
/// <param name="text">資料字串</param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns>加密字串</returns>
public static string Encrypt(string text, string key, string iv)
{
string encrypt = null;
using (AesCryptoServiceProvider csp = new AesCryptoServiceProvider())
{
csp.KeySize = 128;
csp.IV = Encoding.UTF8.GetBytes(iv);
csp.Key = Encoding.UTF8.GetBytes(key);
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
byte[] data = Encoding.UTF8.GetBytes(text);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, csp.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
encrypt = Convert.ToBase64String(ms.ToArray());
}
}
}
return encrypt;
}

/// <summary>
/// 解密
/// </summary>
/// <param name="encryptedText">加密字串</param>
/// <param name="key"></param>
/// <param name="iv"></param>
/// <returns>解密後的資料字串</returns>
public static string Decrypt(string encryptedText, string key, string iv)
{
string plaintext = null;
using (AesCryptoServiceProvider csp = new AesCryptoServiceProvider())
{
csp.KeySize = 128;
csp.IV = Encoding.UTF8.GetBytes(iv);
csp.Key = Encoding.UTF8.GetBytes(key);
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
byte[] cipherText = Convert.FromBase64String(encryptedText);
ICryptoTransform decryptor = csp.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(cipherText))
{
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cs))
{
plaintext = reader.ReadToEnd();
}
}
}
}
return plaintext;
}
}

參考資料

URL 編碼

這應該不用作者我多做介紹吧,常用於 URL 上的字元編碼,網路上有更多其他詳細說明的資源的。

HttpUtility

針對 URL 編碼可透過 HttpUtility 類別來處理,這是微軟提供處理關於 Web 請求時所需的編碼和解碼方法。

使用其中的 UrlEncodeUrlDecode 方法來處理。

UrlEncode - 編碼

1
public static string? UrlEncode (string? str);

UrlDecode - 解碼

1
public static string? UrlDecode (string? str);

JSON 格式編碼

這應該不用作者我多做介紹吧,常用於 JavaScript 上傳輸資料的呈現格式,網路上有更多其他詳細說明的資源的。

JsonConvert

針對 JSON 可透過 Json.NET 類別庫提供的 JsonConvert 類別來處理。首先,須透過 NuGet 先下載 Newtonsoft.Json。

1
Install-Package Newtonsoft.Json

SerializeObject - 序列化

1
2
3
public static string SerializeObject(
Object value
)

DeserializeObject - 反序列

1
2
3
public static T DeserializeObject<T>(
string value
)

完整程式範例

最後依據綠界站內付 2.0 所需的加解密流程,將各步驟的程式碼組合在一起,其中 AES 加解密使用前面撰寫的類別來處理,程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using Newtonsoft.Json;
using System;
using System.Web;

public class ECPayService
{
public string EncryptData(object data, string HashKey, string HashIV)
{
var text = HttpUtility.UrlEncode(JsonConvert.SerializeObject(data));
return AESEncryption.Encrypt(text, HashKey, HashIV);
}

public TResult DecryptData<TResult>(string encryptedText, string HashKey, string HashIV) where TResult : class
{
string plaintext = AESEncryption.Decrypt(encryptedText, HashKey, HashIV);
string jsonStr = HttpUtility.UrlDecode(plaintext);
return JsonConvert.DeserializeObject<TResult>(jsonStr, new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore });
}
}