Flask-第三方金流串接實作(綠界)
在購物網站中,常使用第三方金流作為消費者支付的方式,在此紀錄在綠界上測試API的實作過程。
參考資料 : https://www.maxlist.xyz/2020/02/14/python-ecpay/
前置 :
若於本地IP執行測試,會沒辦法接收到綠界所回傳的訂單資訊,此時可使用Ngrok 開放自己的網域。https://ngrok.com/download
下載完畢後,開啟ngrok,輸入 ngrok http 5000 (或是你的port)
可暫時獲得公開IP,供測試使用。
Step 1 : 點擊觸發綠界輸入頁面
- 撰寫Restful API 處理 Request
# router
@allRoute.post('/account/create_payment') #用戶儲值
def Accountdeposit(): return UserController().Accountdeposit()
# Controller
amount = data.get("amount")
account = data.get("account")
customername = data.get("customername")
result = self.PaymentService.Accountdeposit(user_id,amount,account,customername)
2. 將參數傳入由綠界提供的API文件及範例, returnURL 記得填寫 ngrok 指定的位置。
# PaymentService
def Accountdeposit(self,user_id,amount,account,customername):
# 由綠界公開GitHub可查詢相關文件代碼
....
# returnURL 記得填寫 ngrok 指定的位置
'ReturnURL': 'https://906f-122-118-50-103.ngrok-free.app/api/account/receive_result',
html = ecpay_payment_sdk.gen_html_post_form(action_url, final_order_params)
return html
3. 渲染該html所需的資料,產生綠界網站
# Controller
result = render_template('payment.html', form_html=result)
Step 2: 輸入模擬轉帳,回傳訂單資訊
於信用卡處輸入模擬轉帳使用之信用卡與OTP,不用點選測試鈕,直接在下方輸入該資訊即可測試。
卡號 : 4311–9522–2222–2222
有效年月 : 大於當前日期
安全碼 : 222
OTP : 1234
當送出OTP後,綠界會根據ReturnURL所填寫的API,將訂單資訊回傳。
'ReturnURL': '/api/account/receive_result'
# router
@allRoute.post('/account/receive_result') #處理儲值結果
def Receiveresult(): return UserController().Receiveresult()
此時必須檢查CheckMacValue,確保該訂單的正確性,沒有被竄改或是他人任意打這支API想搞破壞。將訂單的資訊轉化成CheckMacValue,需透過以下步驟 :
- 將傳遞參數依照字母排序
- 參數最前面加上 HashKey、最後面加上 HashIV
- 進行 URL encode
- 轉為小寫
- 以 SHA256 加密方式來產生雜凑值
- 再轉大寫產生 CheckMacValue
官方文檔:https://developers.ecpay.com.tw/?p=2902
參考網站 :https://www.maxlist.xyz/2020/02/14/python-ecpay/
# Controller
check_mac_value = self.PaymentService.get_mac_value(request.form)
# PaymentService
def get_mac_value(self,get_request_form): # 把訂單的資訊轉化成check_mac_value
params = dict(get_request_form)
if params.get('CheckMacValue'):
params.pop('CheckMacValue') #提取出CheckMacValue
# step 1
ordered_params = (sorted(params.items(), key=lambda k: k[0].lower()))
# step 2 (官網有給測試用Key,IV)
HahKy = 'pwFHCqoQZGmho4w6'
HashIV = 'EkRm7iFT261dpevs'
encoding_lst = []
encoding_lst.append('HashKey=%s&' % HahKy)
encoding_lst.append(''.join([
'{}={}&'.format(key, value)
for key, value in ordered_params
]))
encoding_lst.append('HashIV=%s' % HashIV)
# step 3,4
safe_characters = '-_.!*()'
encoding_str = ''.join(encoding_lst)
encoding_str = quote_plus(str(encoding_str),
safe=safe_characters).lower()
# step 5,6
check_mac_value = ''
check_mac_value = hashlib.sha256(
encoding_str.encode('utf-8')).hexdigest().upper()
return check_mac_value
完成check_mac_value後,即可將訂單資訊放入進行比對,判斷訂單正確性,來編寫後續的操作方式。
check_mac_value = self.PaymentService.get_mac_value(request.form)
if request.form['CheckMacValue'] == check_mac_value:
result = self.UserService.Receiveresult(dto) ## 比對通過,進行商業邏輯
print('test passed')
else:
return make_response(jsonify({
"success":False,
"message":str('CheckMacValue Failed')
## 比對失敗,處理訂單失敗邏輯
}),400)
從綠界支付系統接收到包含 CheckMacValue
的訂單資訊。
使用相同的密鑰和演算法,在本地計算訂單資訊的 CheckMacValue
。
比較計算的 CheckMacValue
和綠界支付系統提供的 CheckMacValue
。如果它們匹配,則表示訂單資訊在傳輸過程中未被篡改。