依照參數說明,建立訂單的資料結構(DAY3-參考),詳細參數規格可以在永豐API技術規格文件內找到,此處先以訂單建立(OrderCreate)API進行測試,訂單細節如下:
故使用的參數為:
以Python實作:
neworder = APIModel.ReqOrderCreate(ShopNo="NA0249_001", OrderNo="2021091500001", Amount=40400, \
PrdtName="IPhone 13 Pro Max 256g", ReturnURL="https://0.0.0.0/store/Return", \
BackendURL="https://0.0.0.0/bakcend", PayType="C", AutoBilling="Y", PayTypeSub="ONE")
這邊吐槽一下信用卡API測試環境只能測試一次付清,否則會跳E0602 - 收款方式未啟用錯誤,另外還有預計自動請款天數,在設定自動請款時按照說明書應該會忽略,結果會跳日期範圍不正確錯誤,請款日期範圍也不是文件上的1-21天,而是1-7天
在取得Nonce、HashID、訊息文本等三個參數後,才能夠進行安全簽章(Sign)計算,計算方式概述:
以上節iPhone的信用卡訂單為範例,產生的訊息文本為:
{
"ShopNo": "NA0249_001",
"OrderNo": "2021091500002",
"Amount": 40400,
"CurrencyID": "TWD",
"PrdtName": "IPhone 13 Pro Max 256g",
"Memo": "",
"Param1": "",
"Param2": "",
"Param3": "",
"ReturnURL": "https://0.0.0.0/store/Return",
"BackendURL": "https://0.0.0.0/bakcend",
"PayType": "C",
"ATMParam": {
"ExpireDate": ""
},
"CardParam": {
"AutoBilling": "Y",
"ExpBillingDays": 7,
"ExpMinutes": 10,
"PayTypeSub": "ONE"
}
}
進行步驟1.移除訊息文本中空的參數與節點參數(如留空的參數與ATMParam與CardParam):
{
"ShopNo": "NA0249_001",
"OrderNo": "2021091500002",
"Amount": 40400,
"CurrencyID": "TWD",
"PrdtName": "IPhone 13 Pro Max 256g",
"ReturnURL": "https://0.0.0.0/store/Return",
"BackendURL": "https://0.0.0.0/bakcend",
"PayType": "C",
}
進行步驟2.將參數以不分大小寫方式遞增排序、3. 以[參數名稱1]=[數值1]&[參數名稱2]=[數值2].....的方式串接參數組成字串,記得去掉末尾的'&'
order = "Amount=40400&BackendURL=https://0.0.0.0/bakcend&CurrencyID=TWD&OrderNo=2021091500002&PayType=C&PrdtName=IPhone 13 Pro Max 256g&ReturnURL=https://0.0.0.0/store/Return&ShopNo=NA0249_001"
進行步驟4. 加上Nonce與HashID
nonce = "NjM3NjczMjQwNzM1NTAuOTo5ZWE1MmFhYzk0NDgwMzljY2RiNjhjOGU0MGU3ODc0NzFiMTIwNmNkMTViZWU4MzUwZDU3Zjg1M2VhNjIwODRj"
HashID = "17D8E6558DC60E702A6B57E1B9B7060D"
str_before_sign = "Amount=40400&BackendURL=https://0.0.0.0/bakcend&CurrencyID=TWD&OrderNo=2021091500002&PayType=C&PrdtName=IPhone 13 Pro Max 256g&ReturnURL=https://0.0.0.0/store/Return&ShopNo=NA0249_001NjM3NjczMjQwNzM1NTAuOTo5ZWE1MmFhYzk0NDgwMzljY2RiNjhjOGU0MGU3ODc0NzFiMTIwNmNkMTViZWU4MzUwZDU3Zjg1M2VhNjIwODRj17D8E6558DC60E702A6B57E1B9B7060D"
進行步驟5. 進行字串SHA256計算
sign = "3c883d53f7732ec7c3f8c9d0232691545855b60507b199094a4cde71c911f522"
以下為Python完整實作:
'''
Sample Env.ini
[App]
Version = 1.0.0
ShopNo = BA0026_001
A1 = 86D50DEF3EB7400E
A2 = 01FD27C09E5549E5
B1 = 9E004965F4244953
B2 = 7FB3385F414E4F91
[Server]
Api_URL = https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Order
Nonce_URL = https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Nonce
'''
def main():
env = ConfigParser()
env.read('env.ini')
Hash = SimpleNamespace(A1 = env['App']['A1'], A2 = env['App']['A2'], B1 = env['App']['B1'], B2 = env['App']['B2'])
cfg = SimpleNamespace(Version = env['App']['Version'], ShopNo = env['App']['ShopNo'], HashID = HashID(Hash))
neworder = APIModel.ReqOrderCreate(ShopNo="NA0249_001", OrderNo="2021091500002", Amount=40400, PrdtName="IPhone 13 Pro Max 256g", ReturnURL="https://0.0.0.0/store/Return", BackendURL="https://0.0.0.0/bakcend", PayType="C", AutoBilling="Y", PayTypeSub="ONE")
OrderCreate(neworder, cfg)
def OrderCreate(origin, cfg):
nonce = GetNonce(cfg)
sign = GenSign(origin, nonce, cfg.HashID)
def GetNonce(cfg):
payload = json.dumps({"ShopNo":cfg.ShopNo}, indent=4)
resp = APIPm.sendreq(url=APIPm.nonceservice, data=payload)
return json.loads(resp.text)['Nonce']
def GenSign(origin, Nonce:str, HashID:str):
SignStr = ""
#不分大小寫排序變數
for parm in sorted(origin.__dict__, key=lambda v: v.upper()):
val = origin.__dict__[parm]
# print(f"Parm:{parm}, Val:{val}, Types:{type(val)}")
if(not type(val) == SimpleNamespace and origin.__dict__[parm] != None):
if(type(val) == str and not val):continue
SignStr = SignStr + f"{parm}={origin.__dict__[parm]}&"
SignStr = SignStr.removesuffix('&') + Nonce + HashID
sign = hashlib.sha256(SignStr.encode('utf-8')).hexdigest().upper()
return sign
如何產生簽章大家都會了嗎;阿好像忘了寫怎麼在Python內丟Request,明天補寫,斯米麻賽