open_qq 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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