最近一段时间一直在搞微信平台开发,最近的v3.37版本微信支付接口变化贼大,所以就看着php的demo移植为

python版,为了保持一致,所以接口方法基本都没有变,这样的好处就是不用写demo了,看着微信官方的demo

照葫芦画瓢就可以了。

我已经把代码放到github了,https://github.com/Skycrab/wzhifuSDK,我主要测试了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 ETtry:import pycurlfrom cStringIO import StringIO
except ImportError:pycurl = Noneclass 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 clsinstance = super(Singleton, cls).__new__(impl, *args, **kwargs)instance.__init__(*args, **kwargs)cls._instance = instancereturn cls._instanceclass 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 datadef 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)#设置不输出headerself.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):@classmethoddef configure(cls):if pycurl is not None and WxPayConf_pub.HTTP_CLIENT != "URLLIB":return CurlClientelse:return UrllibClientclass Common_util_pub(object):"""所有接口的基类"""def trimString(self, value):if value is not None and len(value) == 0:value = Nonereturn valuedef 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后加入KEYString = "{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.textarray_data[child.tag] = valuereturn array_datadef 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码,用以获取openidopenid = None  #用户的openidparameters = None  #jsapi参数,格式为jsonprepay_id = None #使用统一支付接口得到的预支付idcurl_timeout = None #curl超时时间def __init__(self, timeout=WxPayConf_pub.CURL_TIMEOUT):self.curl_timeout = timeoutdef createOauthUrlForCode(self, redirectUrl):"""生成可以获得code的url"""urlObj = {}urlObj["appid"] = WxPayConf_pub.APPIDurlObj["redirect_uri"] = redirectUrlurlObj["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?"+bizStringdef createOauthUrlForOpenid(self):"""生成可以获得openid的url"""urlObj = {}urlObj["appid"] = WxPayConf_pub.APPIDurlObj["secret"] = WxPayConf_pub.APPSECRETurlObj["code"] = self.codeurlObj["grant_type"] = "authorization_code"bizString = self.formatBizQueryParaMap(urlObj, False)return "https://api.weixin.qq.com/sns/oauth2/access_token?"+bizStringdef getOpenid(self):"""通过curl向微信提交code,以获取openid"""url = self.createOauthUrlForOpenid()data = HttpClient().get(url)self.openid = json.loads(data)["openid"]return self.openiddef setPrepayId(self, prepayId):"""设置prepay_id"""self.prepay_id = prepayIddef setCode(self, code):"""设置code"""self.code = codedef  getParameters(self):"""设置jsapi的参数"""jsApiObj = {}jsApiObj["appId"] = WxPayConf_pub.APPIDtimeStamp = 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.parametersclass 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   #公众账号IDself.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.responsedef postXmlSSL(self):"""使用证书post请求xml"""xml = self.createXml()self.response = self.postXmlSSLCurl(xml, self.url, self.curl_timeout)return self.responsedef getResult(self):"""获取结果,默认不使用证书"""self.postXml()self.result = self.xmlToArray(self.response)return self.resultclass 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 = timeoutsuper(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  #公众账号IDself.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_idclass 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 = timeoutsuper(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  #公众账号IDself.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 = timeoutsuper(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  #公众账号IDself.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.resultclass 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 = timeoutsuper(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  #公众账号IDself.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.resultclass 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 = timeoutsuper(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  #公众账号IDself.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.resultclass 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 = timeoutsuper(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  #公众账号IDself.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_idclass 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 signdel tmpData['sign']sign = self.getSign(tmpData) #本地签名if self.data['sign'] == sign:return Truereturn Falsedef getData(self):"""获取微信的请求数据"""return self.datadef 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 returnXmlclass 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 #公众账号IDself.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_idclass 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  #公众账号IDself.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?"+bizStringdef getUrl(self):"""返回链接"""self.createLink()return self.urldef test():c = HttpClient()assert c.get("http://www.baidu.com")[:15] == "<!DOCTYPE html>"c2 = HttpClient()assert id(c) == id(c2)if __name__ == "__main__":test()

微信支付SDK(python版)相关推荐

  1. 7月第1周风控关注 微信支付SDK曝XXE漏洞 可伪造订单

    ​易盾业务风控周报每周呈报值得关注的安全技术和事件,包括但不限于内容安全.移动安全.业务安全和网络安全,帮助企业提高警惕,规避这些似小实大.影响业务健康发展的安全风险. 1.微信支付SDK被曝XXE漏 ...

  2. iOS SDK开发系列三之微信支付SDK封装Demo以及xcodebuild简单打包脚本实现

    前言 SDK开发系列文章一 SDK开发系列文章二 之前两个文章介绍了Cocoapods的原理,Xcode环境变量以及动态库和静态库的介绍,这些基本知识就单独抽出来了,方便以后翻阅.看了一遍网上的一些静 ...

  3. 微信支付sdk被曝xxe漏洞,漏洞原理分析

    2019独角兽企业重金招聘Python工程师标准>>> 昨日在国外安全社区seclists有一个署名叫Rose Jackcode的白帽子公布了微信支付sdk的一个严重的安全漏洞(xx ...

  4. tp6中使用微信支付sdk

    一.下载微信支付sdk 二.将lib文件夹下的文件复制到目录:extend->WxPay 将example文件夹下的WxPay.Config.php文件也复制到:extend->WxPay ...

  5. 微信支付SDK的使用

    在此记录一下微信支付sdk的使用 使用微信支付SDK理所应该去看官方文档,按步骤一步步来就好了,怎么还需要写博客呢? 答案是因为使用支付SDK时,遇到了很多弱智的坑,希望后来人不要和我一样SB就好. ...

  6. 微信支付SDK接入流程梳理

    微信SDK的支付功能接入简单梳理. 首先说一下,你需要的官网都有,但是官网提供的东西不管新旧与否先给你放上去,部分地方提供的链接点击时还提示404,不同的页面提示相同的下载内容(demo)还不一样,表 ...

  7. tp5 微信支付sdk

    接触到微信支付,然而微信官方给出的微信支付sdk用起来不太方便,在原来微信支付sdk上进行了修改,测试过能用,现在我的tp5项目都用这个,分享出来大家研究研究,新手一枚,望大神们能指出错处. git地 ...

  8. 微信支付SDK 中 PHP Certificate Downloader 微信支付 APIv3 平台证书的命令行下载工具 使用教程

    使用环境 在linux 环境中使用 (没有服务器可以使用虚拟机 复制到本地) windows环境很麻烦 使用前准备 商户号.商户证书序列号.商户私匙文件(pem格式).ApiV3密钥 安装好 微信支付 ...

  9. Unity接入微信支付SDK

    最近1年转了UE开发,博客更新的比较少,技术栈宽了不少,以后有空尽量多更新,也方便总结记忆 Unity接入微信支付整个过程坑比较多,网上之前的教程要么比较老,要么比较零碎,只能东拼西凑摸索,跑通后还是 ...

最新文章

  1. 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高)...
  2. wifi的基础知识及原理1
  3. n皇后问题java版
  4. AVB2 avbtool.py脚本常用命令
  5. 4-12DataSet Transformations
  6. 王校长撩妹不成反被锤爆?再有钱的舔狗也只是舔狗【Python爬虫实战:微博评论采取】
  7. 【Javascript Demo】图片瀑布流实现
  8. 教你将视频作为背景添加到另一段视频中
  9. win10系统服务器不能创建对象,win10系统Activex部件不能创建对象的详细技巧
  10. DNS服务器常见的攻击方式
  11. 平生事,此时凝睇,谁会凭栏意!(2)
  12. au能否打开m4a文件_什么是M4V文件(以及如何打开一个文件)?
  13. 【python教程入门学习】ASCII码一览表,ASCII码对照表
  14. 色彩平衡校正色彩的原理
  15. 广度优先搜索:迷宫问题
  16. 虚拟试衣-DiOr论文解读
  17. 青烟鸿影一盏茶,孤灯小楼听夜雨
  18. 华为2021校招【软件开发岗】笔+面试总结
  19. 给大家分享一个可以查询sci期刊、中文CSCD期刊实时影响因子的网站
  20. [持续更新] 神经机器翻译论文汇总 Papers on Neural Machine Translation

热门文章

  1. Improving the Sensitivity of Online Controlled Experiments by Utilizing Pre-Experiment Data
  2. yii2 使用redis
  3. 【Grasshopper基础8】电池的序列化与反序列化 Serilization of Grasshopper Component
  4. html怎么引用php文件,html页面怎么跟php文件连接
  5. 折叠::Vim进阶索引[2]
  6. 工业互联网新发展:基于 HTML5 WebGL 的高炉炼铁厂可视化系统
  7. EXCEL网络共享解决方案
  8. 简单的网页设计,以学校官网为例
  9. Learning Atom 学习Atom编辑器 Lynda课程中文字幕
  10. Eclipse每次打包注意事项