iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
永豐金融APIs

試著讀懂與串接永豐金融APIs系列 第 28

Day 0x 1C - odoo addons 永豐金流開發(Part 3 - controller)

*** 模組資料夾 payment_sinopac 以 "/" 來代表此資料夾 ***

0x1 Controller

昨天我們有建立了 Controller 資料夾了,
今天補上自定義的 Route,
先變更 /Controller/__init__.py,增加一行程式

from . import main

0x2 開發到一半的 controller/main.py

如題,卡關卡到懷疑人生
程式先奉上,等等來解釋一下目前遇到的問題,以及思路

# -*- coding: utf-8 -*-
import logging
import json
from odoo import http
from odoo.http import JsonRequest, Response, request
from odoo.tools import date_utils
from .sinopac_sdk import SinopacSDK
from random import randint
from datetime import datetime, timedelta

_logger = logging.getLogger(__name__)


class OverrideJsonRequest(JsonRequest):
    def _json_response(self, result=None, error=None):
        if '/payment/sinopac/receive_msg' in self.httprequest.full_path:
            response = {}

            if error is not None:
                response = error
            if result is not None:
                response = result
        else:
            response = {
                'jsonrpc': '2.0',
                'id': self.jsonrequest.get('id')
            }

            if error is not None:
                response['error'] = error
            if result is not None:
                response['result'] = result

        mime = 'application/json'
        body = json.dumps(response, default=date_utils.json_default)

        return Response(
            body, status=error and error.pop('http_status', 200) or 200,
            headers=[('Content-Type', mime), ('Content-Length', len(body))]
        )


# 因為在 odoo 裡,前底線為受保護成員,但 python 無此規範,所以強制覆寫
JsonRequest._json_response = OverrideJsonRequest._json_response


class SinopacController(http.Controller):
    _return_url = '/payment/sinopac/return'
    _backend_url = '/patment/sinopac/receive_msg'
    sdk = SinopacSDK(
        shop_no='ShopNo',
        key_a1='1234567890ABCDEF',
        key_a2='1234567890ABCDEF',
        key_b1='1234567890ABCDEF',
        key_b2='1234567890ABCDEF'
    )

    def request_dataset(self, service: str, data: dict) -> dict:
        sinopac = self.sdk
        nonce = sinopac.get_nonce()
        hash_id = sinopac.calculate_hash_id()
        iv = sinopac.calculate_iv(nonce)

        return {
            'Version': '1.0.0',
            'ShopNo': self.sdk.shop_no,
            'APIService': service,
            'Nonce': nonce,
            'Sign': sinopac.calculate_sign(data, hash_id=hash_id, nonce=nonce),
            'Message': sinopac.encrypt_message(data, hash_id=hash_id, iv=iv),
        }

    @http.route('/payment/sinopac/receive_msg', type='json', methods=['POST'], auth="public", csrf=False)
    def receive_msg(self):
        data = json.loads(request.httprequest.data)
        data = {
            'ShopNo': data.get('ShopNo', ''),
            'PayToken': data.get('PayToken', ''),
        }

        sinopac = self.sdk

        data = sinopac.call_api(
            url='https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Order',
            data=self.request_dataset('OrderPayQuery', data)
        )

        return {'Status': 'S'}

    @http.route('/payment/ecpay/hold_payment_type', type='json', method=['POST'], auth="public", csrf=False)
    def hold_payment_type(self):
        data = json.loads(request.httprequest.data)
        return data
  • 首先,第一個 OverrideJsonRequest,如字面所敘,主要是自定義 output,
    因為 odoo json output 會是 jsonrpc 格式,所以今天如果需要回應 BackendURL 時那邊就會有問題,
    所以花了很大量的時間在找辦法突破,也很慶幸地找到突破點
  • 接下來是主軸的部分 SinopacController
    • request_dataset : 參照之前 Laravel 的作法
    • receive_msg : 接收訊息, Class OverrideJsonRequest 就是為了這個
    • hold_payment_type : 主要為使用者要付款時,要把選擇的付款方式暫存,不然後端接值的時候不知道是要信用卡還是要 ATM 轉帳
      https://ithelp.ithome.com.tw/upload/images/20211006/20141805jkyNuV832u.png

0x3 畫面如何產生? & 今日結語

這裡是先把 Controller 寫個一版,因為畫面的部分還在測試,
所以今天單純先分享 Controller,
明天不管進度如何會把畫面跟幾個剩餘的部分補上


上一篇
Day 0x1B - odoo addons 永豐金流開發(Part 2 - sinopac sdk... maybe)
下一篇
Day 0x 1D - odoo addons 永豐金流開發(Part 4 - Website template, data... more)
系列文
試著讀懂與串接永豐金融APIs30

尚未有邦友留言

立即登入留言