kingdee_api 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 934391e85b391da659c8495785ac56eca320131a646f6e268e2a590d5bd55ef4
4
+ data.tar.gz: 41fad52c3356633f04bc7409acfa42be1576597f5d17302b27c22d59c4629d3b
5
+ SHA512:
6
+ metadata.gz: d51d6d431c9a39f77f121086f527cf5903e65f3fec8bf7a07394c57e7767596fdb3d5b1de9b8734e617c38ce1786c5e537fb2287a1bd3838b7ed61f9762490a2
7
+ data.tar.gz: 05dc1efb059ab4e576b5855539d86e56f11cfdba2093c96594cc5351a33e6b5d185bc52a3c9c60926f5ead6c12963d526d50114fb0f465695567f7f0b67123b4
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-03-27
4
+
5
+ ### Added
6
+ - Modular configuration, signing, request builder, response parser and HTTP adapter.
7
+ - Env-based configuration with `KingdeeApi.configure`, temporary overrides, and fine-grained timeouts.
8
+ - Multipart uploads, deterministic signature helper, and a tested client facade.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 钟声
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # KingdeeApi
2
+
3
+ 一个用于实现金蝶云 API HTTP 请求加签的 Ruby gem。该 gem 提供了便捷的方式来调用金蝶云开放平台的 API,自动处理请求签名和认证。
4
+
5
+ [金蝶云 API 文档](https://open.jdy.com/#/files/api/detail?index=3&categrayId=3cc8ee9a663e11eda5c84b5d383a2b93&id=adfe4a24712711eda0b307c6992ee459)
6
+
7
+ ## 功能特性
8
+
9
+ - 🔐 自动处理 API 请求签名
10
+ - 🔑 支持环境变量和代码配置两种方式
11
+ - 📦 支持 GET、POST 等多种 HTTP 方法
12
+ - 📎 支持文件上传功能
13
+ - 🚀 简单易用的 API 接口
14
+ - 🧩 模块化设计,配置、签名、请求和响应组件彼此解耦
15
+
16
+ ## 安装
17
+
18
+ ### 使用 Bundler
19
+
20
+ 在 `Gemfile` 中添加:
21
+
22
+ ```ruby
23
+ gem 'kingdee_api'
24
+ ```
25
+
26
+ 然后执行:
27
+
28
+ ```bash
29
+ bundle install
30
+ ```
31
+
32
+ 或者直接使用:
33
+
34
+ ```bash
35
+ bundle add kingdee_api
36
+ ```
37
+
38
+ ### 直接安装
39
+
40
+ 如果未使用 Bundler 管理依赖,可以直接安装:
41
+
42
+ ```bash
43
+ gem install kingdee_api
44
+ ```
45
+
46
+ ## 使用
47
+
48
+ ### 配置
49
+
50
+ #### 方式一:使用环境变量(推荐)
51
+
52
+ 默认使用环境变量进行配置,适合生产环境使用:
53
+
54
+ ```bash
55
+ # 设置环境变量
56
+ export KINGDEE_CLIENT_ID=327910
57
+ export KINGDEE_CLIENT_SECRET=327xxxxxxx910
58
+ export KINGDEE_APP_KEY=gsKeflPn
59
+ export KINGDEE_APP_SECRET=4bf00ef4c9252e4c727f0e9d762a706d418f5e87
60
+ export KINGDEE_DOMAIN=https://tf.jdy.com
61
+ ```
62
+
63
+ #### 方式二:初始化时集中配置
64
+
65
+ 在应用启动阶段调用 `KingdeeApi.configure`,可以将配置集中管理,同时保留在任意位置创建客户端的能力:
66
+
67
+ ```ruby
68
+ KingdeeApi.configure do |config|
69
+ config.client_id = '327910'
70
+ config.client_secret = '327xxxxxxx910'
71
+ config.app_key = 'gsKeflPn'
72
+ config.app_secret = '4bf00ef4c9252e4c727f0e9d762a706d418f5e87'
73
+ config.domain = 'https://tf.jdy.com'
74
+ config.read_timeout = 20
75
+ config.open_timeout = 5
76
+ end
77
+
78
+ client = KingdeeApi.client # 任何需要的地方都可以拿到配置好的客户端
79
+ ```
80
+
81
+ #### 方式三:临时配置某些参数
82
+
83
+ 当少量参数需要按需覆盖时,将它们直接传给 `client` 方法即可:
84
+
85
+ ```ruby
86
+ client = KingdeeApi.client(domain: 'https://api.kingdee.com')
87
+ ```
88
+
89
+ ### 配置参数说明
90
+
91
+ | 参数 | 说明 | 是否必填 |
92
+ |------|------|----------|
93
+ | `client_id` | 客户端 ID | 是 |
94
+ | `client_secret` | 客户端密钥 | 是 |
95
+ | `app_key` | 应用 Key | 是 |
96
+ | `app_secret` | 应用密钥 | 是 |
97
+ | `domain` | API 域名,如 `https://tf.jdy.com` 或 `https://api.kingdee.com` | 是 |
98
+
99
+ ### API 调用示例
100
+
101
+ #### GET 请求示例 - 采购申请单列表
102
+
103
+ 用途说明:获取采购申请单列表
104
+ 请求方式:GET
105
+ 请求地址:`https://api.kingdee.com/jdy/v2/scm/pur_request`
106
+
107
+ ```ruby
108
+ # 基本调用
109
+ response = KingdeeApi.client.get('jdy/v2/scm/pur_request')
110
+
111
+ # 带查询参数
112
+ response = KingdeeApi.client.get('jdy/v2/scm/pur_request', params: {
113
+ page: 1,
114
+ page_size: 20,
115
+ filter: '...'
116
+ })
117
+ ```
118
+
119
+ #### POST 请求示例 - 采购申请单保存
120
+
121
+ 用途说明:采购申请单新增及修改。审核、删除等详见通用操作接口
122
+ 请求方式:POST
123
+ 请求地址:`https://api.kingdee.com/jdy/v2/scm/pur_request`
124
+
125
+ ```ruby
126
+ # 基本 POST 请求
127
+ response = KingdeeApi.client.post('jdy/v2/scm/pur_request', params: {
128
+ bill_date: '2024-01-01',
129
+ # 其他参数...
130
+ })
131
+
132
+ # 带文件上传的 POST 请求
133
+ response = KingdeeApi.client.post('jdy/v2/scm/pur_request', params: {
134
+ bill_date: '2024-01-01',
135
+ # 其他参数...
136
+ }) do |request|
137
+ request.attach 'file/path/1'
138
+ request.attach 'file/path/2'
139
+ end
140
+ ```
141
+
142
+ #### 其他 HTTP 方法
143
+
144
+ ```ruby
145
+ # PUT 请求
146
+ response = KingdeeApi.client.put('jdy/v2/scm/pur_request', params: { ... })
147
+
148
+ # DELETE 请求
149
+ response = KingdeeApi.client.delete('jdy/v2/scm/pur_request', params: { ... })
150
+
151
+ # PATCH 请求
152
+ response = KingdeeApi.client.patch('jdy/v2/scm/pur_request', params: { ... })
153
+ ```
154
+
155
+ ### 请求选项与高级用法
156
+
157
+ - `query:`:强制附加查询字符串(POST/PUT 等也适用)。
158
+ - `headers:`:追加自定义请求头。
159
+ - `timeout:`:覆盖单次请求的 `open_timeout/read_timeout`。
160
+ - `&block`:获取请求构建器并调用 `attach` 方法添加一个或多个文件。也可以通过 `attach(nil, data: '...', filename: 'a.txt')` 传入内存数据。
161
+
162
+ ### 响应处理
163
+
164
+ ```ruby
165
+ response = KingdeeApi.client.get('jdy/v2/scm/pur_request')
166
+
167
+ if response.success?
168
+ response.body # => Hash / Array(自动 JSON 解析)
169
+ else
170
+ warn response.error_message || "请求失败: #{response.status}"
171
+ end
172
+ ```
173
+
174
+ ## 开发
175
+
176
+ ### 环境设置
177
+
178
+ 克隆仓库后,运行以下命令安装依赖:
179
+
180
+ ```bash
181
+ bin/setup
182
+ ```
183
+
184
+ ### 运行测试
185
+
186
+ ```bash
187
+ rake test
188
+ ```
189
+
190
+ ### 交互式控制台
191
+
192
+ 可以使用交互式控制台进行实验:
193
+
194
+ ```bash
195
+ bin/console
196
+ ```
197
+
198
+ ### 本地安装
199
+
200
+ 将 gem 安装到本地机器:
201
+
202
+ ```bash
203
+ bundle exec rake install
204
+ ```
205
+
206
+ ### 发布新版本
207
+
208
+ 1. 更新 `lib/kingdee_api/version.rb` 中的版本号
209
+ 2. 运行发布命令:
210
+
211
+ ```bash
212
+ bundle exec rake release
213
+ ```
214
+
215
+ 这将创建 git 标签、推送提交和标签,并将 `.gem` 文件推送到 [rubygems.org](https://rubygems.org)。
216
+
217
+ ## 常见问题
218
+
219
+ ### Q: 如何获取 API 凭证?
220
+
221
+ A: 请登录金蝶云开放平台,在应用管理中创建应用并获取相应的 `client_id`、`client_secret`、`app_key` 和 `app_secret`。
222
+
223
+ ### Q: 支持哪些环境?
224
+
225
+ A: 支持金蝶云的生产环境和测试环境,通过 `domain` 参数配置不同的环境地址。
226
+
227
+ ### Q: 如何处理请求错误?
228
+
229
+ A: 检查响应状态码和错误信息,根据金蝶云 API 文档中的错误码进行处理。
230
+
231
+ ## Contributing
232
+
233
+ 欢迎提交 Bug 报告和 Pull Request!
234
+
235
+ 项目地址:[https://github.com/zhongsheng/kingdee_api](https://github.com/zhongsheng/kingdee_api)
236
+
237
+ ## License
238
+
239
+ 该 gem 基于 [MIT License](https://opensource.org/licenses/MIT) 开源协议发布。
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ task default: :test
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ class Client
5
+ SUPPORTED_METHODS = %i[get post put patch delete].freeze
6
+
7
+ include Signature
8
+ include Request
9
+
10
+ attr_reader :configuration
11
+ attr_reader :app_key
12
+ attr_reader :app_secret
13
+ attr_reader :client_id
14
+ attr_reader :client_secret
15
+ attr_reader :domain
16
+
17
+ def token
18
+ @token ||= get_token
19
+ end
20
+
21
+ def initialize(configuration, signer: nil, http_adapter: nil)
22
+ @configuration = coerce_configuration(configuration)
23
+ @configuration.validate!
24
+ @app_key = configuration.app_key
25
+ @app_secret = configuration.app_secret
26
+ @client_id = configuration.client_id
27
+ @client_secret = configuration.client_secret
28
+ @domain = configuration.domain
29
+ end
30
+
31
+
32
+
33
+ private
34
+
35
+ attr_reader :configuration, :signer, :http_adapter
36
+
37
+ def coerce_configuration(config)
38
+ return config if config.is_a?(Configuration)
39
+
40
+ Configuration.new.apply!(config || {})
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ class Configuration
5
+ DEFAULT_DOMAIN = "https://api.kingdee.com"
6
+ ATTRIBUTES = %i[
7
+ client_id
8
+ client_secret
9
+ app_key
10
+ app_secret
11
+ domain
12
+ open_timeout
13
+ read_timeout
14
+ logger
15
+ ].freeze
16
+ REQUIRED = %i[client_id client_secret app_key app_secret domain].freeze
17
+
18
+ attr_accessor :client_id, :client_secret, :app_key, :app_secret, :logger
19
+ attr_reader :domain, :open_timeout, :read_timeout
20
+
21
+ def initialize
22
+ reset!
23
+ end
24
+
25
+ def reset!
26
+ self.client_id = ENV["KINGDEE_CLIENT_ID"]
27
+ self.client_secret = ENV["KINGDEE_CLIENT_SECRET"]
28
+ self.app_key = ENV["KINGDEE_APP_KEY"]
29
+ self.app_secret = ENV["KINGDEE_APP_SECRET"]
30
+ self.domain = ENV["KINGDEE_DOMAIN"]
31
+ self.open_timeout = ENV.fetch("KINGDEE_OPEN_TIMEOUT", 5)
32
+ self.read_timeout = ENV.fetch("KINGDEE_READ_TIMEOUT", 30)
33
+ self.logger = nil
34
+ end
35
+
36
+ def dup
37
+ self.class.new.apply!(to_h)
38
+ end
39
+ alias clone dup
40
+
41
+ def apply!(attributes)
42
+ return self if attributes.nil?
43
+
44
+ attributes.each do |key, value|
45
+ writer = "#{key}="
46
+ next unless respond_to?(writer)
47
+
48
+ public_send(writer, value)
49
+ end
50
+ self
51
+ end
52
+
53
+ def to_h
54
+ ATTRIBUTES.each_with_object({}) do |key, memo|
55
+ value = public_send(key)
56
+ memo[key] = value unless value.nil?
57
+ end
58
+ end
59
+
60
+ def validate!
61
+ missing = REQUIRED.reject { |name| present?(public_send(name)) }
62
+ return true if missing.empty?
63
+
64
+ raise ConfigurationError, "Missing configuration: #{missing.join(', ')}"
65
+ end
66
+
67
+ def domain=(value)
68
+ sanitized = value.to_s.strip
69
+ sanitized = nil if sanitized.empty?
70
+ sanitized ||= DEFAULT_DOMAIN
71
+ @domain = sanitized.chomp("/")
72
+ end
73
+
74
+ def open_timeout=(value)
75
+ @open_timeout = normalize_timeout(value, default: 5)
76
+ end
77
+
78
+ def read_timeout=(value)
79
+ @read_timeout = normalize_timeout(value, default: 30)
80
+ end
81
+
82
+ private
83
+
84
+ def normalize_timeout(value, default:)
85
+ Integer(value)
86
+ rescue ArgumentError, TypeError
87
+ default
88
+ end
89
+
90
+ def present?(value)
91
+ !(value.nil? || (value.respond_to?(:empty?) && value.empty?))
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ class Error < StandardError; end
5
+
6
+ class ConfigurationError < Error; end
7
+
8
+ class RequestError < Error; end
9
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ module Request
5
+ HOST = 'https://api.kingdee.com'
6
+
7
+ def get(path, params = nil)
8
+ query_with('GET', path: path, params: params)
9
+ end
10
+
11
+ def post
12
+ end
13
+
14
+ private
15
+ def query_with(method, path:, params: nil)
16
+ # ✅ 构造请求 URL
17
+ uri = URI("#{HOST}#{path}")
18
+ uri.query = URI.encode_www_form(params) unless params.nil?
19
+
20
+ http = Net::HTTP.new(uri.host, uri.port)
21
+ http.use_ssl = true
22
+
23
+ x_api_signature = x_api_signature_with(
24
+ method: method,
25
+ path: path,
26
+ params: params,
27
+ nonce: nonce,
28
+ timestamp: timestamp,
29
+ client_secret: client_secret
30
+ )
31
+
32
+ request_class = Net::HTTP.const_get(method.capitalize)
33
+ request = request_class.new(uri)
34
+ request["Content-Type"] = "application/json"
35
+ request["X-Api-ClientID"] = client_id
36
+ request["X-Api-Auth-Version"] = "2.0"
37
+ request["X-Api-TimeStamp"] = timestamp
38
+ request["X-Api-SignHeaders"] = "X-Api-TimeStamp,X-Api-Nonce"
39
+ request["X-Api-Nonce"] = nonce
40
+ request["X-Api-Signature"] = "#{x_api_signature}"
41
+ request["app-token"] = token
42
+ request["X-GW-Router-Addr"] = domain
43
+
44
+ response = http.request(request)
45
+
46
+ pp response.body
47
+ puts "[HTTP] #{response.code}"
48
+ # puts JSON.parse(response.body)
49
+ # app-token: object false 用于调用星辰接口,有效期为24小时
50
+ response.body
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ class Response
5
+ attr_reader :status, :body, :headers
6
+
7
+ def initialize(http_response)
8
+ @status = http_response.code.to_i
9
+ @headers = extract_headers(http_response)
10
+ @raw_body = http_response.body
11
+ @body = parse_body(@raw_body)
12
+ end
13
+
14
+ def success?
15
+ (200..299).include?(status)
16
+ end
17
+
18
+ def error_message
19
+ return nil if success?
20
+
21
+ if body.is_a?(Hash)
22
+ body["message"] || body["msg"] || body["error"] || body["error_description"]
23
+ end
24
+ end
25
+
26
+ def raw_body
27
+ @raw_body
28
+ end
29
+
30
+ private
31
+
32
+ def parse_body(payload)
33
+ return nil if payload.nil? || payload.empty?
34
+
35
+ JSON.parse(payload)
36
+ rescue JSON::ParserError
37
+ payload
38
+ end
39
+
40
+ def extract_headers(response)
41
+ response.each_header.each_with_object({}) do |(key, value), memo|
42
+ memo[key] = value
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ module Signature
5
+
6
+ SIGN_PATH = '/jdyconnector/app_management/kingdee_auth_token'
7
+ TOKEN_CACHE_TTL = 24 * 60 * 60 # 24小时,单位:秒
8
+
9
+ def get_token
10
+ # 检查缓存是否有效
11
+ cached_token = get_cached_token
12
+ return cached_token if cached_token
13
+
14
+ # 缓存无效或不存在,获取新token
15
+ app_signature = app_signature_with
16
+ params = {
17
+ "app_key" => app_key,
18
+ "app_signature" => app_signature
19
+ }
20
+ x_api_signature = x_api_signature_with(
21
+ method: 'GET',
22
+ path: SIGN_PATH,
23
+ params: params,
24
+ nonce: nonce,
25
+ timestamp: timestamp,
26
+ client_secret: client_secret
27
+ )
28
+
29
+ token = query_token_with(app_signature, x_api_signature)
30
+ # 缓存token
31
+ cache_token(token)
32
+ token
33
+ end
34
+
35
+ private
36
+ def query_token_with(app_signature, x_api_signature)
37
+ # ✅ 构造请求 URL
38
+ uri = URI('https://api.kingdee.com/jdyconnector/app_management/kingdee_auth_token')
39
+ uri.query = URI.encode_www_form({
40
+ "app_key" => app_key,
41
+ "app_signature" => app_signature #app_signature
42
+ })
43
+
44
+ pp uri.query
45
+ pp uri.host
46
+ pp uri.to_s
47
+ http = Net::HTTP.new(uri.host, uri.port)
48
+ http.use_ssl = true
49
+
50
+ request = Net::HTTP::Get.new(uri)
51
+ request["X-Api-ClientID"] = client_id
52
+ request["X-Api-Auth-Version"] = "2.0"
53
+ request["X-Api-TimeStamp"] = timestamp
54
+ request["X-Api-Nonce"] = nonce
55
+ request["X-Api-SignHeaders"] = "X-Api-TimeStamp,X-Api-Nonce"
56
+ request["X-Api-Signature"] = "#{x_api_signature}"
57
+
58
+
59
+
60
+ response = http.request(request)
61
+
62
+ puts "[HTTP] #{response.code}"
63
+ puts JSON.parse(response.body)
64
+ # app-token: object false 用于调用星辰接口,有效期为24小时
65
+ JSON.parse(response.body)["data"]["app-token"]
66
+ end
67
+
68
+
69
+
70
+ def x_api_signature_with(method:, path:, params:, nonce:, timestamp:, client_secret:)
71
+ encoded_path = URI.encode_www_form_component(path)
72
+
73
+ if params.nil? || params.empty?
74
+ encoded_params = ''
75
+ else
76
+ encoded_params = params.sort.to_h.map do |k, v|
77
+ "#{double_encode(k)}=#{double_encode(v)}"
78
+ end.join("&")
79
+ end
80
+
81
+ headers_block = [
82
+ "x-api-nonce:#{nonce}",
83
+ "x-api-timestamp:#{timestamp}"
84
+ ].join("\n")
85
+
86
+ sign_plain = [
87
+ method.upcase,
88
+ encoded_path,
89
+ encoded_params,
90
+ headers_block,
91
+ "" # ⚠️ 末尾必须换行
92
+ ].join("\n")
93
+
94
+ puts sign_plain
95
+
96
+
97
+ Base64.strict_encode64(
98
+ OpenSSL::HMAC.hexdigest("SHA256", client_secret, sign_plain)
99
+ )
100
+ end
101
+ def nonce
102
+ @nonce ||= (Time.now.to_f * 1000).to_i.to_s
103
+ end
104
+
105
+ def timestamp
106
+ @timestamp ||= (Time.now.to_f * 1000).to_i.to_s
107
+ end
108
+
109
+ def app_signature_with
110
+ Base64.strict_encode64(
111
+ OpenSSL::HMAC.hexdigest("SHA256", app_secret, app_key)
112
+ )
113
+ end
114
+
115
+ def double_encode(str)
116
+ URI.encode_www_form_component(
117
+ URI.encode_www_form_component(str)
118
+ ).gsub(/%[0-9a-f]{2}/) { |m| m.upcase }
119
+ end
120
+
121
+ def cache_token(token)
122
+ @token_cache = {
123
+ token: token,
124
+ cached_at: Time.now
125
+ }
126
+ end
127
+
128
+ def get_cached_token
129
+ return nil unless @token_cache
130
+
131
+ cached_at = @token_cache[:cached_at]
132
+ return nil unless cached_at
133
+
134
+ # 检查是否过期(24小时)
135
+ elapsed_time = Time.now - cached_at
136
+ return nil if elapsed_time >= TOKEN_CACHE_TTL
137
+
138
+ @token_cache[:token]
139
+ end
140
+
141
+ end
142
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KingdeeApi
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "net/http"
5
+ require "uri"
6
+ require "openssl"
7
+ require "base64"
8
+ require "securerandom"
9
+ require "digest"
10
+
11
+ require_relative "kingdee_api/version"
12
+ require_relative "kingdee_api/errors"
13
+ require_relative "kingdee_api/configuration"
14
+ require_relative "kingdee_api/signature"
15
+
16
+ require_relative "kingdee_api/request"
17
+ require_relative "kingdee_api/response"
18
+
19
+ require_relative "kingdee_api/client"
20
+
21
+ module KingdeeApi
22
+ class << self
23
+ def configuration
24
+ @configuration ||= Configuration.new
25
+ end
26
+
27
+ def configure
28
+ yield(configuration)
29
+ end
30
+
31
+ def reset!
32
+ @configuration = Configuration.new
33
+ end
34
+
35
+ def client(options = nil, **overrides)
36
+ config = build_configuration(options, overrides)
37
+ Client.new(config)
38
+ end
39
+
40
+ private
41
+
42
+ def build_configuration(options, overrides)
43
+ case options
44
+ when Configuration
45
+ options.dup
46
+ when Hash
47
+ configuration.dup.apply!(options.merge(overrides))
48
+ else
49
+ overrides.empty? ? configuration.dup : configuration.dup.apply!(overrides)
50
+ end
51
+ end
52
+ end
53
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kingdee_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 钟声
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: A lightweight, modular Ruby client that signs and sends HTTP requests
13
+ to the Kingdee Cloud (Jingdian) open platform.
14
+ email:
15
+ - 444133866@qq.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CHANGELOG.md
21
+ - LICENSE.txt
22
+ - README.md
23
+ - Rakefile
24
+ - lib/kingdee_api.rb
25
+ - lib/kingdee_api/client.rb
26
+ - lib/kingdee_api/configuration.rb
27
+ - lib/kingdee_api/errors.rb
28
+ - lib/kingdee_api/request.rb
29
+ - lib/kingdee_api/response.rb
30
+ - lib/kingdee_api/signature.rb
31
+ - lib/kingdee_api/version.rb
32
+ homepage: https://github.com/zhongsheng/kingdee_api
33
+ licenses:
34
+ - MIT
35
+ metadata:
36
+ homepage_uri: https://github.com/zhongsheng/kingdee_api
37
+ source_code_uri: https://github.com/zhongsheng/kingdee_api
38
+ changelog_uri: https://github.com/zhongsheng/kingdee_api/blob/main/CHANGELOG.md
39
+ allowed_push_host: https://rubygems.org
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.6.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.6.9
55
+ specification_version: 4
56
+ summary: Authenticated HTTP client for the Kingdee Cloud API.
57
+ test_files: []