@things-factory/integration-sellercraft 3.7.0 → 3.8.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.
- package/dist-server/constants/index.js +14 -0
- package/dist-server/constants/index.js.map +1 -0
- package/dist-server/constants/platform.js +7 -0
- package/dist-server/constants/platform.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/echo.js +19 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/echo.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/index.js +19 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/index.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-categories.js +40 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-categories.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-category-attributes.js +48 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-category-attributes.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-order-package.js +46 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-order-package.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-order.js +81 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-order.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-product.js +105 -0
- package/dist-server/controllers/sellercraft-channel-integration/apis/ingest-channel-product.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/index.js +30 -0
- package/dist-server/controllers/sellercraft-channel-integration/index.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/platform-action.js +33 -0
- package/dist-server/controllers/sellercraft-channel-integration/platform-action.js.map +1 -0
- package/dist-server/controllers/sellercraft-channel-integration/sellercraft-channel-integration.js +90 -0
- package/dist-server/controllers/sellercraft-channel-integration/sellercraft-channel-integration.js.map +1 -0
- package/dist-server/controllers/{store-api → sellercraft-channel-integration-api}/decorators.js +2 -2
- package/dist-server/controllers/sellercraft-channel-integration-api/decorators.js.map +1 -0
- package/dist-server/controllers/{store-api → sellercraft-channel-integration-api}/index.js +17 -31
- package/dist-server/controllers/sellercraft-channel-integration-api/index.js.map +1 -0
- package/dist-server/controllers/{store-api → sellercraft-channel-integration-api}/types.js +0 -0
- package/dist-server/controllers/sellercraft-channel-integration-api/types.js.map +1 -0
- package/dist-server/index.js +1 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/routers/sellercraft-router.js +174 -0
- package/dist-server/routers/sellercraft-router.js.map +1 -0
- package/dist-server/routes.js +4 -0
- package/dist-server/routes.js.map +1 -1
- package/package.json +15 -14
- package/server/constants/index.ts +1 -0
- package/server/constants/platform.ts +3 -0
- package/server/controllers/sellercraft-channel-integration/apis/echo.ts +14 -0
- package/server/controllers/sellercraft-channel-integration/apis/index.ts +6 -0
- package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-categories.ts +38 -0
- package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-category-attributes.ts +65 -0
- package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-order-package.ts +58 -0
- package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-order.ts +79 -0
- package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-product.ts +110 -0
- package/server/controllers/sellercraft-channel-integration/index.ts +7 -0
- package/server/controllers/sellercraft-channel-integration/platform-action.ts +39 -0
- package/server/controllers/sellercraft-channel-integration/sellercraft-channel-integration.ts +106 -0
- package/server/controllers/sellercraft-channel-integration-api/decorators.ts +45 -0
- package/server/controllers/sellercraft-channel-integration-api/index.ts +45 -0
- package/server/controllers/sellercraft-channel-integration-api/types.ts +0 -0
- package/server/index.ts +1 -0
- package/server/routers/sellercraft-router.ts +202 -0
- package/server/routes.ts +4 -0
- package/dist-server/controllers/store-api/decorators.js.map +0 -1
- package/dist-server/controllers/store-api/index.js.map +0 -1
- package/dist-server/controllers/store-api/types.js.map +0 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4NjQxODU-initiate-order-shipment */
|
|
2
|
+
|
|
3
|
+
export function ingestChannelProduct() {
|
|
4
|
+
return {
|
|
5
|
+
method: 'post',
|
|
6
|
+
path: '/channel/ingest/product',
|
|
7
|
+
denormalize(req) {
|
|
8
|
+
const { products } = req
|
|
9
|
+
|
|
10
|
+
let newProducts = products.map(product => {
|
|
11
|
+
let productVariations: any[] = product.variations.map(variant => {
|
|
12
|
+
return {
|
|
13
|
+
seller_sku: variant.variationSku,
|
|
14
|
+
native_variant_id: variant.variationId,
|
|
15
|
+
label: variant.name,
|
|
16
|
+
is_enabled: variant.isEnabled,
|
|
17
|
+
is_sellable: variant.isSellable,
|
|
18
|
+
variant_attributes: variant?.attributes
|
|
19
|
+
? variant.attributes.map(attribute => {
|
|
20
|
+
return {
|
|
21
|
+
attribute_key: attribute.id,
|
|
22
|
+
values: []
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
: [],
|
|
26
|
+
stock_locked: variant?.stockLocked ? variant.stockLocked : 0,
|
|
27
|
+
native_stock_reported: variant?.stockReported ? variant.stockReported : 0,
|
|
28
|
+
price_full: variant.fullPrice,
|
|
29
|
+
price_discounted: variant.priceDiscounted,
|
|
30
|
+
price_discounts: variant?.product_discounts
|
|
31
|
+
? variant.product_discounts.map(discount => {
|
|
32
|
+
return {
|
|
33
|
+
price_discounted: discount.priceDiscounted,
|
|
34
|
+
native_discount_id: discount.id,
|
|
35
|
+
name: discount.name
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
: [],
|
|
39
|
+
inventory_products: variant?.inventoryProducts
|
|
40
|
+
? variant.inventoryProducts.map(inventoryProduct => {
|
|
41
|
+
return {
|
|
42
|
+
quantity: inventoryProduct.qty,
|
|
43
|
+
name: inventoryProduct.name,
|
|
44
|
+
inventory_sku: inventoryProduct.sku,
|
|
45
|
+
product_versions: inventoryProduct?.productVersions
|
|
46
|
+
? inventoryProduct.productVersions.map(productVersion => {
|
|
47
|
+
return {
|
|
48
|
+
label: productVersion.label,
|
|
49
|
+
package_content: productVersion.packageContent,
|
|
50
|
+
package_length_mm: productVersion?.packageLengthMM ? productVersion.packageLengthMM : 0,
|
|
51
|
+
package_width_mm: productVersion?.packageWidthMM ? productVersion.packageWidthMM : 0,
|
|
52
|
+
package_height_mm: productVersion?.packageHeightMM ? productVersion.packageHeightMM : 0,
|
|
53
|
+
package_weight_gram: productVersion?.packageWeightGram
|
|
54
|
+
? productVersion.packageWeightGram
|
|
55
|
+
: 0,
|
|
56
|
+
stock_available: productVersion.qty
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
: []
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
: []
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
organisation_id: product.organisationId,
|
|
68
|
+
channel_shop_id: product.channelShopId,
|
|
69
|
+
channel_code: product.channelCode,
|
|
70
|
+
channel_country: product.channelCountry,
|
|
71
|
+
native_category_id: product.categoryId,
|
|
72
|
+
native_product_id: product.productId,
|
|
73
|
+
label: product.name,
|
|
74
|
+
brand: product.brand,
|
|
75
|
+
is_verified: product.isVerified,
|
|
76
|
+
images: product.images.map(image => {
|
|
77
|
+
return {
|
|
78
|
+
file_url: image.url
|
|
79
|
+
}
|
|
80
|
+
}),
|
|
81
|
+
product_attributes: product.attributes.map(attribute => {
|
|
82
|
+
return {
|
|
83
|
+
native_attribute_id: attribute.id,
|
|
84
|
+
values: []
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
payload: {}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
normalize(res) {
|
|
95
|
+
const {
|
|
96
|
+
handover_type: handOverType,
|
|
97
|
+
pickup_time: pickupTime,
|
|
98
|
+
pickup_address: pickupAddress,
|
|
99
|
+
dropoff_address: dropoffAddress
|
|
100
|
+
} = res.data
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
handOverType,
|
|
104
|
+
pickupTime,
|
|
105
|
+
pickupAddress,
|
|
106
|
+
dropoffAddress
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SellercraftChannelIntegrationAPI } from '../sellercraft-channel-integration-api'
|
|
2
|
+
import * as APIS from './apis'
|
|
3
|
+
import { action } from './platform-action'
|
|
4
|
+
|
|
5
|
+
export * from './sellercraft-channel-integration'
|
|
6
|
+
|
|
7
|
+
SellercraftChannelIntegrationAPI.registerPlatform('sellercraftChannelIntegration', action, APIS)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { config } from '@things-factory/env'
|
|
2
|
+
|
|
3
|
+
import { SellercraftChannelIntegration } from './sellercraft-channel-integration'
|
|
4
|
+
|
|
5
|
+
const sellercraftConfig = config.get('sellercraftChannelIntegrationConfig', {})
|
|
6
|
+
const { apiKey } = sellercraftConfig
|
|
7
|
+
|
|
8
|
+
function substitute(path, obj) {
|
|
9
|
+
var props = []
|
|
10
|
+
var re = /{([^}]+)}/g
|
|
11
|
+
var text
|
|
12
|
+
|
|
13
|
+
while ((text = re.exec(path))) {
|
|
14
|
+
props.push(text[1])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
var result = path
|
|
18
|
+
props.forEach(prop => {
|
|
19
|
+
let value = obj[prop.trim()]
|
|
20
|
+
result = result.replace(`{${prop}}`, value === undefined ? '' : value)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return result
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const action = async ({ method = 'get', path, request }) => {
|
|
27
|
+
const client = new SellercraftChannelIntegration({ apiKey })
|
|
28
|
+
|
|
29
|
+
const { resource = {}, payload = {} } = request
|
|
30
|
+
|
|
31
|
+
path = substitute(path, resource)
|
|
32
|
+
|
|
33
|
+
var response = await client[method](path, payload)
|
|
34
|
+
if (response.errors) {
|
|
35
|
+
throw response
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return response
|
|
39
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import fetch from 'node-fetch'
|
|
2
|
+
import uuid from 'uuid/v4'
|
|
3
|
+
|
|
4
|
+
const debug = require('debug')('things-factory:integration-sellercraft:sellercraft')
|
|
5
|
+
|
|
6
|
+
export type SellercraftConfig = {
|
|
7
|
+
apiKey: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class SellercraftChannelIntegration {
|
|
11
|
+
private config: SellercraftConfig
|
|
12
|
+
|
|
13
|
+
constructor(config: SellercraftConfig) {
|
|
14
|
+
this.config = {
|
|
15
|
+
...config
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getBaseUrl() {
|
|
20
|
+
return `https://open.sellercraft.co/v1`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
generateRequestId() {
|
|
24
|
+
return uuid()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async post(path: string, data: any = {}) {
|
|
28
|
+
const { apiKey } = this.config
|
|
29
|
+
|
|
30
|
+
debug('data', data)
|
|
31
|
+
|
|
32
|
+
const jsondata = JSON.stringify(data)
|
|
33
|
+
const requestId: string = this.generateRequestId()
|
|
34
|
+
const fullPath: string = `${this.getBaseUrl()}${path}`
|
|
35
|
+
|
|
36
|
+
const response: any = await fetch(fullPath, {
|
|
37
|
+
method: 'post',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
request_id: requestId,
|
|
41
|
+
'x-api-key': apiKey
|
|
42
|
+
},
|
|
43
|
+
body: jsondata
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (response.ok) {
|
|
47
|
+
return await response.json()
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error(`response code - ${response.status}, ${response.statusText}`)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async put(path: string, data: any = {}) {
|
|
54
|
+
const { apiKey } = this.config
|
|
55
|
+
|
|
56
|
+
const jsondata = JSON.stringify(data)
|
|
57
|
+
const requestId: string = this.generateRequestId()
|
|
58
|
+
const fullPath: string = `${this.getBaseUrl()}${path}`
|
|
59
|
+
debug('data', data)
|
|
60
|
+
|
|
61
|
+
const response: any = await fetch(fullPath, {
|
|
62
|
+
method: 'put',
|
|
63
|
+
headers: {
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
request_id: requestId,
|
|
66
|
+
'x-api-key': apiKey
|
|
67
|
+
},
|
|
68
|
+
body: jsondata
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
if (response.ok) {
|
|
72
|
+
return await response.json()
|
|
73
|
+
} else {
|
|
74
|
+
throw new Error(`response code - ${response.status}, ${response.statusText}`)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async get(path: string, data: any = {}) {
|
|
79
|
+
const { apiKey } = this.config
|
|
80
|
+
|
|
81
|
+
const qs = Object.entries(data)
|
|
82
|
+
.map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
|
|
83
|
+
.join('&')
|
|
84
|
+
|
|
85
|
+
const fullPath: string = `${this.getBaseUrl()}${path}`
|
|
86
|
+
const endpoint = `${fullPath}${qs ? '?' + qs : ''}`
|
|
87
|
+
debug('endpoint', endpoint)
|
|
88
|
+
|
|
89
|
+
const requestId: string = this.generateRequestId()
|
|
90
|
+
|
|
91
|
+
const response: any = await fetch(endpoint, {
|
|
92
|
+
method: 'get',
|
|
93
|
+
headers: {
|
|
94
|
+
'Content-Type': 'application/json',
|
|
95
|
+
request_id: requestId,
|
|
96
|
+
'x-api-key': apiKey
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
if (response.ok) {
|
|
101
|
+
return await response.json()
|
|
102
|
+
} else {
|
|
103
|
+
throw new Error(`response code - ${response.status}, ${response.statusText}`)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import Debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import { Sellercraft } from '../../service'
|
|
4
|
+
|
|
5
|
+
const debug = Debug('things-factory:integration-marketplace:store-api-decorator')
|
|
6
|
+
|
|
7
|
+
const NOOP = v => v
|
|
8
|
+
|
|
9
|
+
export const api = (target: Object, property: string, descriptor: TypedPropertyDescriptor<any>): any => {
|
|
10
|
+
const method = descriptor.value
|
|
11
|
+
|
|
12
|
+
descriptor.value = async function (store: Sellercraft, request) {
|
|
13
|
+
const SellercraftChannelIntegrationAPI = this
|
|
14
|
+
|
|
15
|
+
var { platform } = store
|
|
16
|
+
|
|
17
|
+
var { action: platformAction, apis } = SellercraftChannelIntegrationAPI.getPlatform(platform)
|
|
18
|
+
|
|
19
|
+
var m = apis[method.name]
|
|
20
|
+
if (!m) {
|
|
21
|
+
throw Error(`Sellercraft doesn't have API ${method.name}`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var {
|
|
25
|
+
path,
|
|
26
|
+
method: httpMethod = 'post',
|
|
27
|
+
denormalize = NOOP,
|
|
28
|
+
normalize = NOOP,
|
|
29
|
+
action = platformAction
|
|
30
|
+
} = m.apply(this, [request])
|
|
31
|
+
|
|
32
|
+
var denormalized = await denormalize(request || {}, { store })
|
|
33
|
+
debug('request', denormalized)
|
|
34
|
+
|
|
35
|
+
var response = await action.apply(this, [
|
|
36
|
+
{ store, method: httpMethod, path, request: denormalized, platformAction }
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
debug('response', response)
|
|
40
|
+
|
|
41
|
+
return await normalize(response, { store })
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return descriptor
|
|
45
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getRepository } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
import { Sellercraft } from '../../service'
|
|
4
|
+
import { api } from './decorators'
|
|
5
|
+
|
|
6
|
+
export class SellercraftChannelIntegrationAPI {
|
|
7
|
+
static platforms = {}
|
|
8
|
+
|
|
9
|
+
static registerPlatform(name, action, apis) {
|
|
10
|
+
SellercraftChannelIntegrationAPI.platforms[name] = {
|
|
11
|
+
action,
|
|
12
|
+
apis
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static getPlatform(name) {
|
|
17
|
+
return SellercraftChannelIntegrationAPI.platforms[name]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static async getSellercraft(id) {
|
|
21
|
+
const repository = getRepository(Sellercraft)
|
|
22
|
+
return await repository.findOne({
|
|
23
|
+
where: { id },
|
|
24
|
+
relations: ['domain']
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@api
|
|
29
|
+
static echo(sellercraft, req): any {}
|
|
30
|
+
|
|
31
|
+
@api
|
|
32
|
+
static ingestChannelCategories(sellercraft, req): any {}
|
|
33
|
+
|
|
34
|
+
@api
|
|
35
|
+
static ingestChannelCategoryAttributes(sellercraft, req): any {}
|
|
36
|
+
|
|
37
|
+
@api
|
|
38
|
+
static ingestChannelOrderPackage(sellercraft, req): any {}
|
|
39
|
+
|
|
40
|
+
@api
|
|
41
|
+
static ingestChannelOrder(sellercraft, req): any {}
|
|
42
|
+
|
|
43
|
+
@api
|
|
44
|
+
static ingestChannelProduct(sellercraft, req): any {}
|
|
45
|
+
}
|
|
File without changes
|
package/server/index.ts
CHANGED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import Router from 'koa-router'
|
|
2
|
+
|
|
3
|
+
import { config } from '@things-factory/env'
|
|
4
|
+
import { StoreAPI } from '@things-factory/integration-marketplace'
|
|
5
|
+
import { PLATFORM } from '../constants'
|
|
6
|
+
|
|
7
|
+
const debug = require('debug')('things-factory:integration-sellercraft:sellercraft-router')
|
|
8
|
+
|
|
9
|
+
export const sellercraftRouter = new Router()
|
|
10
|
+
|
|
11
|
+
sellercraftRouter.post('/sellercraft/store/update-product-price', async (context, next) => {
|
|
12
|
+
const sellercraftChannelIntegrationConfig = config.get('sellercraftChannelIntegrationConfig', {})
|
|
13
|
+
const { apiKey, tokenCraftUrl } = sellercraftChannelIntegrationConfig
|
|
14
|
+
|
|
15
|
+
const xApiKey = context.headers['x-api-key']
|
|
16
|
+
|
|
17
|
+
if (apiKey !== xApiKey) context.throw(400, 'api key validation failed')
|
|
18
|
+
|
|
19
|
+
const requestBody = context.request.body
|
|
20
|
+
|
|
21
|
+
for (var i = 0; i < requestBody.length; i++) {
|
|
22
|
+
var store: any = {} // get from tokencraft
|
|
23
|
+
var result
|
|
24
|
+
|
|
25
|
+
// https://staging-tokencraft.sellercraft.co/v1/get-shop?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=dd9cf3b7-114f-4d74-a7e2-7b524ae086f2
|
|
26
|
+
var fullPath = tokenCraftUrl + '?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=' + requestBody[i].shop_id
|
|
27
|
+
const response: any = await fetch(fullPath, {
|
|
28
|
+
method: 'get',
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
'x-api-key': apiKey
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
if (response.ok) {
|
|
35
|
+
store = await response.json()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let mappedStore: any = {
|
|
39
|
+
accessKey: store.shop.credential.consumer_key,
|
|
40
|
+
accessSecret: store.shop.credential.consumer_secret,
|
|
41
|
+
storeURL: store.shop.credential.store_url,
|
|
42
|
+
platform: PLATFORM[`${store.shop.org_prefix}`]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (requestBody[i].native_variant_id) {
|
|
46
|
+
const req = {
|
|
47
|
+
costPrice: requestBody[i].full_price,
|
|
48
|
+
sellPrice: requestBody[i].sale_price,
|
|
49
|
+
productId: requestBody[i].native_product_id,
|
|
50
|
+
variationId: requestBody[i].native_variant_id
|
|
51
|
+
}
|
|
52
|
+
result = await StoreAPI.updateStoreProductVariationPrice(mappedStore, req)
|
|
53
|
+
} else {
|
|
54
|
+
const req = {
|
|
55
|
+
costPrice: requestBody[i].full_price,
|
|
56
|
+
sellPrice: requestBody[i].sale_price,
|
|
57
|
+
productId: requestBody[i].native_product_id
|
|
58
|
+
}
|
|
59
|
+
result = await StoreAPI.updateStoreProductPrice(mappedStore, req)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
debug(result)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
context.status = 200
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
sellercraftRouter.post('/sellercraft/store/update-product-stock', async (context, next) => {
|
|
69
|
+
const sellercraftChannelIntegrationConfig = config.get('sellercraftChannelIntegrationConfig', {})
|
|
70
|
+
const { apiKey, tokenCraftUrl } = sellercraftChannelIntegrationConfig
|
|
71
|
+
|
|
72
|
+
const xApiKey = context.headers['x-api-key']
|
|
73
|
+
|
|
74
|
+
if (apiKey !== xApiKey) context.throw(400, 'api key validation failed')
|
|
75
|
+
|
|
76
|
+
const requestBody = context.request.body
|
|
77
|
+
for (var i = 0; i < requestBody.length; i++) {
|
|
78
|
+
var store: any = {} // get from tokencraft
|
|
79
|
+
var result
|
|
80
|
+
|
|
81
|
+
// https://staging-tokencraft.sellercraft.co/v1/get-shop?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=dd9cf3b7-114f-4d74-a7e2-7b524ae086f2
|
|
82
|
+
var fullPath = tokenCraftUrl + '?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=' + requestBody[i].shop_id
|
|
83
|
+
const response: any = await fetch(fullPath, {
|
|
84
|
+
method: 'get',
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
'x-api-key': apiKey
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
if (response.ok) {
|
|
91
|
+
store = await response.json()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let mappedStore: any = {
|
|
95
|
+
accessKey: store.shop.credential.consumer_key,
|
|
96
|
+
accessSecret: store.shop.credential.consumer_secret,
|
|
97
|
+
storeURL: store.shop.credential.store_url,
|
|
98
|
+
platform: PLATFORM[`${store.shop.org_prefix}`]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (requestBody[i].native_variant_id) {
|
|
102
|
+
const req = {
|
|
103
|
+
qty: requestBody[i].stock,
|
|
104
|
+
itemId: requestBody[i].native_product_id,
|
|
105
|
+
variationId: requestBody[i].native_variant_id
|
|
106
|
+
}
|
|
107
|
+
result = await StoreAPI.updateStoreProductVariationStock(mappedStore, req)
|
|
108
|
+
} else {
|
|
109
|
+
const req = {
|
|
110
|
+
qty: requestBody[i].stock,
|
|
111
|
+
itemId: requestBody[i].native_product_id
|
|
112
|
+
}
|
|
113
|
+
result = await StoreAPI.updateStoreProductStock(mappedStore, req)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
debug(result)
|
|
117
|
+
}
|
|
118
|
+
context.status = 200
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
sellercraftRouter.post('/sellercraft/store/update-order-status', async (context, next) => {
|
|
122
|
+
const sellercraftChannelIntegrationConfig = config.get('sellercraftChannelIntegrationConfig', {})
|
|
123
|
+
const { apiKey, tokenCraftUrl } = sellercraftChannelIntegrationConfig
|
|
124
|
+
|
|
125
|
+
const xApiKey = context.headers['x-api-key']
|
|
126
|
+
|
|
127
|
+
if (apiKey !== xApiKey) context.throw(400, 'api key validation failed')
|
|
128
|
+
|
|
129
|
+
const requestBody = context.request.body
|
|
130
|
+
var result
|
|
131
|
+
var store: any = {}
|
|
132
|
+
|
|
133
|
+
// https://staging-tokencraft.sellercraft.co/v1/get-shop?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=dd9cf3b7-114f-4d74-a7e2-7b524ae086f2
|
|
134
|
+
var fullPath = tokenCraftUrl + '?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=' + requestBody.shop_id
|
|
135
|
+
const response: any = await fetch(fullPath, {
|
|
136
|
+
method: 'get',
|
|
137
|
+
headers: {
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
'x-api-key': apiKey
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
if (response.ok) {
|
|
143
|
+
store = await response.json()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let mappedStore: any = {
|
|
147
|
+
accessKey: store.shop.credential.consumer_key,
|
|
148
|
+
accessSecret: store.shop.credential.consumer_secret,
|
|
149
|
+
storeURL: store.shop.credential.store_url,
|
|
150
|
+
platform: PLATFORM[`${store.shop.org_prefix}`]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const reqBody = { orderId: requestBody.native_order_id, status: requestBody.order_status }
|
|
154
|
+
|
|
155
|
+
result = await StoreAPI.updateOrder(mappedStore, reqBody)
|
|
156
|
+
debug(result)
|
|
157
|
+
|
|
158
|
+
context.status = 200
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
sellercraftRouter.post('/sellercraft/store/update-product-attribute', async (context, next) => {
|
|
162
|
+
const sellercraftChannelIntegrationConfig = config.get('sellercraftChannelIntegrationConfig', {})
|
|
163
|
+
const { apiKey, tokenCraftUrl } = sellercraftChannelIntegrationConfig
|
|
164
|
+
|
|
165
|
+
const xApiKey = context.headers['x-api-key']
|
|
166
|
+
|
|
167
|
+
if (apiKey !== xApiKey) context.throw(400, 'api key validation failed')
|
|
168
|
+
|
|
169
|
+
const requestBody = context.request.body
|
|
170
|
+
var store: any = {}
|
|
171
|
+
const attributes: any[] = requestBody.attributes
|
|
172
|
+
|
|
173
|
+
// https://staging-tokencraft.sellercraft.co/v1/get-shop?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=dd9cf3b7-114f-4d74-a7e2-7b524ae086f2
|
|
174
|
+
var fullPath = tokenCraftUrl + '?channel_id=4bfb3362-d57c-47f8-8781-007316d179bf&shop_id=' + requestBody.shop_id
|
|
175
|
+
const response: any = await fetch(fullPath, {
|
|
176
|
+
method: 'get',
|
|
177
|
+
headers: {
|
|
178
|
+
'Content-Type': 'application/json',
|
|
179
|
+
'x-api-key': apiKey
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
if (response.ok) {
|
|
183
|
+
store = await response.json()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let mappedStore: any = {
|
|
187
|
+
accessKey: store.shop.credential.consumer_key,
|
|
188
|
+
accessSecret: store.shop.credential.consumer_secret,
|
|
189
|
+
storeURL: store.shop.credential.store_url,
|
|
190
|
+
platform: PLATFORM[`${store.shop.org_prefix}`]
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await Promise.all(
|
|
194
|
+
attributes.map(async attribute => {
|
|
195
|
+
const attributeReqBody = { attributeId: attribute.native_attribute_id, name: attribute.attribute_key }
|
|
196
|
+
|
|
197
|
+
await StoreAPI.updateProductAttribute(mappedStore, attributeReqBody)
|
|
198
|
+
})
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
context.status = 200
|
|
202
|
+
})
|
package/server/routes.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { sellercraftRouter } from './routers/sellercraft-router'
|
|
2
|
+
|
|
1
3
|
const debug = require('debug')('things-factory:integration-sellercraft:routes')
|
|
2
4
|
|
|
3
5
|
process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
|
|
@@ -7,6 +9,8 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
|
7
9
|
* ex) routes.get('/path', async(context, next) => {})
|
|
8
10
|
* ex) routes.post('/path', async(context, next) => {})
|
|
9
11
|
*/
|
|
12
|
+
|
|
13
|
+
globalPublicRouter.use(sellercraftRouter.routes(), sellercraftRouter.allowedMethods())
|
|
10
14
|
})
|
|
11
15
|
|
|
12
16
|
process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../../server/controllers/store-api/decorators.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,MAAM,KAAK,GAAG,IAAA,eAAK,EAAC,4DAA4D,CAAC,CAAA;AAIjF,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAEZ,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAE,UAAwC,EAAO,EAAE;IACrG,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAA;IAE/B,UAAU,CAAC,KAAK,GAAG,KAAK,WAAW,KAAkB,EAAE,OAAO;QAC5D,MAAM,cAAc,GAAG,IAAI,CAAA;QAE3B,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;QAExB,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;QAE3E,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACzB,IAAI,CAAC,CAAC,EAAE;YACN,MAAM,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;SAC3D;QAED,IAAI,EACF,IAAI,EACJ,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,WAAW,GAAG,IAAI,EAClB,SAAS,GAAG,IAAI,EAChB,MAAM,GAAG,cAAc,EACxB,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;QAE5B,IAAI,YAAY,GAAG,MAAM,WAAW,CAAC,OAAO,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC9D,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;QAE9B,IAAI,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE;YACtC,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE;SAC3E,CAAC,CAAA;QAEF,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QAE3B,OAAO,MAAM,SAAS,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC7C,CAAC,CAAA;IAED,OAAO,UAAU,CAAA;AACnB,CAAC,CAAA;AApCY,QAAA,GAAG,OAoCf"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/controllers/store-api/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAuC;AACvC,2CAA2C;AAC3C,6CAAkC;AAElC,MAAa,cAAc;IAGzB,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI;QACxC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG;YAC/B,MAAM;YACN,IAAI;SACL,CAAA;IACH,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,IAAI;QACrB,OAAO,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACvC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;QAC5B,MAAM,UAAU,GAAG,IAAA,uBAAa,EAAC,qBAAW,CAAC,CAAA;QAC7C,OAAO,MAAM,UAAU,CAAC,OAAO,CAAC;YAC9B,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,SAAS,EAAE,CAAC,QAAQ,CAAC;SACtB,CAAC,CAAA;IACJ,CAAC;IAGD,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGrC,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGhD,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGnD,MAAM,CAAC,qBAAqB,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGtD,MAAM,CAAC,qBAAqB,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGtD,MAAM,CAAC,oBAAoB,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGrD,MAAM,CAAC,sBAAsB,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;IAGvD,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,IAAQ,CAAC;;AA3CvC,wBAAS,GAAG,EAAE,CAAA;AAsBrB;IADC,gBAAG;;;;gCACiC;AAGrC;IADC,gBAAG;;;;2CAC4C;AAGhD;IADC,gBAAG;;;;8CAC+C;AAGnD;IADC,gBAAG;;;;iDACkD;AAGtD;IADC,gBAAG;;;;iDACkD;AAGtD;IADC,gBAAG;;;;gDACiD;AAGrD;IADC,gBAAG;;;;kDACmD;AAGvD;IADC,gBAAG;;;;yCAC0C;AA5ChD,wCA6CC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../server/controllers/store-api/types.ts"],"names":[],"mappings":""}
|