mp_weixin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,365 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe "MpWeixin::ReplyMessage" do
5
+ let(:text_message_hash) {
6
+ {
7
+ ToUserName: "toUser",
8
+ FromUserName: "fromUser",
9
+ CreateTime: "12345678",
10
+ MsgType: "text",
11
+ Content: "你好"
12
+ }
13
+ }
14
+
15
+ let(:text_message_xml) {
16
+ %(
17
+ <xml>
18
+ <ToUserName><![CDATA[toUser]]></ToUserName>
19
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
20
+ <CreateTime>12345678</CreateTime>
21
+ <MsgType><![CDATA[text]]></MsgType>
22
+ <Content><![CDATA[你好]]></Content>
23
+ </xml>
24
+ )
25
+ }
26
+
27
+ let(:image_message_hash) {
28
+ {
29
+ ToUserName: "toUser",
30
+ FromUserName: "fromUser",
31
+ CreateTime: "12345678",
32
+ MsgType: "image",
33
+ Image: {MediaId: 'media_id'}
34
+ }
35
+ }
36
+
37
+ let(:image_message_xml) {
38
+ %(
39
+ <xml>
40
+ <ToUserName><![CDATA[toUser]]></ToUserName>
41
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
42
+ <CreateTime>12345678</CreateTime>
43
+ <MsgType><![CDATA[image]]></MsgType>
44
+ <Image>
45
+ <MediaId><![CDATA[media_id]]></MediaId>
46
+ </Image>
47
+ </xml>
48
+ )
49
+ }
50
+
51
+ let(:voice_message_hash) {
52
+ {
53
+ ToUserName: "toUser",
54
+ FromUserName: "fromUser",
55
+ CreateTime: "12345678",
56
+ MsgType: "voice",
57
+ Voice: {MediaId: 'media_id'}
58
+ }
59
+ }
60
+ let(:voice_message_xml) {
61
+ %(
62
+ <xml>
63
+ <ToUserName><![CDATA[toUser]]></ToUserName>
64
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
65
+ <CreateTime>12345678</CreateTime>
66
+ <MsgType><![CDATA[voice]]></MsgType>
67
+ <Voice>
68
+ <MediaId><![CDATA[media_id]]></MediaId>
69
+ </Voice>
70
+ </xml>
71
+ )
72
+ }
73
+
74
+ let(:video_message_hash) {
75
+ {
76
+ ToUserName: "toUser",
77
+ FromUserName: "fromUser",
78
+ CreateTime: "12345678",
79
+ MsgType: "video",
80
+ Video: {
81
+ MediaId: "media_id",
82
+ Title: "title",
83
+ Description: "description"
84
+ }
85
+ }
86
+ }
87
+ let(:video_message_xml) {
88
+ %(
89
+ <xml>
90
+ <ToUserName><![CDATA[toUser]]></ToUserName>
91
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
92
+ <CreateTime>12345678</CreateTime>
93
+ <MsgType><![CDATA[video]]></MsgType>
94
+ <Video>
95
+ <MediaId><![CDATA[media_id]]></MediaId>
96
+ <Title><![CDATA[title]]></Title>
97
+ <Description><![CDATA[description]]></Description>
98
+ </Video>
99
+ </xml>
100
+ )
101
+ }
102
+
103
+ let(:music_message_hash) {
104
+ {
105
+ ToUserName: "toUser",
106
+ FromUserName: "fromUser",
107
+ CreateTime: "12345678",
108
+ MsgType: "music",
109
+ Music: {
110
+ Title: "TITLE",
111
+ Description: "DESCRIPTION",
112
+ MusicUrl: "MUSIC_Url",
113
+ HQMusicUrl: "HQ_MUSIC_Url",
114
+ ThumbMediaId: "media_id"
115
+ }
116
+ }
117
+ }
118
+ let(:music_message_xml) {
119
+ %(
120
+ <xml>
121
+ <ToUserName><![CDATA[toUser]]></ToUserName>
122
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
123
+ <CreateTime>12345678</CreateTime>
124
+ <MsgType><![CDATA[music]]></MsgType>
125
+ <Music>
126
+ <Title><![CDATA[TITLE]]></Title>
127
+ <Description><![CDATA[DESCRIPTION]]></Description>
128
+ <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
129
+ <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
130
+ <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
131
+ </Music>
132
+ </xml>
133
+ )
134
+ }
135
+
136
+
137
+ let(:news_message_simple_hash) {
138
+ {
139
+ ToUserName: "toUser",
140
+ FromUserName: "fromUser",
141
+ CreateTime: "12345678",
142
+ MsgType: "news",
143
+ ArticleCount: "2",
144
+ Articles: [
145
+ {
146
+ Title: "title1",
147
+ Description: "description1",
148
+ PicUrl: "picurl",
149
+ Url: "url"
150
+ },
151
+ {
152
+ Title: "title",
153
+ Description: "description",
154
+ PicUrl: "picurl",
155
+ Url: "url"
156
+ }
157
+ ]
158
+ }
159
+ }
160
+
161
+ let(:news_message_hash) {
162
+ {
163
+ ToUserName: "toUser",
164
+ FromUserName: "fromUser",
165
+ CreateTime: "12345678",
166
+ MsgType: "news",
167
+ ArticleCount: "2",
168
+ Articles: {
169
+ item: [
170
+ {
171
+ Title: "title1",
172
+ Description: "description1",
173
+ PicUrl: "picurl",
174
+ Url: "url"
175
+ },
176
+ {
177
+ Title: "title",
178
+ Description: "description",
179
+ PicUrl: "picurl",
180
+ Url: "url"
181
+ }
182
+ ]
183
+ }
184
+ }
185
+ }
186
+
187
+ let(:news_message_xml) {
188
+ %(
189
+ <xml>
190
+ <ToUserName><![CDATA[toUser]]></ToUserName>
191
+ <FromUserName><![CDATA[fromUser]]></FromUserName>
192
+ <CreateTime>12345678</CreateTime>
193
+ <MsgType><![CDATA[news]]></MsgType>
194
+ <ArticleCount>2</ArticleCount>
195
+ <Articles>
196
+ <item>
197
+ <Title><![CDATA[title1]]></Title>
198
+ <Description><![CDATA[description1]]></Description>
199
+ <PicUrl><![CDATA[picurl]]></PicUrl>
200
+ <Url><![CDATA[url]]></Url>
201
+ </item>
202
+ <item>
203
+ <Title><![CDATA[title]]></Title>
204
+ <Description><![CDATA[description]]></Description>
205
+ <PicUrl><![CDATA[picurl]]></PicUrl>
206
+ <Url><![CDATA[url]]></Url>
207
+ </item>
208
+ </Articles>
209
+ </xml>
210
+ )
211
+ }
212
+
213
+ context "TextReplyMessage" do
214
+ subject { MpWeixin::TextReplyMessage.new(text_message_hash) }
215
+
216
+ context "initialize new" do
217
+
218
+ it "should return an instance of TextReplyMessage" do
219
+ expect(subject).to be_a(MpWeixin::TextReplyMessage)
220
+ end
221
+
222
+ it "should have correct MsgType" do
223
+ expect(subject.MsgType).to eq("text")
224
+ end
225
+ end
226
+
227
+ context ":to_xml" do
228
+ let(:want_be_hash) { Hash.from_xml(subject.to_xml).deep_symbolize_keys[:xml] }
229
+ let(:weixin_xml_hash) { Hash.from_xml(text_message_xml).deep_symbolize_keys[:xml] }
230
+
231
+ it "should return correct xml" do
232
+ expect(want_be_hash).to eq(weixin_xml_hash)
233
+ end
234
+ end
235
+ end
236
+
237
+ context "ImageReplyMessage" do
238
+ subject { MpWeixin::ImageReplyMessage.new(image_message_hash) }
239
+
240
+ context "initialize new" do
241
+
242
+ it "should return an instance of ImageReplyMessage" do
243
+ expect(subject).to be_a(MpWeixin::ImageReplyMessage)
244
+ end
245
+
246
+ it "should have correct MsgType" do
247
+ expect(subject.MsgType).to eq("image")
248
+ end
249
+ end
250
+
251
+ context ":to_xml" do
252
+ let(:want_be_hash) { Hash.from_xml(subject.to_xml).deep_symbolize_keys[:xml] }
253
+ let(:weixin_xml_hash) { Hash.from_xml(image_message_xml).deep_symbolize_keys[:xml] }
254
+
255
+ it "should return correct xml" do
256
+ expect(want_be_hash).to eq(weixin_xml_hash)
257
+ end
258
+ end
259
+ end
260
+
261
+ context "VoiceReplyMessage" do
262
+ subject { MpWeixin::VoiceReplyMessage.new(voice_message_hash) }
263
+
264
+ context "initialize new" do
265
+
266
+ it "should return an instance of VoiceReplyMessage" do
267
+ expect(subject).to be_a(MpWeixin::VoiceReplyMessage)
268
+ end
269
+
270
+ it "should have correct MsgType" do
271
+ expect(subject.MsgType).to eq("voice")
272
+ end
273
+ end
274
+
275
+ context ":to_xml" do
276
+ let(:want_be_hash) { Hash.from_xml(subject.to_xml).deep_symbolize_keys[:xml] }
277
+ let(:weixin_xml_hash) { Hash.from_xml(voice_message_xml).deep_symbolize_keys[:xml] }
278
+
279
+ it "should return correct xml" do
280
+ expect(want_be_hash).to eq(weixin_xml_hash)
281
+ end
282
+ end
283
+ end
284
+
285
+ context "VideoReplyMessage" do
286
+ subject { MpWeixin::VideoReplyMessage.new(video_message_hash) }
287
+
288
+ context "initialize new" do
289
+
290
+ it "should return an instance of VideoReplyMessage" do
291
+ expect(subject).to be_a(MpWeixin::VideoReplyMessage)
292
+ end
293
+
294
+ it "should have correct MsgType" do
295
+ expect(subject.MsgType).to eq("video")
296
+ end
297
+ end
298
+
299
+ context ":to_xml" do
300
+ let(:want_be_hash) { Hash.from_xml(subject.to_xml).deep_symbolize_keys[:xml] }
301
+ let(:weixin_xml_hash) { Hash.from_xml(video_message_xml).deep_symbolize_keys[:xml] }
302
+
303
+ it "should return correct xml" do
304
+ expect(want_be_hash).to eq(weixin_xml_hash)
305
+ end
306
+ end
307
+ end
308
+
309
+ context "MusicReplyMessage" do
310
+ subject { MpWeixin::MusicReplyMessage.new(music_message_hash) }
311
+
312
+ context "initialize new" do
313
+
314
+ it "should return an instance of MusicReplyMessage" do
315
+ expect(subject).to be_a(MpWeixin::MusicReplyMessage)
316
+ end
317
+
318
+ it "should have correct MsgType" do
319
+ expect(subject.MsgType).to eq("music")
320
+ end
321
+ end
322
+
323
+ context ":to_xml" do
324
+ let(:want_be_hash) { Hash.from_xml(subject.to_xml).deep_symbolize_keys[:xml] }
325
+ let(:weixin_xml_hash) { Hash.from_xml(music_message_xml).deep_symbolize_keys[:xml] }
326
+
327
+ it "should return correct xml" do
328
+ expect(want_be_hash).to eq(weixin_xml_hash)
329
+ end
330
+ end
331
+ end
332
+
333
+ context "NewsReplyMessage" do
334
+ subject { MpWeixin::NewsReplyMessage.new(news_message_hash) }
335
+
336
+ context "initialize new" do
337
+
338
+ it "should return an instance of NewsReplyMessage" do
339
+ expect(subject).to be_a(MpWeixin::NewsReplyMessage)
340
+ end
341
+
342
+ it "should have correct MsgType" do
343
+ expect(subject.MsgType).to eq("news")
344
+ end
345
+ end
346
+
347
+ context ":to_xml" do
348
+ let(:want_be_hash) { Hash.from_xml(subject.to_xml).deep_symbolize_keys[:xml] }
349
+ let(:weixin_xml_hash) { Hash.from_xml(news_message_xml).deep_symbolize_keys[:xml] }
350
+
351
+ it "should return correct xml" do
352
+ expect(want_be_hash).to eq(weixin_xml_hash)
353
+ end
354
+ end
355
+
356
+ context ":to_xml simple type" do
357
+ let(:want_be_hash) { Hash.from_xml(MpWeixin::NewsReplyMessage.new(news_message_simple_hash).to_xml).deep_symbolize_keys[:xml] }
358
+ let(:weixin_xml_hash) { Hash.from_xml(news_message_xml).deep_symbolize_keys[:xml] }
359
+
360
+ it "should return correct xml" do
361
+ expect(want_be_hash).to eq(weixin_xml_hash)
362
+ end
363
+ end
364
+ end
365
+ end
@@ -0,0 +1,165 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe MpWeixin::ServerHelper do
5
+ include MpWeixin::ServerHelper
6
+
7
+ let(:config) { MpWeixin::Config }
8
+ let(:token) { config.token }
9
+ let(:timestamp) { "1388028695" } #{ "#{Time.now.to_i}" }
10
+ let(:nonce) { "121212121" }
11
+ let(:signature) { "9dc548e8c7fe32ac53f887e834a8c719a73cafc3" }# { generate_signature(token, timestamp, nonce) }
12
+ let(:incorrent_signature) { SecureRandom.hex(64) }
13
+
14
+ context "#generate_signature" do
15
+ it "should generate an signature" do
16
+ generate_signature(token, timestamp, nonce).should be_a(String)
17
+ end
18
+ end
19
+
20
+ context "#valid_signature?" do
21
+ it "should return true when every are well" do
22
+ expect(valid_signature?(signature, timestamp, nonce)).to be_true
23
+ end
24
+
25
+ it "should return false if valid with incorrent_signature" do
26
+ expect(valid_signature?(incorrent_signature, timestamp, nonce)).to be_false
27
+ end
28
+ end
29
+
30
+ context "#reply message" do
31
+ let(:text_message_hash) {
32
+ {
33
+ ToUserName: "toUser",
34
+ FromUserName: "fromUser",
35
+ CreateTime: "12345678",
36
+ MsgType: "text",
37
+ Content: "你好"
38
+ }
39
+ }
40
+
41
+ let(:image_message_hash) {
42
+ {
43
+ ToUserName: "toUser",
44
+ FromUserName: "fromUser",
45
+ CreateTime: "12345678",
46
+ MsgType: "image",
47
+ Image: {MediaId: 'media_id'}
48
+ }
49
+ }
50
+
51
+ let(:voice_message_hash) {
52
+ {
53
+ ToUserName: "toUser",
54
+ FromUserName: "fromUser",
55
+ CreateTime: "12345678",
56
+ MsgType: "voice",
57
+ Voice: {MediaId: 'media_id'}
58
+ }
59
+ }
60
+
61
+ let(:video_message_hash) {
62
+ {
63
+ ToUserName: "toUser",
64
+ FromUserName: "fromUser",
65
+ CreateTime: "12345678",
66
+ MsgType: "video",
67
+ Video: {
68
+ MediaId: "media_id",
69
+ Title: "title",
70
+ Description: "description"
71
+ }
72
+ }
73
+ }
74
+
75
+ let(:music_message_hash) {
76
+ {
77
+ ToUserName: "toUser",
78
+ FromUserName: "fromUser",
79
+ CreateTime: "12345678",
80
+ MsgType: "music",
81
+ Music: {
82
+ Title: "TITLE",
83
+ Description: "DESCRIPTION",
84
+ MusicUrl: "MUSIC_Url",
85
+ HQMusicUrl: "HQ_MUSIC_Url",
86
+ ThumbMediaId: "media_id"
87
+ }
88
+ }
89
+ }
90
+
91
+ let(:news_message_simple_hash) {
92
+ {
93
+ ToUserName: "toUser",
94
+ FromUserName: "fromUser",
95
+ CreateTime: "12345678",
96
+ MsgType: "news",
97
+ ArticleCount: "2",
98
+ Articles: [
99
+ {
100
+ Title: "title1",
101
+ Description: "description1",
102
+ PicUrl: "picurl",
103
+ Url: "url"
104
+ },
105
+ {
106
+ Title: "title",
107
+ Description: "description",
108
+ PicUrl: "picurl",
109
+ Url: "url"
110
+ }
111
+ ]
112
+ }
113
+ }
114
+
115
+ let(:news_message_hash) {
116
+ {
117
+ ToUserName: "toUser",
118
+ FromUserName: "fromUser",
119
+ CreateTime: "12345678",
120
+ MsgType: "news",
121
+ ArticleCount: "2",
122
+ Articles: {
123
+ item: [
124
+ {
125
+ Title: "title1",
126
+ Description: "description1",
127
+ PicUrl: "picurl",
128
+ Url: "url"
129
+ },
130
+ {
131
+ Title: "title",
132
+ Description: "description",
133
+ PicUrl: "picurl",
134
+ Url: "url"
135
+ }
136
+ ]
137
+ }
138
+ }
139
+ }
140
+
141
+ it "reply_text_message with attributes should be_a TextReplyMessage" do
142
+ expect(reply_text_message(text_message_hash)).to be_a(MpWeixin::TextReplyMessage)
143
+ end
144
+
145
+ it "reply_image_message with attributes should be_a ImageReplyMessage" do
146
+ expect(reply_image_message(image_message_hash)).to be_a(MpWeixin::ImageReplyMessage)
147
+ end
148
+
149
+ it "reply_voice_message with attributes should be_a VoiceReplyMessage" do
150
+ expect(reply_voice_message(voice_message_hash)).to be_a(MpWeixin::VoiceReplyMessage)
151
+ end
152
+
153
+ it "reply_video_message with attributes should be_a VideoReplyMessage" do
154
+ expect(reply_video_message(video_message_hash)).to be_a(MpWeixin::VideoReplyMessage)
155
+ end
156
+
157
+ it "reply_music_message with attributes should be_a MusicReplyMessage" do
158
+ expect(reply_music_message(music_message_hash)).to be_a(MpWeixin::MusicReplyMessage)
159
+ end
160
+
161
+ it "reply_news_message with attributes should be_a NewsReplyMessage" do
162
+ expect(reply_news_message(news_message_hash)).to be_a(MpWeixin::NewsReplyMessage)
163
+ end
164
+ end
165
+ end