pos self order在线支付 online payment - xiaohao0576/odoo-doc GitHub Wiki

支付页面的触发点

在pos self order的CartPage页面,当用户点击Pay按钮,会执行await this.selfOrder.confirmOrder();

addons/pos_self_order/static/src/app/services/self_order_service.js文件中,如果条件符合,最终会执行 this.router.navigate("payment");

用户的界面会切换到 PaymentPage, 源码: addons/pos_self_order/static/src/app/pages/payment_page/payment_page.xml

PaymentPage页面分析

  • onMounted的时候,如果当前仅有一个在线支付方式,就不需要用户手动选择了,页面直接会帮用户执行selectMethod函数,里面包含了this.startPayment();语句
  • async startPayment()这个js函数,会被继承重写,最重要的一个是在addons/pos_online_payment_self_order/static/src/app/pages/payment_page/payment_page.js文件中, 还有几个重写是在支付方式模块中

pos_online_payment_self_order模块的startPayment函数

文件路径: addons/pos_online_payment_self_order/static/src/app/pages/payment_page/payment_page.js

如果是mobile手机下单模式,最终会执行this.checkAndOpenPaymentPage(order);

首先会使用getOnlinePaymentUrl获取支付url,再在当前的窗口打开这个url。

const onlinePaymentUrl = this.selfOrder.getOnlinePaymentUrl(order, true);
window.open(onlinePaymentUrl, "_self");

getOnlinePaymentUrl函数分析

文件位置: addons/pos_online_payment_self_order/static/src/app/services/self_order_service.js

源码如下:

    getOnlinePaymentUrl(
        { id: order_id, access_token: order_access_token, config_id: order_pos_config_id },
        exitRoute = true
    ) {
        const baseUrl = session.base_url;
        const order = this.currentOrder;
        let exitRouteUrl = baseUrl;

        if (exitRoute) {
            let table = "";
            exitRouteUrl += `/pos-self/${order_pos_config_id.id}`;

            if (this.config.self_ordering_pay_after === "each") {
                exitRouteUrl += `/confirmation/${order.access_token}/order`;
            }

            if (this.currentTable) {
                table = `&table_identifier=${this.currentTable.identifier}`;
            }

            exitRouteUrl += `?access_token=${this.access_token}${table}`;
        }

        const exit = encodeURIComponent(exitRouteUrl);
        return `${baseUrl}/pos/pay/${order_id}?access_token=${order_access_token}&exit_route=${exit}`;
    },

getOnlinePaymentUrl 的 exit_route 设计是回跳自助点餐上下文的关键

跳转到pos支付页面

搜索关键词:def pos_order_pay(self, pos_order_id, access_token=None, exit_route=None):

文件路径: addons/pos_online_payment/controllers/payment_portal.py

这个web controller正常情况下,会返回 The rendered payment form

基本逻辑是,根据订单信息组合成一个rendering_context,最后调用request.render('pos_online_payment.pay', rendering_context)返回payment form

pos_online_payment.pay视图

文件位置: addons/pos_online_payment/views/payment_portal_templates.xml

这是一个qWeb xml视图,里面包含了odoo支付页面,里面最重要的一行代码是<t t-call="payment.form" />

分析payment.form

全文搜索关键字: id="payment.form"

文件位置: addons/payment/views/payment_form_templates.xml

这是一个可以根据传入的参数去配置的qWeb form

里面有一个参数transaction_route ,作用是 The route to call to create the transaction.

所有可以配置的参数如下:

        <form t-if="payment_methods_sudo or tokens_sudo" id="o_payment_form"
              class="o_payment_form"
              t-att-data-mode="mode"
              t-att-data-reference-prefix="reference_prefix"
              t-att-data-amount="amount"
              t-att-data-currency-id="currency and currency.id"
              t-att-data-partner-id="partner_id"
              t-att-data-transaction-route="transaction_route"
              t-att-data-assign-token-route="assign_token_route"
              t-att-data-landing-route="landing_route"
              t-att-data-access-token="access_token"
        >

payment_form.js

文件位置 : addons/payment/static/src/interactions/payment_form.js

作用: 这个js文件,处理前端所有的用户交互和支付逻辑

三种支付流程

Odoo当前支持三种类型的支付流程,分别是 redirect, directtoken

pos_order_pay_transaction 对 flow 有强校验,只允许 redirect/direct/token

源码: addons/pos_online_payment/controllers/payment_portal.py 第226行

pos_order_pay_transaction 未登录用户禁止 tokenization 和 token flow,这个是业务安全边界

后端_send_api_request函数

和第三方支付网状的交互,最终都会通过 _send_api_request来发出

这个方法,标准实现里三种 flow 都可能用到

文件位置 addons/payment/models/payment_provider.py

搜索关键字: def _send_api_request(

redirect + validation flow专用方法

_get_specific_rendering_values_get_redirect_form_view 这两个方法是redirect flow专用的方法

用于获取qWeb xml和表单数据,最终渲染成 redirect_form_html 返回给前端,通过hidden form的方式自动提交给第三方支付网关

token flow专用方法

_charge_with_token_send_payment_request 这两个方法是 token flow专用的方法