def get_token(self, method, app_key, app_secret, user_id, user_pwd_md5): # 获取通用参数 parmse = self.get_parmse(method, app_key) # 增加私有参数 parmse['user_id'] = user_id # 用户ID parmse['user_pwd_md5'] = hashlib.md5(user_pwd_md5).hexdigest() # 用户ID密码的MD5 parmse['expires_in'] = '60' # access token的有效期 # 获取签名 # 将非空字典键值按ASCII码升序排列,然后拼接起来 _, prestr = util.params_filter(parmse) # 将所拼接的字符串进行MD5运算,并将结果使用十六进制表示 parmse['sign'] = binascii.b2a_hex(hashlib.md5(app_secret + prestr + app_secret).hexdigest()) # 访问地址 request_url = urllib.urlencode(parmse) httpsClient = httplib.HTTPConnection(server_url) httpsClient.request('POST', '/route/rest', request_url, {"Content-type": "application/x-www-form-urlencoded"}) ret_json = httpsClient.getresponse().read() ret_dict = json.loads(ret_json) # 判断返回值 if ret_dict.get('message') == 'success': accessToken = ret_dict.get('result').get('accessToken') return accessToken else: return ret_dict.get('message')
def alipay_fuwu(self, **post): """ 支付宝服务窗开发者模式验证和消息接受地址 """ # 将post来的参数排除掉sign后作为待签名参数 sign_params_dic = {} for post_key, post_val in post.items(): if not post_key=='sign': sign_params_dic[post_key] = post_val.decode('utf8') # 待签名参数按key值排序,组合成query字符串 _, sign_query_str = util.params_filter(sign_params_dic) # 使用支付宝公钥签名验签 sign_verify = RSA.load_pub_key('addons-extra/wxsite/static/alipay_rsa_public_key.pem').verify(sign_query_str, post['sign']) # sign_by_ali_pub64 = sign_by_ali_pub.encode('base64') if sign_verify: # 待签名字符串:公钥+success str_to_sign_by_private = '<biz_content>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9vK4cSuzfGJKMJ/XQ82SMxRjbVussG+sI4lrgJLa7cbHZ19+zZRy9IyMYyvpD/gm4blgha0iOhRxPuxmvLHcNerG2u9q+X18NeJ0bLHxZRpPhOXMzgBDp78LDG1m7NtNW5Poat2JZyxSCTBbs1x3Tk9NUVr8mHLpriFO1ik4EEwIDAQAB</biz_content><success>true</success>' # 加载私钥进行签名 rsa_private_key = load_privatekey(FILETYPE_PEM, open('addons-extra/wxsite/static/rsa_private_key.pem').read()) rsa_private_sign = sign(rsa_private_key, str_to_sign_by_private, 'sha1') rsa_private_sign = base64.b64encode(rsa_private_sign) # 拼接返回给支付宝的xml内容 response_xml = '<?xml version="1.0" encoding="GBK"?><alipay><response>'+str_to_sign_by_private+'</response><sign>'+rsa_private_sign+'</sign><sign_type>RSA</sign_type></alipay>' return response_xml.encode('gbk') else: return 'fail'.encode('gbk')
def _get_weixin_signkey(self, acquirer): url = 'https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey' nonce_str = self.random_generator() data = {} data.update({'mch_id': acquirer.weixin_mch_id, 'nonce_str': nonce_str}) _, prestr = util.params_filter(data) key = acquirer.weixin_key _logger.info("+++ prestr %s, Weixin Key %s" % (prestr, key)) data['sign'] = util.build_mysign(prestr, key, 'MD5') data_xml = "<xml>" + self.json2xml(data) + "</xml>" request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) _logger.info( "_______get_weixin_signkey_____ request to %s and the request data is %s, and request result is %s" % (url, data_xml, result) ) return_xml = etree.fromstring(result) if return_xml.find('return_code').text == "SUCCESS" and return_xml.find( 'sandbox_signkey' ).text != False: sandbox_signkey = return_xml.find('sandbox_signkey').text else: return_code = return_xml.find('return_code').text return_msg = return_xml.find('return_msg').text raise UserError("%s, %s" % (return_code, return_msg)) return sandbox_signkey
def _get_weixin_signkey(self, acquirer): url = 'https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey' nonce_str = self.random_generator() data = {} data.update({'mch_id': acquirer.weixin_mch_id, 'nonce_str': nonce_str}) _, prestr = util.params_filter(data) key = acquirer.weixin_key _logger.info("+++ prestr %s, Weixin Key %s" % (prestr, key)) data['sign'] = util.build_mysign(prestr, key, 'MD5') data_xml = "<xml>" + self.json2xml(data) + "</xml>" request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) _logger.info( "_______get_weixin_signkey_____ request to %s and the request data is %s, and request result is %s" % (url, data_xml, result)) return_xml = etree.fromstring(result) if return_xml.find( 'return_code').text == "SUCCESS" and return_xml.find( 'sandbox_signkey').text != False: sandbox_signkey = return_xml.find('sandbox_signkey').text else: return_code = return_xml.find('return_code').text return_msg = return_xml.find('return_msg').text raise UserError("%s, %s" % (return_code, return_msg)) return sandbox_signkey
def search_order(self): weixin_appid = 'wxb3be4c9e8f1add69' weixin_mch_id = '1280015001' weixin_key = 'be9aded460e78703b889f18e2915ea6c' payid = self.env['payment.transaction'].search([('state', '=', 'draft') ]) for payid in payid: out_trade_no = payid.acquirer_reference url = 'https://api.mch.weixin.qq.com/pay/orderquery' nonce_str = self.random_generator() data_post = { 'appid': weixin_appid, 'mch_id': weixin_mch_id, 'out_trade_no': out_trade_no, 'nonce_str': nonce_str, } _, prestr = util.params_filter(data_post) sign = util.build_mysign(prestr, weixin_key, 'MD5') data_post['sign'] = sign data_xml = "<xml>" + self.json2xml(data_post) + "</xml>" request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) json = {} for el in etree.fromstring(str(result)): json[el.tag] = el.text return json
def _gen_weixin_code_url(self, post_data): data = {} data.update({ 'appid': post_data['appid'], 'mch_id': post_data['mch_id'], 'nonce_str': post_data['nonce_str'], 'body': post_data['body'], 'out_trade_no': post_data['out_trade_no'], 'total_fee': post_data['total_fee'], 'spbill_create_ip': post_data['spbill_create_ip'], 'notify_url': post_data['notify_url'], 'trade_type': post_data['trade_type'], }) acquirer = self.search([('weixin_appid', '=', post_data['appid'])]) _logger.info("--- acquirer %s" % (acquirer)) if acquirer.environment == 'prod': key = acquirer.weixin_key else: key = self._get_weixin_signkey(acquirer) _, prestr = util.params_filter(data) _logger.info("+++ prestr %s, Weixin Key %s" % (prestr, key)) data['sign'] = util.build_mysign(prestr, key, 'MD5') data_xml = "<xml>" + self.json2xml(data) + "</xml>" url = acquirer._get_weixin_urls(acquirer.environment)['weixin_url'] request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) _logger.info( "________gen_weixin_code_url_____ request to %s and the request data is %s, and request result is %s" % (url, data_xml, result)) return_xml = etree.fromstring(result) data_json = {} for el in return_xml: data_json[el.tag] = el.text if data_json['return_code'] == "SUCCESS" and data_json.get( 'code_url', False): return data_json['code_url'] else: return_code = data_json.get('return_code') return_msg = data_json.get('return_msg') msg = "[%s] %s " % (return_code, return_msg) _logger.info('+++ some error occurred %s' % msg) # raise UserError(msg) return False
def weixin_form_generate_values(self, tx_values): self.ensure_one() base_url = self.env['ir.config_parameter'].get_param('web.base.url') amount = int(tx_values.get('amount', 0) * 100) nonce_str = self.random_generator() data_post = {} now_time = time.strftime('%Y%m%d%H%M%S') data_post.update({ 'appid': self.weixin_appid, 'body': tx_values['reference'], 'mch_id': self.weixin_mch_id, 'nonce_str': nonce_str, 'notify_url': '%s' % urlparse.urljoin(base_url, WeixinController._notify_url), 'out_trade_no': now_time, 'spbill_create_ip': self._get_ipaddress(), 'total_fee': amount, 'trade_type': 'NATIVE', }) _, prestr = util.params_filter(data_post) sign = util.build_mysign(prestr, self.weixin_key, 'MD5') data_post['sign'] = sign # payid=self.env['payment.transaction'].search([('create_uid','=',self.env.uid),('state','=','draft'),('acquirer_id','=',self.id)]) # for payid in payid: # payid.acquirer_reference=data_post['out_trade_no'] data_xml = "<xml>" + self.json2xml(data_post) + "</xml>" url = self._get_weixin_urls(self.environment)['weixin_url'] request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) data_post.update({ 'data_xml': data_xml, }) return_xml = etree.fromstring(result) if return_xml.find( 'return_code' ).text == "SUCCESS" and return_xml.find('code_url').text != False: qrcode = return_xml.find('code_url').text data_post.update({ 'qrcode': qrcode, }) else: return_code = return_xml.find('return_code').text return_msg = return_xml.find('return_msg').text raise ValidationError("%s, %s" % (return_code, return_msg)) tx_values = data_post return tx_values
def get_didi(self, **post): """ 钉钉权限验证 准备相关数据,输出页面调用钉钉客户端JSAPI来进行权限验证 验证通过后 """ # 获取access_token corpid = 'dinge0b8fc92eb965404' corpsecret = 'MkKb_QDrtkwigaBar13AHo51xQLcJdnzLFiE_giow1kXeQUWLDH0K-1kC9gup7Zx' agentid = '10292872' url = 'https://oapi.dingtalk.com/gettoken?' args = { 'corpid': corpid, 'corpsecret': corpsecret } url += urlencode(args) response = urllib2.urlopen(url, timeout=60) result = json.loads(response.read()) access_token = result.get('access_token') # 获取jsapi_ticket url_1 = 'https://oapi.dingtalk.com/get_jsapi_ticket?access_token=' + access_token + '&type=jsapi' response_1 = urllib2.urlopen(url_1, timeout=60) result_1 = json.loads(response_1.read()) jsapi_ticket = result_1.get('ticket') # 生成一个随机字符串,不长于32位,主要保证签名不可预测 nonceStr = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' chars_length = len(chars) - 1 for i in range(1, 16, 1): nonceStr += chars[random.randint(0, chars_length)] timeStamp = int(time.time()) url = 'http://runbot.qdodoo.com/qdoo/dd/work' key_valu = { 'noncestr': nonceStr, 'timestamp': timeStamp, 'jsapi_ticket': jsapi_ticket, 'url': url, } _, prestr_new = util.params_filter(key_valu) key_valu['signature'] = hashlib.sha1(prestr_new).hexdigest() key_valu['corpId'] = corpid key_valu['agentId'] = agentid key_valu['access_token'] = access_token return request.website.render("qdodoo_dingtalk.didi2", key_valu)
def tenpay_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool["ir.config_parameter"].get_param(cr, SUPERUSER_ID, "web.base.url") acquirer = self.browse(cr, uid, id, context=context) amount = int(tx_values.get("total_fee", 0) * 100) tenpay_tx_values = dict(tx_values) tenpay_tx_values.update( { "total_fee": amount, "spbill_create_ip": acquirer._get_ipaddress(), "partner": acquirer.tenpay_partner_account, "out_trade_no": tx_values["reference"], "body": "%s: %s" % (acquirer.company_id.name, tx_values["reference"]), "bank_type": "DEFAULT", "fee_type": 1, "input_charset": "utf-8", "return_url": "%s" % urlparse.urljoin(base_url, TenpayController._return_url), "notify_url": "%s" % urlparse.urljoin(base_url, TenpayController._notify_url), } ) to_sign = {} to_sign.update( { "total_fee": amount, "spbill_create_ip": acquirer._get_ipaddress(), "partner": acquirer.tenpay_partner_account, "out_trade_no": tx_values["reference"], "body": "%s: %s" % (acquirer.company_id.name, tx_values["reference"]), "bank_type": "DEFAULT", "fee_type": 1, "input_charset": "utf-8", "return_url": "%s" % urlparse.urljoin(base_url, TenpayController._return_url), "notify_url": "%s" % urlparse.urljoin(base_url, TenpayController._notify_url), } ) _, prestr = util.params_filter(to_sign) tenpay_tx_values["sign"] = util.build_mysign(prestr, acquirer.tenpay_partner_key, "MD5") tenpay_tx_values["sign_type"] = "MD5" context = context context["_data_exchange"] = tenpay_tx_values return partner_values, tenpay_tx_values
def get_didi(self, **post): """ 钉钉权限验证 准备相关数据,输出页面调用钉钉客户端JSAPI来进行权限验证 验证通过后 """ # 获取access_token corpid = 'dinge0b8fc92eb965404' corpsecret = 'MkKb_QDrtkwigaBar13AHo51xQLcJdnzLFiE_giow1kXeQUWLDH0K-1kC9gup7Zx' agentid = '10292872' url = 'https://oapi.dingtalk.com/gettoken?' args = {'corpid': corpid, 'corpsecret': corpsecret} url += urlencode(args) response = urllib2.urlopen(url, timeout=60) result = json.loads(response.read()) access_token = result.get('access_token') # 获取jsapi_ticket url_1 = 'https://oapi.dingtalk.com/get_jsapi_ticket?access_token=' + access_token + '&type=jsapi' response_1 = urllib2.urlopen(url_1, timeout=60) result_1 = json.loads(response_1.read()) jsapi_ticket = result_1.get('ticket') # 生成一个随机字符串,不长于32位,主要保证签名不可预测 nonceStr = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' chars_length = len(chars) - 1 for i in range(1, 16, 1): nonceStr += chars[random.randint(0, chars_length)] timeStamp = int(time.time()) url = 'http://runbot.qdodoo.com/qdoo/dd/work' key_valu = { 'noncestr': nonceStr, 'timestamp': timeStamp, 'jsapi_ticket': jsapi_ticket, 'url': url, } _, prestr_new = util.params_filter(key_valu) key_valu['signature'] = hashlib.sha1(prestr_new).hexdigest() key_valu['corpId'] = corpid key_valu['agentId'] = agentid key_valu['access_token'] = access_token return request.website.render("qdodoo_dingtalk.didi2", key_valu)
def tenpay_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) amount = int(tx_values.get('total_fee', 0) * 100) tenpay_tx_values = dict(tx_values) tenpay_tx_values.update({ 'total_fee': amount, 'spbill_create_ip': acquirer._get_ipaddress(), 'partner': acquirer.tenpay_partner_account, 'out_trade_no': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'bank_type': 'DEFAULT', 'fee_type': 1, 'input_charset': 'utf-8', 'return_url': '%s' % urlparse.urljoin(base_url, TenpayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, TenpayController._notify_url), }) to_sign = {} to_sign.update({ 'total_fee': amount, 'spbill_create_ip': acquirer._get_ipaddress(), 'partner': acquirer.tenpay_partner_account, 'out_trade_no': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'bank_type': 'DEFAULT', 'fee_type': 1, 'input_charset': 'utf-8', 'return_url': '%s' % urlparse.urljoin(base_url, TenpayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, TenpayController._notify_url), }) _,prestr = util.params_filter(to_sign) tenpay_tx_values['sign'] = util.build_mysign(prestr, acquirer.tenpay_partner_key, 'MD5') tenpay_tx_values['sign_type'] = 'MD5' context = context context['_data_exchange'] = tenpay_tx_values return partner_values, tenpay_tx_values
def alipay_fuwu(self, **post): """ 支付宝服务窗开发者模式验证和消息接受地址 """ # 将post来的参数排除掉sign后作为待签名参数 sign_params_dic = {} for post_key, post_val in post.items(): if not post_key == 'sign': sign_params_dic[post_key] = post_val.decode('utf8') # 待签名参数按key值排序,组合成query字符串 _, sign_query_str = util.params_filter(sign_params_dic) # 使用支付宝公钥签名验签 sign_verify = RSA.load_pub_key( 'addons-extra/wxsite/static/alipay_rsa_public_key.pem').verify( sign_query_str, post['sign']) # sign_by_ali_pub64 = sign_by_ali_pub.encode('base64') if sign_verify: # 待签名字符串:公钥+success str_to_sign_by_private = '<biz_content>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9vK4cSuzfGJKMJ/XQ82SMxRjbVussG+sI4lrgJLa7cbHZ19+zZRy9IyMYyvpD/gm4blgha0iOhRxPuxmvLHcNerG2u9q+X18NeJ0bLHxZRpPhOXMzgBDp78LDG1m7NtNW5Poat2JZyxSCTBbs1x3Tk9NUVr8mHLpriFO1ik4EEwIDAQAB</biz_content><success>true</success>' # 加载私钥进行签名 rsa_private_key = load_privatekey( FILETYPE_PEM, open('addons-extra/wxsite/static/rsa_private_key.pem').read()) rsa_private_sign = sign(rsa_private_key, str_to_sign_by_private, 'sha1') rsa_private_sign = base64.b64encode(rsa_private_sign) # 拼接返回给支付宝的xml内容 response_xml = '<?xml version="1.0" encoding="GBK"?><alipay><response>' + str_to_sign_by_private + '</response><sign>' + rsa_private_sign + '</sign><sign_type>RSA</sign_type></alipay>' return response_xml.encode('gbk') else: return 'fail'.encode('gbk')
def tenpay_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param( cr, SUPERUSER_ID, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) amount = int(tx_values.get('total_fee', 0) * 100) tenpay_tx_values = dict(tx_values) tenpay_tx_values.update({ 'total_fee': amount, 'spbill_create_ip': acquirer._get_ipaddress(), 'partner': acquirer.tenpay_partner_account, 'out_trade_no': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'bank_type': 'DEFAULT', 'fee_type': 1, 'input_charset': 'utf-8', 'return_url': '%s' % urlparse.urljoin(base_url, TenpayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, TenpayController._notify_url), }) to_sign = {} to_sign.update({ 'total_fee': amount, 'spbill_create_ip': acquirer._get_ipaddress(), 'partner': acquirer.tenpay_partner_account, 'out_trade_no': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'bank_type': 'DEFAULT', 'fee_type': 1, 'input_charset': 'utf-8', 'return_url': '%s' % urlparse.urljoin(base_url, TenpayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, TenpayController._notify_url), }) _, prestr = util.params_filter(to_sign) tenpay_tx_values['sign'] = util.build_mysign( prestr, acquirer.tenpay_partner_key, 'MD5') tenpay_tx_values['sign_type'] = 'MD5' context = context context['_data_exchange'] = tenpay_tx_values return partner_values, tenpay_tx_values
def wx_pay(self, **post): """ 微信JSAPI支付,调用链接如:http://www.qdodoo.com/wxsite/wxpay/20160107125945356,其中20160107125945356是订单号 需先到微信公众号平台配置支付授权目录(如:http://www.qdodoo.com/wxsite/wxpay/)——也可以配置测试目录,但测试有一定限制,因此可以直接在正式环境中使用1分钱订单测试 还需到微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置中设置密钥,对应本函数中的wx_key 参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1 """ cr, uid, context, pool = request.cr,request.uid, request.context, request.registry # 获取当前公司的名称(根据用户模型获取数据) users_obj = pool.get('res.users') users = users_obj.browse(cr, SUPERUSER_ID, uid) company_name = users.company_id.name partner_id = users.partner_id.id order_obj = pool.get('pos.order') if post.get('oid'): res_order_id = int(post.get('oid')) all_money = float(post.get('money')) all_car_num = 0 for order in order_obj.browse(cr, SUPERUSER_ID, res_order_id).lines: all_car_num += order.qty else: # 生成销售订单(POS) order_line_obj = pool.get('pos.order.line') res_order_id = order_obj.create(cr, SUPERUSER_ID, {'partner_id':partner_id,'pricelist_id':1}) # 获取加入购物车的总金额 all_money = 0 all_car_num = 0 car_obj = pool.get('qdodoo.wxsite.car') car_ids = car_obj.search(cr, SUPERUSER_ID, [('user_id','=',uid)]) for key_line in car_obj.browse(cr, SUPERUSER_ID, car_ids): all_money += key_line.number * key_line.name.lst_price #获取总金额 all_car_num += key_line.number # 生成销售单明细 order_line_obj.create(cr, SUPERUSER_ID, {'order_id':res_order_id,'product_id':key_line.name.id, 'qty':key_line.number,'price_unit':key_line.name.lst_price}) car_obj.unlink(cr, SUPERUSER_ID, car_ids) wx_openid = request.session['openid'] #微信用户openid #下面几个变量是微信支付相关配置 wx_appid = 'wxde2cf9dbf3c35624' #公众号号APPID,通常是微信签约时的服务号APPID wx_mchid = '1294510601' #商户号,签约微信支付后分配的商户号 wx_key = '33132ac4f37f151dbfcbfce34f441d71' #微信支付密钥,到微信商户平台设置并填写此处 wx_pay_backnotify = 'http://www.qdodoo.com/shop/wx/backnotify' #接收微信支付异步通知地址,不可携带参数 #生成一个随机字符串,不长于32位,主要保证签名不可预测 nonce_str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' chars_length = len(chars) - 1 for i in range(1, 32, 1): nonce_str += chars[random.randint(0, chars_length)] #微信统一下单接口所需参数 wx_oparam = { 'appid': wx_appid, #公众号号APPID 'mch_id': wx_mchid, #商户号 'nonce_str': nonce_str, 'body': u'点餐订单', #支付单简要描述 'out_trade_no': res_order_id, #商户订单号 'total_fee': int(all_money * 100), #支付金额,单位为“分”,所以要x100 'spbill_create_ip': '115.28.223.85', #用户端IP地址,此处我不知道怎么获取 'notify_url': wx_pay_backnotify, #异步通知地址 'trade_type': 'JSAPI', #交易类型 'openid': wx_openid, #微信用户openid,交易类型为jsapi时,此参数必传 'attach': 'wxsite', #附加数据,用于商户携带自定义数据,在查询API和支付通知中原样返回,可选填,但不要留空 } """ 参数签名,将非空字典键值按ASCII码升序排列,然后按url键值对拼接,最后拼接上微信支付密钥key 将所拼接的字符串进行MD5运算,再将得到的字符串中所有字母转换为大写。即是签名 """ _, prestr = util.params_filter(wx_oparam) wx_oparam['sign'] = hashlib.md5(prestr + '&key=' +wx_key).hexdigest().upper() data_xml = "<xml>" + self.json2xml(wx_oparam) + "</xml>" url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' #接口地址 request_new = urllib2.Request(url, data_xml) res = urllib2.urlopen(request_new) return_xml = etree.fromstring(res.read()) if return_xml.find('return_code').text == 'SUCCESS': if return_xml.find('result_code').text == 'SUCCESS': prepay_id = return_xml.find('prepay_id').text #预下单编号 #再生成一个随机字符串,不长于32位,仍然是保证接下来签名不可预测 nonce_str = '' for i in range(1, 32, 1): nonce_str += chars[random.randint(0, chars_length)] #JSAPI支付所需数据 wx_pay_dict = { 'appId': wx_appid, #微信公众号APPID 'timeStamp': str(time.time()), #当前Unix时间戳 'nonceStr': nonce_str, #随机字符串 'package': 'prepay_id='+prepay_id, #订单详情扩展,主要填写统一下单接口返回的预下单编号 'signType': 'MD5', #签名算法,目前仅支持MD5 } _, prestr_new = util.params_filter(wx_pay_dict) wx_pay_dict['paySign'] = hashlib.md5(prestr_new + '&key=' +wx_key).hexdigest().upper() #转换成json格式,将在页面js脚本中使用该数据 wx_pay_json = json.dumps(wx_pay_dict) #显示微信支付页面 values = { 'pay_json': wx_pay_json, 'company_name':company_name, 'all_car_num': all_car_num, 'all_money':all_money, } return request.website.render("wxsite.wxpay", values) else: error_text = '' if return_xml.find('err_code'): error_text = error_text + u'错误代码为:' + return_xml.find('err_code') if return_xml.find('err_code_des'): error_text = error_text + '\n' + return_xml.find('err_code_des') else: error_text = u'交易发起失败,请稍后重试!' else: if return_xml.find('return_msg'): error_text = return_xml.find('return_msg').text else: error_text = u'交易发起失败,请稍后重试!' values = { 'company_name':company_name, 'error_text':error_text, 'all_car_num':all_car_num, } return request.website.render("wxsite.error", values)
def weixin_form_generate_values(self, partner_values, tx_values): self.ensure_one() base_url = self.env['ir.config_parameter'].get_param('web.base.url') amount = int(tx_values.get('amount', 0) * 100) nonce_str = self.random_generator() weixin_tx_values = dict(tx_values) weixin_tx_values.update({ 'appid': self.weixin_appid, 'mch_id': self.weixin_mch_id, 'nonce_str': nonce_str, 'body': tx_values['reference'], 'out_trade_no': tx_values['reference'], 'total_fee': amount, 'spbill_create_ip': self._get_ipaddress(), 'notify_url': '%s' % urlparse.urljoin(base_url, WeixinController._notify_url), 'trade_type': 'NATIVE', 'product_id': tx_values['reference'], }) data_post = {} data_post.update({ 'appid': self.weixin_appid, 'mch_id': self.weixin_mch_id, 'nonce_str': nonce_str, 'body': tx_values['reference'], 'out_trade_no': tx_values['reference'], 'total_fee': amount, 'spbill_create_ip': self._get_ipaddress(), 'notify_url': '%s' % urlparse.urljoin(base_url, WeixinController._notify_url), 'trade_type': 'NATIVE', 'product_id': tx_values['reference'], }) _, prestr = util.params_filter(data_post) weixin_tx_values['sign'] = util.build_mysign(prestr, self.weixin_key, 'MD5') data_post['sign'] = weixin_tx_values['sign'] data_xml = "<xml>" + self.json2xml(data_post) + "</xml>" url = self._get_weixin_urls(self.environment)['weixin_url'] request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) _logger.info( "request to %s and the request data is %s, and request result is %s" % (url, data_xml, result)) return_xml = etree.fromstring(result) if return_xml.find( 'return_code' ).text == "SUCCESS" and return_xml.find('code_url').text != False: qrcode = return_xml.find('code_url').text weixin_tx_values['qrcode'] = qrcode else: return_code = return_xml.find('return_code').text return_msg = return_xml.find('return_msg').text raise ValidationError("%s, %s" % (return_code, return_msg)) return partner_values, weixin_tx_values
def alipay_form_generate_values(self, tx_values): base_url = self.env['ir.config_parameter' ].sudo().get_param('web.base.url') alipay_tx_values = dict(tx_values) alipay_tx_values.update( { 'partner': self.alipay_partner_account, 'seller_email': self.alipay_seller_email, 'seller_id': self.alipay_partner_account, '_input_charset': 'UTF-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': tx_values['reference'], 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), } ) to_sign = {} to_sign.update( { 'partner': self.alipay_partner_account, 'seller_email': self.alipay_seller_email, 'seller_id': self.alipay_partner_account, '_input_charset': 'UTF-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': tx_values['reference'], 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), } ) payload_direct = { 'service': 'create_direct_pay_by_user', 'total_fee': tx_values['amount'], } payload_escow = { 'service': 'create_partner_trade_by_buyer', 'logistics_type': 'EXPRESS', 'logistics_fee': 0, 'logistics_payment': 'SELLER_PAY', 'price': tx_values['amount'], 'quantity': 1, } if self.alipay_interface_type == 'create_direct_pay_by_user': to_sign.update(payload_direct) alipay_tx_values.update(payload_direct) if self.alipay_interface_type == 'create_partner_trade_by_buyer': to_sign.update(payload_escow) alipay_tx_values.update(payload_escow) _, prestr = util.params_filter(to_sign) alipay_tx_values['sign'] = util.build_mysign( prestr, self.alipay_partner_key, 'MD5' ) alipay_tx_values['sign_type'] = 'MD5' _logger.info('----alipay tx_values is %s' % alipay_tx_values) return alipay_tx_values
def wxpay_backnotify(self, **post): """ 微信支付异步通知地址 当用户成功支付后,微信服务器会POST一份xml格式的支付信息到该地址,通过商户订单号和支付状态进行处理 处理后需返回一个xml信息,格式示例: <xml> <return_code><![CDATA[success]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml> 参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 """ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry config = pool.get('ir.config_parameter') #下面几个变量是微信支付相关配置 wx_key = config.get_param(cr, uid, 'wx_key') #微信支付密钥,到微信商户平台设置并填写此处 order_obj = pool.get('pos.order') payment_obj = pool.get('pos.make.payment') config_obj = pool.get('pos.config') print_list_obj = pool.get('qdodoo.print.list') dict_post_ip = self.pos_id() config_id = config_obj.search(cr, SUPERUSER_ID, [('iface_print_via_proxy','=',True)]) if config_id: proxy_ip = config_obj.browse(cr, SUPERUSER_ID, config_id[0]).proxy_ip # 有返回结果 if post: #解析post过来的xml数据,获取必要的信息 post_dict = json.loads(post) #解析json为dict #需返回给微信的参数,默认处理成功 ret_dict = { 'return_code': 'SUCCESS', 'return_msg': 'OK', } #如果支付成功,则进行处理 if post_dict['return_code'] == 'SUCCESS': #对post过来的数据进行签名,与post参数中的签名sign进行对比 post_sign_dict = {} #捡取非空参数,不包含签名sign for key, val in post_dict.items(): if not val == '' and not key == 'sign': post_sign_dict[key] = val post_sign_dict = sorted(post_sign_dict.iteritems(), key=lambda d:d[0]) post_sign_keyval = '' for key, val in post_sign_dict.items(): post_sign_keyval += key+'='+val+'&' post_sign_keyval += 'key='+wx_key post_sign = hashlib.new("md5", post_sign_keyval).hexdigest().upper() #根据微信post来的参数计算出的签名 if post_sign == post_dict['sign']: #自己计算出来的签名与微信post过来的sign签名一致,则验签通过 oid = post_dict['out_trade_no'] #商户订单号,与发起微信支付时填写的out_trade_no一致,可据此处理对应订单 if oid[0] == '0': oid = oid[1:] wxpay_qid = post_dict['transaction_id'] #微信支付交易流水号,可据此对账 wxpay_sum = int(post_dict['total_fee'])/100 #实际支付金额,单位:分,除以100转换成元 #基本以上参数足够处理订单,以下也是post中必含的参数,可酌情使用 wxpay_openid = post_dict['openid'] #支付的微信用户openid,原则上与发起支付的openid一致 wxpay_tradetype = post_dict['trade_type'] #支付方式,原则上与发起支付的方式一致,如JSAPI wxpay_appid = post_dict['appid'] #公众号APPID wxpay_mch_id = post_dict['mch_id'] #商户号 wxpay_banktype = post_dict['bank_type'] #银行类型,标识所代表的银行可参考官方说明 wxpay_endtime = post_dict['time_end'] #支付完成时间,格式:yyyyMMddHHmmss,如:20160108124035 """ 下面可以根据以上获取的参数对订单进行处理 小提示:微信可能多次发送同一笔支付通知,因此需先检验该订单支付是否已经处理过,未处理过的才进行处理 比如更改订单状态、财务出入帐等 """ order_obj.signal_workflow(cr, SUPERUSER_ID, [int(oid)], 'paid') else: #验签失败 ret_dict['code'] = 'fail' ret_dict['desc'] = 'sign valid fail' #最终,要返回处理结果的xml格式数据 wxpay_ret_xml = Element('xml') for key, val in ret_dict.items(): xml_child = Element(key) xml_child.text = str(val) wxpay_ret_xml.append(xml_child) return wxpay_ret_xml else: # 没有返回结果,执行查询方法 wx_add = 'https://api.mch.weixin.qq.com/pay/orderquery' wx_appid = config.get_param(cr, uid, 'wx_appid') #公众号号APPID,通常是微信签约时的服务号APPID wx_mchid = config.get_param(cr, uid, 'wx_mchid') #商户号,签约微信支付后分配的商户号 wx_fix = config.get_param(cr, uid, 'wx_fix') #付款订单号前缀 # 查询所有未完成的订单 order_ids = order_obj.search(cr, SUPERUSER_ID, [('state','=','draft'),('partner_id','!=',False)]) for order_id in order_ids: #生成一个随机字符串,不长于32位,主要保证签名不可预测 nonce_str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' chars_length = len(chars) - 1 for i in range(1, 32, 1): nonce_str += chars[random.randint(0, chars_length)] out_trade_no = wx_fix + str(order_id) #微信查询接口所需参数 wx_search = { 'appid': wx_appid, #公众号号APPID 'mch_id': wx_mchid, #商户号 'nonce_str': nonce_str, 'out_trade_no': out_trade_no, #商户订单号 } """ 参数签名,将非空字典键值按ASCII码升序排列,然后按url键值对拼接,最后拼接上微信支付密钥key 将所拼接的字符串进行MD5运算,再将得到的字符串中所有字母转换为大写。即是签名 """ _, prestr_select = util.params_filter(wx_search) wx_search['sign'] = hashlib.md5(prestr_select + '&key=' +wx_key).hexdigest().upper() data_xml = "<xml>" + self.json2xml(wx_search) + "</xml>" request_new = urllib2.Request(wx_add, data_xml) res = urllib2.urlopen(request_new) return_xml = etree.fromstring(res.read()) if return_xml.find('return_code').text == "SUCCESS" and return_xml.find('result_code').text != 'FAIL': pay_state = return_xml.find('trade_state').text #交易状态 pos_obj = order_obj.browse(cr, SUPERUSER_ID, int(order_id)) date_order = pos_obj.date_order if pay_state == 'SUCCESS': try: res_id = payment_obj.create(cr, SUPERUSER_ID, {'journal_id':pos_obj.session_id.config_id.journal_ids[0].id, 'amount':pos_obj.amount_total,'payment_name':u'微信支付', 'payment_date':datetime.now().date()}) payment_obj.check(cr, SUPERUSER_ID, [res_id], context={'active_id':pos_obj.id}) # 组织后台打印数据 infomation_new = """<receipt align="center" value-thousands-separator="" width="40"> <div font="b"> <div><pre>订单号 %s</pre></div> <div><pre>%s</pre></div> </div> <br/><br/> <div line-ratio="0.6">++++++"""%(pos_obj.name,datetime.now()) # 组织前台打印数据 infomation = """<receipt align="center" value-thousands-separator="" width="40"> <div font="b"> <div>微信支付-结账单</div> <div>订单号:%s</div> <div>时间:%s</div> <div>==============================================</div> <br/><br/> ++++++<div>产品 数量 单价 金额 @@@@@%s@@@@@</div>++++++"""%(pos_obj.name,datetime.now(),pos_obj.session_id.config_id.front_desk) for line in pos_obj.lines: infomation_new += """<line size="double-height"> <left><pre>%s</pre></left> <right><value>%s</value></right> @@@@@%s@@@@@ </line>++++++"""%(line.product_id.name,line.qty,dict_post_ip.get(line.product_id.pos_categ_id.id)) product_id_name = line.product_id.name if len(product_id_name) < 8: product_id_name += (' ' * (8-len(product_id_name))) else: product_id_name = product_id_name[:8] product_qty = str(line.qty) if len(product_qty) < 6: product_qty += (' ' * 4) else: product_qty = product_qty[:6] product_list = str(line.product_id.list_price) if len(product_list) < 6: product_list += (' ' * 4) else: product_list = product_list[:6] product_subtotal = str(line.price_subtotal_incl) if len(product_subtotal) < 6: product_subtotal += (' ' * 4) else: product_subtotal = product_subtotal[:6] infomation += """<div> %s %s %s %s @@@@@%s@@@@@ </div>++++++"""%(product_id_name,product_qty,product_list, product_subtotal, pos_obj.session_id.config_id.front_desk) infomation_new += """</div> <br/><br/><br/> <div size="double-height"> <left><pre>备注:%s号桌 %s</pre></left> </div> </receipt>"""%(pos_obj.customer_count, pos_obj.note) amount_total = str(pos_obj.amount_total) if len(amount_total) < 6: amount_total += (' ' * 4) else: amount_total = amount_total[:6] note = u'号桌:'+str(pos_obj.customer_count)+' 备注:'+ pos_obj.note infomation += """ <br/><br/><br/> <div size="double-height"> 合计 %s </div> <br/> <div size="double-height"> %s </div> <br/><br/> <div>==============================================</div> <div>%s</div> <div>电话:%s</div> <div>%s</div> </div> </receipt>"""%(amount_total, note, pos_obj.company_id.name, pos_obj.company_id.phone, pos_obj.company_id.website) print_list_obj.create(cr, SUPERUSER_ID, {'name':infomation,'is_print':False}) print_list_obj.create(cr, SUPERUSER_ID, {'name':infomation_new,'is_print':False}) except Exception,e: _logger.info('ERROR------------------------:%s'%e) order_obj.write(cr, SUPERUSER_ID, [int(order_id)], {'is_payment':True}) elif pay_state == 'USERPAYING': pass elif pay_state == 'PAYERROR': order_obj.signal_workflow(cr, SUPERUSER_ID, [int(order_id)], 'cancel') else: if date_order[:10] < datetime.now().date().strftime('%Y-%m-%d'): order_obj.signal_workflow(cr, SUPERUSER_ID, [int(order_id)], 'cancel') else: pass return 'SUCCESS'
def _gen_weixin_code_url(self, post_data): data = {} data.update( { 'appid': post_data['appid'], 'mch_id': post_data['mch_id'], 'nonce_str': post_data['nonce_str'], 'body': post_data['body'], 'out_trade_no': post_data['out_trade_no'], 'total_fee': post_data['total_fee'], 'spbill_create_ip': post_data['spbill_create_ip'], 'notify_url': post_data['notify_url'], 'trade_type': post_data['trade_type'], } ) acquirer = self.search([('weixin_appid', '=', post_data['appid'])]) _logger.info("--- acquirer %s" % (acquirer)) if acquirer.environment == 'prod': key = acquirer.weixin_key else: key = self._get_weixin_signkey(acquirer) _, prestr = util.params_filter(data) _logger.info("+++ prestr %s, Weixin Key %s" % (prestr, key)) data['sign'] = util.build_mysign(prestr, key, 'MD5') data_xml = "<xml>" + self.json2xml(data) + "</xml>" url = acquirer._get_weixin_urls(acquirer.environment)['weixin_url'] request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) _logger.info( "________gen_weixin_code_url_____ request to %s and the request data is %s, and request result is %s" % (url, data_xml, result) ) return_xml = etree.fromstring(result) data_json = {} for el in return_xml: data_json[el.tag] = el.text if data_json['return_code'] == "SUCCESS" and data_json.get( 'code_url', False ): return data_json['code_url'] else: return_code = data_json.get('return_code') return_msg = data_json.get('return_msg') msg = "[%s] %s " % (return_code, return_msg) _logger.info('+++ some error occurred %s' % msg) # raise UserError(msg) return False
def alipay_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) alipay_tx_values = dict(tx_values) alipay_tx_values.update({ 'partner': acquirer.alipay_partner_account, 'seller_email': acquirer.alipay_seller_email, 'seller_id': acquirer.alipay_partner_account, '_input_charset': 'utf-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), }) to_sign = {} to_sign.update({ 'partner': acquirer.alipay_partner_account, 'seller_email': acquirer.alipay_seller_email, 'seller_id': acquirer.alipay_partner_account, '_input_charset': 'utf-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), }) payload_direct = { 'service': 'create_direct_pay_by_user', 'total_fee': tx_values['amount'], } payload_escow = { 'service': 'create_partner_trade_by_buyer', 'logistics_type': 'EXPRESS', 'logistics_fee': 0, 'logistics_payment': 'SELLER_PAY', 'price': tx_values['amount'], 'quantity': 1, } payload_dualfun = { 'service': 'trade_create_by_buyer', 'logistics_type': 'EXPRESS', 'logistics_fee': 0, 'logistics_payment': 'SELLER_PAY', 'price': tx_values['amount'], 'quantity': 1, } if acquirer.alipay_interface_type == 'create_direct_pay_by_user': to_sign.update(payload_direct) alipay_tx_values.update(payload_direct) if acquirer.alipay_interface_type == 'create_partner_trade_by_buyer': to_sign.update(payload_escow) alipay_tx_values.update(payload_direct) if acquirer.alipay_interface_type == 'trade_create_by_buyer': to_sign.update(payload_dualfun) alipay_tx_values.update(payload_direct) _, prestr = util.params_filter(to_sign) alipay_tx_values['sign'] = util.build_mysign(prestr, acquirer.alipay_partner_key, 'MD5') alipay_tx_values['sign_type'] = 'MD5' return partner_values, alipay_tx_values
def weixin_form_generate_values(self, partner_values, tx_values): self.ensure_one() base_url = self.env['ir.config_parameter'].get_param('web.base.url') amount = int(tx_values.get('amount', 0) * 100) nonce_str = self.random_generator() weixin_tx_values = dict(tx_values) weixin_tx_values.update( { 'appid': self.weixin_appid, 'mch_id': self.weixin_mch_id, 'nonce_str': nonce_str, 'body': tx_values['reference'], 'out_trade_no': tx_values['reference'], 'total_fee': amount, 'spbill_create_ip': self._get_ipaddress(), 'notify_url': '%s' % urlparse.urljoin(base_url, WeixinController._notify_url), 'trade_type': 'NATIVE', 'product_id': tx_values['reference'], } ) data_post = {} data_post.update( { 'appid': self.weixin_appid, 'mch_id': self.weixin_mch_id, 'nonce_str': nonce_str, 'body': tx_values['reference'], 'out_trade_no': tx_values['reference'], 'total_fee': amount, 'spbill_create_ip': self._get_ipaddress(), 'notify_url': '%s' % urlparse.urljoin(base_url, WeixinController._notify_url), 'trade_type': 'NATIVE', 'product_id': tx_values['reference'], } ) _, prestr = util.params_filter(data_post) weixin_tx_values['sign'] = util.build_mysign(prestr, self.weixin_key, 'MD5') data_post['sign'] = weixin_tx_values['sign'] data_xml = "<xml>" + self.json2xml(data_post) + "</xml>" url = self._get_weixin_urls(self.environment)['weixin_url'] request = urllib2.Request(url, data_xml) result = self._try_url(request, tries=3) _logger.info("request to %s and the request data is %s, and request result is %s" % (url, data_xml, result)) return_xml = etree.fromstring(result) if return_xml.find('return_code').text == "SUCCESS" and return_xml.find('code_url').text <> False: qrcode = return_xml.find('code_url').text weixin_tx_values['qrcode'] = qrcode else: return_code = return_xml.find('return_code').text return_msg = return_xml.find('return_msg').text raise ValidationError("%s, %s" % (return_code, return_msg)) return partner_values, weixin_tx_values
def alipay(self, **post): """ 支付宝wap支付 """ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry # 获取当前公司的名称(根据用户模型获取数据) users_obj = pool.get('res.users') product_obj = pool.get('product.product') taste_obj = pool.get('qdodoo.product.taste') session_obj = pool.get('pos.session') users = users_obj.browse(cr, SUPERUSER_ID, uid) taste_ids = taste_obj.search(cr, SUPERUSER_ID, []) tastes = taste_obj.browse(cr, SUPERUSER_ID, taste_ids) company_name = users.company_id.name company_id = users.company_id.id partner_id = users.partner_id.id order_obj = pool.get('pos.order') if post.get('oid'): res_order_id = int(post.get('oid')) all_money = float(post.get('money')) wx_fix = order_obj.browse(cr, uid, int(res_order_id)).session_id.config_id.en_name else: session_id = session_obj.search(cr, SUPERUSER_ID, [('config_id.company_id','=',company_id),('state','=','opened')]) if not session_id: values = { 'company_name':company_name, 'error_text':u'支付宝暂停收款,请联系服务员点餐', } return request.website.render("wxsite.error", values) else: # 获取负责人 session_ids = session_obj.browse(cr, SUPERUSER_ID, session_id[0]) wx_fix = session_ids.config_id.en_name uid_session = session_ids.user_id.id car_obj = pool.get('qdodoo.wxsite.car') car_ids = car_obj.search(cr, SUPERUSER_ID, [('user_id','=',uid)]) if car_ids: # 生成销售订单(POS) order_line_obj = pool.get('pos.order.line') res_order_id = order_obj.create(cr, uid_session, {'partner_id':partner_id,'pricelist_id':1,'company_id':company_id}) # 获取加入购物车的总金额 all_money = 0 for key_line in car_obj.browse(cr, SUPERUSER_ID, car_ids): # 根据产品模板id获取产品id product_ids = product_obj.search(cr, SUPERUSER_ID, [('product_tmpl_id','=',key_line.name.id)]) all_money += key_line.number * key_line.name.lst_price # 获取总金额 # 生成销售单明细 order_line_obj.create(cr, uid_session, {'company_id':company_id,'order_id':res_order_id,'product_id':product_ids[0], 'qty':key_line.number,'price_unit':key_line.name.lst_price}) car_obj.unlink(cr, SUPERUSER_ID, car_ids) else: values = { 'company_name':company_name, 'error_text':u'不能支付空的订单', } return request.website.render("wxsite.error", values) config = pool.get('ir.config_parameter') # 下面几个变量是支付宝支付相关配置 alipay_config_dict = { 'partner': '2088121266041788', # 合作身份者id,以2088开头的16位纯数字 'sign_type': 'MD5', # 签名方式 'key': '4nzm1m9udzhvi7clurk2k9s6rs0e0cv5', # 安全检验码,以数字和字母组成的32位字符,如果签名方式设置为“MD5”时,请设置该参数 'private_key_path': '', # 商户的私钥(.pem文件)相对路径,如果签名方式设置为“0001”时,请设置该参数 'ali_public_key_path': '', # 支付宝公钥(.pem文件)相对路径,如果签名方式设置为“0001”时,请设置该参数 'input_charset': 'utf-8', # 字符编码格式 支持 gbk 或 utf-8 'transport': 'http', # 访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http 'cacert': '', # ca证书路径地址,如果访问模式是https,则填写此处 } """ 组织参数,调用授权接口alipay.wap.trade.create.direct获取授权码token """ oid = str(wx_fix) + str(res_order_id) param_dict = { 'format': 'xml', # 要求返回格式 'v': '2.0', # 返回格式版本 'req_id': (datetime.datetime.now()+datetime.timedelta(hours=8)).strftime('%Y%m%d%H%M%S'), # 请求号。使用年月日时分秒,保证每次请求都是唯一 'notify_url': config.get_param(cr, uid, 'web.base.url') + '/shop/wx/alipay/backnotify', # 服务器异步通知页面路径 'call_back_url': config.get_param(cr, uid, 'web.base.url') + '/shop/wx/alipay/frontreturn', # 页面跳转同步通知页面路径 'merchant_url': config.get_param(cr, uid, 'web.base.url') + '/shop/wx/alipay/interrupt', # 操作中断返回地址,用户付款中途退出返回商户的地址。 'seller_email': '*****@*****.**', # 卖家支付宝帐户 'out_trade_no': oid, # 商户订单号,此处如果用str(wx_fix)会返回False 'subject': '订单', # 订单名称 'body': str(wx_fix), # 订单号前缀,期望在后台通知中能原样返回以便解析出订单ID 'total_fee': str(all_money), # 付款金额,单位:元 } # 请求业务参数明细 token_req = '<direct_trade_create_req><notify_url>'+param_dict['notify_url']+'</notify_url><call_back_url>'+param_dict['call_back_url']+'</call_back_url><seller_account_name>'+param_dict['seller_email']+'</seller_account_name><out_trade_no>'+param_dict['out_trade_no']+'</out_trade_no><subject>'+param_dict['subject']+'</subject><total_fee>'+param_dict['total_fee']+'</total_fee><merchant_url>'+param_dict['merchant_url']+'</merchant_url></direct_trade_create_req>' # 请求参数组 req_param_dict = { 'service': 'alipay.wap.trade.create.direct', 'partner': alipay_config_dict['partner'], 'sec_id': alipay_config_dict['sign_type'], 'format': param_dict['format'], 'v': param_dict['v'], 'req_id': param_dict['req_id'], 'req_data': token_req, '_input_charset': alipay_config_dict['input_charset'], } # 签名 _, sign_query_str = util.params_filter(req_param_dict) alipay_md5_sign = hashlib.md5(sign_query_str + alipay_config_dict['key']).hexdigest() # 签名和签名方式加入请求参数中 req_param_dict['sign'] = alipay_md5_sign req_param_dict['sign_type'] = alipay_config_dict['sign_type'] # 发送post请求,获取token alipay_gateway_new = 'http://wappaygw.alipay.com/service/rest.htm?_input_charset='+alipay_config_dict['input_charset'] post_param_query = urllib.urlencode(req_param_dict) http_client = httplib.HTTPConnection('wappaygw.alipay.com', 80, timeout=6000) http_client.request('POST', '/service/rest.htm?_input_charset='+alipay_config_dict['input_charset'], post_param_query, {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/html"}) ret_query = http_client.getresponse().read() ret_query = urllib.unquote(ret_query) # urldecode http_client.close() """ 支付宝返回的数据格式,一般只需要request_token res_data=<?xml version="1.0" encoding="utf-8"?><direct_trade_create_res><request_token>20160304cfe8ccddf25e82eeded3e36d17a1ed1e</request_token></direct_trade_create_res>&service=alipay.wap.trade.create.direct&sec_id=MD5&partner=2088901494850295&req_id=20160304032846&sign=43fb3101321eeb7f928170502e5d1948&v=2.0 """ # 截取出其中的request_token alipay_request_token = ret_query[ret_query.index('<request_token>')+15:ret_query.index('</request_token>')] # 构建请求跳转数组 form_input_dict ={ 'service': 'alipay.wap.auth.authAndExecute', 'partner': alipay_config_dict['partner'], "sec_id": alipay_config_dict['sign_type'], 'format': param_dict['format'], 'v': param_dict['v'], 'req_id': param_dict['req_id'], 'req_data': '<auth_and_execute_req><request_token>'+alipay_request_token+'</request_token></auth_and_execute_req>', '_input_charset': alipay_config_dict['input_charset'], } # 再签名 _, sign_query_str = util.params_filter(form_input_dict) alipay_md5_sign = hashlib.md5(sign_query_str + alipay_config_dict['key']).hexdigest() # 签名和签名方式等加入请求参数中 form_input_dict['sign'] = alipay_md5_sign form_input_dict['sign_type'] = alipay_config_dict['sign_type'] form_input_dict['oid'] = res_order_id form_input_dict['all_money'] = all_money form_input_dict['company_name'] = company_name form_input_dict['tastes'] = tastes # 调用页面form跳转到支付宝支付 return request.website.render("wxsite.alipay", form_input_dict)
def ali_oauth(self, **post): """ 支付宝用户授权回调地址,在此处根据auth_code来获取支付宝用户信息,进行登录/注册处理 """ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry ali_code = post['auth_code'] # 授权code,属于GET参数 _logger.info('----->auth_code:%s'%ali_code) """ 根据code获取支付宝用户ID和access_token, Python方法 """ sign_params_dic = { 'app_id': '2016030201177117', # 支付宝APPID 'method': 'alipay.system.oauth.token', 'charset': 'UTF-8', 'sign_type': 'RSA', 'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'version': '1.0', 'grant_type': 'authorization_code', 'code': ali_code, } # 待签名参数按key值排序,组合成待加密串 _, sign_query_str = util.params_filter(sign_params_dic) # sign_query_str = util.sort(sign_params_dic) rsa_private_key = RSA.importKey(open('addons-extra/wxsite/static/rsa_private_key.pem','r').read()) rsa_private_sign=util.sign(sign_query_str, rsa_private_key) sign_params_dic['sign'] = rsa_private_sign # post到支付宝,获取userId(类似微信的OpenId) post_param_query = urllib.urlencode(sign_params_dic) httpsClient = httplib.HTTPSConnection('openapi.alipay.com', 443, timeout=6000) httpsClient.request('POST', '/gateway.do', post_param_query, {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/html","charset":"utf8"}) ret_json = httpsClient.getresponse().read() ret_dict = json.loads(ret_json.decode('GB2312').encode('UTF-8')) # 解析json ali_userid = ret_dict['alipay_system_oauth_token_response']['user_id'] # 获取userid ali_access_token = ret_dict['alipay_system_oauth_token_response']['access_token'] # 获取access_token """ 在此处根据支付宝userId判断用户是否已存在数据库中 """ users_obj = pool.get('res.users') company_id = request.session['company_id'] login = str(company_id)+ali_userid # company_id = 1 # 支付宝授权链接中不能带自定义参数,不能像微信授权那样传递company_id,此处暂默认为1 wx_user_exists = users_obj.search(cr, SUPERUSER_ID, [('login','=',login),('company_id','=',int(company_id))]) if not wx_user_exists: # 获取用户详细信息如用户名等 sign_params_dic = { 'app_id': '2016030201177117', # 支付宝APPID 'method': 'alipay.user.userinfo.share', 'charset': 'UTF-8', 'sign_type': 'RSA', 'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), # 不知为什么,now()总是晚8小时 'version': '1.0', 'auth_token': ali_access_token, } _, sign_query_str = util.params_filter(sign_params_dic) rsa_private_key = RSA.importKey(open('addons-extra/wxsite/static/rsa_private_key.pem','r').read()) rsa_private_sign=util.sign(sign_query_str, rsa_private_key) sign_params_dic['sign'] = rsa_private_sign # post到支付宝,获取用户名等信息,用于注册 post_param_query = urllib.urlencode(sign_params_dic) httpsClient = httplib.HTTPSConnection('openapi.alipay.com', 443, timeout=6000) httpsClient.request('POST', '/gateway.do', post_param_query, {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/html","charset":"utf8"}) ret_json = httpsClient.getresponse().read() ret_dict = json.loads(ret_json.decode('GB2312').encode('UTF-8')) # 解析json if 'nick_name' in ret_dict['alipay_user_userinfo_share_response']: ali_username = ret_dict['alipay_user_userinfo_share_response']['nick_name'] # 获取支付宝用户昵称 else: ali_username = ret_dict['alipay_user_userinfo_share_response']['alipay_user_id'] # 注册用户 users_obj.create(cr, SUPERUSER_ID, {'login':login,'name':ali_username,'password':'******','oauth_provider_id':'','company_id':int(company_id),'company_ids':[[6, False, [int(company_id)]]]}) request.session['alipay_userid'] = ali_userid return request.redirect("/login?db=%s&login=%s&key=%s&redirect=%s"%(request.session.db,login, 'qdodoo', 'shop/wx/main'))
def ali_oauth(self, **post): """ 支付宝用户授权回调地址,在此处根据auth_code来获取支付宝用户信息,进行登录/注册处理 """ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry ali_code = post['auth_code'] # 授权code,属于GET参数 _logger.info('----->auth_code:%s' % ali_code) """ 根据code获取支付宝用户ID和access_token, Python方法 """ sign_params_dic = { 'app_id': '2016030201177117', # 支付宝APPID 'method': 'alipay.system.oauth.token', 'charset': 'UTF-8', 'sign_type': 'RSA', 'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'version': '1.0', 'grant_type': 'authorization_code', 'code': ali_code, } # 待签名参数按key值排序,组合成待加密串 _, sign_query_str = util.params_filter(sign_params_dic) # sign_query_str = util.sort(sign_params_dic) rsa_private_key = RSA.importKey( open('addons-extra/wxsite/static/rsa_private_key.pem', 'r').read()) rsa_private_sign = util.sign(sign_query_str, rsa_private_key) sign_params_dic['sign'] = rsa_private_sign # post到支付宝,获取userId(类似微信的OpenId) post_param_query = urllib.urlencode(sign_params_dic) httpsClient = httplib.HTTPSConnection('openapi.alipay.com', 443, timeout=6000) httpsClient.request( 'POST', '/gateway.do', post_param_query, { "Content-type": "application/x-www-form-urlencoded", "Accept": "text/html", "charset": "utf8" }) ret_json = httpsClient.getresponse().read() ret_dict = json.loads( ret_json.decode('GB2312').encode('UTF-8')) # 解析json ali_userid = ret_dict['alipay_system_oauth_token_response'][ 'user_id'] # 获取userid ali_access_token = ret_dict['alipay_system_oauth_token_response'][ 'access_token'] # 获取access_token """ 在此处根据支付宝userId判断用户是否已存在数据库中 """ users_obj = pool.get('res.users') company_id = request.session['company_id'] login = str(company_id) + ali_userid # company_id = 1 # 支付宝授权链接中不能带自定义参数,不能像微信授权那样传递company_id,此处暂默认为1 wx_user_exists = users_obj.search( cr, SUPERUSER_ID, [('login', '=', login), ('company_id', '=', int(company_id))]) if not wx_user_exists: # 获取用户详细信息如用户名等 sign_params_dic = { 'app_id': '2016030201177117', # 支付宝APPID 'method': 'alipay.user.userinfo.share', 'charset': 'UTF-8', 'sign_type': 'RSA', 'timestamp': datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S'), # 不知为什么,now()总是晚8小时 'version': '1.0', 'auth_token': ali_access_token, } _, sign_query_str = util.params_filter(sign_params_dic) rsa_private_key = RSA.importKey( open('addons-extra/wxsite/static/rsa_private_key.pem', 'r').read()) rsa_private_sign = util.sign(sign_query_str, rsa_private_key) sign_params_dic['sign'] = rsa_private_sign # post到支付宝,获取用户名等信息,用于注册 post_param_query = urllib.urlencode(sign_params_dic) httpsClient = httplib.HTTPSConnection('openapi.alipay.com', 443, timeout=6000) httpsClient.request( 'POST', '/gateway.do', post_param_query, { "Content-type": "application/x-www-form-urlencoded", "Accept": "text/html", "charset": "utf8" }) ret_json = httpsClient.getresponse().read() ret_dict = json.loads( ret_json.decode('GB2312').encode('UTF-8')) # 解析json if 'nick_name' in ret_dict['alipay_user_userinfo_share_response']: ali_username = ret_dict['alipay_user_userinfo_share_response'][ 'nick_name'] # 获取支付宝用户昵称 else: ali_username = ret_dict['alipay_user_userinfo_share_response'][ 'alipay_user_id'] # 注册用户 users_obj.create( cr, SUPERUSER_ID, { 'login': login, 'name': ali_username, 'password': '******', 'oauth_provider_id': '', 'company_id': int(company_id), 'company_ids': [[6, False, [int(company_id)]]] }) request.session['alipay_userid'] = ali_userid return request.redirect( "/login?db=%s&login=%s&key=%s&redirect=%s" % (request.session.db, login, 'qdodoo', 'shop/wx/main'))
def alipay(self, **post): """ 支付宝wap支付 """ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry # 获取当前公司的名称(根据用户模型获取数据) users_obj = pool.get('res.users') product_obj = pool.get('product.product') taste_obj = pool.get('qdodoo.product.taste') session_obj = pool.get('pos.session') users = users_obj.browse(cr, SUPERUSER_ID, uid) taste_ids = taste_obj.search(cr, SUPERUSER_ID, []) tastes = taste_obj.browse(cr, SUPERUSER_ID, taste_ids) company_name = users.company_id.name company_id = users.company_id.id partner_id = users.partner_id.id order_obj = pool.get('pos.order') if post.get('oid'): res_order_id = int(post.get('oid')) all_money = float(post.get('money')) wx_fix = order_obj.browse( cr, uid, int(res_order_id)).session_id.config_id.en_name else: session_id = session_obj.search( cr, SUPERUSER_ID, [('config_id.company_id', '=', company_id), ('state', '=', 'opened')]) if not session_id: values = { 'company_name': company_name, 'error_text': u'支付宝暂停收款,请联系服务员点餐', } return request.website.render("wxsite.error", values) else: # 获取负责人 session_ids = session_obj.browse(cr, SUPERUSER_ID, session_id[0]) wx_fix = session_ids.config_id.en_name uid_session = session_ids.user_id.id car_obj = pool.get('qdodoo.wxsite.car') car_ids = car_obj.search(cr, SUPERUSER_ID, [('user_id', '=', uid)]) if car_ids: # 生成销售订单(POS) order_line_obj = pool.get('pos.order.line') res_order_id = order_obj.create( cr, uid_session, { 'partner_id': partner_id, 'pricelist_id': 1, 'company_id': company_id }) # 获取加入购物车的总金额 all_money = 0 for key_line in car_obj.browse(cr, SUPERUSER_ID, car_ids): # 根据产品模板id获取产品id product_ids = product_obj.search( cr, SUPERUSER_ID, [('product_tmpl_id', '=', key_line.name.id)]) all_money += key_line.number * key_line.name.lst_price # 获取总金额 # 生成销售单明细 order_line_obj.create( cr, uid_session, { 'company_id': company_id, 'order_id': res_order_id, 'product_id': product_ids[0], 'qty': key_line.number, 'price_unit': key_line.name.lst_price }) car_obj.unlink(cr, SUPERUSER_ID, car_ids) else: values = { 'company_name': company_name, 'error_text': u'不能支付空的订单', } return request.website.render("wxsite.error", values) config = pool.get('ir.config_parameter') # 下面几个变量是支付宝支付相关配置 alipay_config_dict = { 'partner': '2088121266041788', # 合作身份者id,以2088开头的16位纯数字 'sign_type': 'MD5', # 签名方式 'key': '4nzm1m9udzhvi7clurk2k9s6rs0e0cv5', # 安全检验码,以数字和字母组成的32位字符,如果签名方式设置为“MD5”时,请设置该参数 'private_key_path': '', # 商户的私钥(.pem文件)相对路径,如果签名方式设置为“0001”时,请设置该参数 'ali_public_key_path': '', # 支付宝公钥(.pem文件)相对路径,如果签名方式设置为“0001”时,请设置该参数 'input_charset': 'utf-8', # 字符编码格式 支持 gbk 或 utf-8 'transport': 'http', # 访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http 'cacert': '', # ca证书路径地址,如果访问模式是https,则填写此处 } """ 组织参数,调用授权接口alipay.wap.trade.create.direct获取授权码token """ oid = str(wx_fix) + str(res_order_id) param_dict = { 'format': 'xml', # 要求返回格式 'v': '2.0', # 返回格式版本 'req_id': (datetime.datetime.now() + datetime.timedelta(hours=8) ).strftime('%Y%m%d%H%M%S'), # 请求号。使用年月日时分秒,保证每次请求都是唯一 'notify_url': config.get_param(cr, uid, 'web.base.url') + '/shop/wx/alipay/backnotify', # 服务器异步通知页面路径 'call_back_url': config.get_param(cr, uid, 'web.base.url') + '/shop/wx/alipay/frontreturn', # 页面跳转同步通知页面路径 'merchant_url': config.get_param(cr, uid, 'web.base.url') + '/shop/wx/alipay/interrupt', # 操作中断返回地址,用户付款中途退出返回商户的地址。 'seller_email': '*****@*****.**', # 卖家支付宝帐户 'out_trade_no': oid, # 商户订单号,此处如果用str(wx_fix)会返回False 'subject': '订单', # 订单名称 'body': str(wx_fix), # 订单号前缀,期望在后台通知中能原样返回以便解析出订单ID 'total_fee': str(all_money), # 付款金额,单位:元 } # 请求业务参数明细 token_req = '<direct_trade_create_req><notify_url>' + param_dict[ 'notify_url'] + '</notify_url><call_back_url>' + param_dict[ 'call_back_url'] + '</call_back_url><seller_account_name>' + param_dict[ 'seller_email'] + '</seller_account_name><out_trade_no>' + param_dict[ 'out_trade_no'] + '</out_trade_no><subject>' + param_dict[ 'subject'] + '</subject><total_fee>' + param_dict[ 'total_fee'] + '</total_fee><merchant_url>' + param_dict[ 'merchant_url'] + '</merchant_url></direct_trade_create_req>' # 请求参数组 req_param_dict = { 'service': 'alipay.wap.trade.create.direct', 'partner': alipay_config_dict['partner'], 'sec_id': alipay_config_dict['sign_type'], 'format': param_dict['format'], 'v': param_dict['v'], 'req_id': param_dict['req_id'], 'req_data': token_req, '_input_charset': alipay_config_dict['input_charset'], } # 签名 _, sign_query_str = util.params_filter(req_param_dict) alipay_md5_sign = hashlib.md5(sign_query_str + alipay_config_dict['key']).hexdigest() # 签名和签名方式加入请求参数中 req_param_dict['sign'] = alipay_md5_sign req_param_dict['sign_type'] = alipay_config_dict['sign_type'] # 发送post请求,获取token alipay_gateway_new = 'http://wappaygw.alipay.com/service/rest.htm?_input_charset=' + alipay_config_dict[ 'input_charset'] post_param_query = urllib.urlencode(req_param_dict) http_client = httplib.HTTPConnection('wappaygw.alipay.com', 80, timeout=6000) http_client.request( 'POST', '/service/rest.htm?_input_charset=' + alipay_config_dict['input_charset'], post_param_query, { "Content-type": "application/x-www-form-urlencoded", "Accept": "text/html" }) ret_query = http_client.getresponse().read() ret_query = urllib.unquote(ret_query) # urldecode http_client.close() """ 支付宝返回的数据格式,一般只需要request_token res_data=<?xml version="1.0" encoding="utf-8"?><direct_trade_create_res><request_token>20160304cfe8ccddf25e82eeded3e36d17a1ed1e</request_token></direct_trade_create_res>&service=alipay.wap.trade.create.direct&sec_id=MD5&partner=2088901494850295&req_id=20160304032846&sign=43fb3101321eeb7f928170502e5d1948&v=2.0 """ # 截取出其中的request_token alipay_request_token = ret_query[ret_query.index('<request_token>') + 15:ret_query.index('</request_token>' )] # 构建请求跳转数组 form_input_dict = { 'service': 'alipay.wap.auth.authAndExecute', 'partner': alipay_config_dict['partner'], "sec_id": alipay_config_dict['sign_type'], 'format': param_dict['format'], 'v': param_dict['v'], 'req_id': param_dict['req_id'], 'req_data': '<auth_and_execute_req><request_token>' + alipay_request_token + '</request_token></auth_and_execute_req>', '_input_charset': alipay_config_dict['input_charset'], } # 再签名 _, sign_query_str = util.params_filter(form_input_dict) alipay_md5_sign = hashlib.md5(sign_query_str + alipay_config_dict['key']).hexdigest() # 签名和签名方式等加入请求参数中 form_input_dict['sign'] = alipay_md5_sign form_input_dict['sign_type'] = alipay_config_dict['sign_type'] form_input_dict['oid'] = res_order_id form_input_dict['all_money'] = all_money form_input_dict['company_name'] = company_name form_input_dict['tastes'] = tastes # 调用页面form跳转到支付宝支付 return request.website.render("wxsite.alipay", form_input_dict)
def wxpay_backnotify(self, **post): """ 微信支付异步通知地址 当用户成功支付后,微信服务器会POST一份xml格式的支付信息到该地址,通过商户订单号和支付状态进行处理 处理后需返回一个xml信息,格式示例: <xml> <return_code><![CDATA[success]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml> 参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 """ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry #下面几个变量是微信支付相关配置 wx_key = '33132ac4f37f151dbfcbfce34f441d71' #微信支付密钥,到微信商户平台设置并填写此处 order_obj = pool.get('pos.order') payment_obj = pool.get('pos.make.payment') config_obj = pool.get('pos.config') print_list_obj = pool.get('qdodoo.print.list') dict_post_ip = self.pos_id() config_id = config_obj.search(cr, SUPERUSER_ID, [('iface_print_via_proxy','=',True)]) if config_id: proxy_ip = config_obj.browse(cr, SUPERUSER_ID, config_id[0]).proxy_ip # 有返回结果 if post: #解析post过来的xml数据,获取必要的信息 post_dict = json.loads(post) #解析json为dict #需返回给微信的参数,默认处理成功 ret_dict = { 'return_code': 'SUCCESS', 'return_msg': 'OK', } #如果支付成功,则进行处理 if post_dict['return_code'] == 'SUCCESS': #对post过来的数据进行签名,与post参数中的签名sign进行对比 post_sign_dict = {} #捡取非空参数,不包含签名sign for key, val in post_dict.items(): if not val == '' and not key == 'sign': post_sign_dict[key] = val post_sign_dict = sorted(post_sign_dict.iteritems(), key=lambda d:d[0]) post_sign_keyval = '' for key, val in post_sign_dict.items(): post_sign_keyval += key+'='+val+'&' post_sign_keyval += 'key='+wx_key post_sign = hashlib.new("md5", post_sign_keyval).hexdigest().upper() #根据微信post来的参数计算出的签名 if post_sign == post_dict['sign']: #自己计算出来的签名与微信post过来的sign签名一致,则验签通过 oid = post_dict['out_trade_no'] #商户订单号,与发起微信支付时填写的out_trade_no一致,可据此处理对应订单 wxpay_qid = post_dict['transaction_id'] #微信支付交易流水号,可据此对账 wxpay_sum = int(post_dict['total_fee'])/100 #实际支付金额,单位:分,除以100转换成元 #基本以上参数足够处理订单,以下也是post中必含的参数,可酌情使用 wxpay_openid = post_dict['openid'] #支付的微信用户openid,原则上与发起支付的openid一致 wxpay_tradetype = post_dict['trade_type'] #支付方式,原则上与发起支付的方式一致,如JSAPI wxpay_appid = post_dict['appid'] #公众号APPID wxpay_mch_id = post_dict['mch_id'] #商户号 wxpay_banktype = post_dict['bank_type'] #银行类型,标识所代表的银行可参考官方说明 wxpay_endtime = post_dict['time_end'] #支付完成时间,格式:yyyyMMddHHmmss,如:20160108124035 """ 下面可以根据以上获取的参数对订单进行处理 小提示:微信可能多次发送同一笔支付通知,因此需先检验该订单支付是否已经处理过,未处理过的才进行处理 比如更改订单状态、财务出入帐等 """ order_obj.signal_workflow(cr, SUPERUSER_ID, [int(oid)], 'paid') else: #验签失败 ret_dict['code'] = 'fail' ret_dict['desc'] = 'sign valid fail' #最终,要返回处理结果的xml格式数据 wxpay_ret_xml = Element('xml') for key, val in ret_dict.items(): xml_child = Element(key) xml_child.text = str(val) wxpay_ret_xml.append(xml_child) return wxpay_ret_xml else: # 没有返回结果,执行查询方法 wx_add = 'https://api.mch.weixin.qq.com/pay/orderquery' wx_appid = 'wxde2cf9dbf3c35624' #公众号号APPID,通常是微信签约时的服务号APPID wx_mchid = '1294510601' #商户号,签约微信支付后分配的商户号 wx_key = '33132ac4f37f151dbfcbfce34f441d71' #微信支付密钥,到微信商户平台设置并填写此处 # 查询所有未完成的订单 order_ids = order_obj.search(cr, SUPERUSER_ID, [('state','=','draft')]) for order_ids in order_ids: #生成一个随机字符串,不长于32位,主要保证签名不可预测 nonce_str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' chars_length = len(chars) - 1 for i in range(1, 32, 1): nonce_str += chars[random.randint(0, chars_length)] #微信查询接口所需参数 wx_search = { 'appid': wx_appid, #公众号号APPID 'mch_id': wx_mchid, #商户号 'nonce_str': nonce_str, 'out_trade_no': order_ids, #商户订单号 } """ 参数签名,将非空字典键值按ASCII码升序排列,然后按url键值对拼接,最后拼接上微信支付密钥key 将所拼接的字符串进行MD5运算,再将得到的字符串中所有字母转换为大写。即是签名 """ _, prestr_select = util.params_filter(wx_search) wx_search['sign'] = hashlib.md5(prestr_select + '&key=' +wx_key).hexdigest().upper() data_xml = "<xml>" + self.json2xml(wx_search) + "</xml>" request_new = urllib2.Request(wx_add, data_xml) res = urllib2.urlopen(request_new) return_xml = etree.fromstring(res.read()) if return_xml.find('return_code').text == "SUCCESS" and return_xml.find('result_code').text != 'FAIL': pay_state = return_xml.find('trade_state').text #交易状态 pos_id = return_xml.find('out_trade_no').text #订单号 pos_obj = order_obj.browse(cr, SUPERUSER_ID, int(pos_id)) if pay_state == 'SUCCESS': res_id = payment_obj.create(cr, SUPERUSER_ID, {'journal_id':pos_obj.session_id.config_id.journal_ids[0].id, 'amount':pos_obj.amount_total,'payment_name':u'微信支付', 'payment_date':datetime.now().date()}) payment_obj.check(cr, SUPERUSER_ID, [res_id], context={'active_id':pos_obj.id}) infomation = """<receipt align="center" value-thousands-separator="" width="40"> <div font="b"> <div>%s</div> <div>电话:%s</div> <div>%s</div> <div>%s</div> <div>--------------------------------</div> <div>被服务于 %s</div> </div> <br/><br/> <div line-ratio="0.6">"""%(pos_obj.company_id.name,pos_obj.company_id.phone,pos_obj.company_id.email, pos_obj.company_id.website,pos_obj.user_id.name) # 循环订单明细 for line in pos_obj.lines: infomation += """++++++<line><left>%s</left></line> <line indent="1"> <left> <value value-autoint="on" value-decimals="3"> %s </value> %s x <value value-decimals="2"> %s </value> ===%s=== </left> <right> <value>%s</value> </right> </line>++++++"""%(line.product_id.name,line.qty,line.product_id.uom_id.name,line.product_id.list_price, dict_post_ip.get(line.product_id.pos_categ_id.id), line.product_id.list_price) infomation += """</div> <line><right>--------</right></line> <line size="double-height"> <left><pre> 合计</pre></left> <right><value>%s</value></right> </line> <br/><br/> <line> <left>现金 (CNY)</left> <right><value>%s</value></right> </line> <br/> <line size="double-height"> <left><pre> CHANGE</pre></left> <right><value>0</value></right> </line> <br/> <br/> <div font="b"> <div>Order %s</div> <div>%s</div> </div> </receipt>"""%(pos_obj.amount_total,pos_obj.amount_total,pos_obj.name,datetime.now()) print_list_obj.create(cr, SUPERUSER_ID, {'name':infomation,'is_print':False}) elif pay_state == 'USERPAYING': pass else: order_obj.signal_workflow(cr, SUPERUSER_ID, [int(pos_id)], 'cancel') else: pass return 'SUCCESS'
def alipay_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param( cr, SUPERUSER_ID, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) alipay_tx_values = dict(tx_values) alipay_tx_values.update({ 'partner': acquirer.alipay_partner_account, 'seller_email': acquirer.alipay_seller_email, 'seller_id': acquirer.alipay_partner_account, '_input_charset': 'utf-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), }) to_sign = {} to_sign.update({ 'partner': acquirer.alipay_partner_account, 'seller_email': acquirer.alipay_seller_email, 'seller_id': acquirer.alipay_partner_account, '_input_charset': 'utf-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': '%s: %s' % (acquirer.company_id.name, tx_values['reference']), 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), }) payload_direct = { 'service': 'create_direct_pay_by_user', 'total_fee': tx_values['amount'], } payload_escow = { 'service': 'create_partner_trade_by_buyer', 'logistics_type': 'EXPRESS', 'logistics_fee': 0, 'logistics_payment': 'SELLER_PAY', 'price': tx_values['amount'], 'quantity': 1, } payload_dualfun = { 'service': 'trade_create_by_buyer', 'logistics_type': 'EXPRESS', 'logistics_fee': 0, 'logistics_payment': 'SELLER_PAY', 'price': tx_values['amount'], 'quantity': 1, } if acquirer.alipay_interface_type == 'create_direct_pay_by_user': to_sign.update(payload_direct) alipay_tx_values.update(payload_direct) if acquirer.alipay_interface_type == 'create_partner_trade_by_buyer': to_sign.update(payload_escow) alipay_tx_values.update(payload_direct) if acquirer.alipay_interface_type == 'trade_create_by_buyer': to_sign.update(payload_dualfun) alipay_tx_values.update(payload_direct) _, prestr = util.params_filter(to_sign) alipay_tx_values['sign'] = util.build_mysign( prestr, acquirer.alipay_partner_key, 'MD5') alipay_tx_values['sign_type'] = 'MD5' return partner_values, alipay_tx_values
def alipay_form_generate_values(self, tx_values): base_url = self.env['ir.config_parameter'].sudo().get_param( 'web.base.url') alipay_tx_values = dict(tx_values) alipay_tx_values.update({ 'partner': self.alipay_partner_account, 'seller_email': self.alipay_seller_email, 'seller_id': self.alipay_partner_account, '_input_charset': 'UTF-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': tx_values['reference'], 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), }) to_sign = {} to_sign.update({ 'partner': self.alipay_partner_account, 'seller_email': self.alipay_seller_email, 'seller_id': self.alipay_partner_account, '_input_charset': 'UTF-8', 'out_trade_no': tx_values['reference'], 'subject': tx_values['reference'], 'body': tx_values['reference'], 'payment_type': '1', 'return_url': '%s' % urlparse.urljoin(base_url, AlipayController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, AlipayController._notify_url), }) payload_direct = { 'service': 'create_direct_pay_by_user', 'total_fee': tx_values['amount'], } payload_escow = { 'service': 'create_partner_trade_by_buyer', 'logistics_type': 'EXPRESS', 'logistics_fee': 0, 'logistics_payment': 'SELLER_PAY', 'price': tx_values['amount'], 'quantity': 1, } if self.alipay_interface_type == 'create_direct_pay_by_user': to_sign.update(payload_direct) alipay_tx_values.update(payload_direct) if self.alipay_interface_type == 'create_partner_trade_by_buyer': to_sign.update(payload_escow) alipay_tx_values.update(payload_escow) _, prestr = util.params_filter(to_sign) alipay_tx_values['sign'] = util.build_mysign(prestr, self.alipay_partner_key, 'MD5') alipay_tx_values['sign_type'] = 'MD5' _logger.info('----alipay tx_values is %s' % alipay_tx_values) return alipay_tx_values