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, direct和 token
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专用的方法