Odoo 18 JS:如何正确扩展原生payment_paypal模块以启用PayLater功能?
Odoo 18 JS:如何正确扩展原生payment_paypal模块以启用PayLater功能?
我完全懂你现在的处境——想给Odoo的PayPal支付加PayLater选项,可要么改了之后其他支付方式炸了,要么PayPal SDK重复加载出问题。下面给你两个靠谱的方案,按需选就行:
方案一:精准扩展PayPal逻辑(推荐,与原代码耦合度低)
这个方案会完整保留原模块的所有功能(包括其他支付方式的处理),只针对PayPal的SDK URL和初始化逻辑做修改,从根源避免SDK重复加载:
import paymentForm from '@payment/js/payment_form'; import loadJS from '@web/core/assets/load_js'; paymentForm.include({ async _prepareInlineForm(providerId, providerCode, paymentOptionId, paymentMethodCode, flow) { // 非PayPal支付方式直接走原逻辑,确保Stripe等功能不受影响 if (providerCode !== 'paypal') { this._super(...arguments); return; } // 以下完全复用原PayPal模块的核心逻辑,仅修改SDK URL和PayLater相关配置 this._hideInputs(); this._setPaymentFlow('direct'); document.getElementById('o_paypal_button').classList.remove('d-none'); document.getElementById('o_paypal_loading').classList.remove('d-none'); this.paypalData ??= {}; const currentPayPalData = this.paypalData[paymentOptionId]; if (this.selectedOptionId && this.selectedOptionId !== paymentOptionId) { this.paypalData[this.selectedOptionId]['paypalButton'].hide(); } if (currentPayPalData && this.selectedOptionId !== paymentOptionId) { let paypalSDKURL = this.paypalData[paymentOptionId]['sdkURL']; // 给已有的SDK URL补全PayLater参数 if (!paypalSDKURL.includes('enable-funding=paylater')) { paypalSDKURL += (paypalSDKURL.includes('?') ? '&' : '?') + 'enable-funding=paylater&components=buttons,messages'; } const paypalButton = this.paypalData[paymentOptionId]['paypalButton']; await loadJS(paypalSDKURL); paypalButton.show(); } else if (!currentPayPalData) { this.paypalData[paymentOptionId] = {}; const radio = document.querySelector('input[name="o_payment_radio"]:checked'); if (radio) { this.inlineFormValues = JSON.parse(radio.dataset['paypalInlineFormValues']); this.paypalColor = radio.dataset['paypalColor']; } const { client_id, currency_code } = this.inlineFormValues; // 生成包含PayLater支持的SDK URL const paypalSDKURL = `https://www.paypal.com/sdk/js?client-id=${client_id}&components=buttons,messages¤cy=${currency_code}&intent=capture&enable-funding=paylater`; await loadJS(paypalSDKURL); const paypalButton = paypal.Buttons({ fundingSource: paypal.FUNDING.PAYPAL, style: { color: this.paypalColor, label: 'paypal', disableMaxWidth: true, borderRadius: 6, }, createOrder: this._paypalOnClick.bind(this), onApprove: this._paypalOnApprove.bind(this), onCancel: this._paypalOnCancel.bind(this), onError: this._paypalOnError.bind(this), }); this.paypalData[paymentOptionId]['sdkURL'] = paypalSDKURL; this.paypalData[paymentOptionId]['paypalButton'] = paypalButton; paypalButton.render('#o_paypal_button'); // 可选:添加PayLater分期信息条(如果需要展示) paypal.Messages({ style: { layout: 'text' } // 可选text/flex/vertical三种布局 }).render('#o_paypal_messages'); } document.getElementById('o_paypal_loading').classList.add('d-none'); this.selectedOptionId = paymentOptionId; }, });
方案说明
- 保留了原方法对非PayPal支付方式的处理,确保其他支付渠道正常工作
- 仅修改PayPal相关逻辑中的SDK URL,添加
enable-funding=paylater(启用PayLater)和components=buttons,messages(加载分期信息组件)两个关键参数 - 完全复用原模块的按钮状态管理、SDK加载判断逻辑,从根源避免重复加载问题
方案二:全局拦截SDK加载请求(更简洁,适合快速实现)
如果你不想复制太多原模块代码,可以通过拦截loadJS函数自动修改PayPal SDK的请求参数,完全不改动原模块的核心逻辑:
import paymentForm from '@payment/js/payment_form'; import loadJS from '@web/core/assets/load_js'; // 保存原始的loadJS函数 const originalLoadJS = loadJS; // 重写loadJS,自动给PayPal SDK添加PayLater参数 window.loadJS = async function(url, options) { if (url.startsWith('https://www.paypal.com/sdk/js')) { // 解析并修改URL参数 const [baseURL, paramStr] = url.split('?'); const params = new URLSearchParams(paramStr || ''); // 启用PayLater params.set('enable-funding', 'paylater'); // 确保包含messages组件(用于展示分期信息) const components = (params.get('components') || 'buttons').split(','); if (!components.includes('messages')) { components.push('messages'); params.set('components', components.join(',')); } // 重新拼接修改后的URL url = `${baseURL}?${params.toString()}`; } // 调用原始函数加载资源 return originalLoadJS(url, options); }; // 无需修改_prepareInlineForm,原模块逻辑会自动使用修改后的SDK URL paymentForm.include({});
方案说明
- 通过全局拦截
loadJS函数,自动处理所有PayPal SDK的请求,无需修改原模块的任何业务逻辑 - 即使原模块后续更新,只要它还是用
loadJS加载SDK,你的PayLater功能就依然有效 - 仅针对PayPal的SDK URL生效,不会影响其他资源的加载
最后提醒
不管用哪个方案,记得先在PayPal商家后台开启PayLater选项,并确保你的PayPal账户支持该功能。测试前清理浏览器缓存,确保新的SDK配置被正确加载。
内容来源于stack exchange
相关产品推荐
相关产品推荐

