vantuz 3.3.0 → 3.3.2
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.
- package/cli.js +185 -70
- package/core/agent.js +82 -0
- package/core/ai-provider.js +26 -6
- package/core/automation.js +504 -0
- package/core/channels.js +2 -2
- package/core/eia-monitor.js +14 -6
- package/core/engine.js +319 -90
- package/core/gateway.js +68 -16
- package/core/migrations/001-initial-schema.sql +20 -0
- package/core/openclaw-bridge.js +191 -0
- package/core/scrapers/TrendyolScraper.js +74 -19
- package/package.json +85 -91
- package/platforms/amazon.js +5 -3
- package/platforms/ciceksepeti.js +4 -2
- package/platforms/hepsiburada.js +6 -4
- package/platforms/n11.js +5 -3
- package/platforms/pazarama.js +4 -2
- package/platforms/trendyol.js +3 -3
- package/plugins/vantuz/package.json +2 -2
- package/plugins/vantuz/platforms/_request.js +34 -0
- package/plugins/vantuz/platforms/amazon.js +59 -35
- package/plugins/vantuz/platforms/ciceksepeti.js +14 -9
- package/plugins/vantuz/platforms/hepsiburada.js +14 -9
- package/plugins/vantuz/platforms/index.js +101 -54
- package/plugins/vantuz/platforms/n11.js +91 -34
- package/plugins/vantuz/platforms/pazarama.js +30 -17
- package/plugins/vantuz/platforms/pttavm.js +14 -9
- package/plugins/vantuz/platforms/trendyol.js +16 -11
- package/server/app.js +29 -12
- package/server/public/index.html +2 -2
- package/.openclaw/completions/openclaw.bash +0 -227
- package/.openclaw/completions/openclaw.fish +0 -1552
- package/.openclaw/completions/openclaw.ps1 +0 -1966
- package/.openclaw/completions/openclaw.zsh +0 -3571
- package/.openclaw/gateway.cmd +0 -10
- package/.openclaw/identity/device.json +0 -7
- package/.openclaw/openclaw.json +0 -32
- package/DOCS_TR.md +0 -298
- package/onboard.js +0 -322
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* developer-docs.amazon.com/sp-api
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import axios from 'axios';
|
|
7
|
-
import crypto from 'crypto';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import crypto from 'crypto';
|
|
8
|
+
import { requestWithRetry } from './_request.js';
|
|
8
9
|
|
|
9
10
|
const REGIONS = {
|
|
10
11
|
eu: {
|
|
@@ -29,48 +30,70 @@ export class AmazonAPI {
|
|
|
29
30
|
this.clientSecret = config.clientSecret;
|
|
30
31
|
this.refreshToken = config.refreshToken;
|
|
31
32
|
|
|
32
|
-
this.regionConfig = REGIONS[this.region];
|
|
33
|
-
this.accessToken = null;
|
|
34
|
-
this.tokenExpiry = null;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
this.regionConfig = REGIONS[this.region];
|
|
34
|
+
this.accessToken = null;
|
|
35
|
+
this.tokenExpiry = null;
|
|
36
|
+
this._tokenPromise = null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async _getAccessToken() {
|
|
38
40
|
if (this.accessToken && this.tokenExpiry > Date.now()) {
|
|
39
41
|
return this.accessToken;
|
|
40
42
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const response = await axios.post('https://api.amazon.com/auth/o2/token', {
|
|
44
|
-
grant_type: 'refresh_token',
|
|
45
|
-
refresh_token: this.refreshToken,
|
|
46
|
-
client_id: this.clientId,
|
|
47
|
-
client_secret: this.clientSecret
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
this.accessToken = response.data.access_token;
|
|
51
|
-
this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000;
|
|
52
|
-
return this.accessToken;
|
|
53
|
-
} catch (error) {
|
|
54
|
-
throw new Error('Token alınamadı: ' + error.message);
|
|
43
|
+
if (this._tokenPromise) {
|
|
44
|
+
return await this._tokenPromise;
|
|
55
45
|
}
|
|
46
|
+
|
|
47
|
+
this._tokenPromise = (async () => {
|
|
48
|
+
try {
|
|
49
|
+
const response = await requestWithRetry(axios, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
url: 'https://api.amazon.com/auth/o2/token',
|
|
52
|
+
data: {
|
|
53
|
+
grant_type: 'refresh_token',
|
|
54
|
+
refresh_token: this.refreshToken,
|
|
55
|
+
client_id: this.clientId,
|
|
56
|
+
client_secret: this.clientSecret
|
|
57
|
+
}
|
|
58
|
+
}, {
|
|
59
|
+
retries: 3,
|
|
60
|
+
baseDelayMs: 500,
|
|
61
|
+
maxDelayMs: 4000
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
this.accessToken = response.data.access_token;
|
|
65
|
+
this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000;
|
|
66
|
+
return this.accessToken;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw new Error('Token alınamadı: ' + error.message);
|
|
69
|
+
} finally {
|
|
70
|
+
this._tokenPromise = null;
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
|
|
74
|
+
return await this._tokenPromise;
|
|
56
75
|
}
|
|
57
76
|
|
|
58
77
|
async _request(method, path, data = null, params = null) {
|
|
59
78
|
try {
|
|
60
79
|
const token = await this._getAccessToken();
|
|
61
|
-
const response = await axios
|
|
62
|
-
method,
|
|
63
|
-
url: `${this.regionConfig.endpoint}${path}`,
|
|
64
|
-
headers: {
|
|
65
|
-
'x-amz-access-token': token,
|
|
66
|
-
'Content-Type': 'application/json'
|
|
67
|
-
},
|
|
68
|
-
data,
|
|
69
|
-
params: {
|
|
70
|
-
...params,
|
|
71
|
-
MarketplaceIds: this.regionConfig.marketplace
|
|
72
|
-
}
|
|
73
|
-
}
|
|
80
|
+
const response = await requestWithRetry(axios, {
|
|
81
|
+
method,
|
|
82
|
+
url: `${this.regionConfig.endpoint}${path}`,
|
|
83
|
+
headers: {
|
|
84
|
+
'x-amz-access-token': token,
|
|
85
|
+
'Content-Type': 'application/json'
|
|
86
|
+
},
|
|
87
|
+
data,
|
|
88
|
+
params: {
|
|
89
|
+
...params,
|
|
90
|
+
MarketplaceIds: this.regionConfig.marketplace
|
|
91
|
+
}
|
|
92
|
+
}, {
|
|
93
|
+
retries: 3,
|
|
94
|
+
baseDelayMs: 500,
|
|
95
|
+
maxDelayMs: 4000
|
|
96
|
+
});
|
|
74
97
|
return { success: true, data: response.data };
|
|
75
98
|
} catch (error) {
|
|
76
99
|
return {
|
|
@@ -237,3 +260,4 @@ export const amazonApi = {
|
|
|
237
260
|
async updatePrice(sku, price, region) { return instances[region]?.updatePrice(sku, price); },
|
|
238
261
|
async getOrders(params, region) { return instances[region]?.getOrders(params); }
|
|
239
262
|
};
|
|
263
|
+
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* bayi.ciceksepeti.com
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import axios from 'axios';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { requestWithRetry } from './_request.js';
|
|
7
8
|
|
|
8
9
|
const BASE_URL = 'https://apis.ciceksepeti.com/api/v1';
|
|
9
10
|
|
|
@@ -22,14 +23,18 @@ export class CiceksepetiAPI {
|
|
|
22
23
|
|
|
23
24
|
async _request(method, endpoint, data = null, params = null) {
|
|
24
25
|
try {
|
|
25
|
-
const response = await axios
|
|
26
|
-
method,
|
|
27
|
-
url: `${BASE_URL}${endpoint}`,
|
|
28
|
-
headers: this._headers(),
|
|
29
|
-
data,
|
|
30
|
-
params
|
|
31
|
-
}
|
|
32
|
-
|
|
26
|
+
const response = await requestWithRetry(axios, {
|
|
27
|
+
method,
|
|
28
|
+
url: `${BASE_URL}${endpoint}`,
|
|
29
|
+
headers: this._headers(),
|
|
30
|
+
data,
|
|
31
|
+
params
|
|
32
|
+
}, {
|
|
33
|
+
retries: 3,
|
|
34
|
+
baseDelayMs: 500,
|
|
35
|
+
maxDelayMs: 4000
|
|
36
|
+
});
|
|
37
|
+
return { success: true, data: response.data };
|
|
33
38
|
} catch (error) {
|
|
34
39
|
return {
|
|
35
40
|
success: false,
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* developer.hepsiburada.com
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import axios from 'axios';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { requestWithRetry } from './_request.js';
|
|
7
8
|
|
|
8
9
|
const BASE_URL = 'https://mpop-sit.hepsiburada.com'; // Production: mpop.hepsiburada.com
|
|
9
10
|
const LISTING_URL = 'https://listing-external.hepsiburada.com';
|
|
@@ -27,14 +28,18 @@ export class HepsiburadaAPI {
|
|
|
27
28
|
|
|
28
29
|
async _request(method, url, data = null, params = null) {
|
|
29
30
|
try {
|
|
30
|
-
const response = await axios
|
|
31
|
-
method,
|
|
32
|
-
url,
|
|
33
|
-
headers: this._headers(),
|
|
34
|
-
data,
|
|
35
|
-
params
|
|
36
|
-
}
|
|
37
|
-
|
|
31
|
+
const response = await requestWithRetry(axios, {
|
|
32
|
+
method,
|
|
33
|
+
url,
|
|
34
|
+
headers: this._headers(),
|
|
35
|
+
data,
|
|
36
|
+
params
|
|
37
|
+
}, {
|
|
38
|
+
retries: 3,
|
|
39
|
+
baseDelayMs: 500,
|
|
40
|
+
maxDelayMs: 4000
|
|
41
|
+
});
|
|
42
|
+
return { success: true, data: response.data };
|
|
38
43
|
} catch (error) {
|
|
39
44
|
return {
|
|
40
45
|
success: false,
|
|
@@ -133,68 +133,115 @@ export const platformHub = {
|
|
|
133
133
|
/**
|
|
134
134
|
* Çoklu platform fiyat güncelle
|
|
135
135
|
*/
|
|
136
|
-
async updatePriceMulti(barcode, price, targetPlatforms = 'all') {
|
|
137
|
-
const targets = targetPlatforms === 'all'
|
|
138
|
-
? this.getConnected()
|
|
139
|
-
: targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
|
|
140
|
-
|
|
141
|
-
const results = {};
|
|
142
|
-
|
|
143
|
-
const api = platforms[platform];
|
|
144
|
-
if (api?.isConnected()) {
|
|
145
|
-
results[platform] =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
136
|
+
async updatePriceMulti(barcode, price, targetPlatforms = 'all') {
|
|
137
|
+
const targets = targetPlatforms === 'all'
|
|
138
|
+
? this.getConnected()
|
|
139
|
+
: targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
|
|
140
|
+
|
|
141
|
+
const results = {};
|
|
142
|
+
const tasks = targets.map(async (platform) => {
|
|
143
|
+
const api = platforms[platform];
|
|
144
|
+
if (!api?.isConnected()) {
|
|
145
|
+
results[platform] = { success: false, error: 'Not connected' };
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
results[platform] = await api.updatePrice(barcode, price);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
results[platform] = { success: false, error: error.message };
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
await Promise.allSettled(tasks);
|
|
155
|
+
return results;
|
|
156
|
+
},
|
|
150
157
|
|
|
151
158
|
/**
|
|
152
159
|
* Çoklu platform stok güncelle
|
|
153
160
|
*/
|
|
154
|
-
async updateStockMulti(barcode, quantity, targetPlatforms = 'all') {
|
|
155
|
-
const targets = targetPlatforms === 'all'
|
|
156
|
-
? this.getConnected()
|
|
157
|
-
: targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
|
|
158
|
-
|
|
159
|
-
const results = {};
|
|
160
|
-
|
|
161
|
-
const api = platforms[platform];
|
|
162
|
-
if (api?.isConnected()) {
|
|
163
|
-
results[platform] =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
161
|
+
async updateStockMulti(barcode, quantity, targetPlatforms = 'all') {
|
|
162
|
+
const targets = targetPlatforms === 'all'
|
|
163
|
+
? this.getConnected()
|
|
164
|
+
: targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
|
|
165
|
+
|
|
166
|
+
const results = {};
|
|
167
|
+
const tasks = targets.map(async (platform) => {
|
|
168
|
+
const api = platforms[platform];
|
|
169
|
+
if (!api?.isConnected()) {
|
|
170
|
+
results[platform] = { success: false, error: 'Not connected' };
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
results[platform] = await api.updateStock(barcode, quantity);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
results[platform] = { success: false, error: error.message };
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
await Promise.allSettled(tasks);
|
|
180
|
+
return results;
|
|
181
|
+
},
|
|
168
182
|
|
|
169
183
|
/**
|
|
170
184
|
* Tüm platformlardan sipariş çek
|
|
171
185
|
*/
|
|
172
|
-
async getAllOrders(params = {}) {
|
|
173
|
-
const connected = this.getConnected();
|
|
174
|
-
const allOrders = [];
|
|
175
|
-
|
|
176
|
-
const orderPromises = connected.map(async (platform) => {
|
|
177
|
-
const api = platforms[platform];
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
186
|
+
async getAllOrders(params = {}) {
|
|
187
|
+
const connected = this.getConnected();
|
|
188
|
+
const allOrders = [];
|
|
189
|
+
|
|
190
|
+
const orderPromises = connected.map(async (platform) => {
|
|
191
|
+
const api = platforms[platform];
|
|
192
|
+
try {
|
|
193
|
+
const result = await api.getOrders(params);
|
|
194
|
+
if (!result?.success) return [];
|
|
195
|
+
|
|
196
|
+
const data = result.data;
|
|
197
|
+
let orders = [];
|
|
198
|
+
if (Array.isArray(data?.content)) {
|
|
199
|
+
orders = data.content;
|
|
200
|
+
} else if (Array.isArray(data?.orders)) {
|
|
201
|
+
orders = data.orders;
|
|
202
|
+
} else if (Array.isArray(data)) {
|
|
203
|
+
orders = data;
|
|
204
|
+
} else {
|
|
205
|
+
return [];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return orders.map(order => {
|
|
209
|
+
const normalized = { ...order };
|
|
210
|
+
if (platform === 'n11') {
|
|
211
|
+
if (!normalized.orderNumber && normalized.orderNumber !== 0) {
|
|
212
|
+
normalized.orderNumber = normalized.id;
|
|
213
|
+
}
|
|
214
|
+
if (!normalized.customerName) {
|
|
215
|
+
normalized.customerName = normalized.customerfullName || normalized.customerFullName;
|
|
216
|
+
}
|
|
217
|
+
if (!normalized.totalPrice) {
|
|
218
|
+
normalized.totalPrice = normalized.totalAmount || normalized.totalPrice;
|
|
219
|
+
}
|
|
220
|
+
if (!normalized.status) {
|
|
221
|
+
normalized.status = normalized.shipmentPackageStatus || normalized.status;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
...normalized,
|
|
226
|
+
_platform: platform,
|
|
227
|
+
_icon: this.getIcon(platform)
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
} catch {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const results = await Promise.allSettled(orderPromises);
|
|
236
|
+
results.forEach(platformOrders => {
|
|
237
|
+
if (platformOrders.status === 'fulfilled') {
|
|
238
|
+
allOrders.push(...platformOrders.value);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Tarihe göre sırala
|
|
243
|
+
allOrders.sort((a, b) => new Date(b.createdDate || b.orderDate) - new Date(a.createdDate || a.orderDate));
|
|
244
|
+
return allOrders;
|
|
198
245
|
}
|
|
199
246
|
};
|
|
200
247
|
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* api.n11.com/ws/*.wsdl
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import axios from 'axios';
|
|
7
|
-
import { parseStringPromise, Builder } from 'xml2js';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { parseStringPromise, Builder } from 'xml2js';
|
|
8
|
+
import { requestWithRetry } from './_request.js';
|
|
8
9
|
|
|
9
10
|
const WSDL_URLS = {
|
|
10
11
|
product: 'https://api.n11.com/ws/ProductService.wsdl',
|
|
@@ -14,14 +15,16 @@ const WSDL_URLS = {
|
|
|
14
15
|
city: 'https://api.n11.com/ws/CityService.wsdl'
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
const SOAP_ENDPOINTS = {
|
|
18
|
-
product: 'https://api.n11.com/ws/ProductService',
|
|
19
|
-
order: 'https://api.n11.com/ws/OrderService',
|
|
20
|
-
shipment: 'https://api.n11.com/ws/ShipmentService',
|
|
21
|
-
category: 'https://api.n11.com/ws/CategoryService'
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
const SOAP_ENDPOINTS = {
|
|
19
|
+
product: 'https://api.n11.com/ws/ProductService',
|
|
20
|
+
order: 'https://api.n11.com/ws/OrderService',
|
|
21
|
+
shipment: 'https://api.n11.com/ws/ShipmentService',
|
|
22
|
+
category: 'https://api.n11.com/ws/CategoryService'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const REST_BASE = 'https://api.n11.com/rest';
|
|
26
|
+
|
|
27
|
+
export class N11API {
|
|
25
28
|
constructor(config) {
|
|
26
29
|
this.apiKey = config.apiKey;
|
|
27
30
|
this.apiSecret = config.apiSecret;
|
|
@@ -47,15 +50,22 @@ export class N11API {
|
|
|
47
50
|
</SOAP-ENV:Envelope>`;
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
async _soapRequest(service, method, body = '') {
|
|
53
|
+
async _soapRequest(service, method, body = '') {
|
|
51
54
|
try {
|
|
52
55
|
const envelope = this._buildSoapEnvelope(service, method, body);
|
|
53
|
-
const response = await axios
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
const response = await requestWithRetry(axios, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
url: SOAP_ENDPOINTS[service],
|
|
59
|
+
data: envelope,
|
|
60
|
+
headers: {
|
|
61
|
+
'Content-Type': 'text/xml; charset=utf-8',
|
|
62
|
+
'SOAPAction': `${method}`
|
|
63
|
+
}
|
|
64
|
+
}, {
|
|
65
|
+
retries: 3,
|
|
66
|
+
baseDelayMs: 500,
|
|
67
|
+
maxDelayMs: 4000
|
|
68
|
+
});
|
|
59
69
|
|
|
60
70
|
const result = await parseStringPromise(response.data, { explicitArray: false });
|
|
61
71
|
const bodyKey = Object.keys(result['SOAP-ENV:Envelope']['SOAP-ENV:Body'])[0];
|
|
@@ -69,7 +79,31 @@ export class N11API {
|
|
|
69
79
|
error: error.response?.data || error.message
|
|
70
80
|
};
|
|
71
81
|
}
|
|
72
|
-
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async _restRequest(method, path, params = {}) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await requestWithRetry(axios, {
|
|
87
|
+
method,
|
|
88
|
+
url: `${REST_BASE}${path}`,
|
|
89
|
+
headers: {
|
|
90
|
+
appkey: this.apiKey,
|
|
91
|
+
appsecret: this.apiSecret
|
|
92
|
+
},
|
|
93
|
+
params
|
|
94
|
+
}, {
|
|
95
|
+
retries: 3,
|
|
96
|
+
baseDelayMs: 500,
|
|
97
|
+
maxDelayMs: 4000
|
|
98
|
+
});
|
|
99
|
+
return { success: true, data: response.data };
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: error.response?.data || error.message
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
73
107
|
|
|
74
108
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
75
109
|
// ÜRÜN İŞLEMLERİ
|
|
@@ -161,22 +195,45 @@ export class N11API {
|
|
|
161
195
|
// SİPARİŞ İŞLEMLERİ
|
|
162
196
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
163
197
|
|
|
164
|
-
async getOrders(params = {}) {
|
|
165
|
-
const {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
198
|
+
async getOrders(params = {}) {
|
|
199
|
+
const {
|
|
200
|
+
status,
|
|
201
|
+
allStatuses = false,
|
|
202
|
+
startDate,
|
|
203
|
+
endDate,
|
|
204
|
+
page = 0,
|
|
205
|
+
size = 100,
|
|
206
|
+
orderNumber,
|
|
207
|
+
packageIds,
|
|
208
|
+
orderByField,
|
|
209
|
+
orderByDirection
|
|
210
|
+
} = params;
|
|
211
|
+
|
|
212
|
+
const now = Date.now();
|
|
213
|
+
const fifteenDaysMs = 15 * 24 * 60 * 60 * 1000;
|
|
214
|
+
const effectiveStart = startDate ?? (endDate ? endDate - fifteenDaysMs : now - fifteenDaysMs);
|
|
215
|
+
const effectiveEnd = endDate ?? (startDate ? startDate + fifteenDaysMs : now);
|
|
216
|
+
const effectiveStatus = allStatuses ? undefined : (status ?? (orderNumber || packageIds ? undefined : 'Created'));
|
|
217
|
+
const requestParams = {
|
|
218
|
+
status: effectiveStatus,
|
|
219
|
+
startDate: effectiveStart,
|
|
220
|
+
endDate: effectiveEnd,
|
|
221
|
+
page,
|
|
222
|
+
size: Math.min(Number(size) || 100, 100),
|
|
223
|
+
orderNumber,
|
|
224
|
+
packageIds,
|
|
225
|
+
orderByField,
|
|
226
|
+
orderByDirection
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
Object.keys(requestParams).forEach(key => {
|
|
230
|
+
if (requestParams[key] === undefined || requestParams[key] === null || requestParams[key] === '') {
|
|
231
|
+
delete requestParams[key];
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
return await this._restRequest('GET', '/delivery/v1/shipmentPackages', requestParams);
|
|
236
|
+
}
|
|
180
237
|
|
|
181
238
|
async getOrderDetail(orderId) {
|
|
182
239
|
return await this._soapRequest('order', 'OrderDetail', `
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* sellers.pazarama.com
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import axios from 'axios';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { requestWithRetry } from './_request.js';
|
|
7
8
|
|
|
8
9
|
const BASE_URL = 'https://isortagimapi.pazarama.com/api';
|
|
9
10
|
const AUTH_URL = 'https://isortagimapi.pazarama.com/oauth/token';
|
|
@@ -22,11 +23,19 @@ export class PazaramaAPI {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
try {
|
|
25
|
-
const response = await axios
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const response = await requestWithRetry(axios, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
url: AUTH_URL,
|
|
29
|
+
data: {
|
|
30
|
+
grant_type: 'client_credentials',
|
|
31
|
+
client_id: this.clientId,
|
|
32
|
+
client_secret: this.clientSecret
|
|
33
|
+
}
|
|
34
|
+
}, {
|
|
35
|
+
retries: 3,
|
|
36
|
+
baseDelayMs: 500,
|
|
37
|
+
maxDelayMs: 4000
|
|
38
|
+
});
|
|
30
39
|
|
|
31
40
|
this.accessToken = response.data.access_token;
|
|
32
41
|
this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000;
|
|
@@ -39,17 +48,21 @@ export class PazaramaAPI {
|
|
|
39
48
|
async _request(method, endpoint, data = null, params = null) {
|
|
40
49
|
try {
|
|
41
50
|
const token = await this._getAccessToken();
|
|
42
|
-
const response = await axios
|
|
43
|
-
method,
|
|
44
|
-
url: `${BASE_URL}${endpoint}`,
|
|
45
|
-
headers: {
|
|
46
|
-
'Authorization': `Bearer ${token}`,
|
|
47
|
-
'Content-Type': 'application/json'
|
|
48
|
-
},
|
|
49
|
-
data,
|
|
50
|
-
params
|
|
51
|
-
}
|
|
52
|
-
|
|
51
|
+
const response = await requestWithRetry(axios, {
|
|
52
|
+
method,
|
|
53
|
+
url: `${BASE_URL}${endpoint}`,
|
|
54
|
+
headers: {
|
|
55
|
+
'Authorization': `Bearer ${token}`,
|
|
56
|
+
'Content-Type': 'application/json'
|
|
57
|
+
},
|
|
58
|
+
data,
|
|
59
|
+
params
|
|
60
|
+
}, {
|
|
61
|
+
retries: 3,
|
|
62
|
+
baseDelayMs: 500,
|
|
63
|
+
maxDelayMs: 4000
|
|
64
|
+
});
|
|
65
|
+
return { success: true, data: response.data };
|
|
53
66
|
} catch (error) {
|
|
54
67
|
return {
|
|
55
68
|
success: false,
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* pttavm.com/entegrasyon
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import axios from 'axios';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { requestWithRetry } from './_request.js';
|
|
7
8
|
|
|
8
9
|
const BASE_URL = 'https://api.pttavm.com/v1';
|
|
9
10
|
|
|
@@ -24,14 +25,18 @@ export class PttavmAPI {
|
|
|
24
25
|
|
|
25
26
|
async _request(method, endpoint, data = null, params = null) {
|
|
26
27
|
try {
|
|
27
|
-
const response = await axios
|
|
28
|
-
method,
|
|
29
|
-
url: `${BASE_URL}${endpoint}`,
|
|
30
|
-
headers: this._headers(),
|
|
31
|
-
data,
|
|
32
|
-
params
|
|
33
|
-
}
|
|
34
|
-
|
|
28
|
+
const response = await requestWithRetry(axios, {
|
|
29
|
+
method,
|
|
30
|
+
url: `${BASE_URL}${endpoint}`,
|
|
31
|
+
headers: this._headers(),
|
|
32
|
+
data,
|
|
33
|
+
params
|
|
34
|
+
}, {
|
|
35
|
+
retries: 3,
|
|
36
|
+
baseDelayMs: 500,
|
|
37
|
+
maxDelayMs: 4000
|
|
38
|
+
});
|
|
39
|
+
return { success: true, data: response.data };
|
|
35
40
|
} catch (error) {
|
|
36
41
|
return {
|
|
37
42
|
success: false,
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* Rate Limit: 50 req / 10 sec per endpoint
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import axios from 'axios';
|
|
12
|
-
import { log } from '../../../core/ai-provider.js';
|
|
11
|
+
import axios from 'axios';
|
|
12
|
+
import { log } from '../../../core/ai-provider.js';
|
|
13
|
+
import { requestWithRetry } from './_request.js';
|
|
13
14
|
|
|
14
15
|
const BASE_URL = 'https://apigw.trendyol.com/integration';
|
|
15
16
|
const STAGE_URL = 'https://stageapigw.trendyol.com/integration';
|
|
@@ -56,15 +57,19 @@ export class TrendyolAPI {
|
|
|
56
57
|
headers['Content-Type'] = 'application/json';
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
const response = await this.client
|
|
60
|
-
method,
|
|
61
|
-
url,
|
|
62
|
-
headers,
|
|
63
|
-
data,
|
|
64
|
-
params,
|
|
65
|
-
timeout: 30000
|
|
66
|
-
}
|
|
67
|
-
|
|
60
|
+
const response = await requestWithRetry(this.client, {
|
|
61
|
+
method,
|
|
62
|
+
url,
|
|
63
|
+
headers,
|
|
64
|
+
data,
|
|
65
|
+
params,
|
|
66
|
+
timeout: 30000
|
|
67
|
+
}, {
|
|
68
|
+
retries: 3,
|
|
69
|
+
baseDelayMs: 500,
|
|
70
|
+
maxDelayMs: 4000
|
|
71
|
+
});
|
|
72
|
+
return { success: true, data: response.data };
|
|
68
73
|
} catch (error) {
|
|
69
74
|
const errorMsg = error.response?.data?.errors?.[0]?.message || error.message;
|
|
70
75
|
const statusCode = error.response?.status;
|