侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python开发微信公众平台的方法详解【基于weixin-knife】

Python  /  管理员 发布于 7年前   188

本文实例讲述了Python开发微信公众平台的方法。分享给大家供大家参考,具体如下:

这两天将之前基于微信公众平台的代码重构了下,基础功能以库的方式提供,提供了demo使用的是django,看着之前为赶进度写的代码真的惨不忍睹,所以weixin-knife产生了,正如其名,提供的是必要的功能,而不是完整的应用。weixin-knife可以很方便的处理关注,取关注事件,处理文本消息,回复用户信息,jssdk处理,oauth认证,以及微信支付。

github地址:https://github.com/Skycrab/weixin-knife。

首先看看怎么用

from .weixin import handler as [email protected] subscribe(xml):  return "welcome to brain"@HD.unsubscribedef subscribe(xml):  print "leave"  return "leave brain"

上面处理了关注和取关事件,通过装饰器处理的还算透明。

处理文本消息,回复图文消息如下:

@HD.textdef text(xml):  content = xml.Content  if content == "111":    return {"Title":"美女", "Description":"比基尼美女", "PicUrl":"http://9smv.com/static/mm/uploads/150411/2-150411115450247.jpg", "Url":"http://9smv.com/beauty/list?category=5"}  elif content == "222":    return [      ["比基尼美女", "比基尼美女", "http://9smv.com/static/mm/uploads/150411/2-150411115450247.jpg", "http://9smv.com/beauty/list?category=5"],      ["长腿美女", "长腿美女", "http://9smv.com/static/mm/uploads/150506/2-150506111A9648.jpg", "http://9smv.com/beauty/list?category=8"]    ]  elif content == "push":    Helper.send_text_message(xml.FromUserName, "推送消息测试")    return "push ok"  return "hello world"

如何文本是111或222,我们回复图文消息,如何使push,我们使用客服接口推送消息,其它返回“hello world"

一般我们会使用oauth网页授权获取用户的openid,如果是多个链接都需要通过oauth处理,代码会很难看,通过装饰器可以很好的处理这个问题。

def sns_userinfo_callback(callback=None):  """网页授权获取用户信息装饰器  callback(openid, userinfo):    return user  """  def wrap(func):    @wraps(func)    def inner(*args, **kwargs):      request = args[0] #django第一个参数request      openid = request.COOKIES.get('openid')      userinfo = None      if not openid:        code = request.GET.get("code")        if not code:          current = "http://"+ request.get_host() + request.get_full_path()          return redirect(WeixinHelper.oauth2(current))        else:          data = json.loads(WeixinHelper.getAccessTokenByCode(code))          access_token, openid, refresh_token = data["access_token"], data["openid"], data["refresh_token"]          #WeixinHelper.refreshAccessToken(refresh_token)          userinfo = json.loads(WeixinHelper.getSnsapiUserInfo(access_token, openid))      else:        ok, openid = Helper.check_cookie(openid)        if not ok:          return redirect("/")      request.openid = openid      if callable(callback):        request.user = callback(openid, userinfo)      response = func(request)      return response    return inner  return wrapsns_userinfo = sns_userinfo_callback()

在所有需要用户openid的函数前使用sns_userinfo装饰器就可以了,callback函数接收openid,userinfo,返回用户实例,这样就可以使用request.user获取当前用户

@sns_userinfodef oauth(request):  """网页授权获取用户信息"""  resp = HttpResponse(request.openid)  resp.set_cookie("openid", Helper.sign_cookie(request.openid))  return resp

使用oauth需要保存cookie,不然每次用户请求都需要授权,需要走一遍完整的oauth流程,拖慢整体响应。

weixin-knife提供了微信支付支持,稍微修改我之前移植的官方PHP版本,https://github.com/Skycrab/wzhifuSDK

@sns_userinfodef pay(request):  response = render_to_response("pay.html")  response.set_cookie("openid", Helper.sign_cookie(request.openid))  return response@sns_userinfo@catchdef paydetail(request):  """获取支付信息"""  openid = request.openid  money = request.POST.get("money") or "0.01"  money = int(float(money)*100)  jsApi = JsApi_pub()  unifiedOrder = UnifiedOrder_pub()  unifiedOrder.setParameter("openid",openid) #商品描述  unifiedOrder.setParameter("body","充值测试") #商品描述  timeStamp = time.time()  out_trade_no = "{0}{1}".format(WxPayConf_pub.APPID, int(timeStamp*100))  unifiedOrder.setParameter("out_trade_no", out_trade_no) #商户订单号  unifiedOrder.setParameter("total_fee", str(money)) #总金额  unifiedOrder.setParameter("notify_url", WxPayConf_pub.NOTIFY_URL) #通知地址  unifiedOrder.setParameter("trade_type", "JSAPI") #交易类型  unifiedOrder.setParameter("attach", "6666") #附件数据,可分辨不同商家(string(127))  try:    prepay_id = unifiedOrder.getPrepayId()    jsApi.setPrepayId(prepay_id)    jsApiParameters = jsApi.getParameters()  except Exception as e:    print(e)  else:    print jsApiParameters    return HttpResponse(jsApiParameters)FAIL, SUCCESS = "FAIL", "SUCCESS"@catchdef payback(request):  """支付回调"""  xml = request.raw_post_data  #使用通用通知接口  notify = Notify_pub()  notify.saveData(xml)  print xml  #验证签名,并回应微信。  #对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,  #微信会通过一定的策略(如30分钟共8次)定期重新发起通知,  #尽可能提高通知的成功率,但微信不保证通知最终能成功  if not notify.checkSign():    notify.setReturnParameter("return_code", FAIL) #返回状态码    notify.setReturnParameter("return_msg", "签名失败") #返回信息  else:    result = notify.getData()    if result["return_code"] == FAIL:      notify.setReturnParameter("return_code", FAIL)      notify.setReturnParameter("return_msg", "通信错误")    elif result["result_code"] == FAIL:      notify.setReturnParameter("return_code", FAIL)      notify.setReturnParameter("return_msg", result["err_code_des"])    else:      notify.setReturnParameter("return_code", SUCCESS)      out_trade_no = result["out_trade_no"] #商户系统的订单号,与请求一致。      ###检查订单号是否已存在,以及业务代码  return HttpResponse(notify.returnXml())

pay.html就是使用WeixinJSBridge.invode调用

$.post("/paydetail",{  money: $momey  },function(data){   if(data){    var jsonobj = eval('('+data+')');    WeixinJSBridge.invoke('getBrandWCPayRequest', {       "appId" : jsonobj.appId, //公众号名称,由商户传入       "timeStamp" : jsonobj.timeStamp, //时间戳       "nonceStr" : jsonobj.nonceStr, //随机串       "package" : jsonobj.package,//扩展包       "signType" : "MD5", //微信签名方式:1.sha1       "paySign" : jsonobj.paySign //微信签名       });   }  } );

由于access_token, jsapi_ticket需要缓存,而缓存方式又依赖于具体环境,所以提供了一个Helper类,使用了django 的cache缓存。

class Helper(object):  """微信具体逻辑帮组类"""  @class_property  def access_token(cls):    key = "ACCESS_TOKEN"    token = cache.get(key)    if not token:      data = json.loads(WeixinHelper.getAccessToken())      token, expire = data["access_token"], data["expires_in"]      cache.set(key, token, expire-300)    return token  @class_property  def jsapi_ticket(cls):    key = "JSAPI_TICKET"    ticket = cache.get(key)    if not ticket:      data = json.loads(WeixinHelper.getJsapiTicket(cls.access_token))      ticket, expire = data["ticket"], data["expires_in"]      cache.set(key, ticket, expire-300)    return ticket

class_property提供了类级别的property,当然实例也是可以用的。

class class_property(object):  """ A property can decorator class or instance  class Foo(object):    @class_property    def foo(cls):      return 42  print(Foo.foo)  print(Foo().foo)  """  def __init__(self, func, name=None, doc=None):    self.__name__ = name or func.__name__    self.__module__ = func.__module__    self.__doc__ = doc or func.__doc__    self.func = func  def __get__(self, obj, type=None):    value = self.func(type)    return value

使用weixin-knife助力公众平台开发,你完全可以稍加修改用于flask等其它web框架。

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python字符串操作技巧汇总》、《Python编码操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》及《Python入门与进阶经典教程》。

希望本文所述对大家Python程序设计有所帮助。


  • 上一条:
    Python基于scapy实现修改IP发送请求的方法示例
    下一条:
    python 中random模块的常用方法总结
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go语言中实现字符串可逆性压缩及解压缩功能(0个评论)
    • 使用go + gin + jwt + qrcode实现网站生成登录二维码在app中扫码登录功能(0个评论)
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客