fix: update order-fulfilled and order-cancelled webhooks to forward to N8N
- Update GraphQL fragments to include languageCode and all necessary fields - Modify order-fulfilled.ts to forward to N8N instead of sending directly - Modify order-cancelled.ts to forward to N8N instead of sending directly - Regenerate GraphQL types with full order data - Enable multi-language emails for shipped and cancelled orders
This commit is contained in:
Generated
+176
-20
File diff suppressed because one or more lines are too long
@@ -2,12 +2,89 @@ fragment OrderCancelledWebhookPayload on OrderCancelled {
|
||||
order {
|
||||
id
|
||||
number
|
||||
created
|
||||
status
|
||||
userEmail
|
||||
languageCode
|
||||
channel {
|
||||
slug
|
||||
}
|
||||
user {
|
||||
email
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
status
|
||||
shippingAddress {
|
||||
firstName
|
||||
lastName
|
||||
streetAddress1
|
||||
streetAddress2
|
||||
city
|
||||
postalCode
|
||||
country {
|
||||
country
|
||||
}
|
||||
phone
|
||||
}
|
||||
billingAddress {
|
||||
firstName
|
||||
lastName
|
||||
streetAddress1
|
||||
streetAddress2
|
||||
city
|
||||
postalCode
|
||||
country {
|
||||
country
|
||||
}
|
||||
phone
|
||||
}
|
||||
lines {
|
||||
id
|
||||
quantity
|
||||
unitPrice {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
totalPrice {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
variant {
|
||||
name
|
||||
sku
|
||||
product {
|
||||
name
|
||||
media {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
subtotal {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
shippingPrice {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
total {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
metadata {
|
||||
key
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,5 +82,9 @@ fragment OrderCreatedWebhookPayload on OrderCreated {
|
||||
currency
|
||||
}
|
||||
}
|
||||
metadata {
|
||||
key
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,95 @@ fragment OrderFulfilledWebhookPayload on OrderFulfilled {
|
||||
order {
|
||||
id
|
||||
number
|
||||
created
|
||||
status
|
||||
userEmail
|
||||
languageCode
|
||||
channel {
|
||||
slug
|
||||
}
|
||||
user {
|
||||
email
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
status
|
||||
shippingAddress {
|
||||
firstName
|
||||
lastName
|
||||
streetAddress1
|
||||
streetAddress2
|
||||
city
|
||||
postalCode
|
||||
country {
|
||||
country
|
||||
}
|
||||
phone
|
||||
}
|
||||
billingAddress {
|
||||
firstName
|
||||
lastName
|
||||
streetAddress1
|
||||
streetAddress2
|
||||
city
|
||||
postalCode
|
||||
country {
|
||||
country
|
||||
}
|
||||
phone
|
||||
}
|
||||
lines {
|
||||
id
|
||||
quantity
|
||||
unitPrice {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
totalPrice {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
variant {
|
||||
name
|
||||
sku
|
||||
product {
|
||||
name
|
||||
media {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
subtotal {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
shippingPrice {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
total {
|
||||
gross {
|
||||
amount
|
||||
currency
|
||||
}
|
||||
}
|
||||
metadata {
|
||||
key
|
||||
value
|
||||
}
|
||||
fulfillments {
|
||||
id
|
||||
status
|
||||
created
|
||||
trackingNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+697
-25
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,9 @@ import {
|
||||
OrderCancelledWebhookPayloadFragment,
|
||||
} from "@/generated/graphql";
|
||||
import { saleorApp } from "@/saleor-app";
|
||||
import { sendOrderCancelledEmail, formatPrice } from "@/lib/resend";
|
||||
|
||||
// N8N webhook URL for Order Cancelled
|
||||
const N8N_WEBHOOK_URL = "https://n8n.nodecrew.me/webhook/saleor-order-cancelled";
|
||||
|
||||
export const orderCancelledWebhook = new SaleorAsyncWebhook<OrderCancelledWebhookPayloadFragment>({
|
||||
name: "Order Cancelled in Saleor",
|
||||
@@ -15,43 +17,29 @@ export const orderCancelledWebhook = new SaleorAsyncWebhook<OrderCancelledWebhoo
|
||||
});
|
||||
|
||||
export default orderCancelledWebhook.createHandler(async (req, res, ctx) => {
|
||||
const { payload, event, baseUrl, authData } = ctx;
|
||||
const order = payload.order;
|
||||
const { payload, event, authData } = ctx;
|
||||
|
||||
if (!order) {
|
||||
console.error("No order data in webhook payload");
|
||||
return res.status(200).end();
|
||||
}
|
||||
|
||||
console.log(`Order ${order.number} cancelled for customer: ${order.userEmail}`);
|
||||
|
||||
const items = ((order as any).lines || []).map((line: any) => ({
|
||||
id: line.id,
|
||||
name: line.variant?.product?.name || "Unknown Product",
|
||||
quantity: line.quantity,
|
||||
price: formatPrice(line.totalPrice?.gross?.amount || 0, line.totalPrice?.gross?.currency || "USD"),
|
||||
}));
|
||||
|
||||
const orderData = {
|
||||
orderId: order.id,
|
||||
orderNumber: order.number || "Unknown",
|
||||
customerName: (order as any).shippingAddress?.firstName
|
||||
? `${(order as any).shippingAddress.firstName} ${(order as any).shippingAddress.lastName || ""}`.trim()
|
||||
: order.userEmail?.split("@")[0] || "Customer",
|
||||
items,
|
||||
total: formatPrice((order as any).total?.gross?.amount || 0, (order as any).total?.gross?.currency || "USD"),
|
||||
};
|
||||
console.log(`Order cancelled: ${payload.order?.number} for ${payload.order?.userEmail}`);
|
||||
console.log(`Forwarding to N8N: ${N8N_WEBHOOK_URL}`);
|
||||
|
||||
try {
|
||||
if (order.userEmail) {
|
||||
await sendOrderCancelledEmail({
|
||||
to: order.userEmail,
|
||||
orderData,
|
||||
// Forward to N8N
|
||||
const response = await fetch(N8N_WEBHOOK_URL, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-saleor-event": "order.cancelled",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
console.log(`Customer notification sent for cancelled order ${order.number}`);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(`N8N returned ${response.status}: ${await response.text()}`);
|
||||
} else {
|
||||
console.log(`Successfully forwarded to N8N: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to send email:", error);
|
||||
console.error(`Failed to forward to N8N:`, error);
|
||||
}
|
||||
|
||||
return res.status(200).end();
|
||||
|
||||
@@ -4,7 +4,9 @@ import {
|
||||
OrderFulfilledWebhookPayloadFragment,
|
||||
} from "@/generated/graphql";
|
||||
import { saleorApp } from "@/saleor-app";
|
||||
import { sendOrderShippedEmail, formatPrice } from "@/lib/resend";
|
||||
|
||||
// N8N webhook URL for Order Fulfilled/Shipped
|
||||
const N8N_WEBHOOK_URL = "https://n8n.nodecrew.me/webhook/saleor-order-shipped";
|
||||
|
||||
export const orderFulfilledWebhook = new SaleorAsyncWebhook<OrderFulfilledWebhookPayloadFragment>({
|
||||
name: "Order Fulfilled in Saleor",
|
||||
@@ -15,42 +17,29 @@ export const orderFulfilledWebhook = new SaleorAsyncWebhook<OrderFulfilledWebhoo
|
||||
});
|
||||
|
||||
export default orderFulfilledWebhook.createHandler(async (req, res, ctx) => {
|
||||
const { payload, event, baseUrl, authData } = ctx;
|
||||
const order = payload.order;
|
||||
const { payload, event, authData } = ctx;
|
||||
|
||||
if (!order) {
|
||||
console.error("No order data in webhook payload");
|
||||
return res.status(200).end();
|
||||
}
|
||||
|
||||
console.log(`Order ${order.number} fulfilled for customer: ${order.userEmail}`);
|
||||
|
||||
const items = ((order as any).lines || []).map((line: any) => ({
|
||||
id: line.id,
|
||||
name: line.variant?.product?.name || "Unknown Product",
|
||||
quantity: line.quantity,
|
||||
price: formatPrice(line.totalPrice?.gross?.amount || 0, line.totalPrice?.gross?.currency || "USD"),
|
||||
}));
|
||||
|
||||
const orderData = {
|
||||
orderId: order.id,
|
||||
orderNumber: order.number || "Unknown",
|
||||
customerName: (order as any).shippingAddress?.firstName
|
||||
? `${(order as any).shippingAddress.firstName} ${(order as any).shippingAddress.lastName || ""}`.trim()
|
||||
: order.userEmail?.split("@")[0] || "Customer",
|
||||
items,
|
||||
};
|
||||
console.log(`Order fulfilled: ${payload.order?.number} for ${payload.order?.userEmail}`);
|
||||
console.log(`Forwarding to N8N: ${N8N_WEBHOOK_URL}`);
|
||||
|
||||
try {
|
||||
if (order.userEmail) {
|
||||
await sendOrderShippedEmail({
|
||||
to: order.userEmail,
|
||||
orderData,
|
||||
// Forward to N8N
|
||||
const response = await fetch(N8N_WEBHOOK_URL, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-saleor-event": "order.fulfilled",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
console.log(`Customer notification sent for fulfilled order ${order.number}`);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(`N8N returned ${response.status}: ${await response.text()}`);
|
||||
} else {
|
||||
console.log(`Successfully forwarded to N8N: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to send email:", error);
|
||||
console.error(`Failed to forward to N8N:`, error);
|
||||
}
|
||||
|
||||
return res.status(200).end();
|
||||
|
||||
Reference in New Issue
Block a user