您好,欢迎访问一九零五行业门户网

Python使用微信SDK实现的支付功能

这篇文章主要介绍了python使用微信sdk实现的微信支付功能,结合实例形式分析了python调用微信sdk接口实现微信支付功能的具体步骤与相关操作技巧,需要的朋友可以参考下
本文实例讲述了python使用微信sdk实现的微信支付功能。分享给大家供大家参考,具体如下:
最近一段时间一直在搞微信平台开发,v3.37版本微信支付接口变化贼大,所以就看着php的demo移植为python版,为了保持一致,所以接口方法基本都没有变,这样的好处就是不用写demo了,看着微信官方的demo照葫芦画瓢就可以了。
还可以点击此处本站下载。
我主要测试了jsapi调用方式,其它的调用方式并没有测试,如果你发现了bug,请多多pull request,我将不甚感激。
方便观看,代码贴于此。
#coding:utf-8 """ created on 2014-11-24 @author: http://blog.csdn.net/yueguanghaidao * 微信支付帮助库 * ==================================================== * 接口分三种类型: * 【请求型接口】--wxpay_client_ * 统一支付接口类--unifiedorder * 订单查询接口--orderquery * 退款申请接口--refund * 退款查询接口--refundquery * 对账单接口--downloadbill * 短链接转换接口--shorturl * 【响应型接口】--wxpay_server_ * 通用通知接口--notify * native支付——请求商家获取商品信息接口--nativecall * 【其他】 * 静态链接二维码--nativelink * jsapi支付--jsapi * ===================================================== * 【commonutil】常用工具: * trimstring(),设置参数时需要用到的字符处理函数 * createnoncestr(),产生随机字符串,不长于32位 * formatbizqueryparamap(),格式化参数,签名过程需要用到 * getsign(),生成签名 * arraytoxml(),array转xml * xmltoarray(),xml转 array * postxmlcurl(),以post方式提交xml到对应的接口url * postxmlsslcurl(),使用证书,以post方式提交xml到对应的接口url """ import json import time import random import urllib2 import hashlib import threading from urllib import quote import xml.etree.elementtree as et try: import pycurl from cstringio import stringio except importerror: pycurl = none class wxpayconf_pub(object): """配置账号信息""" #=======【基本信息设置】===================================== #微信公众号身份的唯一标识。审核通过后,在微信发送的邮件中查看 appid = "wx8888888888888888" #jsapi接口中获取openid,审核后在公众平台开启开发模式后可查看 appsecret = "48888888888888888888888888888887" #受理商id,身份标识 mchid = "18888887" #商户支付密钥key。审核通过后,在微信发送的邮件中查看 key = "48888888888888888888888888888886" #=======【异步通知url设置】=================================== #异步通知url,商户根据实际开发过程设定 notify_url = "http://******.com/payback" #=======【jsapi路径设置】=================================== #获取access_token过程中的跳转uri,通过跳转将code传入jsapi支付页面 js_api_call_url = "http://******.com/pay/?showwxpaytitle=1" #=======【证书路径设置】===================================== #证书路径,注意应该填写绝对路径 sslcert_path = "/******/cacert/apiclient_cert.pem" sslkey_path = "/******/cacert/apiclient_key.pem" #=======【curl超时设置】=================================== curl_timeout = 30 #=======【http客户端设置】=================================== http_client = "curl" # ("urllib", "curl") class singleton(object): """单例模式""" _instance_lock = threading.lock() def new(cls, *args, **kwargs): if not hasattr(cls, "_instance"): with cls._instance_lock: if not hasattr(cls, "_instance"): impl = cls.configure() if hasattr(cls, "configure") else cls instance = super(singleton, cls).new(impl, *args, **kwargs) instance.init(*args, **kwargs) cls._instance = instance return cls._instance class urllibclient(object): """使用urlib2发送请求""" def get(self, url, second=30): return self.postxml(none, url, second) def postxml(self, xml, url, second=30): """不使用证书""" data = urllib2.urlopen(url, xml, timeout=second).read() return data def postxmlssl(self, xml, url, second=30): """使用证书""" raise typeerror("please use curlclient") class curlclient(object): """使用curl发送请求""" def init(self): self.curl = pycurl.curl() self.curl.setopt(pycurl.ssl_verifyhost, false) self.curl.setopt(pycurl.ssl_verifypeer, false) #设置不输出header self.curl.setopt(pycurl.header, false) def get(self, url, second=30): return self.postxmlssl(none, url, second=second, cert=false, post=false) def postxml(self, xml, url, second=30): """不使用证书""" return self.postxmlssl(xml, url, second=second, cert=false, post=true) def postxmlssl(self, xml, url, second=30, cert=true, post=true): """使用证书""" self.curl.setopt(pycurl.url, url) self.curl.setopt(pycurl.timeout, second) #设置证书 #使用证书:cert 与 key 分别属于两个.pem文件 #默认格式为pem,可以注释 if cert: self.curl.setopt(pycurl.sslkeytype, "pem") self.curl.setopt(pycurl.sslkey, wxpayconf_pub.sslkey_path) self.curl.setopt(pycurl.sslcerttype, "pem") self.curl.setopt(pycurl.sslcert, wxpayconf_pub.sslkey_path) #post提交方式 if post: self.curl.setopt(pycurl.post, true) self.curl.setopt(pycurl.postfields, xml) buff = stringio() self.curl.setopt(pycurl.writefunction, buff.write) self.curl.perform() return buff.getvalue() class httpclient(singleton): @classmethod def configure(cls): if pycurl is not none and wxpayconf_pub.http_client != "urllib": return curlclient else: return urllibclient class common_util_pub(object): """所有接口的基类""" def trimstring(self, value): if value is not none and len(value) == 0: value = none return value def createnoncestr(self, length = 32): """产生随机字符串,不长于32位""" chars = "abcdefghijklmnopqrstuvwxyz0123456789" strs = [] for x in range(length): strs.append(chars[random.randrange(0, len(chars))]) return "".join(strs) def formatbizqueryparamap(self, paramap, urlencode): """格式化参数,签名过程需要使用""" slist = sorted(paramap) buff = [] for k in slist: v = quote(paramap[k]) if urlencode else paramap[k] buff.append("{0}={1}".format(k, v)) return "&".join(buff) def getsign(self, obj): """生成签名""" #签名步骤一:按字典序排序参数,formatbizqueryparamap已做 string = self.formatbizqueryparamap(obj, false) #签名步骤二:在string后加入key string = "{0}&key={1}".format(string,wxpayconf_pub.key) #签名步骤三:md5加密 string = hashlib.md5(string).hexdigest() #签名步骤四:所有字符转为大写 result_ = string.upper() return result_ def arraytoxml(self, arr): """array转xml""" xml = ["<xml>"] for k, v in arr.iteritems(): if v.isdigit(): xml.append("<{0}>{1}</{0}>".format(k, v)) else: xml.append("<{0}><![cdata[{1}]]></{0}>".format(k, v)) xml.append("</xml>") return "".join(xml) def xmltoarray(self, xml): """将xml转为array""" array_data = {} root = et.fromstring(xml) for child in root: value = child.text array_data[child.tag] = value return array_data def postxmlcurl(self, xml, url, second=30): """以post方式提交xml到对应的接口url""" return httpclient().postxml(xml, url, second=second) def postxmlsslcurl(self, xml, url, second=30): """使用证书,以post方式提交xml到对应的接口url""" return httpclient().postxmlssl(xml, url, second=second) class jsapi_pub(common_util_pub): """jsapi支付——h5网页端调起支付接口""" code = none #code码,用以获取openid openid = none #用户的openid parameters = none #jsapi参数,格式为json prepay_id = none #使用统一支付接口得到的预支付id curl_timeout = none #curl超时时间 def init(self, timeout=wxpayconf_pub.curl_timeout): self.curl_timeout = timeout def createoauthurlforcode(self, redirecturl): """生成可以获得code的url""" urlobj = {} urlobj["appid"] = wxpayconf_pub.appid urlobj["redirect_uri"] = redirecturl urlobj["response_type"] = "code" urlobj["scope"] = "snsapi_base" urlobj["state"] = "state#wechat_redirect" bizstring = self.formatbizqueryparamap(urlobj, false) return "https://open.weixin.qq.com/connect/oauth2/authorize?"+bizstring def createoauthurlforopenid(self): """生成可以获得openid的url""" urlobj = {} urlobj["appid"] = wxpayconf_pub.appid urlobj["secret"] = wxpayconf_pub.appsecret urlobj["code"] = self.code urlobj["grant_type"] = "authorization_code" bizstring = self.formatbizqueryparamap(urlobj, false) return "https://api.weixin.qq.com/sns/oauth2/access_token?"+bizstring def getopenid(self): """通过curl向微信提交code,以获取openid""" url = self.createoauthurlforopenid() data = httpclient().get(url) self.openid = json.loads(data)["openid"] return self.openid def setprepayid(self, prepayid): """设置prepay_id""" self.prepay_id = prepayid def setcode(self, code): """设置code""" self.code = code def getparameters(self): """设置jsapi的参数""" jsapiobj = {} jsapiobj["appid"] = wxpayconf_pub.appid timestamp = int(time.time()) jsapiobj["timestamp"] = "{0}".format(timestamp) jsapiobj["noncestr"] = self.createnoncestr() jsapiobj["package"] = "prepay_id={0}".format(self.prepay_id) jsapiobj["signtype"] = "md5" jsapiobj["paysign"] = self.getsign(jsapiobj) self.parameters = json.dumps(jsapiobj) return self.parameters class wxpay_client_pub(common_util_pub): """请求型接口的基类""" response = none #微信返回的响应 url = none #接口链接 curl_timeout = none #curl超时时间 def init(self): self.parameters = {} #请求参数,类型为关联数组 self.result = {} #返回参数,类型为关联数组 def setparameter(self, parameter, parametervalue): """设置请求参数""" self.parameters[self.trimstring(parameter)] = self.trimstring(parametervalue) def createxml(self): """设置标配的请求参数,生成签名,生成接口参数xml""" self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) def postxml(self): """post请求xml""" xml = self.createxml() self.response = self.postxmlcurl(xml, self.url, self.curl_timeout) return self.response def postxmlssl(self): """使用证书post请求xml""" xml = self.createxml() self.response = self.postxmlsslcurl(xml, self.url, self.curl_timeout) return self.response def getresult(self): """获取结果,默认不使用证书""" self.postxml() self.result = self.xmltoarray(self.response) return self.result class unifiedorder_pub(wxpay_client_pub): """统一支付接口类""" def init(self, timeout=wxpayconf_pub.curl_timeout): #设置接口链接 self.url = "https://api.mch.weixin.qq.com/pay/unifiedorder" #设置curl超时时间 self.curl_timeout = timeout super(unifiedorder_pub, self).init() def createxml(self): """生成接口参数xml""" #检测必填参数 if any(self.parameters[key] is none for key in ("out_trade_no", "body", "total_fee", "notify_url", "trade_type")): raise valueerror("missing parameter") if self.parameters["trade_type"] == "jsapi" and self.parameters["openid"] is none: raise valueerror("jsapi need openid parameters") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["spbill_create_ip"] = "127.0.0.1" #终端ip self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) def getprepayid(self): """获取prepay_id""" self.postxml() self.result = self.xmltoarray(self.response) prepay_id = self.result["prepay_id"] return prepay_id class orderquery_pub(wxpay_client_pub): """订单查询接口""" def init(self, timeout=wxpayconf_pub.curl_timeout): #设置接口链接 self.url = "https://api.mch.weixin.qq.com/pay/orderquery" #设置curl超时时间 self.curl_timeout = timeout super(orderquery_pub, self).init() def createxml(self): """生成接口参数xml""" #检测必填参数 if any(self.parameters[key] is none for key in ("out_trade_no", "transaction_id")): raise valueerror("missing parameter") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) class refund_pub(wxpay_client_pub): """退款申请接口""" def init(self, timeout=wxpayconf_pub.curl_timeout): #设置接口链接 self.url = "https://api.mch.weixin.qq.com/secapi/pay/refund" #设置curl超时时间 self.curl_timeout = timeout super(refund_pub, self).init() def createxml(self): """生成接口参数xml""" if any(self.parameters[key] is none for key in ("out_trade_no", "out_refund_no", "total_fee", "refund_fee", "op_user_id")): raise valueerror("missing parameter") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) def getresult(self): """ 获取结果,使用证书通信(需要双向证书)""" self.postxmlssl() self.result = self.xmltoarray(self.response) return self.result class refundquery_pub(wxpay_client_pub): """退款查询接口""" def init(self, timeout=wxpayconf_pub.curl_timeout): #设置接口链接 self.url = "https://api.mch.weixin.qq.com/pay/refundquery" #设置curl超时时间 self.curl_timeout = timeout super(refundquery_pub, self).init() def createxml(self): """生成接口参数xml""" if any(self.parameters[key] is none for key in ("out_refund_no", "out_trade_no", "transaction_id", "refund_id")): raise valueerror("missing parameter") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) def getresult(self): """ 获取结果,使用证书通信(需要双向证书)""" self.postxmlssl() self.result = self.xmltoarray(self.response) return self.result class downloadbill_pub(wxpay_client_pub): """对账单接口""" def init(self, timeout=wxpayconf_pub.curl_timeout): #设置接口链接 self.url = "https://api.mch.weixin.qq.com/pay/downloadbill" #设置curl超时时间 self.curl_timeout = timeout super(downloadbill_pub, self).init() def createxml(self): """生成接口参数xml""" if any(self.parameters[key] is none for key in ("bill_date", )): raise valueerror("missing parameter") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) def getresult(self): """获取结果,默认不使用证书""" self.postxml() self.result = self.xmltoarray(self.response) return self.result class shorturl_pub(wxpay_client_pub): """短链接转换接口""" def init(self, timeout=wxpayconf_pub.curl_timeout): #设置接口链接 self.url = "https://api.mch.weixin.qq.com/tools/shorturl" #设置curl超时时间 self.curl_timeout = timeout super(shorturl_pub, self).init() def createxml(self): """生成接口参数xml""" if any(self.parameters[key] is none for key in ("long_url", )): raise valueerror("missing parameter") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 return self.arraytoxml(self.parameters) def getshorturl(self): """获取prepay_id""" self.postxml() prepay_id = self.result["short_url"] return prepay_id class wxpay_server_pub(common_util_pub): """响应型接口基类""" success, fail = "success", "fail" def init(self): self.data = {} #接收到的数据,类型为关联数组 self.returnparameters = {} #返回参数,类型为关联数组 def savedata(self, xml): """将微信的请求xml转换成关联数组,以方便数据处理""" self.data = self.xmltoarray(xml) def checksign(self): """校验签名""" tmpdata = dict(self.data) #make a copy to save sign del tmpdata['sign'] sign = self.getsign(tmpdata) #本地签名 if self.data['sign'] == sign: return true return false def getdata(self): """获取微信的请求数据""" return self.data def setreturnparameter(self, parameter, parametervalue): """设置返回微信的xml数据""" self.returnparameters[self.trimstring(parameter)] = self.trimstring(parametervalue) def createxml(self): """生成接口参数xml""" return self.arraytoxml(self.returnparameters) def returnxml(self): """将xml数据返回微信""" returnxml = self.createxml() return returnxml class notify_pub(wxpay_server_pub): """通用通知接口""" class nativecall_pub(wxpay_server_pub): """请求商家获取商品信息接口""" def createxml(self): """生成接口参数xml""" if self.returnparameters["return_code"] == self.success: self.returnparameters["appid"] = wxpayconf_pub.appid #公众账号id self.returnparameters["mch_id"] = wxpayconf_pub.mchid #商户号 self.returnparameters["nonce_str"] = self.createnoncestr() #随机字符串 self.returnparameters["sign"] = self.getsign(self.returnparameters) #签名 return self.arraytoxml(self.returnparameters) def getproductid(self): """获取product_id""" product_id = self.data["product_id"] return product_id class nativelink_pub(common_util_pub): """静态链接二维码""" url = none #静态链接 def init(self): self.parameters = {} #静态链接参数 def setparameter(self, parameter, parametervalue): """设置参数""" self.parameters[self.trimstring(parameter)] = self.trimstring(parametervalue) def createlink(self): if any(self.parameters[key] is none for key in ("product_id", )): raise valueerror("missing parameter") self.parameters["appid"] = wxpayconf_pub.appid #公众账号id self.parameters["mch_id"] = wxpayconf_pub.mchid #商户号 time_stamp = int(time.time()) self.parameters["time_stamp"] = "{0}".format(time_stamp) #时间戳 self.parameters["nonce_str"] = self.createnoncestr() #随机字符串 self.parameters["sign"] = self.getsign(self.parameters) #签名 bizstring = self.formatbizqueryparamap(self.parameters, false) self.url = "weixin://wxpay/bizpayurl?"+bizstring def geturl(self): """返回链接""" self.createlink() return self.url def test(): c = httpclient() assert c.get("http://www.baidu.com")[:15] == "<!doctype html>" c2 = httpclient() assert id(c) == id(c2) if name == "main": test()
以上就是python使用微信sdk实现的支付功能的详细内容。
其它类似信息

推荐信息