qq_17up 3.0.3
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 +20 -0
- data/README.md +143 -0
- data/Rakefile +19 -0
- data/lib/generators/open_qq/install_generator.rb +15 -0
- data/lib/generators/templates/open_qq.yml +16 -0
- data/lib/open_qq/error.rb +23 -0
- data/lib/open_qq/gateway.rb +105 -0
- data/lib/open_qq/rails/action_controller.rb +31 -0
- data/lib/open_qq/railtie.rb +33 -0
- data/lib/open_qq/request.rb +36 -0
- data/lib/open_qq/signature.rb +43 -0
- data/lib/open_qq/version.rb +9 -0
- data/lib/open_qq.rb +56 -0
- data/test/benchmark.rb +38 -0
- data/test/open_qq/error_test.rb +30 -0
- data/test/open_qq/gateway_test.rb +61 -0
- data/test/open_qq/request_test.rb +34 -0
- data/test/open_qq/signature_test.rb +71 -0
- data/test/open_qq_test.rb +131 -0
- data/test/test_helper.rb +57 -0
- metadata +155 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 zires
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
open_qq
|
2
|
+
=======
|
3
|
+
|
4
|
+
腾讯开放平台ruby版SDK(v3版本)
|
5
|
+
|
6
|
+
## 安装
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem install open_qq
|
10
|
+
```
|
11
|
+
|
12
|
+
## 使用
|
13
|
+
|
14
|
+
使用非常简单,传入应用的`appid`, `appkey`和环境地址`env`
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
require 'rubygems'
|
18
|
+
require 'open_qq'
|
19
|
+
|
20
|
+
OpenQq.setup(:appid => '123', :appkey => '456', :env => 'https://graph.qq.com')
|
21
|
+
|
22
|
+
# 或者https
|
23
|
+
OpenQq.setup(:appid => '123', :appkey => '456', :env => 'https://graph.qq.com')
|
24
|
+
|
25
|
+
# get请求
|
26
|
+
user_info = OpenQq.get('/user/get_info', :openid => '111',:openkey => '222')
|
27
|
+
|
28
|
+
# 或者post请求
|
29
|
+
user_info = OpenQq.post('/user/get_info',:openid => '111',:openkey => '222')
|
30
|
+
|
31
|
+
user_info.ret # => 0
|
32
|
+
user_info.nickname # => 'foo'
|
33
|
+
```
|
34
|
+
|
35
|
+
如果你只想原样返回未加工的数据,使用`raw => true`
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
user_info = OpenQq.post('/user/get_info', {:openid => '111', :openkey => '222'}, :raw => true)
|
39
|
+
puts user_info
|
40
|
+
# => '{ "ret": 0, "is_lost": 0, "nickname": "foo" }'
|
41
|
+
```
|
42
|
+
|
43
|
+
如果你不想使用全局的配置
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
options = {:appid => 'newappid', :appkey => 'newappkey', :env => 'https://graph.qq.com'}
|
47
|
+
|
48
|
+
user_info = OpenQq.call('/user/get_info', options) do |request|
|
49
|
+
|
50
|
+
request.get {:openid => '111',:openkey => '222'}
|
51
|
+
|
52
|
+
#或者
|
53
|
+
request.post {:openid => '111',:openkey => '222'}
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
user_info.nickname
|
58
|
+
# => 'foo'
|
59
|
+
```
|
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
|
+
|
84
|
+
## 在rails中使用
|
85
|
+
|
86
|
+
首先在Gemfile中添加
|
87
|
+
```
|
88
|
+
gem 'open_qq'
|
89
|
+
```
|
90
|
+
|
91
|
+
执行`bundle install`
|
92
|
+
|
93
|
+
在config目录下生成配置文件config/open_qq.yml
|
94
|
+
```
|
95
|
+
rails g open_qq:install
|
96
|
+
```
|
97
|
+
|
98
|
+
在配置文件中填入appid, appkey和env的值,启动服务后全局都可以使用,例如:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
class OpenQqController < ApplicationController
|
102
|
+
|
103
|
+
# 假设这里是应用的入口
|
104
|
+
def index
|
105
|
+
user_info = OpenQq.post('/user/get_info', params.slice!(:action, :controller))
|
106
|
+
if user_info.ret == 0
|
107
|
+
# do something
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
```
|
114
|
+
|
115
|
+
## 注意和说明
|
116
|
+
|
117
|
+
* 当传入的format为xml时,不会对返回的结果做处理,直接字符串返回
|
118
|
+
* 当传入的format不为xml时,会使用`JSON#parse`转换成hash,并且使用[OpenStruct](http://www.ruby-doc.org/stdlib-1.8.7/libdoc/ostruct/rdoc/OpenStruct.html, 'OpenStruct')封装
|
119
|
+
* 当ret返回`2001`时,是由本api抛出
|
120
|
+
* 关于*signature verification failed*,先仔细对照[文档](http://wiki.open.qq.com/wiki/%E8%85%BE%E8%AE%AF%E5%BC%80%E6%94%BE%E5%B9%B3%E5%8F%B0%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%94%E7%94%A8%E7%AD%BE%E5%90%8D%E5%8F%82%E6%95%B0sig%E7%9A%84%E8%AF%B4%E6%98%8E#.E4.B8.BA.E4.BB.80.E4.B9.88.E6.80.BB.E6.98.AF.E8.BF.94.E5.9B.9E.E2.80.9C-5.EF.BC.9Asignature_verification_failed.E2.80.9D.EF.BC.9F)
|
121
|
+
|
122
|
+
```
|
123
|
+
可以通过联调工具看下签名是否一致
|
124
|
+
|
125
|
+
opts = {:openid => '1111',:openkey => '2222',:pf => 'pengyou'}
|
126
|
+
sig = OpenQq.wrap(:post, '/v3/user/get_info', opts)['sig']
|
127
|
+
|
128
|
+
puts sig # 与联调结果比对
|
129
|
+
|
130
|
+
```
|
131
|
+
|
132
|
+
* 如果不想使用open_qq.yml,只要在使用前全局配置好`OpenQq`即可
|
133
|
+
* 测试基本覆盖,可以下载下来执行`rake`
|
134
|
+
* bug反馈[Issue](https://github.com/zires/open_qq/issues)
|
135
|
+
|
136
|
+
## Changelog
|
137
|
+
|
138
|
+
* 2012/09/11
|
139
|
+
增加对https的支持
|
140
|
+
支持支付回调协议签名验证
|
141
|
+
|
142
|
+
|
143
|
+
## This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'yard'
|
9
|
+
YARD::Rake::YardocTask.new
|
10
|
+
|
11
|
+
require 'rake/testtask'
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'lib'
|
14
|
+
t.libs << 'test'
|
15
|
+
t.pattern = 'test/**/*_test.rb'
|
16
|
+
t.verbose = true
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => :test
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module OpenQq
|
3
|
+
module Generators
|
4
|
+
class InstallGenerator < ::Rails::Generators::Base
|
5
|
+
# Create open_qq.yml under config/initializers/
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
|
8
|
+
desc "Creates a ThemePark initializer file."
|
9
|
+
def copy_initializer
|
10
|
+
template "open_qq.yml", "config/open_qq.yml"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# open_qq configruation.
|
2
|
+
# see http://open.qq.com/
|
3
|
+
development:
|
4
|
+
appid:
|
5
|
+
appkey:
|
6
|
+
env: http://119.147.19.43
|
7
|
+
|
8
|
+
test:
|
9
|
+
appid:
|
10
|
+
appkey:
|
11
|
+
env: http://119.147.19.43
|
12
|
+
|
13
|
+
production:
|
14
|
+
appid:
|
15
|
+
appkey:
|
16
|
+
env: http://openapi.tencentyun.com
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
module OpenQq
|
7
|
+
# behavior response to body method
|
8
|
+
class Error
|
9
|
+
|
10
|
+
def initialize(ret, msg, format = 'json')
|
11
|
+
@ret, @msg, @format = ret, msg, format.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def body
|
15
|
+
if @format == 'xml'
|
16
|
+
%Q(<?xml version="1.0" encoding="UTF-8"?><data><ret>#{@ret}</ret><msg>#{@msg}</msg></data>)
|
17
|
+
else
|
18
|
+
{:ret => @ret, :msg => @msg}.to_json
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
require 'open_qq/signature'
|
7
|
+
require 'open_qq/error'
|
8
|
+
require 'ostruct'
|
9
|
+
require 'net/https'
|
10
|
+
|
11
|
+
module OpenQq
|
12
|
+
class Gateway
|
13
|
+
|
14
|
+
OPEN_HTTP_TRANSLATE_ERROR = 2001
|
15
|
+
|
16
|
+
attr_accessor :appid, :appkey, :env
|
17
|
+
|
18
|
+
# @param [String] appid
|
19
|
+
# @param [String] appkey
|
20
|
+
# @param [String] env 调用的环境地址
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# OpenQq::Gateway.new('1111', '2222', 'http://119.147.19.43')
|
24
|
+
# OpenQq::Gateway.new('1111', '2222', 'https://openapi.tencentyun.com')
|
25
|
+
def initialize(appid, appkey, env)
|
26
|
+
@appid = appid
|
27
|
+
@appkey = appkey
|
28
|
+
self.env = env
|
29
|
+
end
|
30
|
+
|
31
|
+
# override
|
32
|
+
def env=(env)
|
33
|
+
@env = env
|
34
|
+
uri = URI.parse(env)
|
35
|
+
@http = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
# HTTPS
|
37
|
+
if uri.scheme == "https"
|
38
|
+
@http.use_ssl = true
|
39
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param [String] url which api you want to call
|
44
|
+
# @param [Hash] params extra params attach to the url
|
45
|
+
# @param [options] options
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# gateway = OpenQq::Gateway.new('1111', '2222', 'http://119.147.19.43')
|
49
|
+
# user_info = gateway.get('/v3/user/get_info', {:openid => '11'} )
|
50
|
+
# user_info.nickname # => foo
|
51
|
+
#
|
52
|
+
# @example available option
|
53
|
+
# :raw => true will raw the output
|
54
|
+
# user_info = gateway.get('/v3/user/get_info', {:openid => '11'}, {:raw => true} )
|
55
|
+
# user_info.nickname # => '{"nickname":"foo"}'
|
56
|
+
#
|
57
|
+
# @return (see #call)
|
58
|
+
def get(url, params = {}, options = {})
|
59
|
+
parsed_params = Gateway.parsed_params( wrap(:get, url, params) )
|
60
|
+
get_request = Net::HTTP::Get.new("#{url}?#{parsed_params}")
|
61
|
+
self.call( get_request, options.merge(:format => params[:format]) )
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param (see #get)
|
65
|
+
#
|
66
|
+
# @return (see #call)
|
67
|
+
def post(url, params = {}, options = {})
|
68
|
+
post_request = Net::HTTP::Post.new(url)
|
69
|
+
post_request.body = Gateway.parsed_params( wrap(:post, url, params) )
|
70
|
+
post_request.content_type = 'application/x-www-form-urlencoded'
|
71
|
+
self.call( post_request, options.merge(:format => params[:format]) )
|
72
|
+
end
|
73
|
+
|
74
|
+
# wrap `http_method`, `url`, `params` together
|
75
|
+
def wrap(http_method, url, params)
|
76
|
+
params = params.merge(:appid => @appid)
|
77
|
+
params[:sig] = Gateway.signature( "#{@appkey}&", Gateway.make_source(http_method.to_s.upcase, url, params) )
|
78
|
+
params
|
79
|
+
end
|
80
|
+
|
81
|
+
class << self
|
82
|
+
include Signature
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
# Call the request and format the output
|
88
|
+
# @param [Net::HTTP::Request] request be called
|
89
|
+
# @param [Hash] options some option used to format output
|
90
|
+
#
|
91
|
+
# @return [String, Object] unformatted string result or parsed OpenStruct instance
|
92
|
+
def call(request, options)
|
93
|
+
response = begin
|
94
|
+
@http.request(request)
|
95
|
+
rescue Exception => e
|
96
|
+
Error.new(OPEN_HTTP_TRANSLATE_ERROR, "#{e.message}\n#{e.backtrace.inspect}", options[:format])
|
97
|
+
end
|
98
|
+
|
99
|
+
return response.body if options[:raw] || options[:format] == 'xml'
|
100
|
+
|
101
|
+
OpenStruct.new( JSON.parse(response.body) )
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
module OpenQq
|
7
|
+
module Rails
|
8
|
+
module ActionController
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
private
|
12
|
+
# @example
|
13
|
+
# class OpenQqController < ApplicationController
|
14
|
+
# include OpenQq::Rails::ActionController
|
15
|
+
#
|
16
|
+
# def index
|
17
|
+
# if verify_callback_sig
|
18
|
+
# ...do something
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# @return [Boolean]
|
23
|
+
def verify_callback_sig(key = nil)
|
24
|
+
logger.debug "Appkey: #{key ||= OpenQq.appkey} method: #{request.method} url: #{request.fullpath.split("?")[0]}"
|
25
|
+
logger.debug "params: #{params.slice!(:action, :controller).inspect}"
|
26
|
+
OpenQq.verify_callback_sig(request.method, request.fullpath.split("?")[0], params.slice!(:action, :controller), key)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
module OpenQq
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
|
9
|
+
generators do
|
10
|
+
require "generators/open_qq/install_generator"
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer "open_qq.setup" do
|
14
|
+
config_file = Rails.root.join("config", "open_qq.yml")
|
15
|
+
if config_file.file?
|
16
|
+
begin
|
17
|
+
options = YAML.load_file(config_file)[Rails.env]
|
18
|
+
OpenQq.setup(options)
|
19
|
+
rescue Exception => e
|
20
|
+
puts "There is a configuration error with the current open_qq.yml"
|
21
|
+
puts e.message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
initializer "load open_qq controller method" do
|
27
|
+
ActiveSupport.on_load(:action_controller) do
|
28
|
+
require 'open_qq/rails/action_controller'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
require 'open_qq/gateway'
|
7
|
+
|
8
|
+
module OpenQq
|
9
|
+
class Request < Gateway
|
10
|
+
|
11
|
+
attr_accessor :url, :options
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
options = options.dup
|
15
|
+
appid = options.delete(:appid)
|
16
|
+
appkey = options.delete(:appkey)
|
17
|
+
env = options.delete(:env)
|
18
|
+
@url = options.delete(:url)
|
19
|
+
@options = options || {}
|
20
|
+
super(appid, appkey, env)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see Gateway#get
|
24
|
+
def get(params = {}, options = nil)
|
25
|
+
options ||= @options
|
26
|
+
super(@url, params, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @see Gateway#get
|
30
|
+
def post(params = {}, options = nil)
|
31
|
+
options ||= @options
|
32
|
+
super(@url, params, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
require 'base64'
|
7
|
+
require 'openssl'
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
module OpenQq
|
11
|
+
module Signature
|
12
|
+
|
13
|
+
def signature(key, source)
|
14
|
+
Base64.encode64( OpenSSL::HMAC.digest('sha1', key, source) ).rstrip
|
15
|
+
end
|
16
|
+
|
17
|
+
def url_escape(url)
|
18
|
+
URI.escape(url, /[^\.\-_\da-zA-Z]/)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parsed_params(params)
|
22
|
+
params.map{|k,v| "#{url_escape(k.to_s)}=#{url_escape(v.to_s)}"}.join('&')
|
23
|
+
end
|
24
|
+
|
25
|
+
def make_source(http_method, url, params)
|
26
|
+
escape_opt = url_escape( params.sort_by{|k,v| k.to_s}.map{|kv| "#{kv.first}=#{kv.last}" }.join('&') )
|
27
|
+
"#{http_method}&#{url_escape(url)}&#{escape_opt}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def make_callback_source(http_method, url, params)
|
31
|
+
escape_opt = params.sort_by{|k,v| k.to_s}.map do |kv|
|
32
|
+
value = URI.escape(kv.last, /[^0-9a-zA-Z!*()]/)
|
33
|
+
"#{kv.first}=#{value}"
|
34
|
+
end.join('&')
|
35
|
+
"#{http_method}&#{url_escape(url)}&#{url_escape(escape_opt)}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def verify_sig(sig, key, http_method, url, params)
|
39
|
+
sig == url_escape( signature(key, make_callback_source(http_method, url, params)) )
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
data/lib/open_qq.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# --
|
4
|
+
# @author zires
|
5
|
+
#
|
6
|
+
require 'rubygems' if RUBY_VERSION < '1.9'
|
7
|
+
require 'json'
|
8
|
+
require 'open_qq/request'
|
9
|
+
require 'active_support/core_ext/module/delegation'
|
10
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
11
|
+
|
12
|
+
module OpenQq
|
13
|
+
class << self
|
14
|
+
|
15
|
+
def setup(options = {})
|
16
|
+
options = options.with_indifferent_access
|
17
|
+
@gateway ||= OpenQq::Gateway.new(options[:appid], options[:appkey], options[:env])
|
18
|
+
yield @gateway if block_given?
|
19
|
+
end
|
20
|
+
|
21
|
+
# @see Gateway#get
|
22
|
+
delegate :appid, :appkey, :env, :get, :post, :wrap, :to => :@gateway
|
23
|
+
|
24
|
+
# @example
|
25
|
+
# OpenQq.call('/v3/user/get_info', { :appid => 123 }) do |request|
|
26
|
+
# request.get({:openid => '111'})
|
27
|
+
# end
|
28
|
+
def call(url, options)
|
29
|
+
request = OpenQq::Request.new(options.with_indifferent_access)
|
30
|
+
if block_given?
|
31
|
+
yield request
|
32
|
+
else
|
33
|
+
request
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
alias start call
|
38
|
+
|
39
|
+
# @example
|
40
|
+
# params = {openid: 'test001', appid: '33758', sig: 'VvKwcaMqUNpKhx0XfCvOqPRiAnU%3D'}
|
41
|
+
# OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', params)
|
42
|
+
# #diffenert key
|
43
|
+
# OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', params, 'xxxxxx')
|
44
|
+
#
|
45
|
+
# @return [Boolean]
|
46
|
+
def verify_callback_sig(http_method, url, params, key = nil)
|
47
|
+
key ||= appkey
|
48
|
+
params = params.dup
|
49
|
+
sig = params.delete('sig') || params.delete(:sig)
|
50
|
+
Gateway.verify_sig(sig, "#{key}&", http_method.to_s.upcase, url, params)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
require 'open_qq/railtie' if defined?(Rails)
|
data/test/benchmark.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'benchmark'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
n = 500000
|
7
|
+
@os = { :ret => 0,
|
8
|
+
:is_lost => 0,
|
9
|
+
:nickname => 'Peter',
|
10
|
+
:gender => 'boy',
|
11
|
+
:country => 'country',
|
12
|
+
:province => 'province',
|
13
|
+
:city => 'city',
|
14
|
+
:figureurl => 'http://imgcache.qq.com/qzone_v4/client/userinfo_icon/1236153759.gif',
|
15
|
+
:is_yellow_vip => 1,
|
16
|
+
:is_yellow_year_vip => 1,
|
17
|
+
:yellow_vip_level => 7
|
18
|
+
}
|
19
|
+
|
20
|
+
@os_obj = OpenStruct.new(@os)
|
21
|
+
|
22
|
+
Benchmark.bm do |x|
|
23
|
+
|
24
|
+
x.report { for i in 1..n; @os_obj.nickname; end }
|
25
|
+
x.report { for i in 1..n; @os['nickname']; end }
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
@os_json = @os.to_json
|
30
|
+
|
31
|
+
m = 10
|
32
|
+
|
33
|
+
Benchmark.bm do |x|
|
34
|
+
|
35
|
+
x.report { for i in 1..m; JSON.parse(@os_json); end }
|
36
|
+
x.report { for i in 1..m; OpenStruct.new( JSON.parse(@os_json) ); end }
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OpenQq::ErrorTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def test_symbol_format
|
6
|
+
error = OpenQq::Error.new(100, 'error!', :json)
|
7
|
+
assert_equal '{"ret":100,"msg":"error!"}', error.body
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_json_format
|
11
|
+
error = OpenQq::Error.new(100, 'error!', 'json')
|
12
|
+
assert_equal '{"ret":100,"msg":"error!"}', error.body
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_xml_format
|
16
|
+
error = OpenQq::Error.new(100, 'error!', 'xml')
|
17
|
+
assert_equal '<?xml version="1.0" encoding="UTF-8"?><data><ret>100</ret><msg>error!</msg></data>', error.body
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_no_format
|
21
|
+
error = OpenQq::Error.new(100, 'error!')
|
22
|
+
assert_equal '{"ret":100,"msg":"error!"}', error.body
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_unsupported_format
|
26
|
+
error = OpenQq::Error.new(100, 'error!', :ruby)
|
27
|
+
assert_equal '{"ret":100,"msg":"error!"}', error.body
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OpenQq::GatewayTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
# 测试用例的签名通过腾讯联调工具产生 http://open.qq.com/tools
|
7
|
+
@appid = 12345
|
8
|
+
@appkey = '228bf094169a40a3bd188ba37ebe8723'
|
9
|
+
@env = 'http://119.147.19.43'
|
10
|
+
@gateway = OpenQq::Gateway.new(@appid, @appkey, @env)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_call_get_request_without_params
|
14
|
+
assert_equal 'foo', @gateway.get('/v3/user/get_info').nickname
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_call_get_request_with_params
|
18
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
|
19
|
+
assert_equal 'foo', @gateway.get('/v3/user/get_info', params).nickname
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_call_get_request_with_xml_format
|
23
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'xml' }
|
24
|
+
assert_equal '<?xml version="1.0" encoding="UTF-8"?>', @gateway.get('/v3/user/get_info', params)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_call_get_request_without_format_param
|
28
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou }
|
29
|
+
assert_equal 'foo', @gateway.get('/v3/user/get_info', params).nickname
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_call_get_request_with_unknow_format_param
|
33
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'ruby'}
|
34
|
+
assert_equal 'foo', @gateway.get('/v3/user/get_info', params).nickname
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_call_post_request
|
38
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
39
|
+
assert_equal 'foo', @gateway.post('/v3/user/get_info', params).nickname
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_call_post_request_with_raw_output
|
43
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
44
|
+
assert_equal '{ "ret": 0, "is_lost": 0, "nickname": "foo" }', @gateway.post('/v3/user/get_info', params, :raw => true)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_open_http_translate_error
|
48
|
+
gateway = OpenQq::Gateway.new('123456', @appkey, @env)
|
49
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
50
|
+
assert_equal 2001, gateway.get('/v3/user/get_info', params).ret
|
51
|
+
end
|
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
|
+
|
61
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OpenQq::RequestTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
# 测试用例的签名通过腾讯联调工具产生 http://open.qq.com/tools
|
7
|
+
options = { :appid => 12345,
|
8
|
+
:appkey => '228bf094169a40a3bd188ba37ebe8723',
|
9
|
+
:env => 'http://119.147.19.43',
|
10
|
+
:url => '/v3/user/get_info',
|
11
|
+
}
|
12
|
+
@request = OpenQq::Request.new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_call_get_request_without_params
|
16
|
+
assert_equal 'foo', @request.get.nickname
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_call_get_request_with_params
|
20
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
|
21
|
+
assert_equal 'foo', @request.get(params).nickname
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_call_post_request
|
25
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
26
|
+
assert_equal 'foo', @request.post(params).nickname
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_call_post_request_with_raw_output
|
30
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
31
|
+
assert_equal '{ "ret": 0, "is_lost": 0, "nickname": "foo" }', @request.post(params, :raw => true)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Foo
|
4
|
+
include OpenQq::Signature
|
5
|
+
end
|
6
|
+
|
7
|
+
class OpenQq::SignatureTest < MiniTest::Unit::TestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@foo = Foo.new
|
11
|
+
# 测试数据是通过腾讯开放平台联调工具集生成
|
12
|
+
# 详见:http://open.qq.com/tools
|
13
|
+
@url = '/v3/user/get_info'
|
14
|
+
@http_method = :GET
|
15
|
+
@appkey = '228bf094169a40a3bd188ba37ebe8723'
|
16
|
+
|
17
|
+
#openid=11111111111111111&openkey=2222222222222222&pf=qzone&appid=123456&format=json&userip=10.0.0.1
|
18
|
+
@options = { :openid => '11111111111111111', :openkey => '2222222222222222',
|
19
|
+
'appid' => '123456', 'pf' => 'qzone',
|
20
|
+
:userip => '10.0.0.1', :format => :json
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_signature_is_a_module
|
25
|
+
assert_equal Module, ::OpenQq::Signature.class
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_make_source
|
29
|
+
expect_source = 'GET&%2Fv3%2Fuser%2Fget_info&appid%3D123456%26format%3Djson%26openid%3D11111111111111111%26openkey%3D2222222222222222%26pf%3Dqzone%26userip%3D10.0.0.1'
|
30
|
+
assert_equal expect_source, @foo.make_source(@http_method, @url, @options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_parsed_params
|
34
|
+
opt = { '/ +=&' => '123@*!' }
|
35
|
+
assert_equal( "%2F%20%2B%3D%26=123%40%2A%21", @foo.parsed_params(opt) )
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_url_escape
|
39
|
+
assert_equal 'o%2FnGo1QkVEiiN6Bqn%2FfRJtEJwLc%3D', @foo.url_escape('o/nGo1QkVEiiN6Bqn/fRJtEJwLc=')
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_signature
|
43
|
+
source = @foo.make_source(@http_method, @url, @options)
|
44
|
+
assert_equal( 'o/nGo1QkVEiiN6Bqn/fRJtEJwLc=', @foo.signature("#{@appkey}&", source) )
|
45
|
+
end
|
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
|
+
|
71
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class OpenQqTest < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@options = { :appid => 12345,
|
8
|
+
:appkey => '228bf094169a40a3bd188ba37ebe8723',
|
9
|
+
:env => 'http://119.147.19.43',
|
10
|
+
:url => '/v3/user/get_info',
|
11
|
+
}
|
12
|
+
OpenQq.setup(@options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
# Need setup back for the rest test
|
17
|
+
OpenQq.setup{|c|
|
18
|
+
c.appid = 12345
|
19
|
+
c.appkey ='228bf094169a40a3bd188ba37ebe8723'
|
20
|
+
c.env ='http://119.147.19.43'
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_OpenQq_is_a_module
|
25
|
+
assert_kind_of Module, OpenQq
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_setup
|
29
|
+
assert_equal 12345, OpenQq.appid
|
30
|
+
assert_equal '228bf094169a40a3bd188ba37ebe8723', OpenQq.appkey
|
31
|
+
assert_equal 'http://119.147.19.43', OpenQq.env
|
32
|
+
OpenQq.setup do |config|
|
33
|
+
config.appid = 'foo'
|
34
|
+
end
|
35
|
+
assert_equal 'foo', OpenQq.appid
|
36
|
+
end
|
37
|
+
|
38
|
+
# Copy from gateway_test
|
39
|
+
|
40
|
+
def test_call_get_request_without_params
|
41
|
+
assert_equal 'foo', OpenQq.get('/v3/user/get_info').nickname
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_call_get_request_with_params
|
45
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
|
46
|
+
assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_call_get_request_with_xml_format
|
50
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'xml' }
|
51
|
+
assert_equal '<?xml version="1.0" encoding="UTF-8"?>', OpenQq.get('/v3/user/get_info', params)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_call_get_request_without_format_param
|
55
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou }
|
56
|
+
assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_call_get_request_with_unknow_format_param
|
60
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'ruby'}
|
61
|
+
assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_call_post_request
|
65
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
66
|
+
assert_equal 'foo', OpenQq.post('/v3/user/get_info', params).nickname
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_call_post_request_with_raw_output
|
70
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
71
|
+
assert_equal '{ "ret": 0, "is_lost": 0, "nickname": "foo" }', OpenQq.post('/v3/user/get_info', params, :raw => true)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_open_http_translate_error
|
75
|
+
OpenQq.setup do |config|
|
76
|
+
config.appid = '123456'
|
77
|
+
end
|
78
|
+
params = {:openid => '1111', :openkey => '2222', :pf => 'pengyou'}
|
79
|
+
assert_equal 2001, OpenQq.get('/v3/user/get_info', params).ret
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_call_wont_change_get_and_post_method
|
83
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
|
84
|
+
respond = OpenQq.call('/v3/user/get_info', @options){|r| r.get(params) }
|
85
|
+
assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
|
86
|
+
assert_equal 'foo', respond.nickname
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_call_has_alise_method_start
|
90
|
+
params = { :openid => 1111, 'openkey' => '2222', :pf => :pengyou, :format => 'json' }
|
91
|
+
respond = OpenQq.start('/v3/user/get_info', @options){|r| r.get(params) }
|
92
|
+
assert_equal 'foo', OpenQq.get('/v3/user/get_info', params).nickname
|
93
|
+
assert_equal 'foo', respond.nickname
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_verify_callback_sig
|
97
|
+
key = '12345f9a47df4d1eaeb3bad9a7e54321'
|
98
|
+
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'
|
99
|
+
options = {:sig => 'VvKwcaMqUNpKhx0XfCvOqPRiAnU%3D'}
|
100
|
+
params.split('&').each do |param|
|
101
|
+
param = param.split('=')
|
102
|
+
options[param.first] = param.last
|
103
|
+
end
|
104
|
+
assert OpenQq.verify_callback_sig(:GET, '/cgi-bin/temp.py', options, key), 'Verify sig failure 1'
|
105
|
+
OpenQq.setup{|c| c.appkey = key }
|
106
|
+
assert OpenQq.verify_callback_sig(:GET, '/cgi-bin/temp.py', options), 'Verify sig failure 2'
|
107
|
+
assert OpenQq.verify_callback_sig(:get, '/cgi-bin/temp.py', options), 'Verify sig failure 3'
|
108
|
+
end
|
109
|
+
|
110
|
+
#http://wiki.open.qq.com/wiki/v3/pay/buy_goods
|
111
|
+
def test_buy_goods
|
112
|
+
options = { :appid => 600,
|
113
|
+
:appkey => '12345f9a47df4d1eaeb3bad9a7e54321',
|
114
|
+
:env => 'https://119.147.19.43'
|
115
|
+
}
|
116
|
+
params = { :amt => 4,:appmode => 1,:format => 'json',:goodsmeta => '道具*测试描述信息!!!',
|
117
|
+
:goodsurl => 'http://qzonestyle.gtimg.cn/qzonestyle/act/qzone_app_img/app613_613_75.png',
|
118
|
+
:openid => '0000000000000000000000000E111111',
|
119
|
+
:openkey => '1111806DC5D1C52150CF405E42222222',
|
120
|
+
:payitem => '50005*4*1',
|
121
|
+
:pf => 'qzone',
|
122
|
+
:pfkey => '1B59A5C3D77C7C56D7AFC3E2C823105D',
|
123
|
+
:ts => '1333674935'
|
124
|
+
}
|
125
|
+
sig = 'fVcr1Imq8FjJZgf3h24haUE18rA='
|
126
|
+
OpenQq.call('/v3/pay/buy_goods', options) do |request|
|
127
|
+
assert_equal sig, request.wrap(:get, '/v3/pay/buy_goods', params)[:sig]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
begin
|
2
|
+
Bundler.setup(:default, :development)
|
3
|
+
rescue Bundler::BundlerError => e
|
4
|
+
$stderr.puts e.message
|
5
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
6
|
+
exit e.status_code
|
7
|
+
end
|
8
|
+
|
9
|
+
require "test/unit"
|
10
|
+
require 'minitest/autorun'
|
11
|
+
|
12
|
+
# Enable turn if it is available
|
13
|
+
begin
|
14
|
+
require 'turn'
|
15
|
+
rescue LoadError
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'open_qq'
|
19
|
+
|
20
|
+
# fake qq response
|
21
|
+
require 'fakeweb'
|
22
|
+
|
23
|
+
# 测试用例的签名通过腾讯联调工具产生 http://open.qq.com/tools
|
24
|
+
# get
|
25
|
+
FakeWeb.register_uri(:get, "http://119.147.19.43/v3/user/get_info?appid=12345&sig=CRkzTEcrnfRkNMt9LnVtHjGTocI%3D",
|
26
|
+
:body => '{ "ret": 0, "is_lost": 0, "nickname": "foo" }')
|
27
|
+
|
28
|
+
# get with json format
|
29
|
+
FakeWeb.register_uri(:get,
|
30
|
+
"http://119.147.19.43/v3/user/get_info?openid=1111&openkey=2222&pf=pengyou&appid=12345&format=json&sig=qjReS%2Fg%2FGM9qStD9gmYNI%2B65nWo%3D",
|
31
|
+
:body => '{ "ret": 0, "is_lost": 0, "nickname": "foo" }')
|
32
|
+
|
33
|
+
# get without format
|
34
|
+
FakeWeb.register_uri(:get,
|
35
|
+
"http://119.147.19.43/v3/user/get_info?openid=1111&openkey=2222&pf=pengyou&appid=12345&sig=CtBQwNTqB24SnqMnWrSJyh4atg8%3D",
|
36
|
+
:body => '{ "ret": 0, "is_lost": 0, "nickname": "foo" }')
|
37
|
+
|
38
|
+
# get with xml format
|
39
|
+
FakeWeb.register_uri(:get,
|
40
|
+
"http://119.147.19.43/v3/user/get_info?openid=1111&openkey=2222&pf=pengyou&appid=12345&format=xml&sig=t4WtmJ2pG6RDgGAOfiLWMf8E4%2FM%3D",
|
41
|
+
:body => '<?xml version="1.0" encoding="UTF-8"?>')
|
42
|
+
|
43
|
+
# get with unsupported format
|
44
|
+
FakeWeb.register_uri(:get,
|
45
|
+
"http://119.147.19.43/v3/user/get_info?openid=1111&openkey=2222&pf=pengyou&appid=12345&format=ruby&sig=egeboQvMq5HbfntN5jdwbQaB6go%3D",
|
46
|
+
:body => '{ "ret": 0, "is_lost": 0, "nickname": "foo" }')
|
47
|
+
|
48
|
+
# post without set format
|
49
|
+
FakeWeb.register_uri(:post,
|
50
|
+
"http://119.147.19.43/v3/user/get_info",
|
51
|
+
:parameters => {:openid => '1111', :openkey => '2222', :pf => 'pengyou', :appid => '12345', :sig => 'CtBQwNTqB24SnqMnWrSJyh4atg8%3D'},
|
52
|
+
:body => '{ "ret": 0, "is_lost": 0, "nickname": "foo" }')
|
53
|
+
|
54
|
+
# http translate error
|
55
|
+
FakeWeb.register_uri(:get,
|
56
|
+
"http://119.147.19.43/v3/user/get_info?openid=1111&openkey=2222&pf=pengyou&appid=123456&sig=b67OwPW%2BfHFsKwgpu1b82k4dHZU%3D",
|
57
|
+
:exception => Net::HTTPError)
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qq_17up
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 3
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
version: 3.0.3
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- veggie
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2013-09-07 00:00:00 +08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: activesupport
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: turn
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :development
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: minitest
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :development
|
55
|
+
version_requirements: *id003
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: yard
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id004
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rake
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
type: :development
|
79
|
+
version_requirements: *id005
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: fakeweb
|
82
|
+
prerelease: false
|
83
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
type: :development
|
91
|
+
version_requirements: *id006
|
92
|
+
description: !binary |
|
93
|
+
6IW+6K6v5byA5pS+5bmz5Y+wcnVieeeJiFNESyBodHRwOi8vb3Blbi5xcS5j
|
94
|
+
b20v
|
95
|
+
|
96
|
+
email:
|
97
|
+
- kkxlkkxllb@gmail.com
|
98
|
+
executables: []
|
99
|
+
|
100
|
+
extensions: []
|
101
|
+
|
102
|
+
extra_rdoc_files: []
|
103
|
+
|
104
|
+
files:
|
105
|
+
- lib/generators/open_qq/install_generator.rb
|
106
|
+
- lib/generators/templates/open_qq.yml
|
107
|
+
- lib/open_qq/error.rb
|
108
|
+
- lib/open_qq/gateway.rb
|
109
|
+
- lib/open_qq/rails/action_controller.rb
|
110
|
+
- lib/open_qq/railtie.rb
|
111
|
+
- lib/open_qq/request.rb
|
112
|
+
- lib/open_qq/signature.rb
|
113
|
+
- lib/open_qq/version.rb
|
114
|
+
- lib/open_qq.rb
|
115
|
+
- MIT-LICENSE
|
116
|
+
- Rakefile
|
117
|
+
- README.md
|
118
|
+
has_rdoc: true
|
119
|
+
homepage: https://github.com/17up/qq_17up
|
120
|
+
licenses: []
|
121
|
+
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
version: "0"
|
141
|
+
requirements: []
|
142
|
+
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 1.3.6
|
145
|
+
signing_key:
|
146
|
+
specification_version: 3
|
147
|
+
summary: open qq ruby sdk
|
148
|
+
test_files:
|
149
|
+
- test/benchmark.rb
|
150
|
+
- test/open_qq/error_test.rb
|
151
|
+
- test/open_qq/gateway_test.rb
|
152
|
+
- test/open_qq/request_test.rb
|
153
|
+
- test/open_qq/signature_test.rb
|
154
|
+
- test/open_qq_test.rb
|
155
|
+
- test/test_helper.rb
|