odoo POS 集成微信支付和支付宝支付

最近有小伙伴有这方面的需求,市场上又没有十分靠谱的现成的解决方案,于是花了一天的时间把微信和支付宝的POS集成模块做了出来。这里记录一下开发的大概流程和使用介绍。

支付宝

我们之前是对接过支付宝在线支付的,而且因为支付宝有沙箱环境,因此,对接的比较流畅。我们先去支付宝开发中心注册一个开发者账号,然后可以拿到支付宝的沙箱环境账号和密钥。这里需要一部安卓手机,因为支付宝的沙箱钱包只有安卓版没有苹果版本。

沙箱应用中可以找到 APPID,设置密钥 和商家密钥等关键参数。

根据我们之前对接支付宝在线支付的经验,我们需要的参数有一下几个:

  • App Seller Id: 支付宝商家ID
  • Alipay App Id: 支付宝应用ID
  • Mechant Private Key: 商户私钥
  • Alipay Public Key: 支付宝RSA公钥
  • Sign Type: 加密方式

其中支付宝RSA公钥可以通过支付宝提供的生成工具生成,也可以直接自己生成,具体方法参考官方文档,这里不赘述了。

接下来,我们开始对接。首先,我们要搞清楚POS条码支付的流程(区别于用户主动扫码支付,这里称之为条码支付):

  1. 用户出示条码/二维码,实际是出示了自己条码支付的授权码
  2. 商户在通过扫描到自己的系统中之后,系统通过条码支付接口发起扣款请求
  3. 用户在手机端确认金额
  4. 商户系统扣款成功
  5. 用户收到扣款通知

其中第3步,通常为了支付的便捷,小额支付通常会跳过这一步。

因为支付过程中可能会碰到失败的情况,因此需要商户在系统中获取到用户支付中这个状态的时候,进行主动查询确认,一般经过三次尝试如果仍旧支付不成功时,调用撤销接口取消交易。对应到后台,我们需要三个接口:

  1. 支付接口
  2. 查询接口
  3. 撤销接口

支付接口

1
2
3
4
5
6
7
8
9
def barcode_pay(self, order_no, subject, auth_code, amount):
"""条码支付"""
# 条码支付
alipay = self._get_alipay_client()
_logger.debug(f"POS支付宝条码支付:{order_no},{subject},{amount}")
res = alipay.pay.trade_pay(
order_no, 'bar_code', auth_code, subject, total_amount=amount)
_logger.debug(f"POS支付宝支付结果:{res}")
return res

查询接口

1
2
3
4
5
6
def query_payment(self, trade_no):
"""查询支付结果"""
alipay = self._get_alipay_client()
res = alipay.pay.trade_query(trade_no=trade_no)
_logger.debug(f"POS支付宝交易查询结果:{res}")
return res

撤销接口

1
2
3
4
5
6
def cancel_payment(self, trade_no):
"""取消交易"""
alipay = self._get_alipay_client()
res = alipay.pay.trade_cancel(trade_no=trade_no)
_logger.debug(f"POS支付宝交易取消:{trade_no}")
return res

其中,查询和取消接口均可以使用商户订单号或者支付宝流水号,这里我们为了方便起见统一用的时支付宝流水号。

为了在POS系统中新增一个支付方法,我们需要新增一个支付方法,支付宝,并将我们之前讲到的参数放到设置里:

然后我们在门店的设置里新增这个支付方法:

新增之后,我们就可以在POS界面看到新增的支付方法了。

前端的对接相对比较复杂,我们要继承PaymentInterface对象,新生成一个PaymentAlipay 对象,负责处理前端的业务请求。

其中最主要的方法是处理后端传过来的响应并作出合适的反馈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
_alipay_handle_response: function (response) {
var line = this.pos.get_order().selected_paymentline;
var self = this;
if (response.code == '10000') {
self._alipay_success(response.trade_no)
self.pos.gui.close_popup();
}
else if (response.code == '10003') {
line.set_payment_status("pending")
this.pos.gui.show_popup('confirm', {
'title': '支付中',
'body': '等待用户付款',
'confirm': this.check_payment,
'cancel': this.cancel_payment,
'payment_method': line.payment_method,
'trade_no': response.trade_no
});
}
else if (response.code = '40004') {
line.set_payment_status("pending")
this.pos.gui.show_popup('error', {
'title': '支付失败',
"body": response.sub_msg
});
}
},

支付宝在支付以后,通常会返回一下几种状态的结果:

  • 10000: 支付成功
  • 10003: 用户支付中
  • 40004: 支付失败

其中 10003代表等待用户确认支付,一般出现在大额支付或者长期未使用的客户中,此时商户应该等待用户支付完成后,进行查询操作,然后完成后续的业务处理。

微信支付

微信支付的整体流程与支付宝一致,区别在于微信支付的金额单位是分,因此我们需要在处理过程中做一些处理,另外,微信的商户订单号并部支持空格,因此对于odoo默认的”Order 12345”这种订单号也需要做适配,同样地,我们在交易查询和交易撤销的接口中也应该使用微信的交易号而不是商户订单号。

效果展示

支付成功:

支付失败:

需要的同学欢迎到我的淘宝购买哦

你的支持我的动力