open_qq 3.0.1 → 3.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/MIT-LICENSE CHANGED
File without changes
data/README.md CHANGED
@@ -11,7 +11,7 @@ gem install open_qq
11
11
 
12
12
  ## 使用
13
13
 
14
- 使用非常简单,传入应用的appid, appkey和环境地址env _http://openapi.tencentyun.com_ 或者 _http://119.147.19.43_ 即可
14
+ 使用非常简单,传入应用的`appid`, `appkey`和环境地址`env`
15
15
 
16
16
  ```ruby
17
17
  require 'rubygems'
@@ -19,6 +19,9 @@ require 'open_qq'
19
19
 
20
20
  OpenQq.setup(:appid => '123', :appkey => '456', :env => 'http://119.147.19.43')
21
21
 
22
+ # 或者https
23
+ OpenQq.setup(:appid => '123', :appkey => '456', :env => 'https://119.147.19.43')
24
+
22
25
  # get请求
23
26
  user_info = OpenQq.get('/v3/user/get_info', :openid => '111',:openkey => '222')
24
27
 
@@ -42,7 +45,7 @@ puts user_info
42
45
  ```ruby
43
46
  options = {:appid => 'newappid', :appkey => 'newappkey', :env => 'http://newenv'}
44
47
 
45
- user_info = OpenQq.start('/v3/user/get_info', options) do |request|
48
+ user_info = OpenQq.call('/v3/user/get_info', options) do |request|
46
49
 
47
50
  request.get {:openid => '111',:openkey => '222'}
48
51
 
@@ -55,6 +58,29 @@ user_info.nickname
55
58
  # => 'foo'
56
59
  ```
57
60
 
61
+ 回调协议签名验证
62
+
63
+ ```ruby
64
+ params = {openid: 'test001', appid: '33758', sig: 'VvKwcaMqUNpKhx0XfCvOqPRiAnU%3D'}
65
+ OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', params)
66
+ # => true or false
67
+
68
+ #指定特定的appkey
69
+ OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', params, 'xxxxxx')
70
+
71
+ # 在rails中使用
72
+ class OpenQqController < ApplicationController
73
+ include OpenQq::Rails::ActionController
74
+
75
+ def index
76
+ if verify_callback_sig
77
+ ...do something
78
+ end
79
+ end
80
+ end
81
+
82
+ ```
83
+
58
84
  ## 在rails中使用
59
85
 
60
86
  首先在Gemfile中添加
@@ -107,4 +133,11 @@ puts sig # 与联调结果比对
107
133
  * 测试基本覆盖,可以下载下来执行`rake`
108
134
  * bug反馈[Issue](https://github.com/zires/open_qq/issues)
109
135
 
110
- #### This project rocks and uses MIT-LICENSE.
136
+ ## Changelog
137
+
138
+ * 2012/09/11
139
+ 增加对https的支持
140
+ 支持支付回调协议签名验证
141
+
142
+
143
+ ## This project rocks and uses MIT-LICENSE.
data/Rakefile CHANGED
File without changes
File without changes
File without changes
data/lib/open_qq/error.rb CHANGED
File without changes
@@ -7,7 +7,7 @@
7
7
  require 'open_qq/signature'
8
8
  require 'open_qq/error'
9
9
  require 'ostruct'
10
- require 'net/http'
10
+ require 'net/https'
11
11
 
12
12
  module OpenQq
13
13
  class Gateway
@@ -18,7 +18,11 @@ module OpenQq
18
18
 
19
19
  # @param [String] appid
20
20
  # @param [String] appkey
21
- # @param [String] env 调用的环境地址.生产环境: <http://openapi.tencentyun.com> 测试环境: <http://119.147.19.43>
21
+ # @param [String] env 调用的环境地址
22
+ #
23
+ # @example
24
+ # OpenQq::Gateway.new('1111', '2222', 'http://119.147.19.43')
25
+ # OpenQq::Gateway.new('1111', '2222', 'https://openapi.tencentyun.com')
22
26
  def initialize(appid, appkey, env)
23
27
  @appid = appid
24
28
  @appkey = appkey
@@ -30,6 +34,11 @@ module OpenQq
30
34
  @env = env
31
35
  uri = URI.parse(env)
32
36
  @http = Net::HTTP.new(uri.host, uri.port)
37
+ # HTTPS
38
+ if uri.scheme == "https"
39
+ @http.use_ssl = true
40
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
41
+ end
33
42
  end
34
43
 
35
44
  # @param [String] url which api you want to call
@@ -46,28 +55,33 @@ module OpenQq
46
55
  # user_info = gateway.get('/v3/user/get_info', {:openid => '11'}, {:raw => true} )
47
56
  # user_info.nickname # => '{"nickname":"foo"}'
48
57
  #
49
- # @return (@see #call)
58
+ # @return (see #call)
50
59
  def get(url, params = {}, options = {})
51
- parsed_params = each_pair_escape( wrap(:get, url, params) ).map{|k,v| "#{k}=#{v}"}.join('&')
60
+ parsed_params = Gateway.each_pair_escape( wrap(:get, url, params) ).map{|k,v| "#{k}=#{v}"}.join('&')
52
61
  get_request = Net::HTTP::Get.new("#{url}?#{parsed_params}")
53
62
  self.call( get_request, options.merge(:format => params[:format]) )
54
63
  end
55
64
 
56
65
  # @param (see #get)
57
66
  #
58
- # @return (@see #call)
67
+ # @return (see #call)
59
68
  def post(url, params = {}, options = {})
60
69
  post_request = Net::HTTP::Post.new(url)
61
70
  post_request.set_form_data wrap(:post, url, params)
62
71
  self.call( post_request, options.merge(:format => params[:format]) )
63
72
  end
64
73
 
74
+ # wrap `http_method`, `url`, `params` together
65
75
  def wrap(http_method, url, params)
66
76
  params = params.merge(:appid => @appid)
67
- params[:sig] = signature( "#{@appkey}&", make_source(http_method.to_s.upcase, url, params) )
77
+ params[:sig] = Gateway.signature( "#{@appkey}&", Gateway.make_source(http_method.to_s.upcase, url, params) )
68
78
  params
69
79
  end
70
80
 
81
+ class << self
82
+ include Signature
83
+ end
84
+
71
85
  protected
72
86
 
73
87
  # Call the request and format the output
@@ -87,9 +101,5 @@ module OpenQq
87
101
  OpenStruct.new( JSON.parse(response.body) )
88
102
  end
89
103
 
90
- private
91
-
92
- include Signature
93
-
94
104
  end
95
105
  end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ #
3
+ # --
4
+ # @author zires
5
+ # @email zshuaibin@gmail.com
6
+ #
7
+ module OpenQq
8
+ module Rails
9
+ module ActionController
10
+ extend ActiveSupport::Concern
11
+
12
+ private
13
+ # @example
14
+ # class OpenQqController < ApplicationController
15
+ # include OpenQq::Rails::ActionController
16
+ #
17
+ # def index
18
+ # if verify_callback_sig
19
+ # ...do something
20
+ # end
21
+ # end
22
+ # end
23
+ # @return [Boolean]
24
+ def verify_callback_sig(key = nil)
25
+ logger.debug "Appkey: #{key ||= OpenQq.appkey} method: #{request.method} url: #{request.fullpath.split("?")[0]}"
26
+ logger.debug "params: #{params.slice!(:action, :controller).inspect}"
27
+ OpenQq.verify_callback_sig(request.method, request.fullpath.split("?")[0], params.slice!(:action, :controller), key)
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -17,7 +17,13 @@ module OpenQq
17
17
  puts e.message
18
18
  end
19
19
  end
20
- end
20
+ end
21
+
22
+ initializer "load open_qq controller method" do
23
+ ActiveSupport.on_load(:action_controller) do
24
+ require 'open_qq/rails/action_controller'
25
+ end
26
+ end
21
27
 
22
28
  end
23
29
  end
File without changes
@@ -28,5 +28,17 @@ module OpenQq
28
28
  "#{http_method}&#{url_escape(url)}&#{escape_opt}"
29
29
  end
30
30
 
31
+ def make_callback_source(http_method, url, options)
32
+ escape_opt = options.sort_by{|k,v| k.to_s}.map do |kv|
33
+ value = URI.escape(kv.last, /[^0-9a-zA-Z!*()]/)
34
+ "#{kv.first}=#{value}"
35
+ end.join('&')
36
+ "#{http_method}&#{url_escape(url)}&#{url_escape(escape_opt)}"
37
+ end
38
+
39
+ def verify_sig(sig, key, http_method, url, options)
40
+ sig == url_escape( signature(key, make_callback_source(http_method, url, options)) )
41
+ end
42
+
31
43
  end
32
44
  end
@@ -6,5 +6,5 @@
6
6
  #
7
7
  module OpenQq
8
8
  # 3.0表示OpenAPI版本, 小数点第二位表示SDK版本
9
- VERSION = "3.0.1"
9
+ VERSION = "3.0.2"
10
10
  end
data/lib/open_qq.rb CHANGED
@@ -23,10 +23,10 @@ module OpenQq
23
23
  delegate :appid, :appkey, :env, :get, :post, :wrap, :to => :@gateway
24
24
 
25
25
  # @example
26
- # OpenQq.start('/v3/user/get_info', { :appid => 123 }) do |request|
26
+ # OpenQq.call('/v3/user/get_info', { :appid => 123 }) do |request|
27
27
  # request.get({:openid => '111'})
28
28
  # end
29
- def start(url, options)
29
+ def call(url, options)
30
30
  request = OpenQq::Request.new(options.with_indifferent_access)
31
31
  if block_given?
32
32
  yield request
@@ -35,6 +35,22 @@ module OpenQq
35
35
  end
36
36
  end
37
37
 
38
+ alias start call
39
+
40
+ # @example
41
+ # params = {openid: 'test001', appid: '33758', sig: 'VvKwcaMqUNpKhx0XfCvOqPRiAnU%3D'}
42
+ # OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', params)
43
+ # #diffenert key
44
+ # OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', params, 'xxxxxx')
45
+ #
46
+ # @return [Boolean]
47
+ def verify_callback_sig(http_method, url, params, key = nil)
48
+ key ||= appkey
49
+ params = params.dup
50
+ sig = params.delete('sig') || params.delete(:sig)
51
+ Gateway.verify_sig(sig, "#{key}&", http_method.to_s.upcase, url, params)
52
+ end
53
+
38
54
  end
39
55
  end
40
56
 
data/test/benchmark.rb CHANGED
File without changes
File without changes
@@ -50,4 +50,12 @@ class OpenQq::GatewayTest < MiniTest::Unit::TestCase
50
50
  assert_equal 2001, gateway.get('/v3/user/get_info', params).ret
51
51
  end
52
52
 
53
+ def test_https_request
54
+ gateway = OpenQq::Gateway.new(@appid, @appkey, 'https://119.147.19.43')
55
+ http = gateway.instance_variable_get(:@http)
56
+ assert_equal 443, http.port
57
+ assert_equal '119.147.19.43', http.address
58
+ assert http.use_ssl?
59
+ end
60
+
53
61
  end
File without changes
@@ -44,4 +44,28 @@ class OpenQq::SignatureTest < MiniTest::Unit::TestCase
44
44
  assert_equal( 'o/nGo1QkVEiiN6Bqn/fRJtEJwLc=', @foo.signature("#{@appkey}&", source) )
45
45
  end
46
46
 
47
+ #测试用例通过http://wiki.open.qq.com/wiki/回调发货URL的协议说明_V3获得
48
+ def test_make_callback_source
49
+ params = 'openid=test001&appid=33758&ts=1328855301&payitem=323003*8*1&token=53227955F80B805B50FFB511E5AD51E025360&billno=-APPDJT18700-20120210-1428215572&version=v3&zoneid=1&providetype=0&amt=80&payamt_coins=20&pubacct_payamt_coins=10'
50
+ options = {}
51
+ params.split('&').each do |param|
52
+ param = param.split('=')
53
+ options[param.first] = param.last
54
+ end
55
+ expect = 'GET&%2Fcgi-bin%2Ftemp.py&amt%3D80%26appid%3D33758%26billno%3D%252DAPPDJT18700%252D20120210%252D1428215572%26openid%3Dtest001%26payamt_coins%3D20%26payitem%3D323003%2A8%2A1%26providetype%3D0%26pubacct_payamt_coins%3D10%26token%3D53227955F80B805B50FFB511E5AD51E025360%26ts%3D1328855301%26version%3Dv3%26zoneid%3D1'
56
+ assert_equal expect, @foo.make_callback_source(:GET, '/cgi-bin/temp.py', options)
57
+ end
58
+
59
+ def test_verify_sig
60
+ key = '12345f9a47df4d1eaeb3bad9a7e54321&'
61
+ sig = 'VvKwcaMqUNpKhx0XfCvOqPRiAnU%3D'
62
+ params = 'openid=test001&appid=33758&ts=1328855301&payitem=323003*8*1&token=53227955F80B805B50FFB511E5AD51E025360&billno=-APPDJT18700-20120210-1428215572&version=v3&zoneid=1&providetype=0&amt=80&payamt_coins=20&pubacct_payamt_coins=10'
63
+ options = {}
64
+ params.split('&').each do |param|
65
+ param = param.split('=')
66
+ options[param.first] = param.last
67
+ end
68
+ assert @foo.verify_sig(sig, key, :GET, '/cgi-bin/temp.py', options), 'Verify sig failure'
69
+ end
70
+
47
71
  end
data/test/open_qq_test.rb CHANGED
@@ -13,7 +13,7 @@ class OpenQqTest < MiniTest::Unit::TestCase
13
13
 
14
14
  def teardown
15
15
  # Need setup back for the rest test
16
- OpenQq.setup{|c| c.appid = 12345}
16
+ OpenQq.setup{|c| c.appid = 12345;c.appkey ='228bf094169a40a3bd188ba37ebe8723'}
17
17
  end
18
18
 
19
19
  def test_OpenQq_is_a_module
@@ -74,11 +74,32 @@ class OpenQqTest < MiniTest::Unit::TestCase
74
74
  assert_equal 2001, OpenQq.get('/v3/user/get_info', params).ret
75
75
  end
76
76
 
77
- def test_start_wont_change_get_and_post_method
77
+ def test_call_wont_change_get_and_post_method
78
+ params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
79
+ respond = OpenQq.call('/v3/user/get_info', @options){|r| r.get(params) }
80
+ assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
81
+ assert_equal 'foo', respond.nickname
82
+ end
83
+
84
+ def test_call_has_alise_method_start
78
85
  params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
79
86
  respond = OpenQq.start('/v3/user/get_info', @options){|r| r.get(params) }
80
87
  assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
81
88
  assert_equal 'foo', respond.nickname
82
89
  end
83
90
 
91
+ def test_verify_callback_sig
92
+ key = '12345f9a47df4d1eaeb3bad9a7e54321'
93
+ params = 'openid=test001&appid=33758&ts=1328855301&payitem=323003*8*1&token=53227955F80B805B50FFB511E5AD51E025360&billno=-APPDJT18700-20120210-1428215572&version=v3&zoneid=1&providetype=0&amt=80&payamt_coins=20&pubacct_payamt_coins=10'
94
+ options = {:sig => 'VvKwcaMqUNpKhx0XfCvOqPRiAnU%3D'}
95
+ params.split('&').each do |param|
96
+ param = param.split('=')
97
+ options[param.first] = param.last
98
+ end
99
+ assert OpenQq.verify_callback_sig(:GET, '/cgi-bin/temp.py', options, key), 'Verify sig failure 1'
100
+ OpenQq.setup{|c| c.appkey = key }
101
+ assert OpenQq.verify_callback_sig(:GET, '/cgi-bin/temp.py', options), 'Verify sig failure 2'
102
+ assert OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', options), 'Verify sig failure 3'
103
+ end
104
+
84
105
  end
data/test/test_helper.rb CHANGED
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open_qq
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-09 00:00:00.000000000 Z
12
+ date: 2012-09-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -107,7 +107,7 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
- description: see http://open.qq.com/
110
+ description: 腾讯开放平台ruby版SDK(v3版本)http://open.qq.com/
111
111
  email:
112
112
  - zshuaibin@gmail.com
113
113
  executables: []
@@ -118,6 +118,7 @@ files:
118
118
  - lib/generators/templates/open_qq.yml
119
119
  - lib/open_qq/error.rb
120
120
  - lib/open_qq/gateway.rb
121
+ - lib/open_qq/rails/action_controller.rb
121
122
  - lib/open_qq/railtie.rb
122
123
  - lib/open_qq/request.rb
123
124
  - lib/open_qq/signature.rb