白羽
2018-06-06
来源 :网络
阅读 1421
评论 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
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号