Openerp 7微信支払開発


ここでは最も微信のカード決済開発を紹介しなければならない.微信のホームページjsapi、原生決済natvieなどは公式サイトを参考にすることができるが、実際には下位の論理は多くなく、深刻な過程と手順が異なるだけだ.
微信のカード決済の流れは、公式サイトの紹介を見ることができますが、ここでは自分の理解を話したいと思います.
1.微信ユーザーは自分の微信の财布を开くことができて、支払いを见て、それからクリックして1つのバーコードと1つのQRコードで、バーコードは商戸のレジにスキャンガンでスキャンして、别に微信でスキャンしたQRコードで、ここはバーコードのスキャン支払いに関连して、私のここは主に商戸に対して支払うためです.
2.バーコードをスキャンすると認証番号が取得されますが、実はこの数字はバーコードの上の数字ですが、これは主要サーバーがプッシュする情報で、ユーザーが来ても役に立たないのです
3.レジは受け取った一連の数字をスキャンし、バックエンドサーバーに送信し、バックエンドサーバーであるoperrnerpプログラムはこの認証数字を受信し、xml情報のパッチワークを開始し、微信の検証urlに送信する.
4.手順3が完了しました.ここでは2つの状況があります.1つ目はパスワードなしで支払うことです.つまり、フロントで銀を受け取って認証数字をスキャンした後、openerpは深刻なxmlデータを微信のバックグラウンドに直接送信します.もし深刻に正しくなったら、この場合は直接支払うので、ユーザーに聞く必要はありません.第2のケースは、支払いが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   # id
context = request.context
       pay_record
= request.registry['payment.record']  # addons payment_record.models.payment_record.py
       # class PaymentRecord
record = {}
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_ordererrres
form_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 = None
request.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_data
return ret_data



def wechat_validate_data(self, **kwargs):
res = False
post = 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データ(例):
wx 2421 b 1 c 4370 ec 43 b注文追加説明120269300684844649カード決済テスト1000 100000100 aee 146 b 1 dee 7 cec 9100 add 9 b 96 cbe 2 14157673 14.17.22.52 C 29 DB 7 FD 4136 B 84 AE 3560476362 C
2.パスワード支払いが必要な場合は、WeChatサーバに問い合わせる
クエリー・インタフェースのアドレス:https://api.mch.weixin.qq.com/pay/orderquery
xmlデータ:(栗を挙げる)
       wx2421b1c4370ec43b   10000100   ec2316275641faa3aacf3cc599e8730f   1008450740201411110005820873   FDD167FAA73459FD921B144BAF4F4CA2 
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 list
if 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 = 0
while 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 += 10
if check_state == 'SUCCESS':
return None, check_data
else:
#
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 + ', , !', None
elif cancel_state == 'FAIL':
return check_state + ', ! .', None
else:
try:
return wechat_error_codes[check_state]+' , , ', None
except Exception, e:
return check_state, None
elif retData.get('err_code') == 'SUCCESS':
return None, retData
else:
if retData.get('err_code') is not None:
return wechat_error_codes[retData.get('err_code')], None
elif retData.get('return_code') == 'SUCCESS' and retData.get('result_code') == 'SUCCESS':
return None, retData
else:
return "fail", None
else:
return "fail", None

====
def wechat_get_pro_order(self,cr,uid,params,context=None):
# url
base_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_constructor
except ImportError:
import md5
   md5_constructor = md5.new
   md5_hmac = md5
import 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 s
if 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でいいです.