iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
永豐金融APIs

永豐 API 隨意玩系列 第 3

Day03 - 隨意玩之 API 訊息內文以及 Sign

  • 分享至 

  • xImage
  •  

今天預計講解下面兩個 (也就是下圖的步驟 5)

  1. API 的 JSON 內容
  2. 把內容加上 Nonce 以及密鑰 然後做 SHA256 (圖片的 Sign)

https://ithelp.ithome.com.tw/upload/images/20210912/20141787zAz1Ay0TC1.png


API 的 JSON 內容

  • API 除了前面介紹的 Nonce 以外,還有就是 Order 相關的 API
  • Order 相關有分成以下三種
    1. OrderCreate (建立訂單)
    2. OrderQuery (查詢訂單)
    3. OrderPayQuery (訂單付款查詢)

在 Spec 第七章有詳細列出哪一種 Request 的訊息內文需要哪些東西,像是 Spec 在 OrderCreate 給的例子

{
    "ShopNo": "BA0026_001", 
    "OrderNo": "A201804270001", 
    "Amount": 50000, 
    "CurrencyID": "TWD", 
    "PayType": "A", 
    "ATMParam": { "ExpireDate": "20180502" }, 
    "CardParam": { }, 
    "ConvStoreParam": { }, 
    "PrdtName": "虛擬帳號訂單", 
    "ReturnURL": "http://10.11.22.113:8803/QPay.ApiClient/Store/Return", 
    "BackendURL": "http://10.11.22.113:8803/QPay.ApiClient/AutoPush/PushSuccess" 
}

但是實際上在 OrderCreate 必須要有的參數只有下面幾項,其他會根據你的參數不同,有不同需求~

Name Type Required Note
ShopNo bytes(20) Y 商店代號
OrderNo bytes(50) Y 訂單編號
Amount Int(9) Y 訂單總金額
CurrencyID bytes(3) Y 幣別
PrdtName bytes(60) Y 產品名稱
ReturnURL bytes(255) Y 付款完成頁面
PayType bytes(1) Y 收款方式

計算 Sign

https://ithelp.ithome.com.tw/upload/images/20210913/20141787ToXpKdavI1.png

如果要算出訊息的 Sign,需要注意以下幾個事項。

  1. 移除所有是的值
    • 像是上面 OrderCreate 例子的 CardParamConvStoreParam
  2. 如果有多節點,不會加進去 Sign 計算
    • 像是上面 OrderCreate 例子的 ATMParam
  3. 將參數名稱不分大小寫由小至大排列,組成如 param1=value1&param2=value2 的字串
    • 以上面 OrderCreate 的例子會得到下面這樣
    Amount=50000&BackendURL=http://10.11.22.113:8803/QPay.ApiClient/AutoPush/PushSuccess&CurrencyID=TWD&OrderNo=A201804270001&PayType=A&PrdtName=虛擬帳號訂單&ReturnURL=http://10.11.22.113:8803/QPay.ApiClient/Store/Return&ShopNo=BA0026_001
    
  4. 將內文雜湊、Nonce以及 Hash ID 串在一起使用 SHA256 計算出 Hash (Sign)

下面的程式碼是要讓我們的訊息內文轉換成要加密前的形式 (圖中的內文雜湊)

def parseQueryData(msg_param):
    if type(msg_param) != dict:
        return
    
    ## 這裡是將傳進來的 dict 根據 key 做排序
    order_message = dict(sorted(message_content.items(), key = lambda x: x[0]))
    message = ''

    ## 這裡是看是否為空值或是多節點,然後轉換為要求的字串
    for k, v in order_message.items():
        if type(v) == dict or v == '':
            continue
        message += f"{k}={v}&"
    
    return message[:-1]

接著只要把前一天說的 Nonce 以及 Hash ID,將他們接在一起算 SHA256 即可獲得 Sign

## msg_content 是 parseQueryData() 傳回來 value
def calcSign(msg_content, nonce, hash_id):
	sign_msg = msg_content+nonce+hash_id

	s = hashlib.sha256()
	s.update(sign_msg.encode('utf-8'))
	h = s.hexdigest()
	return h.upper()

所以到目前為止,會有下面的程式碼 (部分程式碼有做更改,但基本上功能一樣~)

import requests
import json
import hashlib

shop_no = '<shop_no>'
sinopac_hash = {
	'a1': '',
	'a2': '',
	'b1': '',
	'b2': ''
}

nonce_url = 'https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Nonce'

def getNonce():
	nonce_data = {
		'ShopNo': shop_no
	}

	r = requests.post(nonce_url, json=nonce_data)

	return json.loads(r.content)['Nonce']

def calcHashID():
	a1 = sinopac_hash['a1']
	a2 = sinopac_hash['a2']
	b1 = sinopac_hash['b1']
	b2 = sinopac_hash['b2']

	xor1 = hex(int(a1, base=16)^int(a2, base=16))
	xor2 = hex(int(b1, base=16)^int(b2, base=16))

	hash_id = xor1[2:]+xor2[2:]
	return hash_id.upper()

def calcIV(nonce):
	s = hashlib.sha256()

	s.update(nonce.encode('utf-8'))
	h = s.hexdigest()
	return h[-16:].upper()

def calcSign(msg_content, nonce, hash_id):
	sign_msg = msg_content+nonce+hash_id

	s = hashlib.sha256()
	s.update(sign_msg.encode('utf-8'))
	h = s.hexdigest()
	return h.upper()

order_create = {
    "ShopNo": shop_no, 
    "OrderNo": "A202109120008", 
    "Amount": 50000, 
    "CurrencyID": "TWD", 
    "PayType": "C", 
    "CardParam": { 
    	"AutoBilling": "Y"
	}, 
    "ConvStoreParam": { }, 
    "PrdtName": "信用卡訂單", 
    "ReturnURL": "http://10.11.22.113:8803/QPay.ApiClient-Sandbox/Store/Return", 
    "BackendURL": "https://10.11.22.113:8803/funBIZ.ApiClient/AutoPush/PushSuccess" 
}

nonce = getNonce()
hash_id = calcHashID()
iv = calcIV(nonce)
content = parseQueryData(order_create)
signature = calcSign(content, nonce, hash_id)

預告明天會利用 Python 實作 AES-CBC,敬請期待!


上一篇
Day02 - 隨意玩之工欲善其事,必先利其器
下一篇
Day04 - 隨意玩之 AES-CBC 加/解密
系列文
永豐 API 隨意玩6
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言