一般串接金流時,如果要傳遞資料都需要將資料進行加解密,而最近因案子需求有接觸到綠界站內付 2.0,所以在此紀錄如何用 C# 編寫綠界站內付 2.0 加解密的程式。
綠界站內付 2.0
「站內付 2.0」是綠界在今年(2021)年初推出的全新廠商付款串接規格,付款頁面改用嵌入式以減少跳轉畫面(如下圖),提供流暢的交易體驗,詳情可看綠界的官網服務介紹。
資料如何加解密?
站內付 2.0 的介接方式可以去官網的「串接規格下載」,下載相關的技術文件。根據文件上的說明(如下圖)可知道須透過 JSON 格式編碼、URL 編碼及 AES 加密演算法,這 3 個階段來進行參數加解密。
以下將先個別介紹 3 個階段該如何處理,而於最後整合在一起。
AES 加密演算法
AES(Advanced Encryption Standard)又稱 Rijndael 加密法,是對稱金鑰加密中流行的演算法之一。
AesCryptoServiceProvider
針對 AES 加密演算法可透過 AesCryptoServiceProvider 類別來處理,這是微軟提供有關於 AES 的實作類別,用於執行對稱加密和解密。
- 命名空間:
System.Security.Cryptography
- 官方文件
加解密程式範例
跟據綠界所需的 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 { 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; }
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 請求時所需的編碼和解碼方法。
使用其中的 UrlEncode
與 UrlDecode
方法來處理。
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 }); } }
|