Pending and shipment fulfillment

This commit is contained in:
Dominic Ferrando
2025-10-17 09:49:13 -04:00
parent 0e57e60f3f
commit 533a957996
3 changed files with 55 additions and 15 deletions
+10 -10
View File
@@ -67,6 +67,9 @@ export const app = new Elysia({ prefix: "/api" })
// WEBHOOKS // WEBHOOKS
.post("/webhook/printful", async ({ body }) => { .post("/webhook/printful", async ({ body }) => {
const payload = body as Printful.Webhook.EventPayload; const payload = body as Printful.Webhook.EventPayload;
console.log("Hit webhook", payload.type);
switch (payload.type) { switch (payload.type) {
case Printful.Webhook.Event.ProductUpdated: { case Printful.Webhook.Event.ProductUpdated: {
const printfulProduct = payload.data.sync_product; const printfulProduct = payload.data.sync_product;
@@ -77,6 +80,11 @@ export const app = new Elysia({ prefix: "/api" })
await WebflowService.Products.remove(payload.data.sync_product.external_id); await WebflowService.Products.remove(payload.data.sync_product.external_id);
break; break;
} }
case Printful.Webhook.Event.PackageShipped: {
const webflowOrderId = payload.data.order.external_id;
await WebflowService.Orders.update(webflowOrderId, { status: "fulfilled" });
break;
}
} }
}) })
.post("/webhook/webflow", async ({ request, body, set }) => { .post("/webhook/webflow", async ({ request, body, set }) => {
@@ -87,12 +95,10 @@ export const app = new Elysia({ prefix: "/api" })
const payload = body as Webflow.Webhook.EventPayload; const payload = body as Webflow.Webhook.EventPayload;
console.log(payload.triggerType);
switch (payload.triggerType) { switch (payload.triggerType) {
case Webflow.Webhook.Event.OrderCreated: { case Webflow.Webhook.Event.OrderCreated: {
const webflowOrder = payload.payload; const webflowOrder = payload.payload;
console.log("Creating printful order...");
await PrintfulService.Orders.create({ await PrintfulService.Orders.create({
external_id: webflowOrder.orderId, external_id: webflowOrder.orderId,
// TODO: derive from webflow // TODO: derive from webflow
@@ -113,17 +119,11 @@ export const app = new Elysia({ prefix: "/api" })
}); });
// set webflow order to pending // set webflow order to pending
webflowOrder.status = "pending";
await WebflowService.Orders.update(webflowOrder.orderId, webflowOrder);
console.log("Complete"); console.log("Complete");
break;
}
case Webflow.Webhook.Event.OrderUpdated: {
// read printful order status
// set webflow order to fulfulled (if indeed printful order got confirmed)
break; break;
} }
} }
+28 -5
View File
@@ -121,10 +121,10 @@ export namespace Printful {
export enum Event { export enum Event {
ProductUpdated = "product_updated", ProductUpdated = "product_updated",
ProductDeleted = "product_deleted" ProductDeleted = "product_deleted",
PackageShipped = "package_shipped"
} }
// product updated
export interface ProductUpdated extends MetaData<Event.ProductUpdated, { export interface ProductUpdated extends MetaData<Event.ProductUpdated, {
sync_product: { sync_product: {
id: number; id: number;
@@ -137,7 +137,6 @@ export namespace Printful {
}; };
}> { } }> { }
// product deleted
export interface ProductDeleted extends MetaData<Event.ProductDeleted, { export interface ProductDeleted extends MetaData<Event.ProductDeleted, {
sync_product: { sync_product: {
id: number; id: number;
@@ -146,7 +145,31 @@ export namespace Printful {
}; };
}> { } }> { }
export type EventPayload = ProductUpdated | ProductDeleted export interface PackageShipped extends MetaData<Event.PackageShipped, {
shipment: {
id: number
status: string
store_id: number
tracking_number: string
tracking_url: string
created_at: string
ship_date: string
shipped_at: string
delivered_at: string
reshipment: boolean
}
order: {
id: number
external_id: string
status: string
store_id: number
dashboard_url: string
created_at: string
updated_at: string
}
}> { }
export type EventPayload = ProductUpdated | ProductDeleted | PackageShipped
} }
} }
@@ -210,7 +233,7 @@ export namespace Webflow {
export namespace Orders { export namespace Orders {
export type Order = { export type Order = {
orderId: string orderId: string
status: string status: "pending" | "unfulfilled" | "fulfilled" | "disputed" | "dispute-lost" | "refunded"
comment: string comment: string
orderComment: string orderComment: string
acceptedOn: string acceptedOn: string
+17
View File
@@ -124,6 +124,23 @@ export default class WebflowService {
} }
} }
static Orders = class {
static async update(webflowOrderId: string, webflowOrder: DeepPartial<Webflow.Orders.Order>) {
const res = await fetch(`${env().API_SITES_URL}/orders/${webflowOrderId}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
...env().AUTH_HEADER
},
body: JSON.stringify(webflowOrder)
});
if (!res.ok) {
throw new FetchError("Failed to update Webflow order", res);
}
}
}
static Util = class { static Util = class {
static verifyWebflowSignature(request: Request, body: unknown) { static verifyWebflowSignature(request: Request, body: unknown) {
try { try {