mp_weixin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +7 -0
  4. data/.travis.yml +20 -0
  5. data/CHANGELOG.md +17 -0
  6. data/Gemfile +5 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +308 -0
  9. data/Rakefile +31 -0
  10. data/lib/config/mp_weixin_error.yml +82 -0
  11. data/lib/mp_weixin.rb +59 -0
  12. data/lib/mp_weixin/access_token.rb +172 -0
  13. data/lib/mp_weixin/client.rb +199 -0
  14. data/lib/mp_weixin/config.rb +36 -0
  15. data/lib/mp_weixin/error.rb +27 -0
  16. data/lib/mp_weixin/interface/base.rb +43 -0
  17. data/lib/mp_weixin/interface/group.rb +92 -0
  18. data/lib/mp_weixin/interface/menu.rb +73 -0
  19. data/lib/mp_weixin/interface/message.rb +38 -0
  20. data/lib/mp_weixin/interface/promotion.rb +48 -0
  21. data/lib/mp_weixin/interface/user.rb +39 -0
  22. data/lib/mp_weixin/models/event.rb +123 -0
  23. data/lib/mp_weixin/models/message.rb +227 -0
  24. data/lib/mp_weixin/models/reply_message.rb +180 -0
  25. data/lib/mp_weixin/response.rb +93 -0
  26. data/lib/mp_weixin/response_rule.rb +46 -0
  27. data/lib/mp_weixin/server.rb +39 -0
  28. data/lib/mp_weixin/server_helper.rb +94 -0
  29. data/lib/mp_weixin/version.rb +3 -0
  30. data/lib/support/active_model.rb +3 -0
  31. data/lib/support/active_model/model.rb +99 -0
  32. data/mp_weixin.gemspec +44 -0
  33. data/spec/client_spec.rb +87 -0
  34. data/spec/mp_weixin/access_token_spec.rb +140 -0
  35. data/spec/mp_weixin/client_spec.rb +111 -0
  36. data/spec/mp_weixin/config_spec.rb +24 -0
  37. data/spec/mp_weixin/interface/base_spec.rb +16 -0
  38. data/spec/mp_weixin/interface/group_spec.rb +133 -0
  39. data/spec/mp_weixin/interface/menu_spec.rb +72 -0
  40. data/spec/mp_weixin/interface/message_spec.rb +36 -0
  41. data/spec/mp_weixin/interface/promotion_spec.rb +48 -0
  42. data/spec/mp_weixin/interface/user_spec.rb +76 -0
  43. data/spec/mp_weixin/models/event_spec.rb +94 -0
  44. data/spec/mp_weixin/models/message_spec.rb +300 -0
  45. data/spec/mp_weixin/models/reply_message_spec.rb +365 -0
  46. data/spec/mp_weixin/server_helper_spec.rb +165 -0
  47. data/spec/mp_weixin/server_spec.rb +56 -0
  48. data/spec/spec_helper.rb +51 -0
  49. data/spec/support/mp_weixin.rb +7 -0
  50. data/spec/support/rspec_mixin.rb +8 -0
  51. data/spec/support/weixin.yml +12 -0
  52. metadata +363 -0
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe MpWeixin::Interface::User do
5
+ let(:access_token) { 'ACCESS_TOKEN' }
6
+ let(:token_hash) { {"expires_in" => "7200", "access_token" => access_token} }
7
+ let(:openid) { "o6_bmjrPTlm6_2sgVt7hMZOPfL2M" }
8
+ let(:info_json) {
9
+ MultiJson.encode({
10
+ openid: openid
11
+ })
12
+ }
13
+
14
+ let (:sucess_info) {
15
+ MultiJson.encode({
16
+ subscribe: 1,
17
+ openid: openid,
18
+ nickname: "Band",
19
+ sex: 1,
20
+ language: "zh_CN",
21
+ city: "广州",
22
+ province: "广东",
23
+ country: "中国",
24
+ headimgurl: "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
25
+ subscribe_time: 1382694957
26
+ })
27
+ }
28
+ let(:get_users_json) {
29
+ MultiJson.encode({
30
+ openid: openid
31
+ })
32
+ }
33
+ let(:sucess_get_users) {
34
+ MultiJson.encode({
35
+ total: 2,
36
+ count: 2,
37
+ data: {
38
+ openid:
39
+ ["","OPENID1","OPENID2"]
40
+ },
41
+ next_openid: "NEXT_OPENID"
42
+ })
43
+ }
44
+ let(:client) {
45
+ MpWeixin::Client.from_hash(token_hash) do |builder|
46
+ builder.request :url_encoded
47
+ builder.adapter :test do |stub|
48
+ stub.send(:get, "/cgi-bin/user/info") {|env|
49
+ if env[:params].values.include?(openid)
50
+ [200, {'Content-Type' => 'application/json'}, sucess_info]
51
+ end
52
+ }
53
+ stub.send(:get, "/cgi-bin/user/get") {|env|
54
+ if env[:params].values.include?(openid)
55
+ [200, {'Content-Type' => 'application/json'}, sucess_get_users]
56
+ end
57
+ }
58
+ end
59
+ end
60
+ }
61
+
62
+ context "#menu" do
63
+
64
+ subject { MpWeixin::Interface::User.new(client) }
65
+
66
+ it "info info_hash with sucess_info return" do
67
+ info_hash = JSON.parse info_json
68
+ expect(subject.info(info_hash).body).to eq(sucess_info)
69
+ end
70
+
71
+ it "get_users get_users_hash with sucess_get_users return" do
72
+ get_users_hash = JSON.parse get_users_json
73
+ expect(subject.get_users(get_users_hash).body).to eq(sucess_get_users)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,94 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe MpWeixin::Event do
6
+
7
+ let(:subscribe_event_xml) {
8
+ %(
9
+ <xml>
10
+ <ToUserName><![CDATA[toUser]]></ToUserName>
11
+ <FromUserName><![CDATA[FromUser]]></FromUserName>
12
+ <CreateTime>123456789</CreateTime>
13
+ <MsgType><![CDATA[event]]></MsgType>
14
+ <Event><![CDATA[subscribe]]></Event>
15
+ </xml>
16
+ )
17
+ }
18
+
19
+ let(:location_event_xml) {
20
+ %(
21
+ <xml>
22
+ <ToUserName><![CDATA[toUser]]></ToUserName>
23
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
24
+ <CreateTime>123456789</CreateTime>
25
+ <MsgType><![CDATA[event]]></MsgType>
26
+ <Event><![CDATA[LOCATION]]></Event>
27
+ <Latitude>23.137466</Latitude>
28
+ <Longitude>113.352425</Longitude>
29
+ <Precision>119.385040</Precision>
30
+ </xml>
31
+ )
32
+ }
33
+
34
+ let(:click_event_xml) {
35
+ %(
36
+ <xml>
37
+ <ToUserName><![CDATA[toUser]]></ToUserName>
38
+ <FromUserName><![CDATA[FromUser]]></FromUserName>
39
+ <CreateTime>123456789</CreateTime>
40
+ <MsgType><![CDATA[event]]></MsgType>
41
+ <Event><![CDATA[CLICK]]></Event>
42
+ <EventKey><![CDATA[EVENTKEY]]></EventKey>
43
+ </xml>
44
+ )
45
+ }
46
+
47
+ context "#from_xml" do
48
+ context ":subscribe_event_xml" do
49
+ # subject { MpWeixin::Event.from_xml(subscribe_event_xml) }
50
+ subject { MpWeixin::Message.from_xml(subscribe_event_xml) }
51
+
52
+ it "should return an instance of Event" do
53
+ expect(subject).to be_a(MpWeixin::Event)
54
+ end
55
+
56
+ it "should have corrent Event" do
57
+ expect(subject.Event).to eq("subscribe")
58
+ end
59
+ end
60
+
61
+ context ":location_event_xml" do
62
+ # subject { MpWeixin::Event.from_xml(location_event_xml) }
63
+ subject { MpWeixin::Message.from_xml(location_event_xml) }
64
+
65
+ it "should return an instance of Event" do
66
+ expect(subject).to be_a(MpWeixin::Event)
67
+ end
68
+
69
+ it "should have correct Event" do
70
+ expect(subject.Event).to eq("LOCATION")
71
+ end
72
+ it "should have corrent Latitude" do
73
+ expect(subject.Latitude).to eq("23.137466")
74
+ end
75
+ end
76
+
77
+ context ":click_event_xml" do
78
+ # subject { MpWeixin::Event.from_xml(click_event_xml) }
79
+ subject { MpWeixin::Message.from_xml(click_event_xml) }
80
+
81
+ it "should return an instance of Event" do
82
+ expect(subject).to be_a(MpWeixin::Event)
83
+ end
84
+
85
+ it "should have corrent Event" do
86
+ expect(subject.Event).to eq("CLICK")
87
+ end
88
+
89
+ it "should have corrent EventKey" do
90
+ expect(subject.EventKey).to eq("EVENTKEY")
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,300 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe MpWeixin::Message do
6
+
7
+ let(:text_message_xml) {
8
+ %(
9
+ <xml>
10
+ <ToUserName><![CDATA[toUser]]></ToUserName>
11
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
12
+ <CreateTime>1348831860</CreateTime>
13
+ <MsgType><![CDATA[text]]></MsgType>
14
+ <Content><![CDATA[this is a test]]></Content>
15
+ <MsgId>1234567890123456</MsgId>
16
+ </xml>
17
+ )
18
+ }
19
+
20
+ let(:image_message_xml) {
21
+ %(
22
+ <xml>
23
+ <ToUserName><![CDATA[toUser]]></ToUserName>
24
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
25
+ <CreateTime>1348831860</CreateTime>
26
+ <MsgType><![CDATA[image]]></MsgType>
27
+ <PicUrl><![CDATA[this is a url]]></PicUrl>
28
+ <MediaId><![CDATA[media_id]]></MediaId>
29
+ <MsgId>1234567890123456</MsgId>
30
+ </xml>
31
+ )
32
+ }
33
+
34
+ let(:voice_message_xml) {
35
+ %(
36
+ <xml>
37
+ <ToUserName><![CDATA[toUser]]></ToUserName>
38
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
39
+ <CreateTime>1357290913</CreateTime>
40
+ <MsgType><![CDATA[voice]]></MsgType>
41
+ <MediaId><![CDATA[media_id]]></MediaId>
42
+ <Format><![CDATA[Format]]></Format>
43
+ <MsgId>1234567890123456</MsgId>
44
+ </xml>
45
+ )
46
+ }
47
+
48
+ let(:video_message_xml) {
49
+ %(
50
+ <xml>
51
+ <ToUserName><![CDATA[toUser]]></ToUserName>
52
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
53
+ <CreateTime>1357290913</CreateTime>
54
+ <MsgType><![CDATA[video]]></MsgType>
55
+ <MediaId><![CDATA[media_id]]></MediaId>
56
+ <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
57
+ <MsgId>1234567890123456</MsgId>
58
+ </xml>
59
+ )
60
+ }
61
+
62
+ let(:location_message_xml) {
63
+ %(
64
+ <xml>
65
+ <ToUserName><![CDATA[toUser]]></ToUserName>
66
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
67
+ <CreateTime>1351776360</CreateTime>
68
+ <MsgType><![CDATA[location]]></MsgType>
69
+ <Location_X>23.134521</Location_X>
70
+ <Location_Y>113.358803</Location_Y>
71
+ <Scale>20</Scale>
72
+ <Label><![CDATA[位置信息]]></Label>
73
+ <MsgId>1234567890123456</MsgId>
74
+ </xml>
75
+ )
76
+ }
77
+
78
+
79
+ let(:link_message_xml) {
80
+ %(
81
+ <xml>
82
+ <ToUserName><![CDATA[toUser]]></ToUserName>
83
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
84
+ <CreateTime>1351776360</CreateTime>
85
+ <MsgType><![CDATA[link]]></MsgType>
86
+ <Title><![CDATA[公众平台官网链接]]></Title>
87
+ <Description><![CDATA[公众平台官网链接]]></Description>
88
+ <Url><![CDATA[url]]></Url>
89
+ <MsgId>1234567890123456</MsgId>
90
+ </xml>
91
+ )
92
+ }
93
+
94
+ context :reply do
95
+ let(:message) { MpWeixin::Message.from_xml(text_message_xml) }
96
+
97
+ context :reply_text_message do
98
+ subject { message.reply_text_message(Content: "hellow") }
99
+ it "should reply an text message" do
100
+ expect(subject).to be_a(MpWeixin::TextReplyMessage)
101
+ end
102
+
103
+ it "should have corrent content" do
104
+ expect(subject.Content).to eq("hellow")
105
+ end
106
+ end
107
+
108
+ context :reply_image_message do
109
+ subject { message.reply_image_message(Image: {MediaId: 'media_id'}) }
110
+ it "should reply an image message" do
111
+ expect(subject).to be_a(MpWeixin::ImageReplyMessage)
112
+ end
113
+
114
+ it "should have corrent media_id" do
115
+ expect(subject.Image.MediaId).to eq("media_id")
116
+ end
117
+ end
118
+
119
+ context :reply_voice_message do
120
+ subject { message.reply_voice_message(Voice: {MediaId: 'media_id'}) }
121
+ it "should reply an voice message" do
122
+ expect(subject).to be_a(MpWeixin::VoiceReplyMessage)
123
+ end
124
+
125
+ it "should have corrent media_id" do
126
+ expect(subject.Voice.MediaId).to eq("media_id")
127
+ end
128
+ end
129
+
130
+ context :reply_video_message do
131
+ subject do
132
+ message.reply_video_message({
133
+ Video: {
134
+ MediaId: "media_id",
135
+ Title: "title",
136
+ Description: "description"
137
+ }
138
+ })
139
+ end
140
+
141
+ it "should reply an video message" do
142
+ expect(subject).to be_a(MpWeixin::VideoReplyMessage)
143
+ end
144
+
145
+ it "should have corrent media_id" do
146
+ expect(subject.Video.MediaId).to eq("media_id")
147
+ end
148
+ end
149
+
150
+ context :reply_music_message do
151
+ subject do
152
+ message.reply_music_message({
153
+ Music: {
154
+ Title: "TITLE",
155
+ Description: "DESCRIPTION",
156
+ MusicUrl: "MUSIC_Url",
157
+ HQMusicUrl: "HQ_MUSIC_Url",
158
+ ThumbMediaId: "media_id"
159
+ }
160
+ })
161
+ end
162
+ it "should reply an music message" do
163
+ expect(subject).to be_a(MpWeixin::MusicReplyMessage)
164
+ end
165
+
166
+ it "should have corrent media_id" do
167
+ expect(subject.Music.ThumbMediaId).to eq("media_id")
168
+ end
169
+ end
170
+
171
+ context :reply_news_message do
172
+ subject do
173
+ message.reply_news_message({
174
+ ArticleCount: "2",
175
+ Articles: [
176
+ {
177
+ Title: "title1",
178
+ Description: "description1",
179
+ PicUrl: "picurl",
180
+ Url: "url"
181
+ },
182
+ {
183
+ Title: "title",
184
+ Description: "description",
185
+ PicUrl: "picurl",
186
+ Url: "url"
187
+ }
188
+ ]
189
+ })
190
+ end
191
+ it "should reply an news message" do
192
+ expect(subject).to be_a(MpWeixin::NewsReplyMessage)
193
+ end
194
+
195
+ it "should have corrent article_count" do
196
+ expect(subject.ArticleCount).to eq("2")
197
+ end
198
+
199
+ it "should have corrent title" do
200
+ expect(subject.Articles[0].Title).to eq("title1")
201
+ end
202
+ end
203
+ end
204
+
205
+ context "#from_xml" do
206
+ context ":text_message_xml" do
207
+ subject { MpWeixin::Message.from_xml(text_message_xml) }
208
+
209
+ it "should return an instance of TextMessage" do
210
+ expect(subject).to be_a(MpWeixin::TextMessage)
211
+ end
212
+
213
+ it "should have MsgType text" do
214
+ expect(subject.MsgType).to eq("text")
215
+ end
216
+ it "should have corrent Content" do
217
+ expect(subject.Content).to eq("this is a test")
218
+ end
219
+
220
+ it "should have corrent MsgId" do
221
+ expect(subject.MsgId).to eq("1234567890123456")
222
+ end
223
+ end
224
+
225
+ context ":image_message_xml" do
226
+ subject { MpWeixin::Message.from_xml(image_message_xml) }
227
+
228
+ it "should return an instance of ImageMessage" do
229
+ expect(subject).to be_a(MpWeixin::ImageMessage)
230
+ end
231
+
232
+ it "should have correct MsgType" do
233
+ expect(subject.MsgType).to eq("image")
234
+ end
235
+ it "should have corrent PicUrl" do
236
+ expect(subject.PicUrl).to eq("this is a url")
237
+ end
238
+ end
239
+
240
+ context ":voice_message_xml" do
241
+ subject { MpWeixin::Message.from_xml(voice_message_xml) }
242
+
243
+ it "should return an instance of VoiceMessage" do
244
+ expect(subject).to be_a(MpWeixin::VoiceMessage)
245
+ end
246
+
247
+ it "should have correct MsgType" do
248
+ expect(subject.MsgType).to eq("voice")
249
+ end
250
+ it "should have corrent Format" do
251
+ expect(subject.Format).to eq("Format")
252
+ end
253
+ end
254
+
255
+ context ":video_message_xml" do
256
+ subject { MpWeixin::Message.from_xml(video_message_xml) }
257
+
258
+ it "should return an instance of VoiceMessage" do
259
+ expect(subject).to be_a(MpWeixin::VideoMessage)
260
+ end
261
+
262
+ it "should have correct MsgType" do
263
+ expect(subject.MsgType).to eq("video")
264
+ end
265
+ it "should have corrent ThumbMediaId" do
266
+ expect(subject.ThumbMediaId).to eq("thumb_media_id")
267
+ end
268
+ end
269
+
270
+ context ":location_message_xml" do
271
+ subject { MpWeixin::Message.from_xml(location_message_xml) }
272
+
273
+ it "should return an instance of LocationMessage" do
274
+ expect(subject).to be_a(MpWeixin::LocationMessage)
275
+ end
276
+
277
+ it "should have correct MsgType" do
278
+ expect(subject.MsgType).to eq("location")
279
+ end
280
+ it "should have corrent Location_X" do
281
+ expect(subject.Location_X).to eq("23.134521")
282
+ end
283
+ end
284
+
285
+ context ":link_message_xml" do
286
+ subject { MpWeixin::Message.from_xml(link_message_xml) }
287
+
288
+ it "should return an instance of LinkMessage" do
289
+ expect(subject).to be_a(MpWeixin::LinkMessage)
290
+ end
291
+
292
+ it "should have correct MsgType" do
293
+ expect(subject.MsgType).to eq("link")
294
+ end
295
+ it "should have corrent Url" do
296
+ expect(subject.Url).to eq("url")
297
+ end
298
+ end
299
+ end
300
+ end