前段时间,我们对接了支付宝,这次我们来对接微信支付。
沙箱环境
微信支付没有沙箱环境,要想测试就必须有营业执照。
Python SDK
这里我们使用的是开源SDK库 WechatPy
微信支付
要使用微信支付,你必须要满足一下条件
- APPID: 一个绑定了微信支付的公众号APPID
- API KEY: 在申请微信支付后可以设置,用于调用微信接口
- 商户号: 开通了微信支付的商户编号
- 商户证书文件: 开通了微信支付的商户证书
- 商户密钥文件: 跟商户证书匹配的密钥文件
有了这几个参数才可以正确的调用微信支付的接口
1 2 3 4 5 6 7 8 9 10 11 12 | def _get_wechatpay(self): “””获取微信支付客户端””” try: # WeChatPay has no sandbox enviroment. wechatpay = WeChatPay(self.wechatpay_appid, self.wechatpay_app_key, self.wechatpay_mch_id, mch_cert=self.wechatpay_mch_cert, mch_key=self.wechatpay_mch_key) return wechatpay except Exception as err: _logger.exception(f”生成微信支付客户端失败:{err}”) |
odoo的官方商城支付,对应的微信支付是Navtive方式。
微信与支付不同的是,官方并没有给我们提供一个收银台页面,因此,我们需要自己实现一个,并持续监听,等到客户付款完成后再跳转验证页面。
微信的验证也是两种方式,一种是微信官方的推送消息,一种是我们自己根据订单去微信支付服务器查询。(这点不同于支付宝)。
主动查询
主动查询,用到的是wechatpy的query接口,查询起来比较简单:
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 27 | @api.model def wechatpy_query_pay(self, order): “”” 主动去微信支付查询支付结果 用户支付前没有transcation_id因此,只能用商户自有订单号去查 只有SUCCESS支付成功,其他状态均不成功 “”” wechatpay = self._get_wechatpay() res = wechatpay.order.query(out_trade_no=order) _logger.info(“主动查询微信支付结果:{}”.format(res)) if res[“return_code”] == “SUCCESS” and res[“result_code”] == “SUCCESS”: if res[“trade_state”] == “SUCCESS”: transaction = self.env[“payment.transaction”].sudo().search( [(‘reference’, ‘=’, order)], limit=1) if transaction.state in (‘draft’, ‘pending’, ‘authorized’): # 将支付结果设置完成 result = { “acquirer_reference”: res[‘transaction_id’] } transaction.write(result) transaction._set_transaction_done() return True elif transaction.state == ‘done’: return True else: return False return False |
需要说明的是,我们再验证了支付之后,需要将对应的支付事务完成。
微信消息处理
客户在支付完成后,微信官方会给我们传入的回调地址发送业务通知。这点wechatpy也帮我们封装好了方法,使用起来也很方便:
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 | def _verify_wechatpay(self, data): “””验证微信支付服务器返回的信息””” try: wechatpay = self._get_wechatpay() result = wechatpay.parse_payment_result(data) _logger.info(“解析微信支付返回结果:{}”.format(result)) if result[‘result_code’] == ‘SUCCESS’ and result[‘return_code’] == ‘SUCCESS’: # 支付校验成功 transaction = self.env[“payment.transaction”].sudo().search( [(‘reference’, ‘=’, result[“out_trade_no”])], limit=1) if transaction.state in (‘draft’, ‘pending’, ‘authorized’): # 将支付结果设置完成 result = { “acquirer_reference”: result[‘transaction_id’] } transaction.write(result) transaction._set_transaction_done() return True elif transaction.state == ‘done’: return True else: return False return False except Exception as err: _logger.error(“解析微信支付推送消息失败:{}”.format(traceback.format_exc())) return False |
在验证了微信的消息之后,同样也要将支付事务设置为完成状态。
完整示例
模块开源,下载地址