youzanyun 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4c51390a4fd61285da7d5e0c5ff5759f0d2572e6
4
+ data.tar.gz: 2d0adfeb7b8b0de72af88951945de0f4695f5333
5
+ SHA512:
6
+ metadata.gz: da3c07fbf74d62b2a7b94c51612a2682a94dd660b4fb75278378ef4db719e5dbd32c8faba3cea429417a3044f5f0960435b5653be1d986e518dc855a0b7d102e
7
+ data.tar.gz: 68e3fdca25ea60f42a2be87b4ed8f795e0cd790a0cf248b519086189b2f9999c5a0a0e8be43de04508ea02ab639fc60f7cbcbed0c7b451d3f4f6d8b192f8bc07
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ Gemfile.lock
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,10 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.4.7
7
+ script:
8
+ - bundle exec rspec spec
9
+ services:
10
+ - redis
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+
2
+ source "https://rubygems.org"
3
+
4
+ # Specify your gem's dependencies in youzanyun.gemspec
5
+ gemspec
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "youzanyun"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "youzanyun/version"
4
+ require "rest-client"
5
+ if defined? Yajl
6
+ require 'yajl/json_gem'
7
+ else
8
+ require "json"
9
+ end
10
+ require "erb"
11
+ require "youzanyun/config"
12
+ require "youzanyun/handler"
13
+ require "youzanyun/api"
14
+ require "youzanyun/client"
15
+ module Youzanyun
16
+
17
+ CUSTOM_ENDPOINT = "custom_endpoint".freeze
18
+
19
+ module Token
20
+ autoload(:Store, "youzanyun/token/store")
21
+ autoload(:ObjectStore, "youzanyun/token/object_store")
22
+ autoload(:RedisStore, "youzanyun/token/redis_store")
23
+ end
24
+
25
+ class << self
26
+
27
+ def http_get_without_token(url, url_params={}, endpoint="api")
28
+ get_api_url = endpoint_url(endpoint, url)
29
+ load_json(resource(get_api_url).get(params: url_params))
30
+ end
31
+
32
+ def http_post_without_token(url, post_body = {}, url_params = {}, endpoint="api")
33
+ post_api_url = endpoint_url(endpoint, url)
34
+ load_json(resource(post_api_url).post(JSON.generate(post_body), params: url_params))
35
+ end
36
+
37
+ def http_delete_without_token(url, delete_body={}, url_params={}, endpoint="plain")
38
+ delete_api_url = endpoint_url(endpoint, url)
39
+ load_json(resource(delete_api_url).delete(params: url_params,raw_response: true))
40
+ end
41
+
42
+ def resource(url)
43
+ RestClient::Resource.new(url, rest_client_options)
44
+ end
45
+
46
+ def load_json(string)
47
+ result_hash = JSON.parse(string.force_encoding("UTF-8").gsub(/[\u0011-\u001F]/, ""))
48
+ ResultHandler.new(result_hash["code"], result_hash["message"], result_hash["success"], result_hash)
49
+ end
50
+
51
+ def endpoint_url(endpoint, url)
52
+ return url if endpoint == CUSTOM_ENDPOINT
53
+ send("#{endpoint}_endpoint") + url
54
+ end
55
+
56
+ def api_endpoint
57
+ "https://open.youzanyun.com/api"
58
+ end
59
+
60
+ def calculate_expire(expires_in)
61
+ expires_in.to_i - key_expired.to_i * 1000
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.dirname(__FILE__)}/api/*.rb"].each do |path|
4
+ require path
5
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Youzanyun
4
+ module Api
5
+ module Item
6
+ # 获取单个商品
7
+ def item_get(options)
8
+ http_get(url(".get"), options)
9
+ end
10
+
11
+ def item_sku_update(options)
12
+ http_post(url(".sku.update"), options)
13
+ end
14
+
15
+ private
16
+
17
+ def item_base_url
18
+ "/youzan.item"
19
+ end
20
+
21
+ def version
22
+ "/3.0.0"
23
+ end
24
+
25
+ def url(path)
26
+ item_base_url + path + version
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Youzanyun
4
+ module Api
5
+ module Item
6
+ # 获取单个商品
7
+ def items_inventory_get(options)
8
+ http_get(url(".inventory.get"), options)
9
+ end
10
+
11
+ private
12
+
13
+ def item_base_url
14
+ "/youzan.items"
15
+ end
16
+
17
+ def version
18
+ "/3.0.0"
19
+ end
20
+
21
+ def url(path)
22
+ item_base_url + path + version
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+ require "redis"
5
+ require 'digest/md5'
6
+ module Youzanyun
7
+
8
+ class Client
9
+
10
+ include MonitorMixin
11
+
12
+ include Api::Item
13
+
14
+ attr_accessor :client_id, :client_secret, :grant_id, :expired_at
15
+ attr_accessor :access_token, :token_type, :redis_key
16
+
17
+ def initialize(client_id, client_secret, grant_id, options={})
18
+ @client_id = client_id
19
+ @client_secret = client_secret
20
+ @expired_at = Time.now.to_i
21
+ @grant_id = grant_id
22
+ @redis_key = security_redis_key(options[:redis_key] || "youzanyun_#{client_id}")
23
+ super()
24
+ end
25
+
26
+ def get_access_token
27
+ synchronize { token_store.access_token }
28
+ end
29
+
30
+ def get_token_type
31
+ synchronize { token_store.token_type }
32
+ end
33
+
34
+ def is_valid?
35
+ token_store.valid?
36
+ end
37
+
38
+ def token_store
39
+ Token::Store.init_with(self)
40
+ end
41
+
42
+ def http_get(url, url_params={}, endpoint="api")
43
+ url_params = url_params.merge(access_token_param)
44
+ Youzanyun.http_get_without_token(url, url_params, endpoint)
45
+ end
46
+
47
+ def http_post(url, post_body={}, url_params={}, endpoint="api")
48
+ url_params = access_token_param.merge(url_params)
49
+ Youzanyun.http_post_without_token(url, post_body, url_params, endpoint)
50
+ end
51
+
52
+ def http_delete(url, delete_body={}, url_params={}, endpoint="api")
53
+ url_params = access_token_param.merge(url_params)
54
+ url = "#{url}?access_token=#{get_access_token}"
55
+ Youzanyun.http_delete_without_token(url, delete_body, url_params, endpoint)
56
+ end
57
+
58
+ def verify?(event_sign:, body:)
59
+ str = @client_id + body + @client_secret
60
+ Digest::MD5.hexdigest(str) == event_sign
61
+ end
62
+
63
+ private
64
+
65
+ def access_token_param
66
+ { access_token: get_access_token }
67
+ end
68
+
69
+ def security_redis_key(key)
70
+ Digest::MD5.hexdigest(key.to_s).upcase
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,28 @@
1
+ module Youzanyun
2
+
3
+ class << self
4
+ attr_accessor :config
5
+
6
+ def configure
7
+ yield self.config ||= Config.new
8
+ end
9
+
10
+ def youzanyun_redis
11
+ return nil if config.nil?
12
+ @redis ||= config.redis
13
+ end
14
+
15
+ def key_expired
16
+ config.key_expired rescue 100
17
+ end
18
+
19
+ def rest_client_options
20
+ return { timeout: 5, open_timeout: 5, verify_ssl: true } if config.nil?
21
+ config.rest_client_options
22
+ end
23
+ end
24
+
25
+ class Config
26
+ attr_accessor :redis, :rest_client_options, :key_expired
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ require "youzanyun/handler/result_handler"
5
+ require "youzanyun/handler/exceptions"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Youzanyun
4
+ class ValidAccessTokenException < RuntimeError;end
5
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Youzanyun
4
+
5
+ class ResultHandler
6
+ OK_CODE = 200.freeze
7
+ OK_MSG = "OK"
8
+ attr_accessor :code, :message, :success, :result
9
+
10
+ def initialize(code, message, success, result={})
11
+ @code = code || OK_CODE
12
+ @message = message || OK_MSG
13
+ @success = success
14
+ @result = package_result(result)
15
+ end
16
+
17
+ def is_ok?
18
+ code == OK_CODE
19
+ end
20
+ alias_method :ok?, :is_ok?
21
+
22
+ def full_message
23
+ "#{code}: #{message}."
24
+ end
25
+ alias_method :full_messages, :full_message
26
+
27
+ def full_error_message
28
+ full_message if !is_ok?
29
+ end
30
+ alias_method :full_error_messages, :full_error_message
31
+ alias_method :errors, :full_error_message
32
+
33
+ private
34
+
35
+ def package_result(result)
36
+ return result if !result.is_a?(Hash)
37
+ if defined?(Rails)
38
+ ActiveSupport::HashWithIndifferentAccess.new(result)
39
+ else
40
+ result
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # encoding: utf-8
4
+ module Youzanyun
5
+ module Token
6
+ class ObjectStore < Store
7
+
8
+ def valid?
9
+ super
10
+ end
11
+
12
+ def token_expired?
13
+ client.expired_at <= Time.now.to_i
14
+ end
15
+
16
+ def refresh_token
17
+ super
18
+ end
19
+
20
+ def access_token
21
+ super
22
+ client.access_token
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # encoding: utf-8
4
+ module Youzanyun
5
+ module Token
6
+ class RedisStore < Store
7
+
8
+ def valid?
9
+ youzanyun_redis.del(client.redis_key)
10
+ super
11
+ end
12
+
13
+ def token_expired?
14
+ youzanyun_redis.hvals(client.redis_key).empty?
15
+ end
16
+
17
+ def refresh_token
18
+ super
19
+ youzanyun_redis.hmset(
20
+ client.redis_key, "access_token",
21
+ client.access_token, "expired_at",
22
+ client.expired_at, "token_type",
23
+ client.token_type
24
+ )
25
+ youzanyun_redis.expireat(client.redis_key, client.expired_at.to_i)
26
+ end
27
+
28
+ def access_token
29
+ super
30
+ client.access_token = youzanyun_redis.hget(client.redis_key, "access_token")
31
+ client.expired_at = youzanyun_redis.hget(client.redis_key, "expired_at")
32
+ client.token_type = youzanyun_redis.hget(client.redis_key, "token_type")
33
+ client.access_token
34
+ end
35
+
36
+ def youzanyun_redis
37
+ Youzanyun.youzanyun_redis
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Youzanyun
4
+ module Token
5
+ class Store
6
+
7
+ attr_accessor :client
8
+
9
+ def initialize(client)
10
+ @client = client
11
+ end
12
+
13
+ def self.init_with(client)
14
+ if Youzanyun.youzanyun_redis.nil?
15
+ ObjectStore.new(client)
16
+ else
17
+ RedisStore.new(client)
18
+ end
19
+ end
20
+
21
+ def valid?
22
+ authenticate["valid"]
23
+ end
24
+
25
+ def authenticate
26
+ auth_result = http_get_access_token
27
+ auth = false
28
+ if auth_result.is_ok?
29
+ set_access_token(auth_result.result)
30
+ auth = true
31
+ end
32
+ {"valid" => auth, "handler" => auth_result}
33
+ end
34
+
35
+ def refresh_token
36
+ handle_valid_exception
37
+ set_access_token
38
+ end
39
+
40
+ def access_token
41
+ refresh_token if token_expired?
42
+ end
43
+
44
+ def token_expired?
45
+ raise NotImplementedError, "Subclasses must implement a token_expired? method"
46
+ end
47
+
48
+ def set_access_token(access_token_infos=nil)
49
+ token_infos = access_token_infos || http_get_access_token.result
50
+ client.access_token = token_infos["data"]["access_token"]
51
+ client.expired_at = Youzanyun.calculate_expire(token_infos["data"]["expires"])
52
+ end
53
+
54
+ def http_get_access_token
55
+ Youzanyun.http_post_without_token("https://open.youzanyun.com/auth/token", authenticate_headers, {}, CUSTOM_ENDPOINT)
56
+ end
57
+
58
+ def authenticate_headers
59
+ {
60
+ client_id: client.client_id,
61
+ client_secret: client.client_secret,
62
+ authorize_type: "silent",
63
+ grant_id: client.grant_id
64
+ }
65
+ end
66
+
67
+ private
68
+
69
+ def handle_valid_exception
70
+ auth_result = authenticate
71
+ if !auth_result["valid"]
72
+ result_handler = auth_result["handler"]
73
+ raise ValidAccessTokenException, result_handler.full_error_message
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ module Youzanyun
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,30 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "youzanyun/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "youzanyun"
8
+ spec.version = Youzanyun::VERSION
9
+ spec.authors = ["guoyoujin"]
10
+ spec.email = ["guoyoujin123@gmail.com"]
11
+
12
+ spec.summary = %q{TryCatch.}
13
+ spec.description = %q{youzan yun api Ruby Server SDK.}
14
+ spec.homepage = "https://github.com/guoyoujin/youzanyun"
15
+ spec.license = "MIT"
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ spec.add_dependency "redis", ">= 3.1.0"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_runtime_dependency "rest-client", '>= 1.7'
27
+ spec.add_development_dependency "redis-namespace"
28
+ spec.add_development_dependency 'pry-rails'
29
+
30
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: youzanyun
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - guoyoujin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-07 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.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redis-namespace
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: youzan yun api Ruby Server SDK.
98
+ email:
99
+ - guoyoujin123@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".travis.yml"
107
+ - Gemfile
108
+ - Rakefile
109
+ - bin/console
110
+ - bin/setup
111
+ - lib/youzanyun.rb
112
+ - lib/youzanyun/api.rb
113
+ - lib/youzanyun/api/item.rb
114
+ - lib/youzanyun/api/items.rb
115
+ - lib/youzanyun/client.rb
116
+ - lib/youzanyun/config.rb
117
+ - lib/youzanyun/handler.rb
118
+ - lib/youzanyun/handler/exceptions.rb
119
+ - lib/youzanyun/handler/result_handler.rb
120
+ - lib/youzanyun/token/object_store.rb
121
+ - lib/youzanyun/token/redis_store.rb
122
+ - lib/youzanyun/token/store.rb
123
+ - lib/youzanyun/version.rb
124
+ - youzanyun.gemspec
125
+ homepage: https://github.com/guoyoujin/youzanyun
126
+ licenses:
127
+ - MIT
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.6.14.4
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: TryCatch.
149
+ test_files: []