Python实现微信刷卡支付(条码支付)MicroPay
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7686765.html
一:资料阅读
场景介绍:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_1
支付流程:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_4
提交刷卡支付:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
查询订单支付结果:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
二:配置信息准备
# ========支付相关配置信息=========== _APP_ID = ""; # 公众账号appid _MCH_ID = ""; # 商户号 _API_KEY = ""; # 微信商户平台(pay.weixin.qq.com) -->账户设置 -->API安全 -->密钥设置,设置完成后把密钥复制到这里 _host_name = socket.gethostname() _ip_address = socket.gethostbyname(_host_name) _CREATE_IP = _ip_address; # 发起支付ip # 有关url _MICROPAY_URL = "https://api.mch.weixin.qq.com/pay/micropay"; #刷卡支付api _QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery"; #查询订单支付结果api
三:编写刷卡支付工具类
1:辅助函数
def get_sign_for_wx(self, para, key): ''' 根据算法, 生成微信支付签名 :param cr: :param uid: :param para: :param context: :return: ''' keylist = list(para.keys()) keylist.sort() s = '' for i in range(len(keylist)): s += str(keylist[i]) + '=' + str(para[keylist[i]]) if i != len(keylist) - 1: s += '&' s += '&key=' + key signmd5 = hashlib.md5() signmd5.update(s) sign = (signmd5.hexdigest()).upper() return sign #拼接xml字符串 def get_xml_data(self, doc, para): root = doc.createElement('xml') doc.appendChild(root) for key, value in sorted(para.items()): new_node = doc.createElement(key) node_value = doc.createTextNode(str(value)) new_node.appendChild(node_value) root.appendChild(new_node) return doc
2:提交刷卡支付
def do_micropay(self,orderid,goodsName,goodsPrice,authCode,**kwargs): ''' 刷卡支付 ''' appid = self._APP_ID mch_id = self._MCH_ID key = self._API_KEY nonce_str = str(int(round(time.time() * 1000))) + str(random.randint(1, 999)) + string.join(random.sample( ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'], 5)).replace(" ", "") spbill_create_ip = self._CREATE_IP params = {} params['appid'] = appid params['mch_id'] = mch_id params['nonce_str'] = nonce_str params['out_trade_no'] = orderid.encode('utf-8') # 客户端生成并传过来,参数必须用utf8编码,否则报错 params['total_fee'] = goodsPrice # 单位是分,必须是整数 params['spbill_create_ip'] = spbill_create_ip params['body'] = goodsName.encode('utf-8') # 中文必须用utf-8编码,否则xml格式错误 params['auth_code'] = authCode doc = dom.Document() self.get_xml_data(doc, params) sign = self.get_sign_for_wx(params, self._API_KEY) params['sign'] = sign signnode = doc.createElement('sign') signvalue = doc.createTextNode(sign) signnode.appendChild(signvalue) doc.getElementsByTagName('xml')[0].appendChild(signnode) # 向微信刷卡支付发出请求 req = urllib2.Request(self._MICROPAY_URL) req.headers['Content-Type'] = 'text/xml' req.data = doc.toprettyxml() res_data = urllib2.urlopen(req) # 提取支付结果 res_read = res_data.read() doc = xmltodict.parse(res_read) return_code = doc['xml']['return_code'] # 结果分析 # 此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断 if return_code == 'SUCCESS': result_code = doc['xml']['result_code'] # 业务结果 if result_code == 'SUCCESS': buyer = doc['xml']['openid'] #支付者id return (True, 'SUCCESS', u'支付成功 ',buyer) elif result_code == 'FAIL': error_code = doc['xml']['err_code'] error_code_des = doc['xml']['err_code_des'] return (False, error_code, error_code_des,'') else: return_msg = doc['xml']['return_msg'] return (False, return_code, return_msg,'')
3:根据订单号查询支付结果
def do_micropay_query(self,orderid): appid = self._APP_ID mch_id = self._MCH_ID key = self._API_KEY out_trade_no = orderid.encode('utf-8') # 客户端生成并传过来,参数必须用utf8编码,否则报错 nonce_str = str(int(round(time.time() * 1000))) + str(random.randint(1, 999)) + string.join(random.sample( ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'], 5)).replace(" ", "") params = {} params['appid'] = appid params['mch_id'] = mch_id params['nonce_str'] = nonce_str params['out_trade_no'] = out_trade_no doc = dom.Document() self.get_xml_data(doc, params) sign = self.get_sign_for_wx(params, self._API_KEY) params['sign'] = sign signnode = doc.createElement('sign') signvalue = doc.createTextNode(sign) signnode.appendChild(signvalue) doc.getElementsByTagName('xml')[0].appendChild(signnode) # 发出查询请求 req = urllib2.Request(self._QUERY_URL) req.headers['Content-Type'] = 'text/xml' req.data = doc.toprettyxml() res_data = urllib2.urlopen(req) # 返回查询结果 res_read = res_data.read() doc = xmltodict.parse(res_read) return_code = doc['xml']['return_code'] if return_code == 'SUCCESS': result_code = doc['xml']['result_code'] # 业务结果 if result_code == 'SUCCESS': trade_state = doc['xml']['trade_state'] #支付成功 if trade_state == 'SUCCESS': buyer = doc['xml']['openid'] return (True, 'SUCCESS', u'支付成功 ',buyer) #未支付、支付中 elif trade_state == 'NOTPAY': return (False, 'NOTPAY', u'未支付','') elif trade_state == 'USERPAYING': return (False, 'USERPAYING', u'支付中','') #支付关闭、撤销、失败 elif trade_state == 'CLOSED': return (False, 'CLOSED', u'支付关闭','') elif trade_state == 'REVOKED': return (False, 'REVOKED', u'支付撤销','') elif trade_state == 'PAYERROR': return (False, 'PAYERROR', u'支付失败','') else: error_code = doc['xml']['err_code'] error_code_des = doc['xml']['err_code_des'] return (False, error_code, error_code_des,'') else: return_msg = doc['xml']['return_msg'] return (False, return_code, return_msg,'')