simple_wx 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3352241216ce336988e4fa27a330ba1d723e0558
4
+ data.tar.gz: e07e3618c8533fdf0afae69d27b08ea7b554f6a5
5
+ SHA512:
6
+ metadata.gz: ca678fc595eef2f1424dd3b6b34c21d1577ff80c03b6e6300e22ddc5cb1798b97276fb7fd28c14c01d1853cac726164082233f1b0bdd78df712242e56c4575d2
7
+ data.tar.gz: cb8a81f1373d22ab77a7e5cbb38cfe9cb6a5d8a34218cccd6c3501486e653ac81c402d1beed8e8dd8cc04ca8c0a8c76461f07d17662f08c70dfae47dca026437
data/.gitignore ADDED
@@ -0,0 +1,23 @@
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
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ /.idea
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ ## initializers/simple_wx.rb:
2
+ ```
3
+ WeixinSetting = YAML.load_file(File.join "#{Rails.root}", "config", "weixin.yml")[Rails.env || "development"]
4
+
5
+ module SimpleWx
6
+ @@weixin_config = YAML.load_file(File.join "#{Rails.root}", "config", "weixin.yml")[Rails.env || "development"]
7
+ @@logger = Rails.logger
8
+ @@redis = Redis::Objects.redis
9
+ end
10
+ ```
11
+
12
+ ## config/weixin.yml:
13
+ ```
14
+ development:
15
+ app_id: app_id
16
+ app_secret: app_secret
17
+ serial_no: 微信号 (gh...)
18
+ token: token
19
+
20
+ production:
21
+ # ...
22
+ ```
@@ -0,0 +1,5 @@
1
+ module SimpleWx
2
+ @@weixin_config = YAML.load_file(File.join "#{Rails.root}", "config", "weixin.yml")[Rails.env || "development"]
3
+ @@logger = Rails.logger
4
+ @@redis = Redis::Objects.redis
5
+ end
@@ -0,0 +1,79 @@
1
+ module SimpleWx
2
+ class AccessToken < Base
3
+
4
+ ### Usage
5
+ #
6
+ # ---------- class-methods ----------
7
+ #
8
+ # SimpleWx::AccessToken.access_token
9
+ # SimpleWx::AccessToken.server_ip
10
+ # SimpleWx::AccessToken.jsapi_ticket
11
+ #
12
+ # ---------- instance-methods -----------
13
+ #
14
+ # at = SimpleWx::AccessToken.new
15
+ # at.access_token
16
+ # at.server_ip
17
+ # if at.error.present?
18
+ # ...
19
+ # end
20
+ #
21
+
22
+
23
+ def server_ip
24
+ url = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=#{access_token}"
25
+ response = RestClient.get url
26
+ response_json = errcode_check(JSON.parse(response))
27
+ @server_ip = response_json["ip_list"]
28
+ end
29
+
30
+ def access_token
31
+ SimpleWx.redis.exists("__weixin_access_token__") ? \
32
+ SimpleWx.redis.get("__weixin_access_token__") : get_new_token
33
+ end
34
+
35
+ def jsapi_ticket
36
+ SimpleWx.redis.exists("__jsapi_ticket__") ? \
37
+ SimpleWx.redis.get("__jsapi_ticket__") : get_new_jsapi_ticket
38
+ end
39
+
40
+ private
41
+
42
+ def get_new_jsapi_ticket
43
+ url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=#{access_token}&type=jsapi"
44
+ response = RestClient.get url
45
+ response_json = errcode_check(JSON.parse(response))
46
+ jsapi_ticket = response_json["ticket"]
47
+ if @error.blank?
48
+ SimpleWx.redis.multi do
49
+ SimpleWx.redis.set "__jsapi_ticket__", jsapi_ticket
50
+ SimpleWx.redis.expire "__jsapi_ticket__", 30.minutes.to_i
51
+ end
52
+ end
53
+ jsapi_ticket
54
+ end
55
+
56
+ def get_new_token
57
+ url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{SimpleWx.weixin_config["app_id"]}&secret=#{SimpleWx.weixin_config["app_secret"]}"
58
+ response = RestClient.get url
59
+ response_json = errcode_check(JSON.parse(response))
60
+ access_token = response_json["access_token"]
61
+ if @error.blank?
62
+ SimpleWx.redis.multi do
63
+ SimpleWx.redis.set "__weixin_access_token__", access_token
64
+ SimpleWx.redis.expire "__weixin_access_token__", 30.minutes.to_i
65
+ end
66
+ end
67
+ access_token
68
+ end
69
+
70
+ def self.method_missing m
71
+ instance = self.new
72
+ if instance.public_methods(false).include? m.to_sym
73
+ return instance.send(m)
74
+ else
75
+ super
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,37 @@
1
+ module SimpleWx
2
+ class Base
3
+ attr_accessor :error, :raise_flag
4
+
5
+ def initialize options = {}
6
+ raise 'SimpleWx.weixin_config is blank.' if SimpleWx.weixin_config.blank?
7
+ @raise_flag = options[:raise_flag]
8
+ @log_flag = options[:log_flag]
9
+ @error = {}
10
+ end
11
+
12
+ protected
13
+
14
+ def errcode_check json, log_flag = nil
15
+
16
+ # 每次执行刷新 @error
17
+ # 根据 log_flag 打印日志
18
+ # 检查是否直接抛错
19
+
20
+ @error = {}
21
+ raise "Responsed nothing from Weixin" if json.nil? && @raise_flag
22
+ if json["errcode"].present? && json["errcode"].to_i != 0
23
+ SimpleWx.logger.error(json)
24
+ @error = json
25
+ raise "Weixin response json with errcode: #{json}" if @raise_flag
26
+ else
27
+ if log_flag
28
+ SimpleWx.logger.info("SimpleWxLog:#{self.class.name} -- #{log_flag} -- #{json}")
29
+ else
30
+ SimpleWx.logger.debug("SimpleWxLog:#{self.class.name} -- #{json}")
31
+ end
32
+ end
33
+ json
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,73 @@
1
+ module SimpleWx
2
+ class Menu < Base
3
+
4
+ ### Usage
5
+ #
6
+ # ---------- class-methods ----------
7
+ #
8
+ # SimpleWx::Menu.show
9
+ # SimpleWx::Menu.create(buttons)
10
+ # => true/false
11
+ # SimpleWx::Menu.delete
12
+ # => true/false
13
+ #
14
+ # ---------- instance-methods -----------
15
+ #
16
+ # menu = SimpleWx::Menu.new
17
+ # menu.show
18
+ #
19
+ # if menu.create(buttons)
20
+ # ...
21
+ # else
22
+ # p menu.error
23
+ # end
24
+ #
25
+ # menu.delete!
26
+ # when "errcode" existed in json of response, it will raise the error:
27
+ # => "Weixin response json with errcode: #{json}"
28
+ #
29
+
30
+ def initialize options = {}
31
+ @access_token = options[:access_token] || AccessToken.access_token
32
+ end
33
+
34
+ def show
35
+ url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=#{@access_token}"
36
+ response = RestClient.get url
37
+ response_json = errcode_check(JSON.parse(response))
38
+ @menus = response_json["menu"]
39
+ end
40
+
41
+ def create menu_hash
42
+ url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=#{@access_token}"
43
+ response = RestClient.post(url, JSON.generate({button: menu_hash}))
44
+ errcode_check(JSON.parse(response))
45
+ @error.blank?
46
+ end
47
+
48
+ def delete
49
+ url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=#{@access_token}"
50
+ response = RestClient.get url
51
+ errcode_check(JSON.parse(response))
52
+ @error.blank?
53
+ end
54
+
55
+ def create! menu_hash
56
+ @raise_flag ||= true
57
+ create menu_hash
58
+ end
59
+
60
+ def delete!
61
+ @raise_flag ||= true
62
+ delete
63
+ end
64
+
65
+ def self.method_missing m, *args
66
+ if instance_methods.include? m.to_sym
67
+ self.new.send(m, *args)
68
+ else
69
+ super
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,59 @@
1
+ module SimpleWx
2
+ class Message < Base
3
+ attr_accessor :openid, :json, :xml
4
+ def initialize options
5
+ @openid = options.delete(:openid)
6
+ @access_token = options.delete(:access_token) || AccessToken.access_token
7
+ @custom_msg_url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=#{@access_token}"
8
+ @json = {}
9
+ @xml = {}
10
+ end
11
+
12
+ protected
13
+
14
+ def set_json
15
+ @json[:touser] = @openid
16
+ end
17
+
18
+ def set_xml
19
+ @xml["ToUserName"] = @openid
20
+ @xml["FromUserName"] = SimpleWx.weixin_config["serial_no"]
21
+ @xml["CreateTime"] = Time.now.to_i.to_s
22
+ end
23
+
24
+ def send_json
25
+ set_json
26
+ response = RestClient.post(@custom_msg_url, JSON.generate(@json))
27
+ errcode_check(JSON.parse(response))
28
+ end
29
+
30
+ def send_json!
31
+ @raise_flag ||= true
32
+ send_json
33
+ end
34
+
35
+ def to_xml
36
+ set_xml
37
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
38
+ xml.xml do
39
+ recursively_xml xml, @xml
40
+ end
41
+ end
42
+ builder.to_xml
43
+ end
44
+
45
+ private
46
+
47
+ def recursively_xml builder, hsh
48
+ hsh.each do |k, v|
49
+ if v.is_a? Hash
50
+ builder.send(k) do
51
+ recursively_xml(builder, v)
52
+ end
53
+ else
54
+ builder.send(k, v)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,23 @@
1
+ module SimpleWx
2
+ module Messages
3
+ class ImageMessage < Message
4
+ def initialize options
5
+ super
6
+ @media_id = options[:media_id]
7
+ end
8
+
9
+ def send_json
10
+ @json[:msgtype] = "image"
11
+ @json[:image] = {media_id: @media_id}
12
+ SimpleWx.logger.info("SimpleWxLog:#{self.class.name} -- #{@openid} -- #{json}")
13
+ super
14
+ end
15
+
16
+ def to_xml
17
+ @xml["MsgType"] = "image"
18
+ @xml["Image"] = { "MediaId" => @media_id }
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module SimpleWx
2
+ module Messages
3
+ class TextMessage < Message
4
+ def initialize options
5
+ super
6
+ @content = options[:content]
7
+ end
8
+
9
+ def send_json
10
+ @json[:msgtype] = "text"
11
+ @json[:text] = {content: @content}
12
+ SimpleWx.logger.info("SimpleWxLog:#{self.class.name} -- #{@openid} -- #{json}")
13
+ super
14
+ end
15
+
16
+ def to_xml
17
+ @xml["MsgType"] = "text"
18
+ @xml["Content"] = @content
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,82 @@
1
+ module SimpleWx
2
+ class OAuth < Base
3
+
4
+ ### Usage
5
+ #
6
+ # auth = SimpleWx::OAuth.new(code: "code")
7
+ #
8
+ # 调用 OAth2 的 access_token 接口, 返回结果信息
9
+ # result_json = auth.get_access_token
10
+ #
11
+ # auth 返回的基本参数会赋值给对象属性
12
+ # auth.access_token == result_json["access_token"]
13
+ # => true
14
+ #
15
+ # 检查 access_token 是否过期
16
+ # auth.access_token_valid?
17
+ # => true
18
+ #
19
+ # auth.expires_in
20
+ # => 7200
21
+ # sleep 7201
22
+ # auth.access_token_valid?
23
+ # => false
24
+ #
25
+ # 刷新access_token接口
26
+ # result_json = auth.refresh_token
27
+ # auth.access_token == result_json["access_token"]
28
+ # auth.access_token_valid?
29
+ # => true
30
+ #
31
+
32
+ attr_reader :code, :scope, :expires_in, :unionid, :result
33
+ attr_accessor :access_token, :refresh_token, :openid
34
+
35
+ def initialize options
36
+ @code = options[:code]
37
+ end
38
+
39
+ def get_access_token
40
+ url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{SimpleWx.weixin_config["app_id"]}&secret=#{SimpleWx.weixin_config["app_secret"]}&code=#{@code}&grant_type=authorization_code"
41
+ response = RestClient.get url
42
+ set_result(errcode_check(JSON.parse(response)))
43
+ end
44
+
45
+ def get_user_info
46
+ UserInfo.get_auth_info(o_auth: self)
47
+ end
48
+
49
+ def access_token_valid?
50
+ url = "https://api.weixin.qq.com/sns/auth?access_token=#{@access_token}&openid=#{@openid}"
51
+ response = RestClient.get url
52
+ errcode_check(JSON.parse(response))
53
+ @error.blank?
54
+ end
55
+
56
+ def refresh_token
57
+ url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=#{SimpleWx.weixin_config["app_id"]}&grant_type=refresh_token&refresh_token=#{@refresh_token}"
58
+ response = RestClient.get url
59
+ set_result(errcode_check(JSON.parse(response)))
60
+ end
61
+
62
+ def self.generate_auth_link url, state = "", scope = "snsapi_userinfo"
63
+ params = {
64
+ appid: SimpleWx.weixin_config["app_id"],
65
+ redirect_uri: url,
66
+ response_type: "code",
67
+ scope: scope,
68
+ state: state
69
+ }
70
+ "https://open.weixin.qq.com/connect/oauth2/authorize?#{params.to_query}#wechat_redirect"
71
+ end
72
+
73
+ private
74
+
75
+ def set_result result
76
+ result.each do |k, v|
77
+ instance_variable_set "@#{k}", v
78
+ end
79
+ @result = result
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,31 @@
1
+ module SimpleWx
2
+ class Signaturer < Base
3
+
4
+ ### Usage
5
+ #
6
+ # signer = SimpleWx::Signaturer.new timestamp: params[:timestamp], nonce: params[:nonce]
7
+ # if signer.sign params[:signature]
8
+ # render text: params[:echostr]
9
+ # else
10
+ # ...
11
+ # end
12
+
13
+ def initialize options = {}
14
+ @timestamp = options.fetch :timestamp
15
+ @nonce = options.fetch :nonce
16
+ @token = SimpleWx.weixin_config["token"] #TODO 没有就raise错误,用method_missing
17
+ end
18
+
19
+ def sign signture
20
+ @sort_array = [@timestamp, @nonce, @token].sort
21
+ signture == sha1_encrypt
22
+ end
23
+
24
+ private
25
+
26
+ def sha1_encrypt
27
+ encrypt_str = @sort_array.join
28
+ Digest::SHA1.hexdigest(encrypt_str)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ module SimpleWx
2
+ class UserInfo < Base
3
+
4
+ ### Usage
5
+ #
6
+ # ---------- class-methods ----------
7
+ #
8
+ # instance_of_oauth = SimpleWx::OAuth.new("code")
9
+ # instance_of_oauth.get_access_token
10
+ # user_info_hsh = SimpleWx::UserInfo.get_auth_info(o_auth: instance_of_oauth)
11
+ #
12
+ # user_info_hsh = SimpleWx::UserInfo.get_basic_info(access_token: "token", openid: "openid")
13
+ #
14
+ # ---------- instance-methods -----------
15
+ #
16
+ # @user_info = SimpleWx::UserInfo.new(access_token: "token", openid: "openid")
17
+ # user_info_hsh = @user_info.get_basic_info
18
+ # if @user_info.error.present?
19
+ # ...
20
+ # end
21
+ #
22
+
23
+ def initialize options
24
+ @openid = options[:openid]
25
+ @o_auth = options[:o_auth]
26
+ @access_token = options[:access_token] || AccessToken.access_token
27
+ end
28
+
29
+ def get_basic_info
30
+ url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=#{@access_token}&openid=#{@openid}&lang=zh_CN"
31
+ response = RestClient.get url
32
+ errcode_check(JSON.parse(response))
33
+ end
34
+
35
+ def get_auth_info
36
+ url = "https://api.weixin.qq.com/sns/userinfo?access_token=#{@o_auth.access_token}&openid=#{@o_auth.openid}&lang=zh_CN"
37
+ response = RestClient.get url
38
+ errcode_check(JSON.parse(response))
39
+ end
40
+
41
+ def self.method_missing m, hsh
42
+ if instance_methods.include? m.to_sym
43
+ self.new(hsh).send m
44
+ else
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleWx
2
+ VERSION = "0.0.0"
3
+ end
data/lib/simple_wx.rb ADDED
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ require 'redis'
3
+ require 'yell'
4
+
5
+ module SimpleWx
6
+ @@weixin_config = {}
7
+ @@logger = Yell.new :datefile, 'simple_wx.log'
8
+ @@redis = Redis.new(host: '127.0.0.1', port: '6379', db: '0')
9
+
10
+ def self.weixin_config
11
+ @@weixin_config
12
+ end
13
+
14
+ def self.logger
15
+ @@logger
16
+ end
17
+
18
+ def self.redis
19
+ @@redis
20
+ end
21
+ end
22
+
23
+ require 'simple_wx/base'
24
+ require 'simple_wx/signaturer'
25
+ require 'simple_wx/access_token'
26
+ require 'simple_wx/menu'
27
+ require 'simple_wx/user_info'
28
+ require 'simple_wx/message'
29
+ require 'simple_wx/messages/text_message'
30
+ require 'simple_wx/messages/image_message'
31
+
data/simple_wx.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simple_wx/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simple_wx"
8
+ spec.version = SimpleWx::VERSION
9
+ spec.authors = ["Scott1743"]
10
+ spec.email = ["512981271@qq.com"]
11
+ spec.summary = ""
12
+ spec.description = %q{Ruby Api for WeiXin}
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency 'redis', '~> 3.2.1'
21
+ spec.add_dependency 'yell', '~> 2.0.0'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+
25
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_wx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Scott1743
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: yell
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ description: Ruby Api for WeiXin
56
+ email:
57
+ - 512981271@qq.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - README.md
64
+ - config/initializers/simple_wx.rb.example
65
+ - lib/simple_wx.rb
66
+ - lib/simple_wx/access_token.rb
67
+ - lib/simple_wx/base.rb
68
+ - lib/simple_wx/menu.rb
69
+ - lib/simple_wx/message.rb
70
+ - lib/simple_wx/messages/image_message.rb
71
+ - lib/simple_wx/messages/text_message.rb
72
+ - lib/simple_wx/o_auth.rb
73
+ - lib/simple_wx/signaturer.rb
74
+ - lib/simple_wx/user_info.rb
75
+ - lib/simple_wx/version.rb
76
+ - simple_wx.gemspec
77
+ homepage:
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.2.2
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: ''
101
+ test_files: []