weixin_public 0.0.1 → 0.0.2

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.
data/Gemfile CHANGED
@@ -1,4 +1,7 @@
1
- source 'https://rubygems.org'
1
+ source 'http://ruby.taobao.org'
2
2
 
3
3
  # Specify your gem's dependencies in weixin_public.gemspec
4
4
  gemspec
5
+
6
+ require 'faraday'
7
+ require 'nokogiri'
data/README.md CHANGED
@@ -1,29 +1,40 @@
1
- # WeixinPublic
2
-
3
- TODO: Write a gem description
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'weixin_public'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install weixin_public
18
-
1
+ # Weixin公众账号接口
2
+
3
+ 根据Weixin公众账号Web管理控制台协议工作,本接口实现仅供参考。
4
+
5
+
6
+ 2013-4-30:首次发布
7
+ 2013-5-10:接口修改为HTTPS模式工作,对于无法登录的情况增加sig和cert参数辅助登录冲,部分代码重构
8
+ ```ruby
9
+ 说明:一般情况下,如果登录时返回400,Error-6的错误的错误,请在登录时增加sig和cert参数,可以通过网页登录后在cookie里获取这两个参数的值填到参数里。没有sig参数的web page登录会弹出验证码,有时没这两个参数,或者没有sig时也能成功。
10
+ ```
11
+
12
+ ## Demo
13
+ ```ruby
14
+ require 'weixin_public.rb'
15
+ client = WeixinPublicClient::WeixinPubClient.new('x@gmail.com','123')
16
+ ```
17
+
18
+ 群发文本消息:
19
+ ```ruby
20
+ client.get_fans.each do |fan|
21
+ client.send_message("hello",fan.fakeId)
22
+ end
23
+ ```
24
+
25
+ 获取指定用户的对话信息:
26
+ ```ruby
27
+ fakeId = '1234'
28
+ msgs = client.get_messages(fakeId)
29
+ msgs.each {|m| p "#{m.dateTime} << #{m.content}"}
30
+ ```
31
+
32
+ 图片,音频:
33
+ ```ruby
34
+ fileId = client.avatar_upload('pix.jpg')
35
+ client.send_message(fileId,fan.fakeId)
36
+ ```
19
37
  ## Usage
20
38
 
21
- TODO: Write usage instructions here
22
-
23
- ## Contributing
24
39
 
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
40
+ 微信的消息类型分为文本,图片,音频,视频,AppMsg,对应接口中的类型为1,2,3,4,10。AppMsg类型的消息是富文本,包含图片信息,一般通过管理台事先编辑好,发送时需要调用send_post函数。其它类型的消息调用send_message即可。图片,音频,视频消息发送前需要先通过avatar_upload上传,取得返回的fileId后,使用fileId作为send_message的参数。
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
@@ -1,3 +1,3 @@
1
1
  module WeixinPublic
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/weixin_public.rb CHANGED
@@ -1,20 +1,16 @@
1
1
  require "weixin_public/version"
2
-
3
-
4
2
  require 'digest'
5
- require 'faraday'
6
3
  require 'json'
4
+ require 'openssl'
7
5
  require 'net/http'
8
6
  require 'nokogiri'
9
- require 'openssl'
10
-
11
- OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
7
+ require 'faraday'
12
8
 
13
9
  module WeixinPublic
14
10
 
15
11
  class WeixinObject
16
12
  def initialize(params)
17
- params.each { |var,val| self.send "#{var}=", val if self.class.instance_methods.include?(var.to_sym)}
13
+ params.each { |var,val| self.send "#{var}=", val if self.class.instance_methods.include?(var.to_sym)}
18
14
  end
19
15
  end
20
16
 
@@ -55,8 +51,10 @@ class WeixinPubClient
55
51
 
56
52
 
57
53
  def login(username,pwd)
54
+ puts "login with#{username}-#{pwd}"
58
55
  pwd = Digest::MD5.hexdigest(pwd)
59
- @cookie = @sig?"sig=#{@sig};cert=#{@cert}":""
56
+
57
+ @cookie = @cert?"cert=#{@cert}":""
60
58
  params = {"username"=>username,"pwd"=>pwd,"imgcode"=>'',"f"=>'json'}
61
59
  ret = request(:post,'/cgi-bin/login?lang=zh_CN',params,nil)
62
60
  return 'login failed' if !ret.headers["set-cookie"]
@@ -81,17 +79,6 @@ class WeixinPubClient
81
79
  end
82
80
  ret
83
81
  end
84
-
85
- def get_posts
86
- return if !@cookie && login(@username,@password) =~ /failed/
87
- ret = request(:get,"/cgi-bin/operate_appmsg?sub=list&t=wxm-appmsgs-list-new&type=10&pageIdx=0&pagesize=10&subtype=3&f=json",{},nil)
88
- doc = Nokogiri::HTML(ret.body)
89
- posts = doc.css('#json-msglist').to_s
90
- posts = JSON.parse(posts[posts.index(/{/)..posts.rindex(/}/)])["list"]
91
- ret = []
92
- posts.each {|po| ret << AppMsg.new(po)}
93
- ret
94
- end
95
82
 
96
83
  def get_messages(fakeId,download=false)
97
84
  return if !@cookie && login(@username,@password) =~ /failed/
@@ -104,8 +91,8 @@ class WeixinPubClient
104
91
  messages.each do |m|
105
92
  next if m["type"]=="10" || m["fakeId"]!=fakeId
106
93
  if m["type"]!="10" then
107
- ret << WeixinMessage.new(m)
108
- ret[-1].dateTime = Time.at(m["dateTime"].to_i)
94
+ ret << WeixinMessage.new(m)
95
+ ret[-1].dateTime = Time.at(m["dateTime"].to_i)
109
96
  end
110
97
  if download then
111
98
  download_file(ret[-1])
@@ -114,6 +101,33 @@ class WeixinPubClient
114
101
  ret
115
102
  end
116
103
 
104
+ def get_messages_number_new(lastmsgid)
105
+ return if !@cookie && login(@username,@password) =~ /failed/
106
+ res = request(:post,"/cgi-bin/getnewmsgnum?t=ajax-getmsgnum&lastmsgid=#{lastmsgid}")
107
+ ret = JSON.parse(res.body)["newTotalMsgCount"]
108
+ end
109
+
110
+ def get_messages_today(lastmsgid=0,step=50)
111
+ return if !@cookie && login(@username,@password) =~ /failed/
112
+ offset = 0
113
+ ret = []
114
+ loop do
115
+ params = {"t"=>"ajax-message","lang"=>"zh_CN","count"=>'50',"timeline"=>'1','day'=>'0','cgi'=>'getmessage','offset'=>offset}
116
+ res = request(:post,"/cgi-bin/getmessage",params,nil)
117
+ messages = JSON.parse(res.body)
118
+ n = 0
119
+ messages.each do |m|
120
+ break if m["id"].to_i <= lastmsgid
121
+ ret << WeixinMessage.new(m)
122
+ ret[-1].dateTime = Time.at(m["dateTime"].to_i)
123
+ n = n+1
124
+ end
125
+ break if n < step
126
+ offset = offset + step
127
+ end
128
+ ret
129
+ end
130
+
117
131
  def download_file(message)
118
132
  url="/cgi-bin/downloadfile?msgid=#{message.id}&source="
119
133
  avatar_download(message.filePath,url)
@@ -129,10 +143,9 @@ class WeixinPubClient
129
143
  body["fileid"]=content
130
144
  end
131
145
  ret = request(:post,"/cgi-bin/singlesend?t=ajax-response&lang=zh_CN",body,"https://mp.weixin.qq.com/cgi-bin/singlemsgpage")
132
- puts ret.body
133
146
  end
134
147
 
135
- def send_post(appmsgid,reciever)
148
+ def send_appmsg(appmsgid,reciever)
136
149
  return if !@cookie && login(@username,@password) =~ /failed/
137
150
  body = {"error"=>false,"ajax"=>1,"f"=>"json","tofakeid"=>reciever,"fid"=>appmsgid,"appmsgid"=>appmsgid,"type"=>10}
138
151
  ret = request(:post,"/cgi-bin/singlesend?t=ajax-response&lang=zh_CN",body,"https://mp.weixin.qq.com/cgi-bin/singlemsgpage")
@@ -140,7 +153,7 @@ class WeixinPubClient
140
153
 
141
154
 
142
155
  def avatar_upload(avatar,type="image/png")
143
- return if !@cookie && login(@username,@password) =~ /failed/
156
+ return nil if !@cookie && login(@username,@password) =~ /failed/
144
157
  payload = { :uploadFile => Faraday::UploadIO.new(avatar, type)}
145
158
  @conn_multipart.headers["Cookie"] = @cookie
146
159
  @conn_multipart.headers["Referer"]="http://mp.weixin.qq.com/cgi-bin/indexpage"
@@ -148,13 +161,55 @@ class WeixinPubClient
148
161
  return ret.body.to_s[/\'.*?\'/m][1..-2] if ret.body =~ /suc/m
149
162
  return nil
150
163
  end
151
-
164
+
165
+ def create_appmsg(title,avatar,content,desc="")
166
+ return nil if !@cookie && login(@username,@password) =~ /failed/
167
+ if avatar =~ /^http/ then
168
+ end
169
+ fileid = avatar_upload(avatar)
170
+ return nil if !fileid
171
+ params = {:error=>false,:count=>1,:title0=>title,:digest0=>desc,:content0=>content,:fileid0=>fileid,:ajax=>1,:sub=>"create"}
172
+ ret = request(:post,"/cgi-bin/operate_appmsg?t=ajax-response&lang=zh_CN",params,"https://mp.weixin.qq.com/cgi-bin/operate_appmsg")
173
+ print ret.body
174
+ lst=get_appmsg_lst
175
+ return lst[0].appId if lst
176
+ return nil
177
+ end
178
+
179
+ def get_appmsg_lst
180
+ return nil if !@cookie && login(@username,@password) =~ /failed/
181
+ ret = request(:get,"/cgi-bin/operate_appmsg?sub=list&t=wxm-appmsgs-list-new&type=10&pageIdx=0&pagesize=10&subtype=3&f=json",{},nil)
182
+ doc = Nokogiri::HTML(ret.body)
183
+ posts = doc.css('#json-msglist').to_s
184
+ posts = JSON.parse(posts[posts.index(/{/)..posts.rindex(/}/)])["list"]
185
+ ret = []
186
+ posts.each {|po| ret << AppMsg.new(po)}
187
+ ret
188
+ end
189
+
152
190
  def avatar_download(file,url)
153
191
  puts "download-#{url}"
154
192
  ret = request(:get,url,{},nil)
155
193
  File.open(file, 'wb') { |fp| fp.write(ret.body) }
156
194
  end
157
195
 
196
+ #type:1 -edit mode 2 -dev mode 4 -auto-reply
197
+ def operadvancedfunc(type=1,on_off = 0)
198
+ return nil if !@cookie && login(@username,@password) =~ /failed/
199
+ ret = request(:post,"/cgi-bin/operadvancedfunc?op=switch&lang=zh_CN",{:flag=>on_off,:type=>type,:ajax=>1},nil)
200
+ end
201
+
202
+ def switch_dev_mode
203
+ operadvancedfunc(4,0)
204
+ operadvancedfunc(1,0)
205
+ operadvancedfunc(2,1)
206
+ end
207
+
208
+ def set_dev_callback(url, token)
209
+ return nil if !@cookie && login(@username,@password) =~ /failed/
210
+ ret = request(:post,"/cgi-bin/callbackprofile?t=ajax-response&lang=zh_CN",{:url=>url,:callback_token=>token,:ajax=>1},nil)
211
+ end
212
+
158
213
  def request(method,url,params,referer)
159
214
  @conn.headers["Cookie"] = @cookie
160
215
  @conn.headers["Referer"] = referer if referer
data/test/avatar.jpg ADDED
Binary file
@@ -0,0 +1,3 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rubygems'
3
+ require 'weixin_public'
@@ -0,0 +1,45 @@
1
+ require 'test/unit'
2
+ require 'weixin_public'
3
+ #require File.expand_path('../../lib/weixin_public.rb', __FILE__)
4
+ require 'openssl'
5
+ OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
6
+ class WeixinPublicTest < Test::Unit::TestCase
7
+ def setup
8
+ @client = WeixinPublic::WeixinPubClient.new('xyz@gmail.com','abc')
9
+ @fakeId = "1234567" #=>user who you want to send a message
10
+ @pic_file = "avatar.jpg"
11
+ end
12
+
13
+ def ntest_fans
14
+ @client.get_fans.each {|f| p "#{f.fakeId}-#{f.nickName}"}
15
+ end
16
+
17
+ def ntest_create_appmsg
18
+ @client.create_appmsg(Time.new.to_s,'/home/liteng/teng.png','conetnt')
19
+ end
20
+
21
+ def ntest_app_lst
22
+ po = @client.get_appmsg_lst.each{|m| print "#{m.appId}-#{m.time}\n"}
23
+ end
24
+
25
+ def ntest_send
26
+ puts @client.send_message("hello",@fakeId)
27
+ end
28
+
29
+ def ntest_send
30
+ puts @client.send_appmsg("hello",@fakeId)
31
+ end
32
+
33
+ def ntest_read
34
+ @client.get_messages(@fakeId).each {|m| p "#{m.dateTime} << #{m.content}"}
35
+ end
36
+
37
+ def ntest_upload
38
+ puts @client.avatar_upload(@pic_file)
39
+ end
40
+
41
+ def test_set_callback
42
+ @client.operadvancedfunc(2,1)
43
+ @client.set_dev_callback("http://wxpt2.cfapps.io/","abc")
44
+ end
45
+ end
@@ -20,4 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_dependency "nokogiri"
24
+ spec.add_dependency "faraday"
23
25
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: weixin_public
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - goxplanet
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2013-05-10 00:00:00 Z
13
+ date: 2013-07-08 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -34,6 +34,28 @@ dependencies:
34
34
  version: "0"
35
35
  type: :development
36
36
  version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: nokogiri
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: faraday
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :runtime
58
+ version_requirements: *id004
37
59
  description: "weixin public client "
38
60
  email: otec.teng@gmail.com
39
61
  executables: []
@@ -43,13 +65,15 @@ extensions: []
43
65
  extra_rdoc_files: []
44
66
 
45
67
  files:
46
- - .gitignore
47
68
  - Gemfile
48
69
  - LICENSE.txt
49
70
  - README.md
50
71
  - Rakefile
51
72
  - lib/weixin_public.rb
52
73
  - lib/weixin_public/version.rb
74
+ - test/avatar.jpg
75
+ - test/test_helper.rb
76
+ - test/weixin_test.rb
53
77
  - weixin_public.gemspec
54
78
  homepage: ""
55
79
  licenses:
@@ -78,5 +102,7 @@ rubygems_version: 1.8.10
78
102
  signing_key:
79
103
  specification_version: 3
80
104
  summary: weixin public client,working with web page interface ,using HTTPS
81
- test_files: []
82
-
105
+ test_files:
106
+ - test/avatar.jpg
107
+ - test/test_helper.rb
108
+ - test/weixin_test.rb
data/.gitignore DELETED
@@ -1,17 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp