odoo12 支付宝在线支付

我使用的是这位大佬的模块:
git clone https://github.com/block-cat/payment_alipay

测试这个模块的功能,折腾了一天,踩了不少的坑,还好有了点眉目,现在记录下:

关于公钥私钥的设置

  1. 在支付宝中设置好密钥以后,需要在odoo中进行设置,在odoo中设置的公钥是支付宝公钥,不是应用公钥,不然后边验签失败
  2. 在odoo 中上传的密钥文档首尾需要添加虚线:类似下图密钥格式,不然支付宝页面都打不开:
    image

关于支付宝反馈支付成功的信息:

  1. 支付宝调用notify接口:
    调用这个接口会将payment.transations 的记录标为完成,但是并不会马上生成付款记录,也不会处理订单和发票,在odoo 中有一个Post process payment transactions的定时任务,每10分钟跑一次,跑的时候会把10分钟之前创建的交易记录处理掉,生成付款单,发票,并确认订单.
  2. 支付宝调用validate 接口:
    这个接口在支付完成后会跳转到该地址,验证通过后会再次跳转到/payment/process/接口,直接处理掉用户对应的订单付款信息,相对第一种速度较实时,,但是,存在用户直接关闭页面的情况,所以两种方式都必须存在.

自动开票付款的代码:

# 首先调用定时任务方法:
    @api.multi
    def _cron_post_process_after_done(self):
        if not self:
            ten_minutes_ago = datetime.now() - relativedelta.relativedelta(minutes=10)
            # we don't want to forever try to process a transaction that doesn't go through
            retry_limit_date = datetime.now() - relativedelta.relativedelta(days=2)
            # we retrieve all the payment tx that need to be post processed
            self = self.search([('state', '=', 'done'),
                                ('is_processed', '=', False),
                                ('date', '<=', ten_minutes_ago),
                                ('date', '>=', retry_limit_date),
                            ])
        for tx in self:
            try:
                tx._post_process_after_done()
                self.env.cr.commit()
            except Exception as e:
                _logger.exception("Transaction post processing failed")
                self.env.cr.rollback()
# 2. _post_process_after_done
    @api.multi
    def _post_process_after_done(self):
        self._reconcile_after_transaction_done()
        self._log_payment_transaction_received()
        self.write({'is_processed': True})
        return True
# 3. _reconcile_after_transaction_done
    @api.multi
    def _reconcile_after_transaction_done(self):
        # Validate invoices automatically upon the transaction is posted.
        invoices = self.mapped('invoice_ids').filtered(lambda inv: inv.state == 'draft')
        invoices.action_invoice_open()

        # Create & Post the payments.
        payments = defaultdict(lambda: self.env['account.payment'])
        for trans in self:
            if trans.payment_id:
                payments[trans.acquirer_id.company_id.id] += trans.payment_id
                continue

            payment_vals = trans._prepare_account_payment_vals()
            payment = self.env['account.payment'].create(payment_vals)
            payments[trans.acquirer_id.company_id.id] += payment

            # Track the payment to make a one2one.
            trans.payment_id = payment

        for company in payments:
            payments[company].with_context(force_company=company, company_id=company).post()
#  sale 模块重写了
    @api.multi
    def _reconcile_after_transaction_done(self):
        # Override of '_set_transaction_done' in the 'payment' module
        # to confirm the quotations automatically and to generate the invoices if needed.
        sales_orders = self.mapped('sale_order_ids').filtered(lambda so: so.state in ('draft', 'sent'))
        for so in sales_orders:
            # For loop because some override of action_confirm are ensure_one.
            so.with_context(send_email=True).action_confirm()
        # invoice the sale orders if needed
        self._invoice_sale_orders()
        res = super(PaymentTransaction, self)._reconcile_after_transaction_done()
        if self.env['ir.config_parameter'].sudo().get_param('sale.automatic_invoice'):
            default_template = self.env['ir.config_parameter'].sudo().get_param('sale.default_email_template')
            if default_template:
                for trans in self.filtered(lambda t: t.sale_order_ids):
                    ctx_company = {'company_id': trans.acquirer_id.company_id.id,
                                   'force_company': trans.acquirer_id.company_id.id,
                                   'mark_invoice_as_sent': True,
                                   }
                    trans = trans.with_context(ctx_company)
                    for invoice in trans.invoice_ids:
                        invoice.message_post_with_template(int(default_template), notif_layout="mail.mail_notification_paynow")
        return res

# 发票创建确认
    @api.multi
    def _invoice_sale_orders(self):
        if self.env['ir.config_parameter'].sudo().get_param('sale.automatic_invoice'):
            for trans in self.filtered(lambda t: t.sale_order_ids):
                ctx_company = {'company_id': trans.acquirer_id.company_id.id,
                               'force_company': trans.acquirer_id.company_id.id}
                trans = trans.with_context(**ctx_company)
                trans.sale_order_ids._force_lines_to_invoice_policy_order()
                invoices = trans.sale_order_ids.action_invoice_create()
                trans.invoice_ids = [(6, 0, invoices)]
				

总的流程:
订单--> 交易记录完成--> 订单确认--> 创建发票并确认 --> 创建付款并提交

posted @ 2021-09-26 19:04  那时一个人  阅读(256)  评论(0)    收藏  举报