Odoo13 自定义支付收单模块跳转流程开发问题咨询
Odoo 13 自定义支付收单模块实现方案
1. 支付收单配置模型继承
首先继承payment.acquirer新增收单平台所需的配置字段,示例代码:
# models/payment_acquirer.py from odoo import models, fields import requests class PaymentAcquirerMoncash(models.Model): _inherit = 'payment.acquirer' provider = fields.Selection( selection_add=[('moncash', 'MonCash')], ondelete={'moncash': 'set default'} ) moncash_merchant_id = fields.Char(string='商户ID', required_if_provider='moncash') moncash_secret_key = fields.Char(string='接口密钥', required_if_provider='moncash') moncash_api_base = fields.Char(string='收单平台接口根地址', default='https://收单平台接口域名')
2. 支付跳转链接生成逻辑
重写收单专属的表单参数生成方法,调用收单平台下单接口获取跳转链接,示例代码:
def moncash_form_generate_values(self, values): base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') # 构造收单平台下单参数 order_params = { 'order_id': values['reference'], 'amount': values['amount'], 'currency': values['currency'].name, 'notify_url': f"{base_url}/payment/moncash/callback", 'return_url': f"{base_url}/payment/process", } # 请求收单平台下单接口获取支付跳转链接 order_resp = requests.post( f"{self.moncash_api_base}/create_payment", json=order_params, auth=(self.moncash_merchant_id, self.moncash_secret_key) ) order_data = order_resp.json() # 将支付链接传入前端模板 values.update({ 'moncash_payment_url': order_data.get('payment_url'), 'order_id': values['reference'] }) return values
新增前端支付表单模板,实现自动跳转逻辑,示例代码:
<!-- views/payment_templates.xml --> <odoo> <template id="payment_moncash_form"> <form t-att-action="moncash_payment_url" method="GET"> <input type="hidden" name="orderID" t-att-value="order_id"/> <div class="text-center mt-3 mb-3"> <p>正在跳转至支付页面,若未自动跳转请点击下方按钮</p> <button class="btn btn-primary" type="submit">立即支付</button> </div> </form> <script> document.addEventListener('DOMContentLoaded', function() { document.querySelector('form').submit(); }); </script> </template> </odoo>
3. 异步回调接口实现
新增控制器处理收单平台的GET回调请求,主动核验交易状态后更新本地交易记录,示例代码:
# controllers/main.py from odoo import http from odoo.http import request import logging _logger = logging.getLogger(__name__) class MoncashPaymentController(http.Controller): @http.route('/payment/moncash/callback', type='http', auth='public', methods=['GET'], csrf=False) def moncash_callback(self, **kw): order_id = kw.get('orderID') if not order_id: return 'FAIL: MISSING_ORDER_ID' # 查询对应交易记录 tx = request.env['payment.transaction'].sudo().search([('reference', '=', order_id)], limit=1) if not tx: return 'FAIL: TRANSACTION_NOT_FOUND' # 主动调用收单平台查询接口核验交易真实性 acquirer = tx.acquirer_id verify_resp = requests.get( f"{acquirer.moncash_api_base}/query_order", params={'orderID': order_id}, auth=(acquirer.moncash_merchant_id, acquirer.moncash_secret_key) ) verify_data = verify_resp.json() if verify_data.get('trade_status') == 'SUCCESS': tx._set_transaction_done() tx._post_process_after_done() return 'SUCCESS' else: tx._set_transaction_cancel() return 'FAIL: PAYMENT_FAILED'
4. 交易状态校验逻辑适配
继承payment.transaction模型,实现收单专属的交易匹配和校验方法:
# models/payment_transaction.py from odoo import models, api import requests class PaymentTransactionMoncash(models.Model): _inherit = 'payment.transaction' @api.model def moncash_form_get_tx_from_data(self, data): order_id = data.get('orderID') return self.search([ ('reference', '=', order_id), ('acquirer_id.provider', '=', 'moncash') ], limit=1) def moncash_form_validate(self, data): order_id = data.get('orderID') acquirer = self.acquirer_id # 核验交易状态 verify_resp = requests.get( f"{acquirer.moncash_api_base}/query_order", params={'orderID': order_id}, auth=(acquirer.moncash_merchant_id, acquirer.moncash_secret_key) ) verify_data = verify_resp.json() if verify_data.get('trade_status') == 'SUCCESS': self._set_transaction_done() return True self._set_transaction_cancel( state_message=verify_data.get('fail_reason', '支付失败') ) return False
注意事项
- 所有第三方接口请求需要添加异常捕获逻辑,避免接口不可用时导致Odoo服务报错
- 敏感配置字段建议使用Odoo加密存储能力,不要明文硬编码
- 生产环境部署时需要确认收单平台的服务器IP段可以正常访问你的Odoo站点回调接口
内容的提问来源于stack exchange,提问作者Marceus jethro
相关产品推荐
相关产品推荐

