k3cloud_webapi_sdk 8.2.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 +7 -0
- data/lib/k3cloud_webapi_sdk/const/const_define.rb +25 -0
- data/lib/k3cloud_webapi_sdk/const/header_param.rb +17 -0
- data/lib/k3cloud_webapi_sdk/core/webapi_client.rb +255 -0
- data/lib/k3cloud_webapi_sdk/main.rb +213 -0
- data/lib/k3cloud_webapi_sdk/model/api_config.rb +33 -0
- data/lib/k3cloud_webapi_sdk/model/cookie.rb +33 -0
- data/lib/k3cloud_webapi_sdk/model/cookie_store.rb +37 -0
- data/lib/k3cloud_webapi_sdk/model/identity.rb +31 -0
- data/lib/k3cloud_webapi_sdk/model/query_param.rb +19 -0
- data/lib/k3cloud_webapi_sdk/util/base64_util.rb +84 -0
- data/lib/k3cloud_webapi_sdk/util/config_util.rb +47 -0
- data/lib/k3cloud_webapi_sdk/util/encode_util.rb +32 -0
- data/lib/k3cloud_webapi_sdk/util/hmac_util.rb +15 -0
- data/lib/k3cloud_webapi_sdk.rb +14 -0
- metadata +110 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a27712a9e76c2eda70bb656656b3954970d77675f3de42da92051b45a740f89e
|
|
4
|
+
data.tar.gz: 43933aac6f718c17beecb34fbb5a283125a73127bdcc2657dd62e70f710022f5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8c8e8b13851a2db1e4d358c27e8283c388443ec8e6b9b72cf646a0532af7cc7e1a074e30a157abce3bfc429a09451d480fb2b01c3ca8cd1f19ab9b09094092bf
|
|
7
|
+
data.tar.gz: bf4ec0fd3ef417210f99f8d5bab096204434a52c35ebc78e7fa54022cf5c6a5cc2a0867b110fd63997e73628a9e7c739055bb9331d8edfd634a39b834e62dd11
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Const
|
|
3
|
+
# InvokeMethod constants
|
|
4
|
+
module InvokeMethod
|
|
5
|
+
SYNC = 1
|
|
6
|
+
ASYNC = 2
|
|
7
|
+
QUERY = 3
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# QueryState constants
|
|
11
|
+
module QueryState
|
|
12
|
+
Pending = 0
|
|
13
|
+
Running = 1
|
|
14
|
+
Complete = 2
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# QueryMode constants
|
|
18
|
+
module QueryMode
|
|
19
|
+
BeginMethod_Header = 'beginmethod'
|
|
20
|
+
BeginMethod_Method = 'BeginQueryImpl'
|
|
21
|
+
QueryMethod_Header = 'querymethod'
|
|
22
|
+
QueryMethod_Method = 'QueryAsyncResult'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Const
|
|
3
|
+
module HeaderParam
|
|
4
|
+
X_Api_ClientID = 'X-Api-ClientID'
|
|
5
|
+
X_Api_Auth_Version = 'X-Api-Auth-Version'
|
|
6
|
+
X_Api_Timestamp = 'x-api-timestamp'
|
|
7
|
+
X_Api_Nonce = 'x-api-nonce'
|
|
8
|
+
X_Api_SignHeaders = 'x-api-signheaders'
|
|
9
|
+
X_Api_Signature = 'X-Api-Signature'
|
|
10
|
+
X_KD_AppKey = 'X-Kd-Appkey'
|
|
11
|
+
X_KD_AppData = 'X-Kd-Appdata'
|
|
12
|
+
X_KD_Signature = 'X-Kd-Signature'
|
|
13
|
+
KDService_SessionId = 'kdservice-sessionid'
|
|
14
|
+
Cookie_Set = 'Set-Cookie'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'rest-client'
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'time'
|
|
5
|
+
require_relative '../const/const_define'
|
|
6
|
+
require_relative '../const/header_param'
|
|
7
|
+
require_relative '../model/cookie'
|
|
8
|
+
require_relative '../model/cookie_store'
|
|
9
|
+
require_relative '../model/identity'
|
|
10
|
+
require_relative '../model/query_param'
|
|
11
|
+
require_relative '../util/encode_util'
|
|
12
|
+
require_relative '../util/hmac_util'
|
|
13
|
+
require_relative '../util/base64_util'
|
|
14
|
+
|
|
15
|
+
module K3CloudWebapiSdk
|
|
16
|
+
module Core
|
|
17
|
+
# Result validation function
|
|
18
|
+
def self.valid_result(response_content)
|
|
19
|
+
if response_content.start_with?('response_error:')
|
|
20
|
+
res_error = response_content.sub('response_error:', '').strip
|
|
21
|
+
if !res_error.empty?
|
|
22
|
+
raise RuntimeError, res_error
|
|
23
|
+
else
|
|
24
|
+
raise RuntimeError, 'Empty exception message'
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
response_content
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Web API Client class
|
|
32
|
+
class WebApiClient
|
|
33
|
+
attr_accessor :initialize, :config, :identify, :cookies_store, :connect_timeout, :request_timeout, :proxy
|
|
34
|
+
|
|
35
|
+
def initialize
|
|
36
|
+
@initialize = false
|
|
37
|
+
@config = nil
|
|
38
|
+
@identify = nil
|
|
39
|
+
@cookies_store = Model::CookieStore.new
|
|
40
|
+
@connect_timeout = 120
|
|
41
|
+
@request_timeout = 120
|
|
42
|
+
@proxy = ''
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Initialize the client
|
|
46
|
+
def init(server_url, timeout, sdk_initialize)
|
|
47
|
+
@initialize = sdk_initialize
|
|
48
|
+
|
|
49
|
+
if @config.nil?
|
|
50
|
+
raise 'Configuration file unload, you need initial config firstly!'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if server_url.empty?
|
|
54
|
+
# Cancel default old gateway, require url input by Ann 2025-01-15
|
|
55
|
+
raise 'ServerUrl is required'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
@identify = Model::Identity.new(
|
|
59
|
+
server_url,
|
|
60
|
+
@config.dcid,
|
|
61
|
+
@config.user_name,
|
|
62
|
+
@config.app_id,
|
|
63
|
+
@config.app_secret,
|
|
64
|
+
@config.org_num,
|
|
65
|
+
@config.lcid,
|
|
66
|
+
''
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@connect_timeout = @config.connect_timeout if @config.connect_timeout > 0
|
|
70
|
+
@request_timeout = @config.request_timeout if @config.request_timeout > 0
|
|
71
|
+
@request_timeout = timeout if timeout > 0
|
|
72
|
+
@proxy = @config.proxy if !@config.proxy.empty?
|
|
73
|
+
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Build request headers
|
|
78
|
+
def build_header(service_url)
|
|
79
|
+
path_url = service_url
|
|
80
|
+
if service_url.start_with?('http')
|
|
81
|
+
uri = URI.parse(service_url)
|
|
82
|
+
path_url = uri.path
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
path_url = ERB::Util.url_encode(path_url).gsub('/', '%2F')
|
|
86
|
+
time_stamp = Time.now.to_i.to_s
|
|
87
|
+
nonce = Time.now.to_i.to_s
|
|
88
|
+
client_id = ''
|
|
89
|
+
client_sec = ''
|
|
90
|
+
|
|
91
|
+
arr = @identify.app_id.split('_')
|
|
92
|
+
if arr.length == 2
|
|
93
|
+
client_id = arr[0]
|
|
94
|
+
client_sec = Util::EncodeUtil.decode_app_secret(arr[1])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
api_sign = 'POST\n' + path_url + '\n\nx-api-nonce:' + nonce + '\nx-api-timestamp:' + time_stamp + '\n'
|
|
98
|
+
app_data = @identify.dcid + ',' + @identify.user_name + ',' + @identify.lcid.to_s + ',' + @identify.org_num.to_s
|
|
99
|
+
|
|
100
|
+
dic_header = {
|
|
101
|
+
Const::HeaderParam::X_Api_ClientID => client_id,
|
|
102
|
+
Const::HeaderParam::X_Api_Auth_Version => '2.0',
|
|
103
|
+
Const::HeaderParam::X_Api_Timestamp => time_stamp,
|
|
104
|
+
Const::HeaderParam::X_Api_Nonce => nonce,
|
|
105
|
+
Const::HeaderParam::X_Api_SignHeaders => 'x-api-timestamp,x-api-nonce',
|
|
106
|
+
Const::HeaderParam::X_Api_Signature => Util::HmacUtil.hmac_sha256(api_sign, client_sec),
|
|
107
|
+
Const::HeaderParam::X_KD_AppKey => @identify.app_id,
|
|
108
|
+
Const::HeaderParam::X_KD_AppData => Util::Base64Util.encode(app_data.bytes),
|
|
109
|
+
Const::HeaderParam::X_KD_Signature => Util::HmacUtil.hmac_sha256(@identify.app_id + app_data, @identify.app_secret)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if !@cookies_store.sid.empty?
|
|
113
|
+
dic_header[Const::HeaderParam::KDService_SessionId] = @cookies_store.sid
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
if @cookies_store.cookies.length > 0
|
|
117
|
+
cookie_str = 'Theme=standard'
|
|
118
|
+
@cookies_store.cookies.each_value do |cookie|
|
|
119
|
+
cookie_str += ';' + cookie.to_s
|
|
120
|
+
end
|
|
121
|
+
dic_header['Cookie'] = cookie_str
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
dic_header['Accept-Charset'] = 'utf-8'
|
|
125
|
+
dic_header['User-Agent'] = 'Kingdee/Ruby WebApi SDK 8.2.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)'
|
|
126
|
+
dic_header['Content-Type'] = 'application/json'
|
|
127
|
+
|
|
128
|
+
dic_header
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Post JSON data
|
|
132
|
+
def post_json(service_name, json_data = {}, invoke_type = Const::InvokeMethod::SYNC)
|
|
133
|
+
json_data ||= {}
|
|
134
|
+
|
|
135
|
+
req_url = if @identify.server_url.end_with?('/')
|
|
136
|
+
@identify.server_url + service_name + '.common.kdsvc'
|
|
137
|
+
else
|
|
138
|
+
@identify.server_url + '/' + service_name + '.common.kdsvc'
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
proxies = nil
|
|
142
|
+
if !@proxy.empty?
|
|
143
|
+
proxies = { URI.parse(@proxy).scheme => @proxy }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
if invoke_type == Const::InvokeMethod::QUERY
|
|
147
|
+
json_data[Const::QueryMode::BeginMethod_Header] = Const::QueryMode::BeginMethod_Method
|
|
148
|
+
json_data[Const::QueryMode::QueryMethod_Header] = Const::QueryMode::QueryMethod_Method
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
headers = build_header(req_url)
|
|
152
|
+
|
|
153
|
+
begin
|
|
154
|
+
response = RestClient.post(
|
|
155
|
+
req_url,
|
|
156
|
+
json_data.to_json,
|
|
157
|
+
headers: headers,
|
|
158
|
+
timeout: [@connect_timeout, @request_timeout],
|
|
159
|
+
verify_ssl: false,
|
|
160
|
+
proxy: @proxy.empty? ? nil : @proxy
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if response.code == 200 || response.code == 206
|
|
164
|
+
fill_cookie_and_header(response.cookies, response.headers)
|
|
165
|
+
return Core.valid_result(response.body)
|
|
166
|
+
else
|
|
167
|
+
raise "HTTP Error #{response.code}: #{response.body}"
|
|
168
|
+
end
|
|
169
|
+
rescue RestClient::Exception => e
|
|
170
|
+
raise "Request failed: #{e.message}"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Fill cookies and headers
|
|
175
|
+
def fill_cookie_and_header(cookies, headers)
|
|
176
|
+
@cookies_store.set_sid(cookies[Const::HeaderParam::KDService_SessionId])
|
|
177
|
+
|
|
178
|
+
if headers[Const::HeaderParam::Cookie_Set]
|
|
179
|
+
@cookies_store.cookies.clear
|
|
180
|
+
headers[Const::HeaderParam::Cookie_Set].split(',').each do |item|
|
|
181
|
+
ck = Model::Cookie.parse(item)
|
|
182
|
+
if ck
|
|
183
|
+
@cookies_store.cookies[ck.name] = ck
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Execute API call
|
|
190
|
+
def execute(service_name, json_data = nil, invoke_type = Const::InvokeMethod::SYNC)
|
|
191
|
+
if !@initialize
|
|
192
|
+
raise '拒绝请求,请先正确初始化!'
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
if @config.nil?
|
|
196
|
+
raise '请先初始化SDK配置信息!'
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
case invoke_type
|
|
200
|
+
when Const::InvokeMethod::SYNC
|
|
201
|
+
post_json(service_name, json_data, Const::InvokeMethod::SYNC)
|
|
202
|
+
when Const::InvokeMethod::QUERY
|
|
203
|
+
execute_by_query(service_name, json_data)
|
|
204
|
+
else
|
|
205
|
+
raise 'Not support for InvokeMode:' + invoke_type.to_s
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Execute by query method
|
|
210
|
+
def execute_by_query(service_name, json_data = nil)
|
|
211
|
+
response_content = post_json(service_name, json_data, Const::InvokeMethod::QUERY)
|
|
212
|
+
json_result = JSON.parse(response_content)
|
|
213
|
+
|
|
214
|
+
if json_result['Status'] == Const::QueryState::Complete
|
|
215
|
+
return json_result['Result'].to_json
|
|
216
|
+
else
|
|
217
|
+
return query_task_result(
|
|
218
|
+
service_name,
|
|
219
|
+
{ 'TaskId' => json_result['TaskId'], 'Cancelled' => false },
|
|
220
|
+
5
|
|
221
|
+
)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Query task result
|
|
226
|
+
def query_task_result(service_name, param, retry_count)
|
|
227
|
+
sleep(1)
|
|
228
|
+
|
|
229
|
+
dot_index = service_name.rindex('.')
|
|
230
|
+
query_service = if dot_index
|
|
231
|
+
service_name[0, dot_index] + '.' + Const::QueryMode::QueryMethod_Method
|
|
232
|
+
else
|
|
233
|
+
service_name + '.' + Const::QueryMode::QueryMethod_Method
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
begin
|
|
237
|
+
response_content = post_json(query_service, { 'queryInfo' => param.to_json }, Const::InvokeMethod::SYNC)
|
|
238
|
+
json_result = JSON.parse(response_content)
|
|
239
|
+
|
|
240
|
+
if json_result['Status'] == Const::QueryState::Complete
|
|
241
|
+
json_result['Result'].to_json
|
|
242
|
+
else
|
|
243
|
+
query_task_result(service_name, param, 5)
|
|
244
|
+
end
|
|
245
|
+
rescue => err
|
|
246
|
+
if retry_count > 0
|
|
247
|
+
query_task_result(service_name, param, retry_count - 1)
|
|
248
|
+
else
|
|
249
|
+
raise err
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
require_relative 'core/webapi_client'
|
|
2
|
+
require_relative 'const/const_define'
|
|
3
|
+
require_relative 'util/config_util'
|
|
4
|
+
|
|
5
|
+
module K3CloudWebapiSdk
|
|
6
|
+
# Main K3Cloud API SDK class
|
|
7
|
+
class K3CloudApiSdk < Core::WebApiClient
|
|
8
|
+
attr_accessor :server_url, :timeout
|
|
9
|
+
|
|
10
|
+
def initialize(server_url, timeout = 120)
|
|
11
|
+
super()
|
|
12
|
+
@server_url = server_url
|
|
13
|
+
@timeout = timeout
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Initialize configuration with parameters
|
|
17
|
+
def init_config(acct_id, user_name, app_id, app_secret, server_url, lcid = 2052, org_num = 0,
|
|
18
|
+
connect_timeout = 120, request_timeout = 120, proxy = '')
|
|
19
|
+
|
|
20
|
+
@config = Util::ConfigUtil.init_config_by_params(
|
|
21
|
+
acct_id, user_name, app_id, app_secret, server_url, lcid, org_num,
|
|
22
|
+
connect_timeout, request_timeout, proxy
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
init(@server_url, @timeout, is_valid)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Initialize configuration from file
|
|
29
|
+
def init(config_path = 'conf.ini', config_node = 'config')
|
|
30
|
+
@config = Util::ConfigUtil.init_config(config_path, config_node)
|
|
31
|
+
init(@server_url, @timeout, is_valid)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Check if configuration is valid
|
|
35
|
+
def is_valid
|
|
36
|
+
messages = []
|
|
37
|
+
|
|
38
|
+
messages << '账套ID' if @config.dcid.empty?
|
|
39
|
+
messages << '用户' if @config.user_name.empty?
|
|
40
|
+
messages << '应用ID' if @config.app_id.empty?
|
|
41
|
+
messages << '应用密钥' if @config.app_secret.empty?
|
|
42
|
+
|
|
43
|
+
if !messages.empty?
|
|
44
|
+
puts 'SDK初始化失败,缺少必填授权项:' + messages.join(',')
|
|
45
|
+
return false
|
|
46
|
+
else
|
|
47
|
+
return true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Get data centers
|
|
52
|
+
def get_data_centers
|
|
53
|
+
execute('Kingdee.BOS.ServiceFacade.ServicesStub.Account.AccountService.GetDataCenterList')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Execute operation
|
|
57
|
+
def execute_operation(formid, op_number, data)
|
|
58
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExcuteOperation',
|
|
59
|
+
{ 'formid' => formid, 'opNumber' => op_number, 'data' => data })
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Save data
|
|
63
|
+
def save(formid, data)
|
|
64
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save',
|
|
65
|
+
{ 'formid' => formid, 'data' => data })
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Batch save
|
|
69
|
+
def batch_save(formid, data)
|
|
70
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave',
|
|
71
|
+
{ 'formid' => formid, 'data' => data })
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Batch save with query
|
|
75
|
+
def batch_save_query(formid, data)
|
|
76
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave',
|
|
77
|
+
{ 'formid' => formid, 'data' => data },
|
|
78
|
+
Const::InvokeMethod::QUERY)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Audit
|
|
82
|
+
def audit(formid, data)
|
|
83
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit',
|
|
84
|
+
{ 'formid' => formid, 'data' => data })
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Delete
|
|
88
|
+
def delete(formid, data)
|
|
89
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete',
|
|
90
|
+
{ 'formid' => formid, 'data' => data })
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Undo audit
|
|
94
|
+
def un_audit(formid, data)
|
|
95
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit',
|
|
96
|
+
{ 'formid' => formid, 'data' => data })
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Submit
|
|
100
|
+
def submit(formid, data)
|
|
101
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit',
|
|
102
|
+
{ 'formid' => formid, 'data' => data })
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# View
|
|
106
|
+
def view(formid, data)
|
|
107
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.View',
|
|
108
|
+
{ 'formid' => formid, 'data' => data })
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Execute bill query
|
|
112
|
+
def execute_bill_query(data)
|
|
113
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery',
|
|
114
|
+
{ 'data' => data })
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Bill query
|
|
118
|
+
def bill_query(data)
|
|
119
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BillQuery',
|
|
120
|
+
{ 'data' => data })
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Draft
|
|
124
|
+
def draft(formid, data)
|
|
125
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Draft',
|
|
126
|
+
{ 'formid' => formid, 'data' => data })
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Allocate
|
|
130
|
+
def allocate(formid, data)
|
|
131
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Allocate',
|
|
132
|
+
{ 'formid' => formid, 'data' => data })
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Flex save
|
|
136
|
+
def flex_save(formid, data)
|
|
137
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.FlexSave',
|
|
138
|
+
{ 'formid' => formid, 'data' => data })
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Send message
|
|
142
|
+
def send_msg(data)
|
|
143
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.SendMsg',
|
|
144
|
+
{ 'data' => data })
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Push
|
|
148
|
+
def push(formid, data)
|
|
149
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Push',
|
|
150
|
+
{ 'formid' => formid, 'data' => data })
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Group save
|
|
154
|
+
def group_save(formid, data)
|
|
155
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.GroupSave',
|
|
156
|
+
{ 'formid' => formid, 'data' => data })
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Disassembly
|
|
160
|
+
def disassembly(formid, data)
|
|
161
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Disassembly',
|
|
162
|
+
{ 'formid' => formid, 'data' => data })
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Query business info
|
|
166
|
+
def query_business_info(data)
|
|
167
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.QueryBusinessInfo',
|
|
168
|
+
{ 'data' => data })
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Query group info
|
|
172
|
+
def query_group_info(data)
|
|
173
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.QueryGroupInfo',
|
|
174
|
+
{ 'data' => data })
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Workflow audit
|
|
178
|
+
def workflow_audit(data)
|
|
179
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.WorkflowAudit',
|
|
180
|
+
{ 'data' => data })
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Group delete
|
|
184
|
+
def group_delete(data)
|
|
185
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.GroupDelete',
|
|
186
|
+
{ 'data' => data })
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Switch organization
|
|
190
|
+
def switch_org(data)
|
|
191
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.SwitchOrg',
|
|
192
|
+
{ 'data' => data })
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Get system report data
|
|
196
|
+
def get_sys_report_data(formid, data)
|
|
197
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.GetSysReportData',
|
|
198
|
+
{ 'formid' => formid, 'data' => data })
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Upload attachment
|
|
202
|
+
def attachment_upload(data)
|
|
203
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.AttachmentUpload',
|
|
204
|
+
{ 'data' => data })
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Download attachment
|
|
208
|
+
def attachment_download(data)
|
|
209
|
+
execute('Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.AttachmentDownLoad',
|
|
210
|
+
{ 'data' => data })
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Model
|
|
3
|
+
class ApiConfig
|
|
4
|
+
# Class variable for XOR code (equivalent to Python's class variable)
|
|
5
|
+
@@xor_code = ''
|
|
6
|
+
|
|
7
|
+
attr_accessor :server_url, :dcid, :user_name, :app_id, :app_secret,
|
|
8
|
+
:lcid, :org_num, :connect_timeout, :request_timeout, :proxy
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
# Cancel default old gateway, require url input by Ann 2025-01-15
|
|
12
|
+
@server_url = ''
|
|
13
|
+
@dcid = ''
|
|
14
|
+
@user_name = ''
|
|
15
|
+
@app_id = ''
|
|
16
|
+
@app_secret = ''
|
|
17
|
+
@lcid = 2052
|
|
18
|
+
@org_num = 0
|
|
19
|
+
@connect_timeout = 120
|
|
20
|
+
@request_timeout = 120
|
|
21
|
+
@proxy = ''
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.xor_code
|
|
25
|
+
@@xor_code
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.xor_code=(value)
|
|
29
|
+
@@xor_code = value
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Model
|
|
3
|
+
class Cookie
|
|
4
|
+
attr_accessor :name, :value, :domain, :path, :expires, :http_only, :secure
|
|
5
|
+
|
|
6
|
+
def initialize(name: '', value: '', domain: '', path: '/', expires: nil, http_only: false, secure: false)
|
|
7
|
+
@name = name
|
|
8
|
+
@value = value
|
|
9
|
+
@domain = domain
|
|
10
|
+
@path = path
|
|
11
|
+
@expires = expires
|
|
12
|
+
@http_only = http_only
|
|
13
|
+
@secure = secure
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
"#{@name}=#{@value}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_h
|
|
21
|
+
{
|
|
22
|
+
name: @name,
|
|
23
|
+
value: @value,
|
|
24
|
+
domain: @domain,
|
|
25
|
+
path: @path,
|
|
26
|
+
expires: @expires,
|
|
27
|
+
http_only: @http_only,
|
|
28
|
+
secure: @secure
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module K3cloudWebapiSdk
|
|
2
|
+
module Model
|
|
3
|
+
class CookieStore
|
|
4
|
+
attr_accessor :sid, :cookies
|
|
5
|
+
|
|
6
|
+
def initialize(sid = '', cookies = nil)
|
|
7
|
+
@sid = sid
|
|
8
|
+
@cookies = cookies || {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def set_sid(sid)
|
|
12
|
+
@sid = sid if !sid.nil? && !sid.empty?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def set_cookie(name, value, domain = '', path = '/', expires = nil)
|
|
16
|
+
@cookies[name] = {
|
|
17
|
+
value: value,
|
|
18
|
+
domain: domain,
|
|
19
|
+
path: path,
|
|
20
|
+
expires: expires
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def get_cookie(name)
|
|
25
|
+
@cookies[name]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete_cookie(name)
|
|
29
|
+
@cookies.delete(name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def clear_cookies
|
|
33
|
+
@cookies.clear
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Model
|
|
3
|
+
class Identity
|
|
4
|
+
attr_accessor :server_url, :dcid, :lcid, :user_name, :pwd, :app_id, :app_secret, :org_num
|
|
5
|
+
|
|
6
|
+
def initialize(server_url, dcid, user_name, app_id, app_secret, org_num, lcid = 2052, pwd = '')
|
|
7
|
+
@server_url = server_url
|
|
8
|
+
@dcid = dcid
|
|
9
|
+
@lcid = lcid
|
|
10
|
+
@user_name = user_name
|
|
11
|
+
@pwd = pwd
|
|
12
|
+
@app_id = app_id
|
|
13
|
+
@app_secret = app_secret
|
|
14
|
+
@org_num = org_num
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_h
|
|
18
|
+
{
|
|
19
|
+
server_url: @server_url,
|
|
20
|
+
dcid: @dcid,
|
|
21
|
+
lcid: @lcid,
|
|
22
|
+
user_name: @user_name,
|
|
23
|
+
pwd: @pwd,
|
|
24
|
+
app_id: @app_id,
|
|
25
|
+
app_secret: @app_secret,
|
|
26
|
+
org_num: @org_num
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Model
|
|
3
|
+
class QueryTaskParam
|
|
4
|
+
attr_accessor :task_id, :cancelled
|
|
5
|
+
|
|
6
|
+
def initialize(task_id = '', is_cancelled = false)
|
|
7
|
+
@task_id = task_id
|
|
8
|
+
@cancelled = is_cancelled
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_h
|
|
12
|
+
{
|
|
13
|
+
task_id: @task_id,
|
|
14
|
+
cancelled: @cancelled
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module K3CloudWebapiSdk
|
|
2
|
+
module Util
|
|
3
|
+
module Base64Util
|
|
4
|
+
CHARSET = ('A'..'Z').to_a.join + ('a'..'z').to_a.join + ('0'..'9').to_a.join + '+/'
|
|
5
|
+
|
|
6
|
+
# Custom base64 encode (Ruby equivalent of Python's base64_util.py)
|
|
7
|
+
def self.encode(origin_bytes)
|
|
8
|
+
return '' if origin_bytes.nil? || origin_bytes.empty?
|
|
9
|
+
|
|
10
|
+
# Convert to binary string
|
|
11
|
+
base64_bytes = origin_bytes.bytes.map { |b| b.to_s(2).rjust(8, '0') }
|
|
12
|
+
|
|
13
|
+
resp = ''
|
|
14
|
+
nums = base64_bytes.length / 3
|
|
15
|
+
remain = base64_bytes.length % 3
|
|
16
|
+
|
|
17
|
+
# Process complete 3-byte chunks
|
|
18
|
+
(0...nums).each do |i|
|
|
19
|
+
tmp_unit = base64_bytes[i*3..i*3+2].join('')
|
|
20
|
+
[0, 6, 12, 18].each do |offset|
|
|
21
|
+
value = tmp_unit[offset, 6].to_i(2)
|
|
22
|
+
resp << CHARSET[value]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Handle remaining bytes
|
|
27
|
+
if remain > 0
|
|
28
|
+
remain_part = base64_bytes[nums*3..-1].join('').ljust((3-remain)*8, '0')
|
|
29
|
+
[0, 6, 12, 18].each_with_index do |offset, idx|
|
|
30
|
+
break if idx >= remain + 1
|
|
31
|
+
value = remain_part[offset, 6].to_i(2)
|
|
32
|
+
resp << CHARSET[value]
|
|
33
|
+
end
|
|
34
|
+
resp << '=' * (3 - remain)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
resp
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Custom base64 decode
|
|
41
|
+
def self.decode(base64_str)
|
|
42
|
+
return [] if !valid_base64_str(base64_str)
|
|
43
|
+
|
|
44
|
+
# Remove padding for processing
|
|
45
|
+
chars_to_process = base64_str.gsub('=', '')
|
|
46
|
+
|
|
47
|
+
# Convert to 6-bit chunks
|
|
48
|
+
base64_bytes = chars_to_process.chars.map do |c|
|
|
49
|
+
CHARSET.index(c).to_s(2).rjust(6, '0')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
resp = []
|
|
53
|
+
nums = base64_bytes.length / 4
|
|
54
|
+
remain = base64_bytes.length % 4
|
|
55
|
+
|
|
56
|
+
# Process complete 4-chunk units
|
|
57
|
+
(0...nums).each do |i|
|
|
58
|
+
tmp_unit = base64_bytes[i*4..i*4+3].join('')
|
|
59
|
+
[0, 8, 16].each do |offset|
|
|
60
|
+
value = tmp_unit[offset, 8].to_i(2)
|
|
61
|
+
resp << value
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Handle remaining chunks
|
|
66
|
+
if remain > 0
|
|
67
|
+
remain_part = base64_bytes[nums*4..-1].join('')
|
|
68
|
+
(0...remain-1).each do |i|
|
|
69
|
+
value = remain_part[i*8, 8].to_i(2)
|
|
70
|
+
resp << value
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
resp
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Validate base64 string
|
|
78
|
+
def self.valid_base64_str(b_str)
|
|
79
|
+
return false if b_str.length % 4 != 0
|
|
80
|
+
b_str.each_char.all? { |m| CHARSET.include?(m) }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require_relative '../model/api_config'
|
|
2
|
+
|
|
3
|
+
module K3CloudWebapiSdk
|
|
4
|
+
module Util
|
|
5
|
+
module ConfigUtil
|
|
6
|
+
# Initialize configuration from file
|
|
7
|
+
def self.init_config(config_path, config_node)
|
|
8
|
+
raise 'Init config failed: Lack of config path!' if config_path.nil? || config_path.empty?
|
|
9
|
+
raise 'Init config failed: Lack of config node!' if config_node.nil? || config_node.empty?
|
|
10
|
+
|
|
11
|
+
# For Ruby, we'll use a simple YAML-like format or ENV variables
|
|
12
|
+
# In a real implementation, you'd use a config file parser
|
|
13
|
+
assign_api_config = Model::ApiConfig.new
|
|
14
|
+
|
|
15
|
+
# TODO: Implement file parsing for .ini or .yaml files
|
|
16
|
+
# For now, return empty config
|
|
17
|
+
assign_api_config
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Initialize configuration by parameters
|
|
21
|
+
def self.init_config_by_params(acct_id, user_name, app_id, app_secret, server_url,
|
|
22
|
+
lcid = 2052, org_num = 0, connect_timeout = 120,
|
|
23
|
+
request_timeout = 120, proxy = '')
|
|
24
|
+
assign_api_config = Model::ApiConfig.new
|
|
25
|
+
|
|
26
|
+
if !server_url.nil? && !server_url.empty?
|
|
27
|
+
assign_api_config.server_url = server_url
|
|
28
|
+
else
|
|
29
|
+
# Cancel default old gateway, require url input by Ann 2025-01-15
|
|
30
|
+
raise 'ServerUrl is required'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
assign_api_config.dcid = acct_id
|
|
34
|
+
assign_api_config.user_name = user_name
|
|
35
|
+
assign_api_config.app_id = app_id
|
|
36
|
+
assign_api_config.app_secret = app_secret
|
|
37
|
+
assign_api_config.lcid = lcid > 0 ? lcid : 2052
|
|
38
|
+
assign_api_config.org_num = org_num > 0 ? org_num : 0
|
|
39
|
+
assign_api_config.connect_timeout = connect_timeout > 0 ? connect_timeout : 120
|
|
40
|
+
assign_api_config.request_timeout = request_timeout > 0 ? request_timeout : 120
|
|
41
|
+
assign_api_config.proxy = proxy
|
|
42
|
+
|
|
43
|
+
assign_api_config
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require_relative 'base64_util'
|
|
2
|
+
|
|
3
|
+
module K3CloudWebapiSdk
|
|
4
|
+
module Util
|
|
5
|
+
module EncodeUtil
|
|
6
|
+
# Decode application secret
|
|
7
|
+
def self.decode_app_secret(app_secret)
|
|
8
|
+
return '' if app_secret.length != 32
|
|
9
|
+
|
|
10
|
+
base64_decode = Base64Util.decode(app_secret)
|
|
11
|
+
base64_xor = xor_code(base64_decode)
|
|
12
|
+
Base64Util.encode(base64_xor.pack('C*'))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Encode character using ROT13-like cipher
|
|
16
|
+
def self.encode_char(ch)
|
|
17
|
+
if ch =~ /[a-z]/
|
|
18
|
+
((ch.ord - 97 + 13) % 26 + 97).chr
|
|
19
|
+
elsif ch =~ /[A-Z]/
|
|
20
|
+
((ch.ord - 65 + 13) % 26 + 65).chr
|
|
21
|
+
else
|
|
22
|
+
ch
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# ROT function
|
|
27
|
+
def self.rot(s)
|
|
28
|
+
s.chars.map { |c| encode_char(c) }.join('')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
require 'openssl'
|
|
3
|
+
|
|
4
|
+
module K3CloudWebapiSdk
|
|
5
|
+
module Util
|
|
6
|
+
module HmacUtil
|
|
7
|
+
# Calculate HMAC-SHA256 signature (Ruby equivalent of Python's hmac_util.py)
|
|
8
|
+
def self.hmac_sha256(content, sign_key, encode_format = 'utf-8')
|
|
9
|
+
digest = OpenSSL::HMAC.digest('SHA256', sign_key.encode(encode_format), content.encode(encode_format))
|
|
10
|
+
sign_hex = digest.unpack1('H*')
|
|
11
|
+
Base64.strict_encode64([sign_hex].pack('H*'))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'rest-client'
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'securerandom'
|
|
6
|
+
|
|
7
|
+
# Load all modules
|
|
8
|
+
Dir[File.expand_path('../**/*.rb', __FILE__)].each do |file|
|
|
9
|
+
require_relative file.sub(/.*\/lib\//, '')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module K3CloudWebapiSdk
|
|
13
|
+
VERSION = "8.2.0"
|
|
14
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: k3cloud_webapi_sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 8.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Converted from Python SDK
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rest-client
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: json
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.8'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.8'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rake
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '13.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '13.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rspec
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.0'
|
|
68
|
+
description: Ruby SDK for K3Cloud API integration
|
|
69
|
+
email:
|
|
70
|
+
- support@kingdee.com
|
|
71
|
+
executables: []
|
|
72
|
+
extensions: []
|
|
73
|
+
extra_rdoc_files: []
|
|
74
|
+
files:
|
|
75
|
+
- lib/k3cloud_webapi_sdk.rb
|
|
76
|
+
- lib/k3cloud_webapi_sdk/const/const_define.rb
|
|
77
|
+
- lib/k3cloud_webapi_sdk/const/header_param.rb
|
|
78
|
+
- lib/k3cloud_webapi_sdk/core/webapi_client.rb
|
|
79
|
+
- lib/k3cloud_webapi_sdk/main.rb
|
|
80
|
+
- lib/k3cloud_webapi_sdk/model/api_config.rb
|
|
81
|
+
- lib/k3cloud_webapi_sdk/model/cookie.rb
|
|
82
|
+
- lib/k3cloud_webapi_sdk/model/cookie_store.rb
|
|
83
|
+
- lib/k3cloud_webapi_sdk/model/identity.rb
|
|
84
|
+
- lib/k3cloud_webapi_sdk/model/query_param.rb
|
|
85
|
+
- lib/k3cloud_webapi_sdk/util/base64_util.rb
|
|
86
|
+
- lib/k3cloud_webapi_sdk/util/config_util.rb
|
|
87
|
+
- lib/k3cloud_webapi_sdk/util/encode_util.rb
|
|
88
|
+
- lib/k3cloud_webapi_sdk/util/hmac_util.rb
|
|
89
|
+
homepage: https://github.com/kingdee/k3cloud-ruby-sdk
|
|
90
|
+
licenses:
|
|
91
|
+
- MIT
|
|
92
|
+
metadata: {}
|
|
93
|
+
rdoc_options: []
|
|
94
|
+
require_paths:
|
|
95
|
+
- lib
|
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
|
+
requirements:
|
|
98
|
+
- - ">="
|
|
99
|
+
- !ruby/object:Gem::Version
|
|
100
|
+
version: '0'
|
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
|
+
requirements:
|
|
103
|
+
- - ">="
|
|
104
|
+
- !ruby/object:Gem::Version
|
|
105
|
+
version: '0'
|
|
106
|
+
requirements: []
|
|
107
|
+
rubygems_version: 3.6.9
|
|
108
|
+
specification_version: 4
|
|
109
|
+
summary: K3Cloud API Ruby SDK
|
|
110
|
+
test_files: []
|