@things-factory/integration-marketplace 4.2.5 → 4.2.9
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/dist-server/controllers/index.js +1 -0
- package/dist-server/controllers/index.js.map +1 -1
- package/dist-server/controllers/magento/apis/update-order-status.js +6 -6
- package/dist-server/controllers/magento/apis/update-order-status.js.map +1 -1
- package/dist-server/controllers/store-api/index.js +14 -0
- package/dist-server/controllers/store-api/index.js.map +1 -1
- package/dist-server/controllers/tiktok/apis/echo.js +19 -0
- package/dist-server/controllers/tiktok/apis/echo.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-order-document.js +27 -0
- package/dist-server/controllers/tiktok/apis/get-store-order-document.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-order-package.js +47 -0
- package/dist-server/controllers/tiktok/apis/get-store-order-package.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-order-packages.js +39 -0
- package/dist-server/controllers/tiktok/apis/get-store-order-packages.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-order.js +137 -0
- package/dist-server/controllers/tiktok/apis/get-store-order.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-orders.js +47 -0
- package/dist-server/controllers/tiktok/apis/get-store-orders.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-product-attributes.js +30 -0
- package/dist-server/controllers/tiktok/apis/get-store-product-attributes.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-product-categories.js +28 -0
- package/dist-server/controllers/tiktok/apis/get-store-product-categories.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-product.js +91 -0
- package/dist-server/controllers/tiktok/apis/get-store-product.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/get-store-products.js +36 -0
- package/dist-server/controllers/tiktok/apis/get-store-products.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/index.js +26 -0
- package/dist-server/controllers/tiktok/apis/index.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/update-order-status.js +27 -0
- package/dist-server/controllers/tiktok/apis/update-order-status.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/update-store-product-variation-price.js +28 -0
- package/dist-server/controllers/tiktok/apis/update-store-product-variation-price.js.map +1 -0
- package/dist-server/controllers/tiktok/apis/update-store-product-variation-stock.js +32 -0
- package/dist-server/controllers/tiktok/apis/update-store-product-variation-stock.js.map +1 -0
- package/dist-server/controllers/tiktok/client/index.js +15 -0
- package/dist-server/controllers/tiktok/client/index.js.map +1 -0
- package/dist-server/controllers/tiktok/client/signature.js +63 -0
- package/dist-server/controllers/tiktok/client/signature.js.map +1 -0
- package/dist-server/controllers/tiktok/client/tiktok.js +113 -0
- package/dist-server/controllers/tiktok/client/tiktok.js.map +1 -0
- package/dist-server/controllers/tiktok/client/types.js +3 -0
- package/dist-server/controllers/tiktok/client/types.js.map +1 -0
- package/dist-server/controllers/tiktok/index.js +30 -0
- package/dist-server/controllers/tiktok/index.js.map +1 -0
- package/dist-server/controllers/tiktok/platform-action.js +44 -0
- package/dist-server/controllers/tiktok/platform-action.js.map +1 -0
- package/dist-server/controllers/woocommerce/apis/get-store-products.js +17 -6
- package/dist-server/controllers/woocommerce/apis/get-store-products.js.map +1 -1
- package/package.json +2 -2
- package/server/controllers/index.ts +1 -0
- package/server/controllers/magento/apis/update-order-status.ts +6 -6
- package/server/controllers/store-api/index.ts +6 -0
- package/server/controllers/tiktok/apis/echo.ts +14 -0
- package/server/controllers/tiktok/apis/get-store-order-document.ts +26 -0
- package/server/controllers/tiktok/apis/get-store-order-package.ts +46 -0
- package/server/controllers/tiktok/apis/get-store-order-packages.ts +43 -0
- package/server/controllers/tiktok/apis/get-store-order.ts +169 -0
- package/server/controllers/tiktok/apis/get-store-orders.ts +52 -0
- package/server/controllers/tiktok/apis/get-store-product-attributes.ts +29 -0
- package/server/controllers/tiktok/apis/get-store-product-categories.ts +27 -0
- package/server/controllers/tiktok/apis/get-store-product.ts +95 -0
- package/server/controllers/tiktok/apis/get-store-products.ts +38 -0
- package/server/controllers/tiktok/apis/index.ts +13 -0
- package/server/controllers/tiktok/apis/update-order-status.ts +22 -0
- package/server/controllers/tiktok/apis/update-store-product-variation-price.ts +24 -0
- package/server/controllers/tiktok/apis/update-store-product-variation-stock.ts +28 -0
- package/server/controllers/tiktok/client/index.ts +2 -0
- package/server/controllers/tiktok/client/signature.ts +78 -0
- package/server/controllers/tiktok/client/tiktok.ts +153 -0
- package/server/controllers/tiktok/client/types.ts +20 -0
- package/server/controllers/tiktok/index.ts +8 -0
- package/server/controllers/tiktok/platform-action.ts +48 -0
- package/server/controllers/woocommerce/apis/get-store-products.ts +33 -22
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import crypto from 'crypto'
|
|
2
|
+
import { Parameter, PublicRequestParameters } from './types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* { key: value } => 'keyvalue'
|
|
6
|
+
* @param {Object} parameters
|
|
7
|
+
* @return {string} concatString
|
|
8
|
+
*/
|
|
9
|
+
const concatObjectKeyValue = (parameters: Parameter): string => {
|
|
10
|
+
if (!parameters) return ''
|
|
11
|
+
return Object.entries(parameters)
|
|
12
|
+
.sort(([k1, v1], [k2, v2]) => (k2 > k1 ? -1 : 1))
|
|
13
|
+
.map(([k, v]) => `${k}${v}`)
|
|
14
|
+
.join('')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Calculate a signature hash
|
|
19
|
+
* @param {string} appSecret
|
|
20
|
+
* @param {string} apiPath e.g. /order/get
|
|
21
|
+
* @param {Object} params
|
|
22
|
+
* @return {string} signature hash
|
|
23
|
+
*/
|
|
24
|
+
export const signRequest = (appSecret: string, apiPath: string, params: Parameter): string => {
|
|
25
|
+
const hash = crypto
|
|
26
|
+
.createHmac('sha256', appSecret)
|
|
27
|
+
.update(appSecret + apiPath + concatObjectKeyValue(params) + appSecret)
|
|
28
|
+
.digest('hex')
|
|
29
|
+
|
|
30
|
+
return hash
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Gather system and business parameters to compute signature
|
|
35
|
+
* @param {string} appKey
|
|
36
|
+
* @param {string} appSecret
|
|
37
|
+
* @param {string} apiPath
|
|
38
|
+
* @param {string?} accessToken
|
|
39
|
+
* @param {Parameter?} payload
|
|
40
|
+
* @return {SystemParameters}
|
|
41
|
+
*/
|
|
42
|
+
export function makePublicRequestParameters(
|
|
43
|
+
appKey: string,
|
|
44
|
+
appSecret: string,
|
|
45
|
+
apiPath: string,
|
|
46
|
+
accessToken: string,
|
|
47
|
+
shopId: string,
|
|
48
|
+
payload?: Parameter
|
|
49
|
+
): PublicRequestParameters {
|
|
50
|
+
const ts = Math.floor(new Date(new Date().toUTCString()).getTime() / 1000).toString()
|
|
51
|
+
|
|
52
|
+
const publicRequestParams: {
|
|
53
|
+
app_key: string
|
|
54
|
+
timestamp: string
|
|
55
|
+
access_token: string
|
|
56
|
+
shop_id?: string
|
|
57
|
+
} = {
|
|
58
|
+
app_key: appKey,
|
|
59
|
+
timestamp: ts,
|
|
60
|
+
access_token: accessToken
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let signatureParams: any = {
|
|
64
|
+
app_key: publicRequestParams.app_key,
|
|
65
|
+
timestamp: publicRequestParams.timestamp
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (shopId) {
|
|
69
|
+
publicRequestParams.shop_id = shopId
|
|
70
|
+
|
|
71
|
+
signatureParams.shop_id = shopId
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
...publicRequestParams,
|
|
76
|
+
sign: signRequest(appSecret, apiPath, { ...payload, ...signatureParams })
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import fetch from 'node-fetch'
|
|
2
|
+
|
|
3
|
+
import { makePublicRequestParameters } from './signature'
|
|
4
|
+
import { Parameter } from './types'
|
|
5
|
+
|
|
6
|
+
const debug = require('debug')('things-factory:integration-marketplace:tiktok')
|
|
7
|
+
|
|
8
|
+
export type TiktokConfig = {
|
|
9
|
+
appKey: string
|
|
10
|
+
appSecret: string
|
|
11
|
+
accessToken: string
|
|
12
|
+
channelShopId: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class Tiktok {
|
|
16
|
+
private config: TiktokConfig
|
|
17
|
+
|
|
18
|
+
constructor(config: TiktokConfig) {
|
|
19
|
+
this.config = {
|
|
20
|
+
...config
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getBaseURL() {
|
|
25
|
+
return `https://open-api.tiktokglobalshop.com`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @summary Get Method
|
|
30
|
+
* @description Using v3 API, map the consumer_key, consumer_secret to the endpoint path.
|
|
31
|
+
* X-WP-Total is to get the total items from the response
|
|
32
|
+
*/
|
|
33
|
+
async get(path: string, params: Parameter) {
|
|
34
|
+
const { appKey, appSecret, accessToken, channelShopId } = this.config
|
|
35
|
+
|
|
36
|
+
const qs = Object.entries({
|
|
37
|
+
...params,
|
|
38
|
+
...makePublicRequestParameters(appKey, appSecret, path, accessToken, channelShopId, params)
|
|
39
|
+
})
|
|
40
|
+
.map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
|
|
41
|
+
.join('&')
|
|
42
|
+
|
|
43
|
+
const endpoint = `${this.getBaseURL()}${path}?${qs ? qs : ''}`
|
|
44
|
+
debug('endpoint', endpoint)
|
|
45
|
+
|
|
46
|
+
const response = await fetch(endpoint, {
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json'
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
var result: any = {}
|
|
53
|
+
const resResult: any = await response.json()
|
|
54
|
+
result.data = resResult.data
|
|
55
|
+
|
|
56
|
+
debug('response result', result)
|
|
57
|
+
|
|
58
|
+
return result
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async post(path: string, data: any = {}) {
|
|
62
|
+
const { appKey, appSecret, accessToken, channelShopId } = this.config
|
|
63
|
+
|
|
64
|
+
debug('data', data)
|
|
65
|
+
|
|
66
|
+
const jsondata = JSON.stringify(data)
|
|
67
|
+
|
|
68
|
+
const { app_key, timestamp, access_token, sign, shop_id } = makePublicRequestParameters(
|
|
69
|
+
appKey,
|
|
70
|
+
appSecret,
|
|
71
|
+
path,
|
|
72
|
+
accessToken,
|
|
73
|
+
channelShopId
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const qs = Object.entries({
|
|
77
|
+
app_key,
|
|
78
|
+
timestamp,
|
|
79
|
+
access_token,
|
|
80
|
+
sign,
|
|
81
|
+
shop_id
|
|
82
|
+
})
|
|
83
|
+
.map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
|
|
84
|
+
.join('&')
|
|
85
|
+
|
|
86
|
+
const endpoint = `${this.getBaseURL()}${path}?${qs ? '&' + qs : ''}`
|
|
87
|
+
const response = await fetch(endpoint, {
|
|
88
|
+
method: 'post',
|
|
89
|
+
headers: {
|
|
90
|
+
'Content-Type': 'application/json'
|
|
91
|
+
},
|
|
92
|
+
body: jsondata
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
if (response.ok) {
|
|
96
|
+
const result = await response.json()
|
|
97
|
+
if (result?.data) {
|
|
98
|
+
return result
|
|
99
|
+
} else {
|
|
100
|
+
throw new Error(`(${result.code}) ${result.message}`)
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
const result = await response.json()
|
|
104
|
+
throw new Error(`(${result.code}) ${result.message}`)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async put(path: string, data: any = {}) {
|
|
109
|
+
const { appKey, appSecret, accessToken, channelShopId } = this.config
|
|
110
|
+
|
|
111
|
+
debug('data', data)
|
|
112
|
+
|
|
113
|
+
const jsondata = JSON.stringify(data)
|
|
114
|
+
|
|
115
|
+
const { app_key, timestamp, access_token, sign } = makePublicRequestParameters(
|
|
116
|
+
appKey,
|
|
117
|
+
appSecret,
|
|
118
|
+
path,
|
|
119
|
+
accessToken,
|
|
120
|
+
channelShopId
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
const qs = Object.entries({
|
|
124
|
+
app_key,
|
|
125
|
+
timestamp,
|
|
126
|
+
access_token,
|
|
127
|
+
sign
|
|
128
|
+
})
|
|
129
|
+
.map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
|
|
130
|
+
.join('&')
|
|
131
|
+
|
|
132
|
+
const endpoint = `${this.getBaseURL()}${path}?${qs ? '&' + qs : ''}`
|
|
133
|
+
const response = await fetch(endpoint, {
|
|
134
|
+
method: 'put',
|
|
135
|
+
headers: {
|
|
136
|
+
'Content-Type': 'application/json'
|
|
137
|
+
},
|
|
138
|
+
body: jsondata
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
if (response.ok) {
|
|
142
|
+
const result = await response.json()
|
|
143
|
+
if (result?.data) {
|
|
144
|
+
return result
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error(`(${result.code}) ${result.message}`)
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
const result = await response.json()
|
|
150
|
+
throw new Error(`(${result.code}) ${result.message}`)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type Parameter = {
|
|
2
|
+
[key: string]: any
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tiktok Open Platform Public Request Parameters
|
|
7
|
+
* @typedef PublicRequestParameters
|
|
8
|
+
* @property {string} timestamp :mandatory
|
|
9
|
+
* @property {string} app_key :mandatory
|
|
10
|
+
* @property {string} access_token :mandatory
|
|
11
|
+
* @property {string} shop_id :mandatory
|
|
12
|
+
* @property {string} sign :mandatory
|
|
13
|
+
*/
|
|
14
|
+
export interface PublicRequestParameters {
|
|
15
|
+
timestamp: string
|
|
16
|
+
app_key: string
|
|
17
|
+
access_token: string
|
|
18
|
+
sign: string
|
|
19
|
+
shop_id?: string
|
|
20
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Tiktok } from './client/tiktok'
|
|
2
|
+
|
|
3
|
+
function substitute(path, obj) {
|
|
4
|
+
var props = []
|
|
5
|
+
var re = /{([^}]+)}/g
|
|
6
|
+
var text
|
|
7
|
+
|
|
8
|
+
while ((text = re.exec(path))) {
|
|
9
|
+
props.push(text[1])
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var result = path
|
|
13
|
+
props.forEach(prop => {
|
|
14
|
+
let value = obj[prop.trim()]
|
|
15
|
+
result = result.replace(`{${prop}}`, value === undefined ? '' : value)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return result
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @summary Building Path Method and Payload
|
|
23
|
+
* @description After denormalise of data is done,
|
|
24
|
+
* platform API method will be called with its path and payload,
|
|
25
|
+
* this section is to build path and substitution of the resource in url as well as the payload for body request.
|
|
26
|
+
* Every Tiktok API call requires consumer_key, consumer_secret, access_token.
|
|
27
|
+
* consumer_key, consumer_secret, access_token are retrieved from tokencraft
|
|
28
|
+
* to avoid permission error from TikTok.
|
|
29
|
+
*/
|
|
30
|
+
export const action = async ({ store, method = 'get', path, request }) => {
|
|
31
|
+
const client = new Tiktok({
|
|
32
|
+
appKey: store.accessKey || '5p6q6g',
|
|
33
|
+
appSecret: store.accessSecret || 'c30cf452265ab418514bb81fa49fc333aecbf081',
|
|
34
|
+
accessToken: store.accessToken,
|
|
35
|
+
channelShopId: store.channelShopId
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const { resource = {}, payload = {} } = request
|
|
39
|
+
|
|
40
|
+
path = substitute(path, resource)
|
|
41
|
+
|
|
42
|
+
var response = await client[method](path, payload)
|
|
43
|
+
if (!response.data) {
|
|
44
|
+
throw response
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return response
|
|
48
|
+
}
|
|
@@ -17,7 +17,6 @@ export function getStoreProducts() {
|
|
|
17
17
|
return { payload }
|
|
18
18
|
},
|
|
19
19
|
async normalize(res, { store }) {
|
|
20
|
-
|
|
21
20
|
const { items, totalItems: totalProducts } = res
|
|
22
21
|
|
|
23
22
|
let results: any[] = []
|
|
@@ -36,13 +35,17 @@ export function getStoreProducts() {
|
|
|
36
35
|
images: product.images.map(image => {
|
|
37
36
|
return image.src
|
|
38
37
|
}),
|
|
39
|
-
attributes:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
attributes:
|
|
39
|
+
product?.attributes?.map(attribute => {
|
|
40
|
+
return {
|
|
41
|
+
attributeId: attribute.id,
|
|
42
|
+
name: attribute.name,
|
|
43
|
+
originalValue: attribute.options,
|
|
44
|
+
native_attribute_id: attribute.id,
|
|
45
|
+
attribute_key: attribute.name,
|
|
46
|
+
values: attribute.options
|
|
47
|
+
}
|
|
48
|
+
}) || [],
|
|
46
49
|
isVerified: product.purchasable,
|
|
47
50
|
variations:
|
|
48
51
|
productVariations.length === 0
|
|
@@ -57,13 +60,17 @@ export function getStoreProducts() {
|
|
|
57
60
|
primaryUnitValue: product.weight === '' ? null : parseFloat(product.weight),
|
|
58
61
|
costPrice: product.price === '' ? null : parseFloat(product.price),
|
|
59
62
|
sellPrice: product.sale_price === '' ? null : parseFloat(product.sale_price),
|
|
60
|
-
attributes:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
attributes:
|
|
64
|
+
product?.attributes?.map(attribute => {
|
|
65
|
+
return {
|
|
66
|
+
attributeId: attribute.id,
|
|
67
|
+
name: attribute.name,
|
|
68
|
+
originalValue: attribute.options,
|
|
69
|
+
native_attribute_id: attribute.id,
|
|
70
|
+
attribute_key: attribute.name,
|
|
71
|
+
values: attribute.options
|
|
72
|
+
}
|
|
73
|
+
}) || [],
|
|
67
74
|
isEnabled: product.purchasable,
|
|
68
75
|
length: product.dimensions.length * 10,
|
|
69
76
|
width: product.dimensions.width * 10,
|
|
@@ -83,13 +90,17 @@ export function getStoreProducts() {
|
|
|
83
90
|
primaryUnitValue: variant.weight === '' ? null : parseFloat(variant.weight),
|
|
84
91
|
costPrice: variant.price === '' ? null : parseFloat(variant.price),
|
|
85
92
|
sellPrice: variant.sale_price === '' ? null : parseFloat(variant.sale_price),
|
|
86
|
-
attributes:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
attributes:
|
|
94
|
+
variant?.attributes?.map(attribute => {
|
|
95
|
+
return {
|
|
96
|
+
attributeId: attribute.id,
|
|
97
|
+
name: attribute.name,
|
|
98
|
+
originalValue: attribute.options,
|
|
99
|
+
native_attribute_id: attribute.id,
|
|
100
|
+
attribute_key: attribute.name,
|
|
101
|
+
values: [attribute.option]
|
|
102
|
+
}
|
|
103
|
+
}) || [],
|
|
93
104
|
isEnabled: variant.purchasable,
|
|
94
105
|
length: variant.dimensions.length * 10,
|
|
95
106
|
width: variant.dimensions.width * 10,
|