Python实现微信小程序支付功能
正文
由于最近自己在做小程序的支付,就在这里简单介绍一下讲一下用python做小程序支付这个流程。当然在进行开发之前还是建议读一下具体的流程,清楚支付的过程。
1.支付交互流程
当然具体的参数配置可以参考官方文档https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
2.获取openid(微信用户标识)
importrequests fromconfigimportAPPID,SECRET classOpenidUtils(object): def__init__(self,jscode): self.url="https://api.weixin.qq.com/sns/jscode2session" self.appid=APPID#小程序id self.secret=SECRET#不要跟后面支付的key搞混 self.jscode=jscode#前端传回的动态jscode defget_openid(self): #url一定要拼接,不可用传参方式 url=self.url+"?appid="+self.appid+"&secret="+self.secret+"&js_code="+self.jscode+"&grant_type=authorization_code" r=requests.get(url) print(r.json()) openid=r.json()['openid'] returnopenid
3.支付请求
#-*-coding:utf-8-*- importrequests importhashlib importxmltodict importtime importrandom importstring importurllib2 importsys classWX_PayToolUtil(): """微信支付工具""" def__init__(self,APP_ID,MCH_ID,API_KEY,NOTIFY_URL): self._APP_ID=APP_ID#小程序ID self._MCH_ID=MCH_ID##商户号 self._API_KEY=API_KEY self._UFDODER_URL="https://api.mch.weixin.qq.com/pay/unifiedorder"#接口链接 self._NOTIFY_URL=NOTIFY_URL#异步通知 defgenerate_sign(self,param): '''生成签名''' stringA='' ks=sorted(param.keys()) #参数排序 forkinks: stringA+=(k+'='+param[k]+'&') #拼接商户KEY stringSignTemp=stringA+"key="+self._API_KEY #md5加密,也可以用其他方式 hash_md5=hashlib.md5(stringSignTemp.encode('utf8')) sign=hash_md5.hexdigest().upper() returnsign ''' #python2另外一种实现方法 defgenerate_sign(self,params): ret=[] forkinsorted(params.keys()): if(k!='sign')and(k!='')and(params[k]isnotNone): ret.append('%s=%s'%(k,params[k])) params_str='&'.join(ret) params_str='%(params_str)s&key=%(partner_key)s'%{'params_str':params_str,'partner_key':key} reload(sys) sys.setdefaultencoding('utf8') params_str=hashlib.md5(params_str.encode('utf-8')).hexdigest() sign=params_str.upper() returnsign ''' defgetPayUrl(self,orderid,openid,goodsPrice,**kwargs): """向微信支付端发出请求,获取url""" key=self._API_KEY nonce_str=''.join(random.sample(string.letters+string.digits,30))#生成随机字符串,小于32位 params={ 'appid':self._APP_ID,#小程序ID 'mch_id':self._MCH_ID,#商户号 'nonce_str':nonce_str,#随机字符串 "body":'测试订单',#支付说明 'out_trade_no':orderid,#生成的订单号 'total_fee':str(goodsPrice),#标价金额 'spbill_create_ip':"127.0.0.1",#小程序不能获取客户ip,web用socekt实现 'notify_url':self._NOTIFY_URL, 'trade_type':"JSAPI",#支付类型 "openid":openid,#用户id } #生成签名 params['sign']=self.generate_sign(params) #python3一种写法 param={'root':params} xml=xmltodict.unparse(param) response=requests.post(self._UFDODER_URL,data=xml.encode('utf-8'),headers={'Content-Type':'text/xml'}) #xml2dict msg=response.text xmlmsg=xmltodict.parse(msg) #4.获取prepay_id ifxmlmsg['xml']['return_code']=='SUCCESS': ifxmlmsg['xml']['result_code']=='SUCCESS': prepay_id=xmlmsg['xml']['prepay_id'] #时间戳 timeStamp=str(int(time.time())) #5.五个参数 data={ "appId":self._APP_ID, "nonceStr":nonce_str, "package":"prepay_id="+prepay_id, "signType":'MD5', "timeStamp":timeStamp, } #6.paySign签名 paySign=self.generate_sign(data) data["paySign"]=paySign#加入签名 #7.传给前端的签名后的参数 returndata #python2一种写法 ''' request_xml_str='' forkey,valueinparams.items(): ifisinstance(value,str): request_xml_str='%s<%s>%s>'%(request_xml_str,key,value,key,) else: request_xml_str='%s<%s>%s%s>'%(request_xml_str,key,value,key,) request_xml_str='%s '%request_xml_str #向微信支付发出请求,并提取回传数据 res=urllib2.Request(self._UFDODER_URL,data=request_xml_str.encode("utf-8")) res_data=urllib2.urlopen(res) res_read=res_data.read() doc=xmltodict.parse(res_read) return_code=doc['xml']['return_code'] ifreturn_code=="SUCCESS": result_code=doc['xml']['result_code'] ifresult_code=="SUCCESS": doc=doc['xml'] data={ "appId":self._APP_ID, "nonceStr":nonce_str, "package":"prepay_id="+doc["prepay_id"], "signType":'MD5', "timeStamp":str(int(time.time())), } #paySign签名 paySign=self.generate_sign(data) data["paySign"]=paySign#加入签名 returndata else: err_des=doc['xml']['err_code_des'] returnerr_des else: fail_des=doc['xml']['return_msg'] returnfail_des '''
当然你可能会遇到的错误有签名错误,一般的情况是你的appSecret和商户号的API密钥两个弄错了,当然如果不是还有可能是其他问题,解决方案链接https://www.nhooo.com/article/166176.htm 。
其他的支付方式获取用户的ip地址可以通过socket.gethostbyname(socket.gethostname())方法来获取。
4.支付回调
#统一下单回调处理 importxmltodict fromdjango.httpimportHttpResponse defpayback(request): msg=request.body.decode('utf-8') xmlmsg=xmltodict.parse(msg) return_code=xmlmsg['xml']['return_code'] ifreturn_code=='FAIL': #官方发出错误 returnHttpResponse("""""", content_type='text/xml',status=200) elifreturn_code=='SUCCESS': #拿到这次支付的订单号 out_trade_no=xmlmsg['xml']['out_trade_no'] #根据需要处理业务逻辑 returnHttpResponse(""" """, content_type='text/xml',status=200)
当然微信回调的参数有很多详细可以参考https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8
在回调的时候可能遇到这样一个问题,支付成功以后没有调回调函数,有可能是回调地址是https然后改为http就行,遇到过这个坑,具体原因也不知道。服务器没有屏蔽https访问,https证书也没有问题,把https改为http最后就可以了。
5.安全问题
在使用的过程中商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。
我在开发过程中的解决方式是在向微信支付端发起请求的时候,把订单号,金额,签名等存入数据库,然后在回调函数那里进行校验判断。在确认跟前面订单情况一样的情况下,才进行后续一系列的操作。
最后送给大家一段祝福
#_oo8oo_ #o8888888o #88"."88 #(|-_-|) #0\=/0 #___/'==='\___ #.'\\||#'. #/\\|||:|||#\ #/_|||||-:-|||||_\ #||\\\-#/|| #|\_|''\---/''|_/| #\.-\__'-'__/-./ #___'..'/--.--\'..'___ #.""'<'.___\_<|>_/___.'>'"". #||:`-\`.:`\_/`:.`/-`:|| #\\`-.\___\/___/.-`// #=====`-.____`.___\_____/___.`____.-`===== #`=---=` # # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # #
总结
以上所述是小编给大家介绍的Python实现微信小程序支付功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。