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 26路由堆叠

>>:  Day 23:将你的 Hexo 使用 Git 指令备份到 Github 储存库另一个分支

Day 1:同步与非同步执行

Hi 各位好,又到了我们一年一度的 iT邦铁人赛的挑战,这次我所挑战的主题是 Kotlin 中用来处...

格线系统(2) DAY44

今天要先来介绍 Sass @each 与 map Sass map-get 这里要先宣告变数(有点类...

Day 22:1863. Sum of All Subset XOR Totals

今日题目 题目连结:1863. Sum of All Subset XOR Totals 题目主题:...

Vue.js 从零开始 mitt

还记得区域元件有自己的作用域吗?已知外层元件可以跟内层元件传递资料(props),或是传递事件(em...

Day 19 利用transformer自己实作一个翻译程序(一)

前言 当初想说将每天学到的东西打成一篇文章,纪录看看30天後学会了什麽 但是最近翻自己的文章就发现内...