openerp7微信支付开发

这里最要介绍一下微信的刷卡支付开发,至于微信的网页jsapi、原生支付natvie等等的可以参考一下官方网站,其实底层逻辑都差不多,只是严重过程跟步骤不一样而已。

微信的刷卡支付流程,可以查看官方网站的介绍,但是这里我想说一下自己的理解:

1.微信用户可以打开自己的微信的钱包,看到付款,然后点击进去就是一个条形码跟一个二维码,条形码是给商户收银台用扫描枪扫描的,另外就是用微信扫描的二维码,这里只是涉及到条形码的扫描支付,因为我这里主要针对商户支付。

2.条形码扫描后会获取到一串认证数字,其实这串数字就是条形码上面的那一串数字,但是这是主要服务器要推送的信息,用户要来也没有用

3.收银台扫描收到的一串数字,发送到后端服务器,后端服务器也就是opernerp程序接收到了这串认证数字,就开始拼凑xml信息,并发送到微信的验证url去

4.步骤3完了,这里有两种情况,第一种情况是免密码支付,也就是前台收银扫描认证数字后,openerp直接发送要严重的xml数据到微信后台,如果严重正确了,这种情况下是直接支付的,不需要询问用户,第二种情况就是当支付不大于1000块或者当天不超过5次支付或者不是出现了后端程序跟微信服务器通信故障的话,就要微信客户端的用户输入支付密码,同时后端服务器的也会根据当前用户输入密码这个过程中,隔时间去查询微信服务器验证当前微信用户支付流程是否已经正确完成了,一旦查询出用户支付成功,我们可以根据微信服务器返回的交易代码做相应的处理。

main.py  # 主要是生产内部访问url,由前端调用

# -*- coding: utf-8 -*-省略一大推代码@http.route([‘/shop_wechat/payment/jsapi/order‘], type=‘json‘, auth=‘none‘)  # 微信网页支付一大堆代码

@http.route([‘/shop_wechat/payment/native/order‘], type=‘json‘, auth=‘user‘)   # 微信二维码支付一大推代码

@http.route([‘/shop_wechat/payment/scan/order‘], type=‘json‘, auth=‘none‘)  # 微信刷卡支付def wechat_scan_order(self, **post):ret_data = {‘return_code‘: "FAIL", ‘return_msg‘: ""}cr = request.cr        uid = SUPERUSER_ID   # 当前用户idcontext = request.context        pay_record = request.registry[‘payment.record‘]  # 注册addons里面的payment_record.models.payment_record.py        # 里面的class PaymentRecordrecord = {}record[‘ref_id‘] = str(post[‘orderID‘])record[‘type‘] = ‘微信‘record[‘sub_type‘] = ‘微信刷卡支付‘record[‘fee‘] = str(post[‘money‘])record_id = pay_record.createrecord(cr, uid, record)  # return record[‘record_id‘]req_data = dict()req_data[‘out_trade_no‘] = record_id        req_data[‘total_fee‘] = record[‘fee‘]req_data[‘auth_code‘] = str(post[‘auth_code‘])req_data[‘device_info‘] = str(post.get(‘device_info‘, ‘‘))req_data[‘openid‘] = request.session.wechat_openid  # 其实在完成后的支付打印信息来看,openid是空值,但是为了统一代码就保留了req_data[‘product_id‘] = str(post.get(‘product_id‘, ‘‘))  # 其实在完成后的支付打印信息来看,product_id空值req_data[‘body‘] = ‘订单:‘+ str(post[‘orderID‘])req_data[‘trade_type‘] = ‘WeiXinScan‘req_data[‘spbill_create_ip‘] = ‘192.168.1.100‘req_data[‘notify_url‘] = ‘/payment/wechat/notify/‘  # 微信支付后的返回信息的接收地址req_data[‘attach‘] = request.session.db   # 读取会话中使用的数据库

if req_data[‘out_trade_no‘] and req_data[‘total_fee‘]:   # 如果有商品订单号并且有总金额err, res = request.registry[‘payment.acquirer‘].wechat_get_pro_order(cr, uid, req_data)  # 把req_data传到# wechat_get_pro_order方法处理,并返回err,resform_data = {‘out_trade_no‘: post[‘orderID‘],‘trade_status‘: ‘Draft‘,‘payment_type‘: req_data[‘trade_type‘],‘fees‘: req_data[‘total_fee‘],‘openid‘: req_data[‘openid‘],}tx = Nonerequest.registry[‘payment.transaction‘].wechat_form_validate(cr, uid, tx, form_data)if err:ret_data[‘return_msg‘] = err                form_data[‘trade_status‘] = ‘Error‘request.registry[‘payment.transaction‘].wechat_form_validate(cr, uid, tx, form_data)else:reference = post[‘orderID‘]if reference:tx_ids = request.registry[‘payment.transaction‘].search(cr, uid, [(‘reference‘, ‘=‘, reference)])if tx_ids:tx = request.registry[‘payment.transaction‘].browse(cr, uid, tx_ids[0], context=context)if tx.state == ‘draft‘:form_data[‘trade_status‘] = ‘Completed‘request.registry[‘payment.transaction‘].wechat_form_validate(cr, uid, tx, form_data)ret_data[‘return_code‘] = res.get(‘result_code‘)ret_data[‘return_msg‘] = res.get(‘return_msg‘)else:ret_data[‘return_msg‘] = u‘参数错误!商品订单号以及金额没有‘print ret_data[‘return_msg‘]print ret_datareturn ret_data

def wechat_validate_data(self, **kwargs):res = Falsepost = kwargs.get(‘post‘)request.session.db = post.get(‘attach‘)cr = request.cr        uid = SUPERUSER_ID        _KEY = request.registry[‘payment.acquirer‘]._get_wechat_partner_key(cr, uid)_, prestr = util.params_filter(post)mysign = util.build_mysign(prestr, _KEY, ‘MD5‘)if mysign != post.get(‘sign‘):return ‘false‘

pay_record = request.registry[‘payment.record‘]record = {}record[‘record_id‘] = post.get(‘out_trade_no‘)ref_id = pay_record.paysucess(cr, uid, record)

reference = ref_id        post[‘out_trade_no‘] = reference        transaction_id = post.get(‘transaction_id‘)openid = post.get(‘openid‘)fees = post.get(‘cash_fee‘)tx = None

if reference:tx_ids = request.registry[‘payment.transaction‘].search(cr, uid, [(‘reference‘, ‘=‘, reference)])if tx_ids:tx = request.registry[‘payment.transaction‘].browse(cr, uid, tx_ids[0])if tx.state == ‘pending‘:post[‘transaction_id‘] = transaction_id                    post[‘openid‘] = openid                    post[‘trade_status‘] = ‘Completed‘post[‘fees‘] = fees                    res = request.registry[‘payment.transaction‘].wechat_form_validate(cr, uid, tx, post)return res

这里要说明一下刷卡支付要相关要传送的xml数据内容跟格式

1.提交刷卡支付API

接口地址:https://api.mch.weixin.qq.com/pay/micropay

发送的xml数据(举例):

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <attach>订单额外描述</attach>
   <auth_code>120269300684844649</auth_code>
   <body>刷卡支付测试</body>
   <device_info>1000</device_info>
   <goods_tag></goods_tag>
   <mch_id>10000100</mch_id>
   <nonce_str>8aaee146b1dee7cec9100add9b96cbe2</nonce_str>
   <out_trade_no>1415757673</out_trade_no>
   <spbill_create_ip>14.17.22.52</spbill_create_ip>
   <time_expire></time_expire>
   <total_fee>1</total_fee>
   <sign>C29DB7DB1FD4136B84AE35604756362C</sign>
</xml>

2.如果是需要密码支付的话,就要查询微信服务器

查询接口地址:https://api.mch.weixin.qq.com/pay/orderquery

xml数据:(举个栗子)

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <mch_id>10000100</mch_id>
   <nonce_str>ec2316275641faa3aacf3cc599e8730f</nonce_str>
   <transaction_id>1008450740201411110005820873</transaction_id>
   <sign>FDD167FAA73459FD921B144BAF4F4CA2</sign>
</xml>

3.还有一个撤单的流程,因为需要证书所以没有办法去做。

wechat.py  # 主要处理跟微信后台的xml数据通信,并根据相关返回的信息做相应的处理

# -*- coding: utf-8 -*-import base64省略一大堆import

def WechatScanOrder(self, cr, uid, params, context=None):"""统一下单"""conf_ids = self.search(cr, uid, [(‘name‘, ‘=‘, ‘wechat‘)], context=context)  # 查询payment.acquirer的# 数据库表payment_acquirer的name字段等于 wechat的记录listif len(conf_ids) != 1:return "配置错误,微信支付模块没有安装",None

acquirer = self.browse(cr, uid, conf_ids[0], context=context)if self._wechat_required(params):                              # 检测是否有相关微信传输要求的字段params[‘appid‘] = acquirer.wechat_app_id            params[‘mch_id‘] = int(acquirer.wechat_partner_account)params[‘sub_mch_id‘] = ‘‘params[‘nonce_str‘] = util.random_str()params[‘total_fee‘] = str(int(params[‘total_fee‘] * 100))del params[‘trade_type‘]     # 刷卡支付不需要支付类型del params[‘product_id‘]     # 刷卡支付不需要商品号del params[‘openid‘]         # 刷卡支付不需要用户标示_, prestr = util.params_filter(params)   # params_filter将数据转换成UTF-8,估计是预防中文乱码情况params[‘sign‘] = util.build_mysign(prestr, acquirer.wechat_partner_key, ‘MD5‘)  # 生产sign签名retData = self._post(self._get_wechat_urls(cr, uid)[‘WEIXIN_SCAN_PAY_URL‘], util.buildXml(params))

if retData.get(‘return_code‘) == ‘SUCCESS‘ and retData.get(‘result_code‘) != ‘SUCCESS‘:if retData.get(‘err_code‘) == ‘USERPAYING‘:to_check_data = {‘appid‘: acquirer.wechat_app_id,‘mch_id‘: int(acquirer.wechat_partner_account),‘out_trade_no‘: params[‘out_trade_no‘],‘nonce_str‘: util.random_str()}# to_check_data是在判断retDatade错误代码后(刷卡密码支付会产生),往微信的查询入口去查询当前状态返回的信息_, prestr = util.params_filter(to_check_data)to_check_data[‘sign‘] = util.build_mysign(prestr, acquirer.wechat_partner_key, ‘MD5‘)time.sleep(3)t = 0while t < 30:time.sleep(10)check_data = self._post(self._get_wechat_urls(cr, uid)[‘CHECK_WEIXIN_SCAN_PAY_URL‘],                                                util.buildXml(to_check_data))if check_data.get(‘return_code‘) == ‘SUCCESS‘ and check_data.get(‘result_code‘) == ‘SUCCESS‘:check_state = check_data.get(‘trade_state‘)elif check_data.get(‘return_code‘) == ‘SUCCESS‘ and check_data.get(‘result_code‘) != ‘SUCCESS‘:check_state = check_data.get(‘return_msg‘)else:check_state = u‘微信支付查询出现问题或者用户没有输入密码超过30秒!‘

if check_state == ‘SUCCESS‘:break

t += 10if check_state == ‘SUCCESS‘:return None, check_dataelse:# 超时撤单代码to_cancel_data = {‘appid‘: acquirer.wechat_app_id,‘mch_id‘: int(acquirer.wechat_partner_account),‘out_trade_no‘: params[‘out_trade_no‘],‘nonce_str‘: util.random_str()}_, prestr = util.params_filter(to_cancel_data)to_cancel_data[‘sign‘] = util.build_mysign(prestr, acquirer.wechat_partner_key, ‘MD5‘)# 调用撤单方法cancel_state = self.to_cancel_scanpay_process(cr, uid, to_cancel_data, context)if cancel_state == ‘SUCCESS‘:return check_state + ‘,并且撤单成功,请重新生产支付单!‘, Noneelif cancel_state == ‘FAIL‘:return check_state + ‘,并且撤单失败!请求技术人员支持.‘, Noneelse:try:return wechat_error_codes[check_state]+‘但是已经支付超时,如果有发生扣款情况,请返回扣款‘, Noneexcept Exception, e:return check_state, Noneelif retData.get(‘err_code‘) == ‘SUCCESS‘:return None, retDataelse:if retData.get(‘err_code‘) is not None:return wechat_error_codes[retData.get(‘err_code‘)], Noneelif retData.get(‘return_code‘) == ‘SUCCESS‘ and retData.get(‘result_code‘) == ‘SUCCESS‘:return None, retDataelse:return "fail", Noneelse:return "fail", None

省略一大推代码====def wechat_get_pro_order(self,cr,uid,params,context=None):# 获取当前访问urlbase_url = self.pool[‘ir.config_parameter‘].get_param(cr, SUPERUSER_ID, ‘web.base.url‘)

# 生产新的parmas_data字典if params[‘trade_type‘] == ‘WeiXinScan‘:params_data = {‘body‘: params[‘body‘],‘out_trade_no‘: params[‘out_trade_no‘],‘total_fee‘: float(params[‘total_fee‘]),‘spbill_create_ip‘: params[‘spbill_create_ip‘],‘auth_code‘: params[‘auth_code‘],‘trade_type‘: params[‘trade_type‘],‘product_id‘: params[‘product_id‘],‘openid‘: params[‘openid‘],‘attach‘: params.get(‘attach‘),}return self.WechatScanOrder(cr, uid, params_data, context)else:params_data = {‘body‘: params[‘body‘],‘out_trade_no‘: params[‘out_trade_no‘],‘total_fee‘: float(params[‘total_fee‘]),‘spbill_create_ip‘: params[‘spbill_create_ip‘],‘product_id‘: params[‘product_id‘],‘trade_type‘: params[‘trade_type‘],‘openid‘: params[‘openid‘],‘attach‘: params.get(‘attach‘),‘notify_url‘: base_url + params[‘notify_url‘],}# 把params_data 传输到_wechat_unified_order进行处理并返回数据return self._wechat_unified_order(cr, uid, params_data, context)省略一大推代码====

util.py # 主要是做xml数据的格式处理,sign的生产等等,这个会在wechat.py里面调用到、

# -*- coding: utf-8 -*-

try:import hashlib    md5_constructor = hashlib.md5    md5_hmac = md5_constructor    sha_constructor = hashlib.sha1    sha_hmac = sha_constructorexcept ImportError:import md5    md5_constructor = md5.new    md5_hmac = md5import sha    sha_constructor = sha.new    sha_hmac = sha

import sys

reload(sys)sys.setdefaultencoding(‘utf8‘)

md5 = md5_constructor

def smart_str(s, encoding=‘utf-8‘, strings_only=False, errors=‘strict‘):"""    Returns a bytestring version of ‘s‘, encoded as specified in ‘encoding‘.

    If strings_only is True, don‘t convert (some) non-string-like objects.    """if strings_only and isinstance(s, (types.NoneType, int)):return sif not isinstance(s, basestring):try:return str(s)except UnicodeEncodeError:if isinstance(s, Exception):return ‘ ‘.join([smart_str(arg, encoding, strings_only,                        errors) for arg in s])return unicode(s).encode(encoding, errors)elif isinstance(s, unicode):return s.encode(encoding, errors)elif s and encoding != ‘utf-8‘:return s.decode(‘utf-8‘, errors).encode(encoding, errors)else:return s

def params_filter(params):ks = params.keys()ks.sort()newparams = {}prestr = ‘‘for k in ks:v = params[k]k = smart_str(k, ‘utf-8‘)if k not in (‘sign‘,‘sign_type‘) and v != ‘‘:newparams[k] = smart_str(v, ‘utf-8‘)prestr += ‘%s=%s&‘ % (k, newparams[k])prestr = prestr[:-1]return newparams, prestr

def build_mysign(prestr, key, sign_type = ‘MD5‘):if sign_type == ‘MD5‘:return md5(prestr + key).hexdigest()return ‘‘

test_url.py # 主要用来测试,直接模拟http发送

省略代码

剩下的就是测试环境,如果没有扫描枪,可以直接在‘auth_code‘:‘微信条形码上面的数字串‘,然后运行test_url.py就可以了。

时间: 2024-10-15 01:22:20

openerp7微信支付开发的相关文章

PHP微信支付开发实例

这篇文章主要为大家详细介绍了PHP微信支付开发过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 PHP微信支付开发过程,分享给大家,供大家参考,具体内容如下 1.开发环境 Thinkphp 3.2.3 微信:服务号,已认证 开发域名:http://test.paywechat.com (自定义的域名,外网不可访问) 2.需要相关文件和权限 微信支付需申请开通 微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 微信支付开发者文档

微信支付开发 c# SDK JSAPI支付开发的流程和微信大坑

微信支付开发流程 1. 开通微信支付功能 省略 2. 下载微信的C#版的微信SDK 下载连接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 各个版本的都有,可惜咱最熟悉C# 我的下载时间是2016-02-28日,所以所有的流程都是基于这个版本的SDK. 3. 配置各种参数 首先在微信支付的开发配置中配置发起支付的路径如下: 代码的solution中找到lib的config.cs文件,如下图,所有的参数都在这里,这里配置

微信支付开发流程

授人以鱼不如授人以渔 微信支付开发流程 下面以PHP语言为例,对微信支付的开发流程进行一下说明. 1.获取订单信息 2.根据订单信息和支付相关的账号生成sign,并且生成支付参数 3.将支付参数信息POST到微信服务器,获取返回信息 4.根据返回信息生成相应的支付代码(微信内部)或是支付二维码(非微信内),完成支付. 下面分步骤的讲一下: 1.微信支付中相关的必须的订单参数有三个,分别是:body(商品名或订单描述),out_trade_no(一般为订单号)和total_fee(订单金额,单位“

微信支付开发(11) Native支付

关键字:微信公众平台 微信支付 Native原生支付作者:方倍工作室原文:http://www.cnblogs.com/txw1958/p/wxpay-native.html 在这篇微信公众平台开发教程中,我们将介绍如何开发实现微信支付的Native功能. 本文分为以下三个部分: 生成Native支付URL 生成二维码 生成Package 一.生成Native支付URL Native(原生)支付URL是一系列具有weixin://wxpay/bizpayurl?前缀的URL,同时后面紧跟着一系列

微信支付开发1 微信支付URL配置

本文介绍微信支付申请时如何设置授权目录及URL. 一.选择支付类型 目前有两种支付类型 JS API网页支付 Native原生支付 如果没有特殊要求,两种都勾选. 二.支付授权目录 目前可以选择http还是https协议,没有特别要求,选择http.对安全要求比较高的企业,请选择https. 支付授权目录填写自己公司的域名加上目录,目录可以是不存在的目录,例如wxpay. 一个完整的目录参考如下: http://www.doucube.com/wxpay/ 蓝色部分表示要选择的. 红色部分表示要

微信支付开发(8) 维权通知

本文介绍微信支付中如何获得维权通知. 一.维权通知URL 在 微信支付开发(1) 微信支付URL配置 已提到,维权通知URL为 http://www.doucube.com/wxpay/rights.php 二.用户维权系统接口 用户在公众号进行支付贩买行为出现异常时,通常会投诉到腾讯客服,因此微信侧需要即时了解公众号不用户交易的详情.同时,为了最快效率的解决用户的问题,微信作为连接用户和商户的桥梁,会通过此客服系统即时将问题同步给商户,并将解决结果反馈至用户. 用户在新增投诉单后,微信后台通知

微信支付开发(7) 告警通知

本文介绍微信支付中如何获得告警通知. 一.告警通知 为了及时通知商户异常,提高商户在微信平台的服务质量.微信后台会向商户推送告警通知,包括发货延迟.调用失败.通知失败等情况,通知的地址是商户在申请支付时填写的告警通知URL,在"公众平台-服务-服务中心-商户功能-商户基本资料-告警通知URL"可以查看.商户接收到告警通知后需要尽快修复其中提到的问题,以免影响线上经营. 告警通知URL接收的postData中还将含xml数据,格式如下: <xml> <AppId>

微信支付开发(6) 发货通知

本文介绍微信支付中发货通知功能的实现. 一.发货通知 为了更好地跟踪订单的情况,需要第三方在收到最终支付通知之后,调用发货通知API告知微信后台该订单的发货状态. 发货时间限制:虚拟.服务类24小时内,实物类72小时内. 请在收到支付通知后,按时发货,并使用发货通知接口将相关信息同步到微信后台.若平台在规定时间内没有收到,将视作发货超时处理. 发货通知API的URL为: https://api.weixin.qq.com/pay/delivernotify?access_token=xxxxxx

微信支付开发(5) 订单查询

本文介绍微信支付中订单查询功能的实现. 作者:方倍工作室 地址:http://www.cnblogs.com/txw1958/p/wxpay-order-query.html 一.订单查询 因为某一方技术的原因,可能导致商户在预期时间内都收不到最终支付通知,此时商户可以通过该API来查询订单的详细支付状态. 订单查询API的URL为: https://api.weixin.qq.com/pay/orderquery?access_token=xxxxxx URL中的参数只包含目前微信公众平台凭证