国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python開發微信公眾平臺的方法詳解【基于weixin-knife】

2020-01-04 16:57:46
字體:
來源:轉載
供稿:網友

本文實例講述了Python開發微信公眾平臺的方法。分享給大家供大家參考,具體如下:

這兩天將之前基于微信公眾平臺的代碼重構了下,基礎功能以庫的方式提供,提供了demo使用的是django,看著之前為趕進度寫的代碼真的慘不忍睹,所以weixin-knife產生了,正如其名,提供的是必要的功能,而不是完整的應用。weixin-knife可以很方便的處理關注,取關注事件,處理文本消息,回復用戶信息,jssdk處理,oauth認證,以及微信支付。

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

首先看看怎么用

from .weixin import handler as HD@HD.subscribedef 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程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新宾| 安化县| 渝北区| 郯城县| 柳林县| 樟树市| 隆化县| 毕节市| 竹山县| 红河县| 满洲里市| 海伦市| 松潘县| 方正县| 房山区| 阳曲县| 阜平县| 扬州市| 霞浦县| 天镇县| 奉节县| 马尔康县| 萨迦县| 连平县| 大化| 岗巴县| 潞城市| 绥滨县| 佛山市| 吉木萨尔县| 江陵县| 井研县| 岚皋县| 富顺县| 正镶白旗| 元朗区| 卫辉市| 苗栗市| 罗田县| 依兰县| 安溪县|