教你使用微信公众平台开发利器-weixin-knife(Python版)
白羽 2018-06-06 来源 :网络 阅读 1040 评论 0

摘要:weixin-knife可以很方便的处理关注,取关注事件,处理文本消息,回复用户信息,jssdk处理,oauth认证,以及微信支付。


 

首先看看怎么用

[python] view plain copy
1. from .weixin import handler as HD  
2. @HD.subscribe  
3. def subscribe(xml):  
4.     return "welcome to brain"  
5.  
6. @HD.unsubscribe  
7. def subscribe(xml):  
8.     print "leave"  
9.     return "leave  brain"  
上面处理了关注和取关事件,通过装饰器处理的还算透明。
处理文本消息,回复图文消息如下:
[python] view plain copy
1. @HD.text  
2. def text(xml):  
3.     content = xml.Content  
4.     if content == "111":  
5.         return {"Title":"美女", "Description":"比基尼美女", "PicUrl":"//9smv.com/static/mm/uploads/150411/2-150411115450247.jpg", "Url":"//9smv.com/beauty/list?category=5"}  
6.     elif content == "222":  
7.         return [  
8.             ["比基尼美女", "比基尼美女", "//9smv.com/static/mm/uploads/150411/2-150411115450247.jpg", "//9smv.com/beauty/list?category=5"],  
9.             ["长腿美女", "长腿美女", "//9smv.com/static/mm/uploads/150506/2-150506111A9648.jpg", "//9smv.com/beauty/list?category=8"]  
10.         ]  
11.     elif content == "push":  
12.         Helper.send_text_message(xml.FromUserName, "推送消息测试")  
13.         return "push ok"  
14.   
15.     return "hello world"  
如何文本是111或222,我们回复图文消息,如何使push,我们使用客服接口推送消息,其它返回“hello world"
 
一般我们会使用oauth网页授权获取用户的openid,如果是多个链接都需要通过oauth处理,代码会很难看,通过装饰器可以很好的处理这个问题。
[python] view plain copy
1. def sns_userinfo_callback(callback=None):  
2.     """网页授权获取用户信息装饰器 
3.     callback(openid, userinfo): 
4.         return user 
5.     """  
6.     def wrap(func):  
7.         @wraps(func)  
8.         def inner(*args, **kwargs):  
9.             request = args[0]  #django第一个参数request  
10.             openid = request.COOKIES.get('openid')  
11.             userinfo = None  
12.             if not openid:  
13.                 code = request.GET.get("code")  
14.                 if not code:  
15.                     current = "//"+ request.get_host() + request.get_full_path()  
16.                     return redirect(WeixinHelper.oauth2(current))  
17.                 else:  
18.                     data = json.loads(WeixinHelper.getAccessTokenByCode(code))  
19.                     access_token, openid, refresh_token = data["access_token"], data["openid"], data["refresh_token"]  
20.                     #WeixinHelper.refreshAccessToken(refresh_token)  
21.                     userinfo = json.loads(WeixinHelper.getSnsapiUserInfo(access_token, openid))  
22.             else:  
23.                 ok, openid = Helper.check_cookie(openid)  
24.                 if not ok:  
25.                     return redirect("/")  
26.             request.openid = openid  
27.             if callable(callback):  
28.                 request.user = callback(openid, userinfo)  
29.             response = func(request)  
30.             return response  
31.         return inner  
32.     return wrap  
33.   
34. sns_userinfo = sns_userinfo_callback()  
在所有需要用户openid的函数前使用sns_userinfo装饰器就可以了,callback函数接收openid,userinfo,返回用户实例,这样
就可以使用request.user获取当前用户
[python] view plain copy
1. @sns_userinfo  
2. def oauth(request):  
3.     """网页授权获取用户信息"""  
4.     resp = HttpResponse(request.openid)  
5.     resp.set_cookie("openid", Helper.sign_cookie(request.openid))  
6.     return resp  
使用oauth需要保存cookie,不然每次用户请求都需要授权,需要走一遍完整的oauth流程,拖慢整体响应。
 
weixin-knife提供了微信支付支持,稍微修改我之前移植的官方PHP版本,https://github.com/Skycrab/wzhifuSDK
[html] view plain copy
1. @sns_userinfo  
2. def pay(request):  
3.     response = render_to_response("pay.html")  
4.     response.set_cookie("openid", Helper.sign_cookie(request.openid))  
5.     return response  
6.   
7. @sns_userinfo  
8. @catch  
9. def paydetail(request):  
10.     """获取支付信息"""  
11.     openid = request.openid  
12.     money = request.POST.get("money") or "0.01"  
13.     money = int(float(money)*100)  
14.   
15.     jsApi = JsApi_pub()  
16.     unifiedOrder = UnifiedOrder_pub()  
17.     unifiedOrder.setParameter("openid",openid) #商品描述  
18.     unifiedOrder.setParameter("body","充值测试") #商品描述  
19.     timeStamp = time.time()  
20.     out_trade_no = "{0}{1}".format(WxPayConf_pub.APPID, int(timeStamp*100))  
21.     unifiedOrder.setParameter("out_trade_no", out_trade_no) #商户订单号  
22.     unifiedOrder.setParameter("total_fee", str(money)) #总金额  
23.     unifiedOrder.setParameter("notify_url", WxPayConf_pub.NOTIFY_URL) #通知地址   
24.     unifiedOrder.setParameter("trade_type", "JSAPI") #交易类型  
25.     unifiedOrder.setParameter("attach", "6666") #附件数据,可分辨不同商家(string(127))  
26.     try:  
27.         prepay_id = unifiedOrder.getPrepayId()  
28.         jsApi.setPrepayId(prepay_id)  
29.         jsApiParameters = jsApi.getParameters()  
30.     except Exception as e:  
31.         print(e)  
32.     else:  
33.         print jsApiParameters  
34.         return HttpResponse(jsApiParameters)  
35.   
36.   
37. FAIL, SUCCESS = "FAIL", "SUCCESS"  
38. @catch  
39. def payback(request):  
40.     """支付回调"""  
41.     xml = request.raw_post_data  
42.     #使用通用通知接口  
43.     notify = Notify_pub()  
44.     notify.saveData(xml)  
45.     print xml  
46.     #验证签名,并回应微信。  
47.     #对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,  
48.     #微信会通过一定的策略(如30分钟共8次)定期重新发起通知,  
49.     #尽可能提高通知的成功率,但微信不保证通知最终能成功  
50.     if not notify.checkSign():  
51.         notify.setReturnParameter("return_code", FAIL) #返回状态码  
52.         notify.setReturnParameter("return_msg", "签名失败") #返回信息  
53.     else:  
54.         result = notify.getData()  
55.   
56.         if result["return_code"] == FAIL:  
57.             notify.setReturnParameter("return_code", FAIL)  
58.             notify.setReturnParameter("return_msg", "通信错误")  
59.         elif result["result_code"] == FAIL:  
60.             notify.setReturnParameter("return_code", FAIL)  
61.             notify.setReturnParameter("return_msg", result["err_code_des"])  
62.         else:  
63.             notify.setReturnParameter("return_code", SUCCESS)  
64.             out_trade_no = result["out_trade_no"] #商户系统的订单号,与请求一致。  
65.             ###检查订单号是否已存在,以及业务代码  
66.   
67.     return  HttpResponse(notify.returnXml())  
pay.html就是使用WeixinJSBridge.invode调用
[javascript] view plain copy
1. $.post("/paydetail",{  
2.    money: $momey  
3.    },function(data){  
4.      if(data){  
5.        var jsonobj = eval('('+data+')');  
6.        WeixinJSBridge.invoke('getBrandWCPayRequest', {  
7.               "appId" : jsonobj.appId, //公众号名称,由商户传入  
8.               "timeStamp" : jsonobj.timeStamp, //时间戳  
9.               "nonceStr" : jsonobj.nonceStr, //随机串  
10.               "package" : jsonobj.package,//扩展包  
11.               "signType" : "MD5", //微信签名方式:1.sha1  
12.               "paySign" : jsonobj.paySign //微信签名  
13.               });  
14.      }  
15.    }  
16.  );  
 
由于access_token, jsapi_ticket需要缓存,而缓存方式又依赖于具体环境,所以提供了一个Helper类,使用了django 的cache
缓存。
[python] view plain copy
1. class Helper(object):  
2.     """微信具体逻辑帮组类"""  
3.  
4.     @class_property  
5.     def access_token(cls):  
6.         key = "ACCESS_TOKEN"  
7.         token = cache.get(key)  
8.         if not token:  
9.             data = json.loads(WeixinHelper.getAccessToken())  
10.             token, expire = data["access_token"], data["expires_in"]  
11.             cache.set(key, token, expire-300)  
12.         return token  
13.  
14.     @class_property  
15.     def jsapi_ticket(cls):  
16.         key = "JSAPI_TICKET"  
17.         ticket = cache.get(key)  
18.         if not ticket:  
19.             data = json.loads(WeixinHelper.getJsapiTicket(cls.access_token))  
20.             ticket, expire = data["ticket"], data["expires_in"]  
21.             cache.set(key, ticket, expire-300)  
22.         return ticket  
class_property提供了类级别的property,当然实例也是可以用的。
[python] view plain copy
1. class class_property(object):  
2.     """ A property can decorator class or instance 
3.  
4.     class Foo(object): 
5.         @class_property 
6.         def foo(cls): 
7.             return 42 
8.  
9.  
10.     print(Foo.foo) 
11.     print(Foo().foo) 
12.  
13.     """  
14.     def __init__(self, func, name=None, doc=None):  
15.         self.__name__ = name or func.__name__  
16.         self.__module__ = func.__module__  
17.         self.__doc__ = doc or func.__doc__  
18.         self.func = func  
19.   
20.     def __get__(self, obj, type=None):  
21.         value = self.func(type)  
22.         return value

 

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

 


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之微信频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程