将昨天产生产生的讯息文本,传送至测试服务器https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Order,如果没有问题的话会收到如下讯息:
{
"Version": "1.0.0",
"ShopNo": "NA0249_001",
"APIService": "OrderCreate",
"Sign": "FBF41F9BFA5607F5141D508DA6B914DCAB97CE7CDE22EE636C9FDD81A9AC3277",
"Nonce": "NjM3Njc0NzY1MDExMjc6MjVmMDE2NDUyYThjNDE4ODY1MmI4Mzk0OGM3YWY1Mjg0M2Y4NDdlMjAyMTk0YWM3MGFhZGZmNDcyMGQ5ZjhjNw==",
"Message": "FAE9E297DB4D0B16D3E5A56561B28DDC41CD135B23D5309F971091033425405BA96669FE5A27B1D42DC4EB9636EBB0D9D9D618BC2B3969124A4F73CBB760CB83084623E1C2DED846BB46525E1B74F187EEF42A0F483AC49B0A12268D28452F44D268D38BDB91C464B74B1BB80D6DFC372622D8006005B0ABF5637287CB587FCE6ABB9D2BA377A29EC2E7E696CFDE2E305739CF2E6CBC1F2B71741064CA21CE3A6C6BFBAD663140A4CCC5AB24BE77569A26E1EA3A71EC2BC7AFC6E0F43ED537E42CDF535E910E25413BF4BC649D800F592FEA277BA18BF312EDD9A062D7F24A6405AC01EEF3F7F55EBC5978EEFC7AB097A802A1D05B675CC08E5ABD3FD9106EE0C624839EB0451EBE0F10E85C6DFCE4C9E0D29B3E633928F1A73102C04FA9DB91D7391D8917DC263437DBC50A7ACAF2CA06F8114669F783EF5189925B61EC9D7ECC3C504D09996665BC7CD3C3725F5D778F1D843FC42183153E565BF06307405F30401BA7E83EFAC91B54612D92E284F3BCFE324E26F8E7BFB1AE6326D96E2513D53A4D25DC1C1C24437A403A5BF281DA95A4EE018D6224F18128EB5FBFF3EF73EEE19E0EFD9429AB2976AB70C8DB050EFD81DB591831FD820157ACC4B60F101ABEF75AAA420EFF4C6FD7495226872B410CB87E958E7C92BFF3E3D35B4367B927F167A30F495876E82428ACC0D51BD61C7D30DB0A5FAEA26CDA24F79EA132000FFCF9C2E6EBCA124C6D8F546DF954C333"
}
通过先前产生讯息文本的相同方式进行解密(但本回Nonce由回应中的栏位取得),分别得出
将Message栏位取出,以Hex方式读取,同样用AES-CBC(256bits)方式进行解密,会得出
{"OrderNo":"2021091500002","ShopNo":"NA0249_001","TSNo":"NA024900000173","Amount":40400,"Status":"S","Description":"S0000 – 处理成功","Param1":"","Param2":"","Param3":"","PayType":"C","CardParam":{"CardPayURL":"https://sandbox.sinopac.com/QPay.WebPaySite/Bridge/PayCard?TD=NA024900000173&TK=a135ccb2-2e4c-4af4-b4ef-dfece6367731"}}
def AES_CBC_Decrypt(HashID, iv, data):
try:
key = str.encode(HashID)
iv = str.encode(iv)
data = bytes.fromhex(data)
cipher = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
pt = unpad(cipher.decrypt(data), AES.block_size)
return pt.decode("utf-8")
except (ValueError, KeyError):
print("Incorrect decryption")
undecrypt_msg = js_resp['Message']
msg = AES_CBC_Decrypt(HashID, iv=iv, data=undecrypt_msg)
看到这边,你一定想哇成功了对不对,其实还没有,还少了最後一步,签名验证(Sign),收发的资讯传输过程都需要验证讯息文本与金钥的配对,以确认资料的防窜改,关於如何产生Sign,可以参照Day4,在这边我们要取讯息文本中的Sign,与解密後Message中的参数进行比对是否相同
def GetRespSign(msg:str, nonce:str, HashID:str):
msg = json.loads(msg)
SignStr = ""
for parm in sorted(msg, key=lambda v: v.upper()):
val = msg[parm]
if(type(val) == dict or not val):continue
SignStr = SignStr + f"{parm}={msg[parm]}&"
SignStr = SignStr.removesuffix('&') + nonce + HashID
sign = hashlib.sha256(SignStr.encode('utf-8')).hexdigest().upper()
return sign
resp_vsign = js_resp['Sign']
resp_csign = GetRespSign(msg=msg, nonce=nonce, HashID=HashID)
if(resp_vsign == resp_csign):
print("签章检验成功")
return true
else:
print("签章验证失败")
return false
呼,到现在已经将大致上的API如何使用完成时做了,接下来准备小跑进入实作环节,搭建一个储值卡系统希望有时间做得完
<<: #04 No-code 之旅 — Next.js 中的 Pre-render 与 Data Fetching
正文: 利用 UserDefault 储存资料 预览图: 程序码: import UIKit cla...
资通安全责任等级 依照资通安全责任等级分级办法,由主管机关核定相对应之等级,按照等级决定导入系统之...
鳕鱼:「再来要设计对战游戏,可以切换场景,人物可以在场地随意移动,发射武器互相攻击,人物会与墙壁、敌...
从上图可知衣装仪态的重要性。 其实,稽核专业的形象,一直是我所追求的目标,即使我在资安顾问的年资已...
讨论演算法的执行时间到现在,我们只提最糟糕的情况,好像不断在强调演算法的效能可以有多差。 你可能会想...