youzan_api 0.0.1
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 +7 -0
- data/lib/youzan/token_client.rb +102 -0
- data/lib/youzan_api.rb +113 -0
- metadata +119 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 41788662990b40cc7eb653c9b57bf2f376d0c9cc
|
|
4
|
+
data.tar.gz: 7f8584abfc657e18e3e23ba1047a27febaf9d262
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e614029c04e7ce32293641c1557cccdb7bd4281fd84982d22cfe3a8852fcd6ae2ab1e34b62a20e4edb566d709d622a50a2f95345ae9019c632380c016f14a574
|
|
7
|
+
data.tar.gz: 76b78ec5952e4f3cf6647cd2249692cce0ea3de216c4d83a8a314357145fcfc0066da592869e2caec54893e54d276bf11a8046349e3caf1900867c3184cfbb84
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'byebug'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'redis'
|
|
5
|
+
require 'dotenv/load'
|
|
6
|
+
|
|
7
|
+
module Youzan
|
|
8
|
+
|
|
9
|
+
CLIENT_ID = ENV['YOUZAN_CLIENT_ID']
|
|
10
|
+
CLIENT_SECRET = ENV['YOUZAN_CLIENT_SECRET']
|
|
11
|
+
KDT_ID = ENV['KDT_ID']
|
|
12
|
+
GRANT_TYPE = 'silent'
|
|
13
|
+
|
|
14
|
+
class InvalidTokenParameter < RuntimeError; end
|
|
15
|
+
|
|
16
|
+
def self.redis
|
|
17
|
+
# You can reuse existing redis connection and remove this method if require
|
|
18
|
+
$redis = Redis.new(host: ENV['REDIS_HOST'], port: 6379, db: 2) # use global redis
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class TokenClient
|
|
22
|
+
|
|
23
|
+
attr_reader :client, :token_life_in_seconds, :got_token_at
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
@random_generator = Random.new
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def access_token
|
|
30
|
+
read_token_from_store
|
|
31
|
+
refresh if remain_life_seconds < @random_generator.rand(60..5 * 60)
|
|
32
|
+
@access_token
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def connection
|
|
38
|
+
@client ||= Faraday.new
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def read_token_from_store
|
|
42
|
+
td = read_token
|
|
43
|
+
@token_life_in_seconds = td.fetch('expires_in').to_i
|
|
44
|
+
@got_token_at = td.fetch('got_token_at').to_i
|
|
45
|
+
@access_token = td.fetch('access_token') # return access_token same time
|
|
46
|
+
rescue JSON::ParserError, Errno::ENOENT, KeyError, TypeError
|
|
47
|
+
refresh
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def read_token
|
|
51
|
+
JSON.parse(Youzan.redis.get(youzan_token_key)) || {}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def remain_life_seconds
|
|
55
|
+
token_life_in_seconds - (Time.now.to_i - got_token_at)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def refresh
|
|
59
|
+
data = fetch_access_token
|
|
60
|
+
write_token_to_store(data)
|
|
61
|
+
read_token_from_store
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def fetch_access_token
|
|
65
|
+
res = generate_oauth_token
|
|
66
|
+
JSON.parse(res.body)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def generate_oauth_token
|
|
70
|
+
connection.post do |req|
|
|
71
|
+
req.url oauth_token_url
|
|
72
|
+
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
73
|
+
req.body = {
|
|
74
|
+
'client_id' => CLIENT_ID, 'client_secret' => CLIENT_SECRET,
|
|
75
|
+
'grant_type' => GRANT_TYPE, 'kdt_id' => KDT_ID
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def oauth_token_url
|
|
81
|
+
Youzan::Api::BASE_API_URL + '/oauth/token'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def write_token_to_store(token_hash)
|
|
85
|
+
raise InvalidTokenParameter unless token_hash.is_a?(Hash) && token_hash['access_token']
|
|
86
|
+
|
|
87
|
+
token_hash['got_token_at'.freeze] = Time.now.to_i
|
|
88
|
+
token_hash['expires_in'.freeze] = token_hash.delete('expires_in')
|
|
89
|
+
write_token(token_hash)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def write_token(token_hash)
|
|
93
|
+
Youzan.redis.set youzan_token_key, token_hash.to_json
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def youzan_token_key
|
|
97
|
+
"youzan_token_#{CLIENT_ID}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
end
|
data/lib/youzan_api.rb
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require 'byebug'
|
|
2
|
+
require 'faraday'
|
|
3
|
+
require 'youzan/token_client'
|
|
4
|
+
|
|
5
|
+
module Youzan
|
|
6
|
+
class Api
|
|
7
|
+
|
|
8
|
+
BASE_API_URL = 'https://open.youzan.com'.freeze
|
|
9
|
+
|
|
10
|
+
attr_reader :api_path, :api_version, :request_method, :token_client
|
|
11
|
+
|
|
12
|
+
def initialize(api_path = nil, api_version = nil, request_method = nil)
|
|
13
|
+
@api_path = api_path
|
|
14
|
+
@api_version = api_version
|
|
15
|
+
@request_method = request_method
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# This is a common method to call the youzan's service API
|
|
19
|
+
# But you need to initialize the `api_path`, `api_version` and `request_method`
|
|
20
|
+
def call_api(options)
|
|
21
|
+
res = call_youzan_api(options)
|
|
22
|
+
parse_response_data(res)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# 获取单笔交易的信息
|
|
26
|
+
# API name: youzan.trade.get
|
|
27
|
+
def get_youzan_trade(tid)
|
|
28
|
+
@api_path = 'youzan.trade.get'
|
|
29
|
+
@api_version = '4.0.0'
|
|
30
|
+
@request_method = 'GET'
|
|
31
|
+
res = call_youzan_api(tid: tid)
|
|
32
|
+
parse_response_data(res)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# 使用购买虚拟商品获得的码
|
|
36
|
+
# API name: youzan.trade.virtualcode.apply
|
|
37
|
+
#
|
|
38
|
+
# Success Response
|
|
39
|
+
#
|
|
40
|
+
# { "response": { "is_success": true } }
|
|
41
|
+
#
|
|
42
|
+
# Error Response
|
|
43
|
+
#
|
|
44
|
+
# { "error_response": { "code": 101300000, "msg": "订单不存在" } }
|
|
45
|
+
# { "error_response": { "code": 101600002, "msg": "订单已被关闭无法核销" } }
|
|
46
|
+
# { "error_response": { "code": 101600002, "msg": "订单已被核销,重复核销无效" } }
|
|
47
|
+
def apply_virtual_code(code)
|
|
48
|
+
@api_path = 'youzan.trade.virtualcode.apply'
|
|
49
|
+
@api_version = '3.0.0'
|
|
50
|
+
@request_method = 'GET'
|
|
51
|
+
res = call_youzan_api(code: code)
|
|
52
|
+
parse_response_data(res)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def access_token
|
|
59
|
+
@token_client ||= Youzan::TokenClient.new
|
|
60
|
+
@token_client.access_token
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def connection
|
|
64
|
+
@client ||= Faraday.new
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def call_youzan_api(param_hash)
|
|
68
|
+
raise InvalidRequestMethod unless %w[GET POST].include?(request_method)
|
|
69
|
+
|
|
70
|
+
param_hash.merge!(access_token: access_token)
|
|
71
|
+
|
|
72
|
+
case request_method
|
|
73
|
+
when 'GET'
|
|
74
|
+
api_via_get_method(param_hash)
|
|
75
|
+
when 'POST'
|
|
76
|
+
api_via_post_method(param_hash)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def api_via_get_method(parameters)
|
|
81
|
+
raise InvalidHashParameter unless parameters.is_a?(Hash)
|
|
82
|
+
connection.get do |req|
|
|
83
|
+
req.url api_oauthentry_url
|
|
84
|
+
req.params.merge!(parameters)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def api_via_post_method(parameters)
|
|
89
|
+
raise InvalidHashParameter unless parameters.is_a?(Hash)
|
|
90
|
+
connection.post do |req|
|
|
91
|
+
req.url api_oauthentry_url
|
|
92
|
+
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
93
|
+
req.body = parameters
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def parse_response_data(response)
|
|
98
|
+
JSON.parse(response.body)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def api_oauthentry_url
|
|
102
|
+
raise InvokeApiError unless api_path_valid?
|
|
103
|
+
result = /((?:\w+\.)+)(\w+)/.match(api_path).to_a
|
|
104
|
+
api_action = result.last
|
|
105
|
+
api_name = result[-2].chop
|
|
106
|
+
Youzan::Api::BASE_API_URL + '/api/oauthentry/' + "#{api_name}/" + api_version + "/#{api_action}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def api_path_valid?
|
|
110
|
+
api_path =~ /((?:\w+\.)+)(\w+)/
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: youzan_api
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Keon Ye
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2010-09-18 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: byebug
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '10.0'
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 10.0.2
|
|
23
|
+
type: :development
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - "~>"
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '10.0'
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 10.0.2
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: dotenv
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.3'
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: 2.3.0
|
|
43
|
+
type: :development
|
|
44
|
+
prerelease: false
|
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - "~>"
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '2.3'
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 2.3.0
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: redis
|
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '4.0'
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 4.0.2
|
|
63
|
+
type: :development
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - "~>"
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '4.0'
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 4.0.2
|
|
73
|
+
- !ruby/object:Gem::Dependency
|
|
74
|
+
name: faraday
|
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - "~>"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: 0.15.2
|
|
80
|
+
type: :development
|
|
81
|
+
prerelease: false
|
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - "~>"
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: 0.15.2
|
|
87
|
+
description: An easy way to call the youzan API's gem
|
|
88
|
+
email: staven.vanderbilt@gmail.com
|
|
89
|
+
executables: []
|
|
90
|
+
extensions: []
|
|
91
|
+
extra_rdoc_files: []
|
|
92
|
+
files:
|
|
93
|
+
- lib/youzan/token_client.rb
|
|
94
|
+
- lib/youzan_api.rb
|
|
95
|
+
homepage: https://github.com/keonjeo/youzan_api
|
|
96
|
+
licenses:
|
|
97
|
+
- MIT
|
|
98
|
+
metadata: {}
|
|
99
|
+
post_install_message:
|
|
100
|
+
rdoc_options: []
|
|
101
|
+
require_paths:
|
|
102
|
+
- lib
|
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">="
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '0'
|
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
|
+
requirements:
|
|
110
|
+
- - ">="
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: '0'
|
|
113
|
+
requirements: []
|
|
114
|
+
rubyforge_project:
|
|
115
|
+
rubygems_version: 2.6.14
|
|
116
|
+
signing_key:
|
|
117
|
+
specification_version: 4
|
|
118
|
+
summary: Youzan API
|
|
119
|
+
test_files: []
|