Skip to content

Commit 825113b

Browse files
committed
Merge branch 'release/0.4.12'
2 parents dbdd202 + 2c32771 commit 825113b

File tree

8 files changed

+1125
-294
lines changed

8 files changed

+1125
-294
lines changed

README.md

Lines changed: 195 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,236 @@
1-
# Wechat SDK
2-
An UnOfficial WeChat python SDK. For the primal version, the SDK support the `Official Account` only.
1+
# 微信公众号Python-SDK
32

4-
Author: [@jeff_kit](http://twitter.com/jeff_kit)
3+
作者: [@jeff_kit](http://twitter.com/jeff_kit)
54

6-
# Getting start
5+
本SDK支持微信公众号以及企业号的上行消息及OAuth接口。本文档及SDK假设使用者已经具备微信公众号开发的基础知识,及有能力通过微信公众号、企业号的文档来查找相关的接口详情。
76

8-
Before getting start, you should have learnt what wechat official account is, and have registed acccount. if you don't, click [here](http://mp.weixin.qq.com) to learn more.
97

10-
Now, we are going to create an echo robot, the robot will send back what you sent to the official account. ps. I use Django web framework for the example.
8+
## 1. 安装
119

12-
## 1. install Wechat sdk
10+
### pip
11+
12+
pip install wechat
13+
14+
### 源码安装
1315

1416
git clone git@github.com:jeffkit/wechat.git
1517
cd wechat
1618
python setup.py install
19+
20+
21+
## 2. 用户上行消息处理框架
1722

18-
## 2. setup your web server
19-
You can use any webframework you like for the response server, just set it up and have it run.
23+
对于微信用户在公众号内发送的上行消息,本sdk提供了一个微型处理框架,开发者只需继承wechat.official.WxApplication类, 实现各种消息对应的方法,然后把该类与自己熟悉的web框架结合起来使用即可。
2024

21-
Your offical account should turn into develop mode, and config the interface url and token.
25+
WxApplication内部会实现请求的合法性校验以及消息的分发等功能,还对上行消息对行了结构化,开发者把精力放到业务逻辑的编写即可。
2226

23-
For example, start a Django project and config a view to interactive with Official account.
24-
25-
django-admin.py startproject demo
26-
cd demo
27-
python manage.py startapp echo
28-
29-
modify demo/settings.py, append echo to INSTALLED_APPS:
27+
WxApplication类核心方法:
3028

31-
INSTALLED_APPS = (
32-
'django.contrib.auth',
33-
'django.contrib.contenttypes',
34-
'django.contrib.sessions',
35-
'django.contrib.sites',
36-
'django.contrib.messages',
37-
'django.contrib.staticfiles',
38-
'echo',
39-
)
40-
add view for official account interface. edit echo/views.py:
41-
42-
from django.http import HttpResponse
29+
### WxApplication.process(params, xml, token=None, app_id=None, aes_key=None)
4330

44-
def wechat(request):
45-
return HttpResponse('hello wechat')
31+
WxApplication的process函数,接受以下参数:
32+
33+
- params, url参数字典,需要解析自微信回调的url的querystring。格式如:{'nonce': 1232, 'signature': 'xsdfsdfsd'}
34+
- xml, 微信回调时post的xml内容。
35+
- token, 公众号的上行token,可选,允许在子类配置。
36+
- app_id, 公众号应用id,可选,允许在子类配置。
37+
- aes_key, 公众号加密secret,可选,允许在子类配置。
38+
39+
process最后返回一串文本(xml或echoStr)。
40+
41+
42+
#### 使用场景1:上行URL有效性验证
43+
44+
在微信公众号的后台设置好URL及token等相关信息后,微信会通过GET的方式访问一次该URL,开发者在URL的响应程序里直接调用app.process(params, xml=None)即可返回echStr。
4645

47-
config urls.py:
46+
qs = 'nonce=1221&signature=19selKDJF&timestamp=12312'
47+
query = dict([q.split('=') for q in qs.split('&')])
48+
app = YourApplication()
49+
echo_str = app.process(query, xml=None)
50+
# 返回echo_str给微信即可
4851

49-
urlpatterns = patterns('',
50-
url(r'^wechat/', 'echo.views.wechat'),
51-
)
5252

53+
#### 使用场景2:处理上行消息
54+
55+
用户在微信公众号上发消息给公众号,微信服务器调用上行的URL,开发者需要对每次的的请求进行合法性校验及对消息进行处理,同样的,直接调用app.process方法就好。
56+
57+
qs = 'nonce=1221&signature=19selKDJF&timestamp=12312'
58+
query = dict([q.split('=') for q in qs.split('&')])
59+
body = '<xml> ..... </xml>'
60+
app = YourApplication()
61+
result = app.process(query, xml=body)
62+
# 返回result给微信即可
5363

54-
## 3.Warm up
55-
Let's get familar with Official account objects.
5664

57-
### WxRequest
58-
A WxRequest instance represent an incoming wechat message. One message is piece of xml. WxRequest map elements of xml to it's own attributes, so you can access the message directly. for more information, see [this link](http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97#.E6.B6.88.E6.81.AF.E6.8E.A8.E9.80.81).
65+
### WxApplication子类示例
66+
67+
下面先看看一个WxApplication的示例代码,用于把用户上行的文本返还给用户:
68+
69+
from wechat.official import WxApplication, WxTextResponse, WxMusic,\
70+
WxMusicResponse
71+
72+
class WxApp(WxApplication):
73+
74+
SECRET_TOKEN = 'test_token'
75+
WECHAT_APPID = 'wx1234556'
76+
WECHAT_APPSECRET = 'sevcs0j'
77+
78+
def on_text(self, text):
79+
return WxTextResponse(text.Content, text)
80+
81+
82+
需要配置几个类参数,几个参数均可在公众号管理后台的开发者相关页面找到,前三个参数如果不配置,则需要在调用process方法时传入。
5983

60-
from wechat.official import WxRequest
61-
wxreq = WxRequest(req.body) # init with a xml string. The req is a django HttpRequest instance
62-
wxreq.MsgType # text, image, location, event, link
63-
wxreq.Content # if it's a text message
84+
- SECRET_TOKEN: 微信公众号回调的TOKEN
85+
- APP_ID: 微信公众号的应用ID
86+
- ENCODING_AES_KEY: (可选),加密用的SECRET,如您的公众号未采取加密传输,不需填。
87+
- UNSUPPORT_TXT:(可选),收到某种不支持类型的消息时自动响应给用户的文本消息。
88+
- WELCOME_TXT:(可选), 新关注时默认响应的文本消息。
89+
90+
然后,您需要逐一实现WxApplication的各个on_xxxx函数。不同类型的上行消息及事件均有对应的on_xxx函数
91+
92+
### on_xxx函数
93+
94+
95+
所有的on_xxx函数列举如下:
96+
97+
- on_text, 响应用户文本
98+
- on_link,响应用户上行的链接
99+
- on_image,响应用户上行图片
100+
- on_voice,响应用户上行语音
101+
- on_video,响应用户上行视频
102+
- on_location,响应用户上行地理位置
103+
- on_subscribe,响应用户关注事件
104+
- on_unsubscribe,响应用户取消关注事件
105+
- on_click,响应用户点击自定义菜单事件
106+
- on_scan,响应用户扫描二维码事件
107+
- on_location_update,响应用户地理位置变更事件
108+
- on_view,响应用户点击自定义菜单访问网页事件
109+
- on_scancode_push
110+
- on_scancode_waitmsg
111+
- on_pic_sysphoto
112+
- on_pic_photo_or_album
113+
- on_pic_weixin
114+
- on_location_select
115+
116+
on_xxx函数的定义如下:
117+
118+
def on_xxx(self, req):
119+
return WxResponse()
64120

65-
### WxResponse
66-
A WxResponse instance represent and outgoing wechat message. One message is piece of xml too. there are now three types of Outgoing message: text, link, news. so, there are three WxResponse subclasses for you.
121+
on_xxx函数,接受一个WxRequest参数req,返回一个WxResponse的子类实例。
67122

68-
#### WxTextResponse
69-
from wechat.official import WxTextResponse
70-
resp = WxTextResponse("hello world", wxreq).as_xml()
123+
#### WxRequest
71124

72-
#### WxMusicResponse
125+
req是一个代表用户上行消息的WxRequest实例。其属性与消息的XML属性一一对应,不同的消息有几个相同的属性:
73126

74-
from wechat.official import WxMusicResponse, WxMusic
75-
resp = WxMusicResponse(WxMusic(Title="hey jude", Description="2012 London",
76-
MusicUrl="http://yourhost.com/jude.mp3",
77-
HQMusicUrl="http://yourhost.com/jude.hd.mp3"), wxreq).as_xml()
127+
- ToUserName
128+
- FromUserName
129+
- CreateTime
130+
- MsgType
131+
- MsgId
78132

79-
#### WxNewsResponse
80-
from wechat.official import WxNewsResponse, WxArticle
81-
resp = WxNewsResponse([WxArticle(Title="iPhone 6 is here!",
82-
Description="It is not a joke",
83-
Url="http://jeffkit.info",
84-
PicUrl="http://jeffkit.info/avatar.jpg")], wxreq).as_xml()
85-
86-
### WxApplication
87-
You should process the WxRequest and return WxResponse in WxApplication. Every time you make a wechat official account application, you should write a subclass of WxApplication, overwrite the following method, every method start with 'on_' should return a WxResponse instance.
133+
不同的消息类型对应有各自的属性,属性名与消息的xml标签名保一致。如MsgType为text的的req,有一个Content属怀,而MsgType为image的req,则有PicUrl及MediaId两个属性。更多消息详情请查看微信公众号[官方文档](http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html)
88134

89-
#### on_text(self, text)
90-
Call when recive a text type message.
91-
#### on_image(self, image)
92-
Call when recive a image type message.
93-
#### on_link(self, link)
94-
call when recive a link type message.
95-
#### on_location(self, location)
96-
Call when recive a location type message.
97-
#### on_subscribe(self, sub)
98-
Call when recive a subscribe event.
99-
#### on_unsubscribe(self, unsub)
100-
Call when recive an unsubscribe event.
101-
#### on_click(self, click)
102-
Call when recive an custome event.
135+
#### WxResponse
103136

104-
Here is the echo robt's sample code:
137+
on_xxx函数需要返回一个WxResponse的子类实例。WxResponse的子类及其构造的方式有:
105138

106-
from wechat.official import WxApplication, WxTextResponse
139+
##### WxTextResponse, 文本消息
140+
141+
WxTextResponse("hello", req)
142+
143+
##### WxImageResponse, 图片消息
144+
145+
WxImageResponse(WxImage(MediaId='xxyy'),req)
107146

108-
class EchoApp(WxApplication):
109-
def on_text(self, text):
110-
return WxTextResponse(text.Content, text)
111-
def on_image(self, image):
112-
return WxTextResponse(image.PicUrl, image)
147+
##### WxVoiceResponse, 语音消息
113148

149+
WxVoiceResponse(WxVoice(MediaId='xxyy'),req)
150+
151+
##### WxVideoResponse, 视频消息
114152

115-
We only overwrite to 'on_' style method in the sample. if recive an message which type is neither text nor image, the echo robot will reply an UNSUPPORT_TXT message. you can define you own UNSUPPORT_TXT in you WxApplication subclass.
153+
WxVideoResponse(WxVideo(MediaId='xxyy', Title='video', Description='test'),req)
154+
155+
##### WxMusicResponse, 音乐消息
116156

117-
## 4.Run the Application
157+
WxMusicResponse(WxMusic(Title='hey jude',
158+
Description='dont make it bad',
159+
PicUrl='http://heyjude.com/logo.png',
160+
Url='http://heyjude.com/mucis.mp3'), req)
118161

119-
The robot's code is simple. edit the echo/views.py:
162+
##### WxNewsResponse, 图文消息
120163

121-
from django.http import HttpResponse
164+
WxNewsResponse(WxArticle(Title='test news',
165+
Description='this is a test',
166+
Picurl='http://smpic.com/pic.jpg',
167+
Url='http://github.com/jeffkit'), req)
168+
##### WxEmptyResponse, 无响应
122169

123-
class EchoApp(WxApplication) ………
124-
……………………
170+
WxEmptyResponse(req)
171+
172+
### 在Django中使用WxApplication
173+
174+
175+
下面以Django为例说明,实现一个微信回调的功能(view),利用上面示例代码中的WxApp:
176+
177+
from django.http import HttpResponse
125178

126179
def wechat(request):
127-
app = EchoApp()
128-
result = app.process(request.GET, request.body, token='your token')
180+
app = WxApp()
181+
result = app.process(request.GET, request.body)
182+
return HttpResponse(result)
183+
184+
配置 urls.py:
185+
186+
urlpatterns = patterns('',
187+
url(r'^wechat/', 'myapp.views.wechat'),
188+
)
189+
190+
191+
### 在Flask中使用WxApplication
192+
from flask import request
193+
from flask import Flask
194+
app = Flask(__name__)
195+
196+
@app.route('/wechat')
197+
def wechat():
198+
app = WxApp()
199+
return app.process(request.args, request.data)
200+
201+
202+
OK.就这么多,WxApplication本身与web框架无关,不管你使用哪个Framework都可以享受到它带来的便利。
203+
204+
### 什么?你不喜欢写WxApplication的子类?!
205+
206+
好吧,其实,你可以在任何地方写on_xxx的响应函数。然后在使用之前,告诉一个WxApplication你要用哪个函数来响应对应的事件就好。以Django为例:
207+
208+
# 在任何地方写你自己的消息处理函数。
209+
# @any_decorator # 添加任何装饰器。
210+
def my_text_handler(req):
211+
return WxTextResponse(req.Content, req)
212+
213+
# 在web的程序里这样使用:
214+
def wechat_view(request):
215+
app = WxApplication() # 实例化基类就好。
216+
app.handlers = {'text': my_text_handler} # 设置你自己的处理器
217+
result = app.process(request.GET, request.body,
218+
token='xxxx', app_id='xxxx', aes_key='xxxx')
129219
return HttpResponse(result)
220+
130221
222+
嗯,可以自定义消息的handlers,而如果要针对事件自定义handlers的话,要修改app.event_handlers,数据的格式是一样的。具体的消息和事件类型的key,就直接看看源码得了。卡卡。
223+
224+
225+
## 3. OAuth API
226+
227+
OAuth API目前仅支持下列常用接口:
228+
229+
- 发送消息
230+
- 用户管理
231+
- 自定义菜单管理
232+
- 多媒体上传下载
233+
- 二维码
131234

132-
It's easy!
133-
## 5.deploy
134-
That's all. deploy you web application, and have fun!
235+
其他接口拟于未来的版本中支持,同时欢迎大家来增补。
135236

demo/echo/views.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
# Create your views here.
22
from django.http import HttpResponse
3-
from wechat.official import WxRequest, WxTextResponse
4-
from wechat.official import WxClient
3+
from wechat.official import WxApplication, WxTextResponse
4+
5+
6+
class EchoApp(WxApplication):
7+
"""把用户输入的文本原样返回。
8+
"""
9+
10+
SECRET_TOKEN = ''
11+
APP_ID = ''
12+
ENCODING_AES_KEY = ''
13+
14+
def on_text(req):
15+
return WxTextResponse(req.Content, req)
516

617

718
def wechat(request):
8-
cli = WxClient("your official account token")
9-
ret = cli.is_valid_params(request.GET) # validate the request
10-
if not ret:
11-
return HttpResponse('invalid request')
12-
if request.method == 'GET':
13-
return HttpResponse(ret[1]) # for interface validation
14-
else:
15-
req = WxRequest(request.body)
16-
if req.MsgType == 'text':
17-
return HttpResponse(WxTextResponse(req.Content, req).as_xml())
18-
elif req.MsgType == 'event' and req.Event == 'subscribe':
19-
return HttpResponse(WxTextResponse('welcome to echo bot!',
20-
req).as_xml())
21-
else:
22-
return HttpResponse(WxTextResponse('support text only',
23-
req).as_xml())
19+
echo = EchoApp()
20+
return HttpResponse(echo.process(request.GEt, request.body))

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
maintainer_email="bbmyth@gmail.com",
1515
url = url,
1616
long_description=long_description,
17+
install_requires = ['requests'],
1718
packages=find_packages('.'),
1819
)
1920

wechat/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#encoding=utf-8
2-
VERSION = "0.4.3"
2+
VERSION = "0.4.12"
33

0 commit comments

Comments
 (0)