iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
永豐金融APIs

從永豐金融APIs進入Open API的30天挑戰系列 第 16

[Day16] 建立訂單交易API_9

本節將繼續完成的虛擬訂單請求發送

以下是完整程式碼

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import json
import uuid
import requests
import hashlib

def get_hash_id(hash_a1, hash_a2, hash_b1, hash_b2):
    hash_a = format((int(hash_a1, 16) ^ int(hash_a2, 16)), 'x')
    hash_b = format((int(hash_b1, 16) ^ int(hash_b2, 16)), 'x')
    hash_id = hash_a + hash_b
    return hash_id.upper()

def get_nonce(shop_no):
    nonce_url = "https://sandbox.sinopac.com/QPay.WebAPI/api/Nonce"
    req_body = {"ShopNo": shop_no}
    r = requests.post(url=nonce_url, json = req_body)
    return r.json()["Nonce"]

def get_iv(nonce):
    sha_nonce_value = hashlib.sha256(nonce.encode("utf-8")).hexdigest().upper()
    return sha_nonce_value[-16:]

def get_message_hash(data):
    sorted_key_list = sorted(data.keys())
    first = True
    result = ""
    for key in sorted_key_list:
        if type(data[key]) != dict:
            if first:
                temp = key + "=" + str(data[key])
                first = False
            else:
                temp = "&" + key + "=" + str(data[key])
            result += temp
    return result

def get_sign(data, nonce, hash_id):
    hash_value = data + nonce + hash_id
    return hashlib.sha256(hash_value.encode("utf-8")).hexdigest().upper()

def aes_encrypt(key, content, iv):
    cipher = AES.new(key.encode("utf8"), AES.MODE_CBC, iv.encode("utf8"))
    return cipher.encrypt(pad(content.encode("utf8"), AES.block_size))

def get_message(hash_id, data, iv):
    print('IV: ' + iv)
    encrypt_data = aes_encrypt(hash_id, data, iv)
    return encrypt_data.hex().upper()

def get_order_no(need_pay):
    order = str(uuid.uuid4())
    if need_pay:
        order = order + "1"
    else:
        order = order + "9"
    return order

def get_order(shop_no, need_pay, return_url, backend_url, hash_a1, hash_a2, hash_b1, hash_b2, amount):

    url = 'https://sandbox.sinopac.com/QPay.WebAPI/api/Order'

    origin_message = {
        'ShopNo': shop_no,
        'OrderNo': get_order_no(need_pay),
        'Amount': amount * 100,
        'CurrencyID': 'TWD',
        'PayType': 'A',
        'ATMParam': {
            'ExpireDate': '20210929'
        },
        'CardParam': {},
        'PrdtName': '虛擬帳號訂單',
        'ReturnURL': return_url,
        'BackendURL': backend_url
    }
    
    origin_json_message = json.dumps(origin_message, ensure_ascii=False, separators=(',', ':'))

    hash_id = get_hash_id(hash_a1, hash_a2, hash_b1, hash_b2)
    nonce = get_nonce(shop_no)
    sign = get_sign(get_message_hash(origin_message), nonce, hash_id)
    messge = get_message(hash_id, origin_json_message, get_iv(nonce))
    
    reqest_body = {
        'Version': '1.0.0',
        'ShopNo': shop_no,
        'APIService': 'OrderCreate',
        'Sign': sign,
        'Nonce': nonce,
        'Message': messge
    }

    r = requests.post(url=url, json=reqest_body)
    return r.json()

shop_no = 'NA0249_001'
hash_a1 = '86D50DEF3EB7400E'
hash_a2 = '01FD27C09E5549E5'
hash_b1 = '9E004965F4244953'
hash_b2 = '7FB3385F414E4F91'
need_pay = True

order_url = 'https://sandbox.sinopac.com/QPay.WebAPI/api/Order'
return_url = 'http://10.11.22.113:8803/QPay.ApiClient/Store/Return'
backend_url = 'http://10.11.22.113:8803/QPay.ApiClient/AutoPush/PushSuccess'

print(get_order(shop_no, need_pay, return_url, backend_url, hash_a1, hash_a2, hash_b1, hash_b2, 500))

response為

{
    "Version": "1.0.0",
    "ShopNo": "NA0249_001",
    "APIService": "OrderCreate",
    "Sign": "6E185202050FADCF5672F95EE77E96727A77A206B0C12716221E182340BB50B4",
    "Nonce": "NjM3Njg3MjA0ODEwNTUuNToxZDMwZTgzZmQ3ZTYxZWI3NTY4ZmQ4NDRiNWY5Njc3YTY3ODgyNTBjYTBmNDY4NWMwYmYzZmNkNTYzYTNjYTZk",
    "Message": "CF0BA4B409F546BCDEEEDC58B5C7B49C629D35D561ED81009CD0051011AF18C92F2DDBAB643A7354D175AD2287C558C90EBF43B3BBA6DF6C01DE1FDC8F9D33E3E4D2EE733CA0C1AB5EA1EFF85E4430C10EECF14CCE57ABEE01A02B0F4E9B0DDDA368C75C5DC669DD4E0C1B3ECA79E31896862A4E0F441774CECDF4F95379AA38A3C14622684595052F59049A539CE57ACEF095331646CAD27AB7689D48C6682FA4761BA041A87DE17EB9A63C68BC28E63A9601DADD8FCCA98C481B12E00F51EFC7BB1C9DEF995874F7D885C035764499CF1E6F55A2E4559105CD7686355E0A388868F0A787D7FE53A2426441EDC57EB7"
}

下一節將繼續解析response結果


上一篇
[Day15] 建立訂單交易API_8
下一篇
[Day17] 建立訂單交易API_10
系列文
從永豐金融APIs進入Open API的30天挑戰18

尚未有邦友留言

立即登入留言