Initial commit
This commit is contained in:
266
api/hooks/webhook/post_create.js
Normal file
266
api/hooks/webhook/post_create.js
Normal file
@@ -0,0 +1,266 @@
|
||||
const { bigcommerceApiOAuth, serverBaseURL, bigcommerceStoreHash } = require("../config.js")
|
||||
let { clearSSRCache, createTibiCustomer, updateTibiCustomer } = require("../lib/utils")
|
||||
const {
|
||||
getProductImages,
|
||||
getOrderProductsById,
|
||||
getProductById,
|
||||
getCustomerById,
|
||||
getOrderById,
|
||||
createInternalOrderObject,
|
||||
} = require("../lib/bigcommerceRestAPI.js")
|
||||
const { createPrintfulWebhook, getPrintfulOrderShipments } = require("../lib/printfulRestAPI.js")
|
||||
const { postPurchase } = require("../lib/facebookRestAPI.js")
|
||||
;(function () {
|
||||
const data = context.data
|
||||
if (context?.user?.auth()?.id) {
|
||||
if (context.data.type === "printful") {
|
||||
createPrintfulWebhook(context.data.scope)
|
||||
return
|
||||
} else {
|
||||
let url = `https://api.bigcommerce.com/stores/${bigcommerceStoreHash}/v3/hooks`
|
||||
|
||||
let options = {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", "X-Auth-Token": bigcommerceApiOAuth },
|
||||
body: JSON.stringify({
|
||||
scope: context?.data?.scope,
|
||||
destination: `${serverBaseURL}webhook`,
|
||||
is_active: context?.data?.active,
|
||||
events_history_enabled: true,
|
||||
headers: { token: "super_secure_and_extremely_secret_big_commerce_webhook_token_123" },
|
||||
}),
|
||||
}
|
||||
|
||||
const response = context.http.fetch(url, options).body.json()
|
||||
const hookResponse = {
|
||||
data: context.data,
|
||||
}
|
||||
// @ts-ignore
|
||||
hookResponse.data.webhookId = response.data.id
|
||||
return hookResponse
|
||||
}
|
||||
}
|
||||
if (data) {
|
||||
if (data?.type === "order_updated") {
|
||||
const bigCommerceOrderId = data?.data?.order?.external_id
|
||||
const order = context.db.find("bigCommerceOrder", {
|
||||
filter: {
|
||||
bigCommerceId: Number(bigCommerceOrderId),
|
||||
},
|
||||
})[0]
|
||||
if (order) {
|
||||
context.db.update("bigCommerceOrder", order.id, {
|
||||
status: data?.data?.order?.status,
|
||||
statusSetAt: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
throw {
|
||||
status: 200,
|
||||
data: {
|
||||
message: "",
|
||||
},
|
||||
}
|
||||
} else if (data?.type == "shipment_sent") {
|
||||
const bigCommerceOrderId = data?.data?.order?.external_id
|
||||
|
||||
const printfulOrderShipments = getPrintfulOrderShipments(Number(bigCommerceOrderId))
|
||||
|
||||
const order = context.db.find("bigCommerceOrder", {
|
||||
filter: {
|
||||
bigCommerceId: Number(bigCommerceOrderId),
|
||||
},
|
||||
})[0]
|
||||
if (order) {
|
||||
context.db.update("bigCommerceOrder", order.id, {
|
||||
shipments: (printfulOrderShipments || []).map((shipped) => {
|
||||
return {
|
||||
trackingUrl: shipped.tracking_url,
|
||||
trackingNumber: data?.data?.shipment?.tracking_number,
|
||||
carrier: shipped.carrier,
|
||||
sentAt: new Date(),
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
throw {
|
||||
status: 200,
|
||||
data: {
|
||||
message: "",
|
||||
},
|
||||
}
|
||||
} else if (data?.scope?.includes("product")) {
|
||||
if (data.scope.includes("product/deleted")) {
|
||||
handleProductDeleted(data.data.id)
|
||||
clearSSRCache()
|
||||
} else {
|
||||
const product = getProductById(data?.data?.id)
|
||||
const productImage = getProductImages(data?.data?.id)
|
||||
|
||||
if (data.scope.includes("product/created") && product?.id) {
|
||||
handleProductCreateOrUpdate(product, productImage)
|
||||
}
|
||||
if (data.scope.includes("product/updated") && product?.id) {
|
||||
handleProductCreateOrUpdate(product, productImage)
|
||||
}
|
||||
clearSSRCache()
|
||||
}
|
||||
throw {
|
||||
status: 200,
|
||||
data: {
|
||||
message: "",
|
||||
},
|
||||
}
|
||||
} else if (data?.scope?.includes("order")) {
|
||||
if (data.scope.includes("order/statusUpdated")) {
|
||||
if (data.data.status.new_status_id == 11) {
|
||||
const internalOrderReference = createInternalOrderObject(data.data.id)
|
||||
// make sure the order doesn't already exist
|
||||
const orderExists = context.db.find("bigCommerceOrder", {
|
||||
filter: {
|
||||
bigCommerceId: Number(data.data.id),
|
||||
},
|
||||
})
|
||||
if (!orderExists.length) context.db.create("bigCommerceOrder", internalOrderReference)
|
||||
else context.db.update("bigCommerceOrder", orderExists[0].id, internalOrderReference)
|
||||
/*
|
||||
not necessary for now, as bigcommerce itself takes care of it
|
||||
try {
|
||||
if (!orderExists) {
|
||||
postPurchase(internalOrderReference.cost.replace(",", "."))
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}*/
|
||||
} else {
|
||||
const order = context.db.find("bigCommerceOrder", {
|
||||
filter: {
|
||||
bigCommerceId: data.data.id,
|
||||
},
|
||||
})[0]
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any} orderStatus
|
||||
* @returns {PrintfulStates | false}
|
||||
*/
|
||||
function mapOrderStatusToPrintful(orderStatus) {
|
||||
switch (orderStatus.new_status_id) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 7:
|
||||
case 11:
|
||||
return "draft" // Unvollständig
|
||||
case 6:
|
||||
return "failed" // Abgelehnt
|
||||
case 10:
|
||||
return "fulfilled" // Versandt, Versand ausstehend, Abgeschlossen
|
||||
case 3:
|
||||
return "partial" // Teilweise Versandt, Teilweise erstattet
|
||||
case 12:
|
||||
case 13:
|
||||
return "onhold" // Manuelle Überprüfung erforderlich, Umstritten (closest match)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (order && mapOrderStatusToPrintful(data.data.status) !== false) {
|
||||
context.db.update("bigCommerceOrder", order.id, {
|
||||
status: mapOrderStatusToPrintful(data.data.status),
|
||||
statusSetAt: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
throw {
|
||||
status: 200,
|
||||
data: {
|
||||
message: "",
|
||||
},
|
||||
}
|
||||
} else if (data?.scope?.includes("customer")) {
|
||||
let internalCustomer
|
||||
if (data.data?.id)
|
||||
/** @type {Customer} */
|
||||
internalCustomer =
|
||||
context.db.find("bigCommerceCustomer", {
|
||||
filter: {
|
||||
bigCommerceId: data.data.id,
|
||||
},
|
||||
})?.[0] || null
|
||||
|
||||
if (data.scope.includes("customer/deleted") && !!internalCustomer) {
|
||||
context.db.delete("bigCommerceCustomer", internalCustomer.id)
|
||||
} else {
|
||||
const customer = getCustomerById(data?.data?.id)
|
||||
|
||||
if (!internalCustomer && customer?.id) {
|
||||
createTibiCustomer(customer)
|
||||
} else if (data.scope.includes("customer/updated") && !!internalCustomer) {
|
||||
updateTibiCustomer(customer, internalCustomer)
|
||||
}
|
||||
}
|
||||
throw {
|
||||
status: 200,
|
||||
data: {
|
||||
message: "",
|
||||
},
|
||||
}
|
||||
} else
|
||||
throw {
|
||||
status: 403,
|
||||
error: "Forbidden",
|
||||
}
|
||||
} else
|
||||
throw {
|
||||
status: 403,
|
||||
error: "Forbidden",
|
||||
}
|
||||
})()
|
||||
|
||||
/**
|
||||
* Handles both product creation and update by checking if the product exists and then
|
||||
* creating or updating the record accordingly.
|
||||
*
|
||||
* @param {V2OrderProductsResponseBase} [product] The product data.
|
||||
* @param { ProductImage[]} [productImage] The product image data.
|
||||
*/
|
||||
function handleProductCreateOrUpdate(product, productImage) {
|
||||
const internalProduct =
|
||||
context.db.find("bigCommerceProduct", {
|
||||
filter: {
|
||||
bigCommerceId: Number(product?.id),
|
||||
},
|
||||
})?.[0] || null
|
||||
if (internalProduct) {
|
||||
// If the product exists, update it.
|
||||
context.db.update("bigCommerceProduct", internalProduct.id || "", {
|
||||
productName: product?.name_customer || product?.name,
|
||||
bigCommerceSKU: product?.sku,
|
||||
previewImage: productImage?.[0]?.url_thumbnail,
|
||||
bigCommerceId: Number(product?.id),
|
||||
})
|
||||
} else {
|
||||
// If the product does not exist, create it.
|
||||
context.db.create("bigCommerceProduct", {
|
||||
productName: product?.name_customer || product?.name,
|
||||
bigCommerceSKU: product?.sku,
|
||||
previewImage: productImage?.[0]?.url_thumbnail,
|
||||
bigCommerceId: Number(product?.id),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles product deletion by removing the product record if it exists.
|
||||
* @param { V2OrderProductsResponseBase } [id] The product data to delete.
|
||||
*/
|
||||
function handleProductDeleted(id) {
|
||||
const internalProduct = context.db.find("bigCommerceProduct", {
|
||||
filter: {
|
||||
bigCommerceId: Number(id),
|
||||
},
|
||||
})[0]
|
||||
if (internalProduct) {
|
||||
context.db.delete("bigCommerceProduct", internalProduct.id || "")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user