hookwright 1.2.3 → 1.4.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/cli.js +1128 -158
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ var init_package = __esm({
|
|
|
24
24
|
"package.json"() {
|
|
25
25
|
package_default = {
|
|
26
26
|
name: "hookwright",
|
|
27
|
-
version: "1.
|
|
27
|
+
version: "1.4.0",
|
|
28
28
|
description: "Build real, signed e-commerce webhooks from a live Shopify catalogue \u2014 interactive terminal UI, no backend",
|
|
29
29
|
keywords: [
|
|
30
30
|
"webhook",
|
|
@@ -171,7 +171,11 @@ var DEFAULT_CONFIG = {
|
|
|
171
171
|
targets: {
|
|
172
172
|
"cashfree-occ": { webhookUrl: "", webhookSecret: "" },
|
|
173
173
|
"razorpay-magic": { webhookUrl: "", webhookSecret: "" },
|
|
174
|
-
nitro: { webhookUrl: "", webhookSecret: "" }
|
|
174
|
+
nitro: { webhookUrl: "", webhookSecret: "" },
|
|
175
|
+
shopflo: { webhookUrl: "", webhookSecret: "" },
|
|
176
|
+
flexype: { webhookUrl: "", webhookSecret: "" },
|
|
177
|
+
"return-prime": { webhookUrl: "", webhookSecret: "" },
|
|
178
|
+
fastrr: { webhookUrl: "", webhookSecret: "" }
|
|
175
179
|
},
|
|
176
180
|
customer: {
|
|
177
181
|
firstName: "",
|
|
@@ -407,6 +411,9 @@ function cartPermalink(domain, items) {
|
|
|
407
411
|
function money2(value) {
|
|
408
412
|
return Math.round(Number(value) * 100) / 100;
|
|
409
413
|
}
|
|
414
|
+
function minor(value) {
|
|
415
|
+
return Math.round(Number(value) * 100);
|
|
416
|
+
}
|
|
410
417
|
function normalizeCollection(collection) {
|
|
411
418
|
return {
|
|
412
419
|
id: String(collection.id),
|
|
@@ -603,7 +610,7 @@ var fieldMap2 = [
|
|
|
603
610
|
{ source: "email", target: "email" },
|
|
604
611
|
{ source: "phone", target: "phone", required: true, note: "falls back to Shipping_address.Phone" },
|
|
605
612
|
{ source: "currency", target: "pricing.currency", required: true, note: "read from the ROOT, unlike Cashfree" },
|
|
606
|
-
{ source: "line_items_total", target: "pricing.totalPrice", required: true, note: "
|
|
613
|
+
{ source: "line_items_total", target: "pricing.totalPrice", required: true, note: "a STRING in the smallest currency unit \u2014 the consumer parseFloats it and divides by 100" },
|
|
607
614
|
{ source: "platform", target: "\u2014", note: "documented root field" },
|
|
608
615
|
{ source: "utm_parameters", target: "\u2014", note: "documented root field" },
|
|
609
616
|
{ source: "customer.first_name", target: "customer.firstName" },
|
|
@@ -622,14 +629,15 @@ var fieldMap2 = [
|
|
|
622
629
|
{ source: "customer.Shipping_address.Zip", target: "customer.zip" },
|
|
623
630
|
{ source: "line_items[0].name", target: "cart.productName", required: true },
|
|
624
631
|
{ source: "line_items[0].image_url", target: "cart.image", note: "blank if the product has no image" },
|
|
625
|
-
{ source: "line_items[0].quantity", target: "cart.quantity" }
|
|
632
|
+
{ source: "line_items[0].quantity", target: "cart.quantity" },
|
|
633
|
+
{ source: "line_items[].price", target: "\u2014", note: "smallest currency unit, like line_items_total; the consumer reads no item price" }
|
|
626
634
|
];
|
|
627
635
|
var editableFields2 = [
|
|
628
636
|
{ group: "Checkout", path: "abandoned_checkout_url", label: "Abandoned checkout URL", hint: "must be non-empty \u2014 this is the schema gate" },
|
|
629
637
|
{ group: "Checkout", path: "created_at", label: "Created at" },
|
|
630
638
|
{ group: "Checkout", path: "shop_id", label: "Shop domain" },
|
|
631
639
|
{ group: "Checkout", path: "cart_token", label: "Cart token" },
|
|
632
|
-
{ group: "Pricing", path: "line_items_total", label: "Line items total (
|
|
640
|
+
{ group: "Pricing", path: "line_items_total", label: "Line items total (minor units, string)", hint: "paise for INR, cents for USD; the consumer divides by 100" },
|
|
633
641
|
{ group: "Pricing", path: "currency", label: "Currency" },
|
|
634
642
|
{ group: "Customer", path: "customer.first_name", label: "First name" },
|
|
635
643
|
{ group: "Customer", path: "customer.last_name", label: "Last name" },
|
|
@@ -652,7 +660,7 @@ function buildPayload2(ctx) {
|
|
|
652
660
|
const domain = config.shopify.domain;
|
|
653
661
|
const cust = config.customer;
|
|
654
662
|
const lineItems = items.map(({ product, variant, quantity }) => {
|
|
655
|
-
const price =
|
|
663
|
+
const price = minor(variant?.price ?? 0);
|
|
656
664
|
return {
|
|
657
665
|
image_url: imageForVariant(product, variant),
|
|
658
666
|
name: product.title,
|
|
@@ -670,9 +678,9 @@ function buildPayload2(ctx) {
|
|
|
670
678
|
gram: "0"
|
|
671
679
|
};
|
|
672
680
|
});
|
|
673
|
-
const total =
|
|
674
|
-
const discount =
|
|
675
|
-
const net2 =
|
|
681
|
+
const total = lineItems.reduce((sum, li) => sum + li.price * li.quantity, 0);
|
|
682
|
+
const discount = Math.min(minor(ctx.discount ?? 0), total);
|
|
683
|
+
const net2 = total - discount;
|
|
676
684
|
const checkoutUrl = cartPermalink(domain, items.map(({ variant, quantity }) => ({ variantId: variant?.id, quantity })));
|
|
677
685
|
return {
|
|
678
686
|
shop_id: domain,
|
|
@@ -684,9 +692,9 @@ function buildPayload2(ctx) {
|
|
|
684
692
|
phone,
|
|
685
693
|
abandoned_checkout_url: checkoutUrl,
|
|
686
694
|
currency,
|
|
687
|
-
// Documented as a string, in the smallest currency unit
|
|
695
|
+
// Documented as a string, already in the smallest currency unit.
|
|
688
696
|
// The consumer parses it with parseFloat and divides by 100.
|
|
689
|
-
line_items_total: String(
|
|
697
|
+
line_items_total: String(net2),
|
|
690
698
|
line_items: lineItems,
|
|
691
699
|
tax_details: {},
|
|
692
700
|
promotions: [],
|
|
@@ -743,7 +751,7 @@ function summarize2(payload) {
|
|
|
743
751
|
items: items.map((i) => `${i.name} x${i.quantity}`).join(", "),
|
|
744
752
|
total: Number.parseFloat(payload?.line_items_total ?? "0") / 100,
|
|
745
753
|
currency: payload?.currency,
|
|
746
|
-
extra: `${payload?.line_items_total}
|
|
754
|
+
extra: `${payload?.line_items_total} minor units`,
|
|
747
755
|
link: payload?.abandoned_checkout_url
|
|
748
756
|
};
|
|
749
757
|
}
|
|
@@ -801,7 +809,7 @@ var FIELD_MAPS = {
|
|
|
801
809
|
...PAGE_FIELDS,
|
|
802
810
|
{ source: "eventVal.resource_id", target: "eventVal.resource_id", required: true, note: "the collection id" },
|
|
803
811
|
{ source: "eventVal.resource", target: "eventVal.resource" },
|
|
804
|
-
{ source: "eventVal.
|
|
812
|
+
{ source: "eventVal.resource_id", target: "collection lookup", required: true, note: "the consumer fetches the collection by this id" },
|
|
805
813
|
{ source: "eventVal.domain", target: "eventVal.domain" }
|
|
806
814
|
],
|
|
807
815
|
product_view: [
|
|
@@ -820,7 +828,7 @@ var FIELD_MAPS = {
|
|
|
820
828
|
{ source: "eventVal.init_cart", target: "eventVal.init_cart" },
|
|
821
829
|
{ source: "eventVal.empty_cart", target: "eventVal.empty_cart" },
|
|
822
830
|
{ source: "eventVal.bik_customer_id", target: "eventVal.bik_customer_id" },
|
|
823
|
-
{ source: "eventVal.line_items[0].
|
|
831
|
+
{ source: "eventVal.line_items[0].title", target: "cart enrichment", required: true }
|
|
824
832
|
],
|
|
825
833
|
removefromcart: [
|
|
826
834
|
...COMMON_FIELDS,
|
|
@@ -828,7 +836,7 @@ var FIELD_MAPS = {
|
|
|
828
836
|
{ source: "eventVal.init_cart", target: "eventVal.init_cart" },
|
|
829
837
|
{ source: "eventVal.empty_cart", target: "eventVal.empty_cart" },
|
|
830
838
|
{ source: "eventVal.bik_customer_id", target: "eventVal.bik_customer_id" },
|
|
831
|
-
{ source: "eventVal.line_items[0].
|
|
839
|
+
{ source: "eventVal.line_items[0].title", target: "cart enrichment" }
|
|
832
840
|
],
|
|
833
841
|
checkout: [
|
|
834
842
|
...COMMON_FIELDS,
|
|
@@ -867,7 +875,7 @@ var EDITABLE = {
|
|
|
867
875
|
],
|
|
868
876
|
collection: [
|
|
869
877
|
{ group: "Collection", path: "eventVal.resource_id", label: "Collection id" },
|
|
870
|
-
{ group: "Collection", path: "eventVal.
|
|
878
|
+
{ group: "Collection", path: "eventVal.resource_id", label: "Collection id", type: "number" },
|
|
871
879
|
{ group: "Collection", path: "eventVal.l", label: "Collection URL" }
|
|
872
880
|
],
|
|
873
881
|
product: [
|
|
@@ -912,104 +920,102 @@ function buildPayload3(ctx) {
|
|
|
912
920
|
const session = crypto3.randomBytes(8).toString("hex");
|
|
913
921
|
const first = items[0];
|
|
914
922
|
const lineItems = items.map(({ product, variant, quantity }) => ({
|
|
915
|
-
id: variant ? String(variant.id) : null,
|
|
916
|
-
product_id: String(product.id),
|
|
917
|
-
name: product.title,
|
|
918
|
-
title: product.title,
|
|
919
923
|
quantity,
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
924
|
+
title: product.title,
|
|
925
|
+
line_price: money2((variant?.price ?? 0) * quantity).toFixed(2),
|
|
926
|
+
id: Number(variant?.id ?? product.id),
|
|
927
|
+
product_id: Number(product.id),
|
|
928
|
+
image_url: imageForVariant(product, variant)
|
|
923
929
|
}));
|
|
924
|
-
const cartValue = money2(
|
|
925
|
-
const productUrl = first ? `https://${domain}/products/${first.product.handle ?? ""}` : `https://${domain}`;
|
|
930
|
+
const cartValue = money2(items.reduce((sum, i) => sum + money2(i.variant?.price ?? 0) * i.quantity, 0));
|
|
926
931
|
const customer = {
|
|
927
|
-
phone,
|
|
928
932
|
email: cust.email,
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
last_name: cust.lastName
|
|
933
|
+
phone,
|
|
934
|
+
name: `${cust.firstName} ${cust.lastName}`.trim()
|
|
932
935
|
};
|
|
936
|
+
const pageUrl = eventName === "product_view" ? `https://${domain}/products/${first?.product?.handle ?? ""}` : eventName === "category_view" ? `https://${domain}/collections/${ctx.collection?.handle ?? "all"}` : `https://${domain}/`;
|
|
937
|
+
const isBrowsing = ["view", "category_view", "product_view"].includes(eventName);
|
|
933
938
|
const base = {
|
|
934
|
-
org_token: config.defaults.orgToken ?? crypto3.
|
|
939
|
+
org_token: config.defaults.orgToken ?? crypto3.randomUUID(),
|
|
935
940
|
eventName,
|
|
941
|
+
u: isBrowsing ? pageUrl : "",
|
|
942
|
+
lang: config.defaults.lang ?? "en",
|
|
936
943
|
userId: crypto3.randomUUID(),
|
|
937
944
|
timestamp: now.toISOString(),
|
|
938
945
|
country: cust.countryCode,
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
page: eventName === "product_view" ? "product" : eventName === "category_view" ? "collection" : "home",
|
|
943
|
-
h: domain,
|
|
944
|
-
l: productUrl,
|
|
945
|
-
_ss: session,
|
|
946
|
-
domain
|
|
946
|
+
state: isBrowsing ? cust.province : null,
|
|
947
|
+
city: isBrowsing ? cust.city : null,
|
|
948
|
+
pincode: isBrowsing ? cust.zip : null
|
|
947
949
|
};
|
|
948
950
|
let eventVal;
|
|
949
951
|
switch (eventName) {
|
|
950
952
|
case "view":
|
|
951
|
-
eventVal = { page:
|
|
953
|
+
eventVal = { page: pageUrl, h: domain, l: pageUrl, _ss: session, customer };
|
|
952
954
|
break;
|
|
953
|
-
case "category_view":
|
|
954
|
-
const collection = ctx.collection;
|
|
955
|
+
case "category_view":
|
|
955
956
|
eventVal = {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
resource: "collection",
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
957
|
+
page: pageUrl,
|
|
958
|
+
resource_id: ctx.collection?.id ? Number(ctx.collection.id) : null,
|
|
959
|
+
resource: ctx.collection?.id ? "collection" : null,
|
|
960
|
+
domain,
|
|
961
|
+
h: domain,
|
|
962
|
+
l: pageUrl,
|
|
963
|
+
_ss: session,
|
|
963
964
|
customer
|
|
964
965
|
};
|
|
965
966
|
break;
|
|
966
|
-
}
|
|
967
967
|
case "product_view":
|
|
968
968
|
eventVal = {
|
|
969
|
-
|
|
969
|
+
page: pageUrl,
|
|
970
|
+
resource_id: Number(first?.product?.id ?? 0),
|
|
970
971
|
resource: "product",
|
|
971
|
-
|
|
972
|
-
title: first?.product?.title,
|
|
973
|
-
image: first ? imageForVariant(first.product, first.variant) : void 0,
|
|
972
|
+
domain,
|
|
974
973
|
price: money2(first?.variant?.price ?? 0),
|
|
974
|
+
h: domain,
|
|
975
|
+
l: pageUrl,
|
|
976
|
+
_ss: session,
|
|
977
|
+
image: first ? imageForVariant(first.product, first.variant) : void 0,
|
|
978
|
+
title: first?.product?.title,
|
|
975
979
|
customer
|
|
976
980
|
};
|
|
977
981
|
break;
|
|
978
982
|
case "addtocart":
|
|
979
|
-
case "removefromcart":
|
|
983
|
+
case "removefromcart": {
|
|
984
|
+
const added = eventName === "addtocart";
|
|
980
985
|
eventVal = {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
986
|
+
line_items: added ? lineItems : [],
|
|
987
|
+
cart_value: added ? cartValue : 0,
|
|
988
|
+
recent_product_image: added ? lineItems[0]?.image_url ?? null : null,
|
|
989
|
+
init_cart: false,
|
|
990
|
+
empty_cart: !added,
|
|
991
|
+
items_added: added ? lineItems : [],
|
|
992
|
+
items_removed: added ? [] : lineItems,
|
|
993
|
+
customer,
|
|
994
|
+
bik_customer_id: null
|
|
988
995
|
};
|
|
989
996
|
break;
|
|
997
|
+
}
|
|
990
998
|
case "checkout":
|
|
991
999
|
eventVal = {
|
|
992
1000
|
checkout: cartPermalink(domain, items.map(({ variant, quantity }) => ({ variantId: variant?.id, quantity }))),
|
|
993
|
-
cart_value: cartValue,
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
customer
|
|
1001
|
+
cart_value: cartValue.toFixed(2),
|
|
1002
|
+
customer,
|
|
1003
|
+
bik_customer_id: null
|
|
997
1004
|
};
|
|
998
1005
|
break;
|
|
999
1006
|
case "orders/create":
|
|
1000
1007
|
case "orders/updated": {
|
|
1001
1008
|
const orderNumber = 1e3 + Math.floor(Math.random() * 9e3);
|
|
1002
1009
|
eventVal = {
|
|
1003
|
-
url: `https://${domain}/
|
|
1004
|
-
order_id:
|
|
1010
|
+
url: `https://${domain}/${crypto3.randomBytes(5).toString("hex")}/orders/${crypto3.randomBytes(16).toString("hex")}/authenticate?key=${crypto3.randomBytes(16).toString("hex")}`,
|
|
1011
|
+
order_id: Number(`${Date.now()}`.slice(-13)),
|
|
1005
1012
|
order_number: orderNumber,
|
|
1006
|
-
order_name:
|
|
1007
|
-
price: cartValue,
|
|
1013
|
+
order_name: crypto3.randomBytes(4).toString("hex").toUpperCase(),
|
|
1014
|
+
price: cartValue.toFixed(2),
|
|
1008
1015
|
currency,
|
|
1009
1016
|
order_created_at: now.toISOString(),
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
customer
|
|
1017
|
+
customer,
|
|
1018
|
+
bik_customer_id: null
|
|
1013
1019
|
};
|
|
1014
1020
|
break;
|
|
1015
1021
|
}
|
|
@@ -1039,9 +1045,10 @@ function summarize3(payload) {
|
|
|
1039
1045
|
const items = Array.isArray(ev.line_items) ? ev.line_items : [];
|
|
1040
1046
|
return {
|
|
1041
1047
|
event: payload?.eventName,
|
|
1042
|
-
|
|
1048
|
+
// the schema keeps the domain inside eventVal, not at the root
|
|
1049
|
+
store: payload?.eventVal?.h ?? payload?.eventVal?.domain,
|
|
1043
1050
|
customer: `${ev.customer?.name ?? ""} \xB7 ${ev.customer?.phone ?? ""}`.trim(),
|
|
1044
|
-
items: items.map((i) => `${i.
|
|
1051
|
+
items: items.map((i) => `${i.title} x${i.quantity}`).join(", ") || payload?.eventVal?.title || "\u2014",
|
|
1045
1052
|
total: ev.cart_value ?? ev.price ?? void 0,
|
|
1046
1053
|
currency: ev.currency,
|
|
1047
1054
|
extra: ev.order_name ? `order ${ev.order_name}` : ev.checkout ? "checkout started" : "",
|
|
@@ -1072,6 +1079,981 @@ var nitro_default = {
|
|
|
1072
1079
|
summarize: summarize3
|
|
1073
1080
|
};
|
|
1074
1081
|
|
|
1082
|
+
// src/providers/shopflo.mjs
|
|
1083
|
+
var EVENTS2 = [
|
|
1084
|
+
{ eventName: "store_page_view", type: "shopflo_store_page_view", label: "Store Page View", selection: "none", subject: "a page, no product", envelope: "eventPayload" },
|
|
1085
|
+
{ eventName: "collection_page_viewed", type: "shopflo_collection_page_viewed", label: "Collection Page View", selection: "collection", subject: "one collection", envelope: "data" },
|
|
1086
|
+
{ eventName: "product_page_viewed", type: "shopflo_product_page_viewed", label: "Product Page View", selection: "product", subject: "one product", envelope: "data" },
|
|
1087
|
+
{ eventName: "added_to_cart_ui", type: "shopflo_added_to_cart", label: "Added To Cart", selection: "cart", subject: "cart contents", envelope: "root" },
|
|
1088
|
+
{ eventName: "checkout_clicked", type: "shopflo_checkout_clicked", label: "Checkout Clicked", selection: "cart", subject: "cart contents", envelope: "root" },
|
|
1089
|
+
{ eventName: "checkout_abandoned", type: "shopflo_checkout_abandoned", label: "Abandoned Checkout", selection: "cart", subject: "cart contents", envelope: "root" },
|
|
1090
|
+
{ eventName: "order_completed", type: "shopflo_order_completed", label: "Order Completed", selection: "cart", subject: "ordered items", envelope: "root" }
|
|
1091
|
+
];
|
|
1092
|
+
var DEFAULT_EVENT2 = "checkout_abandoned";
|
|
1093
|
+
var eventDef = (eventName) => EVENTS2.find((e) => e.eventName === eventName) ?? EVENTS2.find((e) => e.eventName === DEFAULT_EVENT2);
|
|
1094
|
+
function eventFromPayload2(payload) {
|
|
1095
|
+
return payload?.event_name ?? payload?.eventName;
|
|
1096
|
+
}
|
|
1097
|
+
function selectionFor2(eventName) {
|
|
1098
|
+
return eventDef(eventName).selection;
|
|
1099
|
+
}
|
|
1100
|
+
var COMMON_FIELDS2 = [
|
|
1101
|
+
{ source: "event_name / eventName", target: "\xABgate\xBB", required: true, note: "the schema matches EITHER spelling" },
|
|
1102
|
+
{ source: "customer.phone / user_data.phone", target: "phone", required: true, note: "missing phone is rejected on every event" }
|
|
1103
|
+
];
|
|
1104
|
+
var BROWSING_FIELDS = [
|
|
1105
|
+
{ source: "uiData.pageUrl / data.page_url", target: "page.url" },
|
|
1106
|
+
{ source: "uiData.pageTitle / data.page_title", target: "page.title" },
|
|
1107
|
+
{ source: "uiData.landingPageUrl", target: "page.landingPage" },
|
|
1108
|
+
{ source: "uiData.referrerPageUrl", target: "page.referrer" },
|
|
1109
|
+
{ source: "clientData.brandUrl", target: "storeUrl" },
|
|
1110
|
+
{ source: "session_id", target: "sessionId" }
|
|
1111
|
+
];
|
|
1112
|
+
var CART_FIELDS = [
|
|
1113
|
+
{ source: "line_items[].title", target: "cart.productName", required: true, note: "the first PAID line wins; freebies rank last" },
|
|
1114
|
+
{ source: "line_items[].product_image", target: "cart.image" },
|
|
1115
|
+
{ source: "line_items[].price", target: "\u2014 (ranking only)", note: "a zero price marks the line a freebie" },
|
|
1116
|
+
{ source: "line_items[].quantity", target: "cart.quantity" },
|
|
1117
|
+
{ source: "total_price", target: "pricing.totalPrice" },
|
|
1118
|
+
{ source: "subtotal_price", target: "pricing.subtotal" },
|
|
1119
|
+
{ source: "total_discount", target: "pricing.totalDiscount" },
|
|
1120
|
+
{ source: "currency", target: "pricing.currency" },
|
|
1121
|
+
{ source: "note_attributes[shopflo_checkout_url]", target: "checkoutUrl", note: "checkout_abandoned puts the link here, not in token_id" }
|
|
1122
|
+
];
|
|
1123
|
+
var FIELD_MAPS2 = {
|
|
1124
|
+
store_page_view: [...COMMON_FIELDS2, ...BROWSING_FIELDS],
|
|
1125
|
+
collection_page_viewed: [...COMMON_FIELDS2, ...BROWSING_FIELDS, { source: "data.collection_page_url", target: "collection.url" }],
|
|
1126
|
+
product_page_viewed: [
|
|
1127
|
+
...COMMON_FIELDS2,
|
|
1128
|
+
...BROWSING_FIELDS,
|
|
1129
|
+
{ source: "data.product_name", target: "product.name" },
|
|
1130
|
+
{ source: "data.product_image", target: "product.image" },
|
|
1131
|
+
{ source: "data.product_url", target: "product.url" },
|
|
1132
|
+
{ source: "data.product_price", target: "product.price" }
|
|
1133
|
+
],
|
|
1134
|
+
added_to_cart_ui: [...COMMON_FIELDS2, ...CART_FIELDS],
|
|
1135
|
+
checkout_clicked: [...COMMON_FIELDS2, ...CART_FIELDS],
|
|
1136
|
+
checkout_abandoned: [...COMMON_FIELDS2, ...CART_FIELDS],
|
|
1137
|
+
order_completed: [
|
|
1138
|
+
...COMMON_FIELDS2,
|
|
1139
|
+
...CART_FIELDS,
|
|
1140
|
+
{ source: "order_id", target: "order.id" },
|
|
1141
|
+
{ source: "order_name", target: "order.name" },
|
|
1142
|
+
{ source: "payment_mode", target: "order.paymentMode" },
|
|
1143
|
+
{ source: "total_payable", target: "order.totalPayable" }
|
|
1144
|
+
]
|
|
1145
|
+
};
|
|
1146
|
+
var fieldMap4 = FIELD_MAPS2[DEFAULT_EVENT2];
|
|
1147
|
+
function editableFieldsFor2(eventName) {
|
|
1148
|
+
const def = eventDef(eventName);
|
|
1149
|
+
const base = [
|
|
1150
|
+
{ group: "Event", path: "session_id", label: "Session id" },
|
|
1151
|
+
{ group: "Customer", path: "customer.first_name", label: "First name" },
|
|
1152
|
+
{ group: "Customer", path: "customer.last_name", label: "Last name" },
|
|
1153
|
+
{ group: "Customer", path: "customer.email", label: "Email" },
|
|
1154
|
+
{ group: "Customer", path: "customer.phone", label: "Phone", hint: "must parse to E.164" }
|
|
1155
|
+
];
|
|
1156
|
+
if (def.envelope === "eventPayload") {
|
|
1157
|
+
return [
|
|
1158
|
+
{ group: "Event", path: "eventPayload.uiData.pageUrl", label: "Page URL" },
|
|
1159
|
+
{ group: "Event", path: "eventPayload.uiData.pageTitle", label: "Page title" },
|
|
1160
|
+
{ group: "Event", path: "eventPayload.clientData.brandUrl", label: "Store URL" },
|
|
1161
|
+
{ group: "Customer", path: "eventPayload.userData.firstName", label: "First name" },
|
|
1162
|
+
{ group: "Customer", path: "eventPayload.userData.email", label: "Email" },
|
|
1163
|
+
{ group: "Customer", path: "eventPayload.userData.phone", label: "Phone", hint: "must parse to E.164" }
|
|
1164
|
+
];
|
|
1165
|
+
}
|
|
1166
|
+
if (def.envelope === "data") {
|
|
1167
|
+
return [
|
|
1168
|
+
{ group: "Event", path: "data.page_url", label: "Page URL" },
|
|
1169
|
+
{ group: "Event", path: "data.page_title", label: "Page title" },
|
|
1170
|
+
{ group: "Customer", path: "data.user_data.firstName", label: "First name" },
|
|
1171
|
+
{ group: "Customer", path: "data.user_data.email", label: "Email" },
|
|
1172
|
+
{ group: "Customer", path: "data.user_data.phone", label: "Phone", hint: "must parse to E.164" }
|
|
1173
|
+
];
|
|
1174
|
+
}
|
|
1175
|
+
return [
|
|
1176
|
+
...base,
|
|
1177
|
+
{ group: "Pricing", path: "total_price", label: "Total price", type: "number" },
|
|
1178
|
+
{ group: "Pricing", path: "subtotal_price", label: "Subtotal", type: "number" },
|
|
1179
|
+
{ group: "Pricing", path: "total_discount", label: "Discount", type: "number" },
|
|
1180
|
+
{ group: "Pricing", path: "currency", label: "Currency" },
|
|
1181
|
+
...def.eventName === "order_completed" ? [
|
|
1182
|
+
{ group: "Order", path: "order_name", label: "Order name" },
|
|
1183
|
+
{ group: "Order", path: "payment_mode", label: "Payment mode" },
|
|
1184
|
+
{ group: "Order", path: "total_payable", label: "Total payable", type: "number" }
|
|
1185
|
+
] : []
|
|
1186
|
+
];
|
|
1187
|
+
}
|
|
1188
|
+
var editableFields4 = editableFieldsFor2(DEFAULT_EVENT2);
|
|
1189
|
+
function buildPayload4(ctx) {
|
|
1190
|
+
const { config, items, phone, collection } = ctx;
|
|
1191
|
+
const eventName = ctx.eventName ?? DEFAULT_EVENT2;
|
|
1192
|
+
const def = eventDef(eventName);
|
|
1193
|
+
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
1194
|
+
const currency = ctx.currency || config.defaults.currency;
|
|
1195
|
+
const domain = config.shopify.domain;
|
|
1196
|
+
const cust = config.customer;
|
|
1197
|
+
const first = items?.[0];
|
|
1198
|
+
if (def.envelope === "eventPayload") {
|
|
1199
|
+
return {
|
|
1200
|
+
eventName,
|
|
1201
|
+
session_id: ctx.sessionId ?? `sf-${now.getTime()}`,
|
|
1202
|
+
channel: "web",
|
|
1203
|
+
eventPayload: {
|
|
1204
|
+
userData: { firstName: cust.firstName, lastName: cust.lastName, email: cust.email, phone },
|
|
1205
|
+
uiData: {
|
|
1206
|
+
pageUrl: `https://${domain}/`,
|
|
1207
|
+
pageTitle: config.shopify.shop?.name ?? domain,
|
|
1208
|
+
landingPageUrl: `https://${domain}/`,
|
|
1209
|
+
referrerPageUrl: ""
|
|
1210
|
+
},
|
|
1211
|
+
clientData: { brandUrl: `https://${domain}` }
|
|
1212
|
+
},
|
|
1213
|
+
timestamp: now.getTime()
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
if (def.envelope === "data") {
|
|
1217
|
+
const isProduct = def.selection === "product";
|
|
1218
|
+
return {
|
|
1219
|
+
event_name: eventName,
|
|
1220
|
+
session_id: ctx.sessionId ?? `sf-${now.getTime()}`,
|
|
1221
|
+
channel: "web",
|
|
1222
|
+
data: {
|
|
1223
|
+
page_url: isProduct ? `https://${domain}/products/${first?.product?.handle ?? ""}` : `https://${domain}/collections/${collection?.handle ?? "all"}`,
|
|
1224
|
+
page_title: isProduct ? first?.product?.title : collection?.title,
|
|
1225
|
+
landing_page_url: `https://${domain}/`,
|
|
1226
|
+
referrer_page_url: "",
|
|
1227
|
+
...isProduct ? {
|
|
1228
|
+
product_name: first?.product?.title,
|
|
1229
|
+
product_image: imageForVariant(first?.product, first?.variant),
|
|
1230
|
+
product_url: `https://${domain}/products/${first?.product?.handle ?? ""}`,
|
|
1231
|
+
product_price: money2(first?.variant?.price ?? 0),
|
|
1232
|
+
product_compare_at_price: money2(first?.variant?.compareAtPrice ?? first?.variant?.price ?? 0),
|
|
1233
|
+
product_type: first?.product?.productType ?? ""
|
|
1234
|
+
} : { collection_page_url: `https://${domain}/collections/${collection?.handle ?? "all"}` },
|
|
1235
|
+
user_data: { firstName: cust.firstName, lastName: cust.lastName, email: cust.email, phone }
|
|
1236
|
+
},
|
|
1237
|
+
timestamp: now.getTime()
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
const lineItems = (items ?? []).map(({ product, variant, quantity }) => ({
|
|
1241
|
+
id: String(variant?.id ?? product.id),
|
|
1242
|
+
product_id: String(product.id),
|
|
1243
|
+
title: product.title,
|
|
1244
|
+
price: money2(variant?.price ?? 0).toFixed(2),
|
|
1245
|
+
quantity,
|
|
1246
|
+
product_image: imageForVariant(product, variant)
|
|
1247
|
+
}));
|
|
1248
|
+
const subtotal = money2(lineItems.reduce((sum, li) => sum + Number(li.price) * li.quantity, 0));
|
|
1249
|
+
const discount = money2(Math.min(ctx.discount ?? 0, subtotal));
|
|
1250
|
+
const total = money2(subtotal - discount);
|
|
1251
|
+
const checkoutUrl = cartPermalink(domain, (items ?? []).map(({ variant, quantity }) => ({ variantId: variant?.id, quantity })));
|
|
1252
|
+
return {
|
|
1253
|
+
event_name: eventName,
|
|
1254
|
+
session_id: ctx.sessionId ?? `sf-${now.getTime()}`,
|
|
1255
|
+
token_id: checkoutUrl,
|
|
1256
|
+
source: "shopflo",
|
|
1257
|
+
channel: "web",
|
|
1258
|
+
email: cust.email,
|
|
1259
|
+
phone,
|
|
1260
|
+
created_at: now.toISOString(),
|
|
1261
|
+
// checkout_abandoned carries the recovery link here; the consumer prefers it
|
|
1262
|
+
note_attributes: [
|
|
1263
|
+
{ name: "landing_page", value: `/products/${items?.[0]?.product?.handle ?? ""}` },
|
|
1264
|
+
{ name: "shopflo_checkout_url", value: checkoutUrl }
|
|
1265
|
+
],
|
|
1266
|
+
line_items: lineItems,
|
|
1267
|
+
customer: { uid: "sf-user", first_name: cust.firstName, last_name: cust.lastName, email: cust.email, phone },
|
|
1268
|
+
currency,
|
|
1269
|
+
subtotal_price: subtotal,
|
|
1270
|
+
total_discount: discount,
|
|
1271
|
+
total_price: total,
|
|
1272
|
+
...eventName === "order_completed" ? {
|
|
1273
|
+
order_id: ctx.orderId ?? Math.floor(now.getTime() / 1e3),
|
|
1274
|
+
order_name: ctx.orderName ?? `#${String(now.getTime()).slice(-5)}`,
|
|
1275
|
+
payment_mode: "prepaid",
|
|
1276
|
+
total_shipping: 0,
|
|
1277
|
+
total_tax: 0,
|
|
1278
|
+
total_payable: total
|
|
1279
|
+
} : {},
|
|
1280
|
+
timestamp: now.getTime()
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
function sign4() {
|
|
1284
|
+
return { signature: null, timestamp: null, headers: { "content-type": "application/json" } };
|
|
1285
|
+
}
|
|
1286
|
+
function webhookUrl4(config) {
|
|
1287
|
+
return String(targetFor(config, "shopflo").webhookUrl ?? "").trim();
|
|
1288
|
+
}
|
|
1289
|
+
function webhookSecret4(config) {
|
|
1290
|
+
return String(targetFor(config, "shopflo").webhookSecret ?? "");
|
|
1291
|
+
}
|
|
1292
|
+
function storeOf(payload) {
|
|
1293
|
+
const brandUrl = payload?.eventPayload?.clientData?.brandUrl;
|
|
1294
|
+
const candidate = brandUrl ?? payload?.token_id;
|
|
1295
|
+
if (!candidate) return void 0;
|
|
1296
|
+
try {
|
|
1297
|
+
return new URL(candidate).host;
|
|
1298
|
+
} catch {
|
|
1299
|
+
return candidate;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
function summarize4(payload) {
|
|
1303
|
+
const name = eventFromPayload2(payload);
|
|
1304
|
+
const items = Array.isArray(payload?.line_items) ? payload.line_items : [];
|
|
1305
|
+
const envelope = payload?.eventPayload ?? payload?.data ?? {};
|
|
1306
|
+
const user = envelope?.userData ?? envelope?.user_data ?? payload?.customer ?? {};
|
|
1307
|
+
return {
|
|
1308
|
+
event: eventDef(name).label.toLowerCase(),
|
|
1309
|
+
store: storeOf(payload),
|
|
1310
|
+
customer: `${user.firstName ?? user.first_name ?? ""} ${user.lastName ?? user.last_name ?? ""} \xB7 ${payload?.phone ?? user.phone ?? ""}`.replace(/\s+/g, " ").trim(),
|
|
1311
|
+
items: items.map((i) => `${i.title} x${i.quantity}`).join(", ") || (envelope?.product_name ?? "\u2014"),
|
|
1312
|
+
total: payload?.total_price,
|
|
1313
|
+
currency: payload?.currency,
|
|
1314
|
+
extra: `envelope: ${eventDef(name).envelope}`,
|
|
1315
|
+
link: payload?.note_attributes?.find((n) => n.name === "shopflo_checkout_url")?.value ?? payload?.token_id
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
var shopflo_default = {
|
|
1319
|
+
id: "shopflo",
|
|
1320
|
+
urlKey: "shopflo",
|
|
1321
|
+
label: "Shopflo",
|
|
1322
|
+
events: EVENTS2,
|
|
1323
|
+
defaultEvent: DEFAULT_EVENT2,
|
|
1324
|
+
eventType: "shopflo_checkout_abandoned",
|
|
1325
|
+
gate: { path: "event_name", value: DEFAULT_EVENT2 },
|
|
1326
|
+
gateFor: (eventName) => ({ path: eventDef(eventName).envelope === "eventPayload" ? "eventName" : "event_name", value: eventName }),
|
|
1327
|
+
signatureScheme: "none documented \u2014 every request is accepted",
|
|
1328
|
+
signatureHeader: null,
|
|
1329
|
+
fieldMap: fieldMap4,
|
|
1330
|
+
fieldMapFor: (eventName) => FIELD_MAPS2[eventName] ?? FIELD_MAPS2[DEFAULT_EVENT2],
|
|
1331
|
+
editableFields: editableFields4,
|
|
1332
|
+
editableFieldsFor: editableFieldsFor2,
|
|
1333
|
+
selectionFor: selectionFor2,
|
|
1334
|
+
eventFromPayload: eventFromPayload2,
|
|
1335
|
+
buildPayload: buildPayload4,
|
|
1336
|
+
sign: sign4,
|
|
1337
|
+
webhookUrl: webhookUrl4,
|
|
1338
|
+
webhookSecret: webhookSecret4,
|
|
1339
|
+
summarize: summarize4
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
// src/phone.mjs
|
|
1343
|
+
var CALLING_CODES = {
|
|
1344
|
+
IN: "91",
|
|
1345
|
+
US: "1",
|
|
1346
|
+
CA: "1",
|
|
1347
|
+
GB: "44",
|
|
1348
|
+
AE: "971",
|
|
1349
|
+
SG: "65",
|
|
1350
|
+
AU: "61",
|
|
1351
|
+
NZ: "64",
|
|
1352
|
+
DE: "49",
|
|
1353
|
+
FR: "33",
|
|
1354
|
+
IT: "39",
|
|
1355
|
+
ES: "34",
|
|
1356
|
+
NL: "31",
|
|
1357
|
+
SE: "46",
|
|
1358
|
+
RO: "40",
|
|
1359
|
+
PL: "48",
|
|
1360
|
+
ZA: "27",
|
|
1361
|
+
NG: "234",
|
|
1362
|
+
KE: "254",
|
|
1363
|
+
BD: "880",
|
|
1364
|
+
PK: "92",
|
|
1365
|
+
LK: "94",
|
|
1366
|
+
NP: "977",
|
|
1367
|
+
MY: "60",
|
|
1368
|
+
ID: "62",
|
|
1369
|
+
PH: "63",
|
|
1370
|
+
TH: "66",
|
|
1371
|
+
VN: "84",
|
|
1372
|
+
JP: "81",
|
|
1373
|
+
KR: "82",
|
|
1374
|
+
CN: "86",
|
|
1375
|
+
SA: "966",
|
|
1376
|
+
QA: "974",
|
|
1377
|
+
KW: "965",
|
|
1378
|
+
OM: "968",
|
|
1379
|
+
BH: "973",
|
|
1380
|
+
BR: "55",
|
|
1381
|
+
MX: "52"
|
|
1382
|
+
};
|
|
1383
|
+
function callingCode(regionCode) {
|
|
1384
|
+
return CALLING_CODES[String(regionCode || "").toUpperCase()] || null;
|
|
1385
|
+
}
|
|
1386
|
+
function toE164(raw, regionCode) {
|
|
1387
|
+
const cleaned = String(raw ?? "").replace(/\s+/g, "");
|
|
1388
|
+
if (!cleaned) return { ok: false, reason: "phone is empty" };
|
|
1389
|
+
if (cleaned.startsWith("+")) {
|
|
1390
|
+
const digits2 = cleaned.slice(1).replace(/\D/g, "");
|
|
1391
|
+
if (digits2.length < 8 || digits2.length > 15) return { ok: false, reason: `+${digits2} is not a plausible E.164 length` };
|
|
1392
|
+
return { ok: true, value: `+${digits2}` };
|
|
1393
|
+
}
|
|
1394
|
+
const cc = callingCode(regionCode);
|
|
1395
|
+
if (!cc) {
|
|
1396
|
+
return {
|
|
1397
|
+
ok: false,
|
|
1398
|
+
reason: `no country calling code known for region "${regionCode}" \u2014 give the phone in +E.164 form instead`
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
let national = cleaned.replace(/\D/g, "").replace(/^0+/, "");
|
|
1402
|
+
if (national.startsWith(cc) && national.length > 10) national = national.slice(cc.length);
|
|
1403
|
+
const value = `+${cc}${national}`;
|
|
1404
|
+
const digits = value.slice(1);
|
|
1405
|
+
if (digits.length < 8 || digits.length > 15) return { ok: false, reason: `${value} is not a plausible E.164 length` };
|
|
1406
|
+
return { ok: true, value };
|
|
1407
|
+
}
|
|
1408
|
+
var knownRegions = Object.keys(CALLING_CODES);
|
|
1409
|
+
function splitPhone(raw, regionCode) {
|
|
1410
|
+
const digits = String(raw ?? "").replace(/[^\d]/g, "");
|
|
1411
|
+
if (!digits) return { dialCode: "", national: "" };
|
|
1412
|
+
const fromRegion = callingCode(regionCode);
|
|
1413
|
+
if (fromRegion && digits.startsWith(fromRegion)) {
|
|
1414
|
+
return { dialCode: fromRegion, national: digits.slice(fromRegion.length) };
|
|
1415
|
+
}
|
|
1416
|
+
const longestFirst = [...new Set(Object.values(CALLING_CODES))].sort((a, b) => b.length - a.length);
|
|
1417
|
+
const matched = longestFirst.find((code) => digits.startsWith(code));
|
|
1418
|
+
if (matched) return { dialCode: matched, national: digits.slice(matched.length) };
|
|
1419
|
+
return { dialCode: "", national: digits };
|
|
1420
|
+
}
|
|
1421
|
+
function nationalNumber(raw, regionCode) {
|
|
1422
|
+
return splitPhone(raw, regionCode).national;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// src/providers/flexype.mjs
|
|
1426
|
+
var GATE_PATH3 = "event_type";
|
|
1427
|
+
var GATE_VALUE2 = "ABANDONED_CHECKOUT";
|
|
1428
|
+
var fieldMap5 = [
|
|
1429
|
+
{ source: "event_type", target: "\xABgate\xBB", required: true, note: "must be ABANDONED_CHECKOUT or the event is dropped" },
|
|
1430
|
+
{ source: "payload.user.phone_with_dial_code", target: "phone", required: true, note: "falls back to dial_code + phone" },
|
|
1431
|
+
{ source: "payload.user.first_name", target: "customer.firstName" },
|
|
1432
|
+
{ source: "payload.user.last_name", target: "customer.lastName" },
|
|
1433
|
+
{ source: "payload.user.full_name", target: "customer.name" },
|
|
1434
|
+
{ source: "payload.user.email", target: "customer.email" },
|
|
1435
|
+
{ source: "payload.checkout_url", target: "checkoutUrl", required: true },
|
|
1436
|
+
{ source: "payload.session_id", target: "sessionId" },
|
|
1437
|
+
{ source: "payload.session_state", target: "sessionState" },
|
|
1438
|
+
{ source: "payload.cart_items[].title", target: "cart.productName", required: true, note: "the first PAID line wins; freebies rank last" },
|
|
1439
|
+
{ source: "payload.cart_items[].image", target: "cart.image" },
|
|
1440
|
+
{ source: "payload.cart_items[].total_price", target: "pricing.totalPrice", note: "summed across the cart" },
|
|
1441
|
+
{ source: "payload.cart_items[].total_discount", target: "pricing.totalDiscount", note: "summed across the cart" },
|
|
1442
|
+
{ source: "payload.cart_items[].quantity", target: "cart.quantity" },
|
|
1443
|
+
{ source: "payload.coupons[0].code", target: "pricing.couponCode" },
|
|
1444
|
+
{ source: "payload.checkout_context.presentment_currency", target: "pricing.currency" },
|
|
1445
|
+
{ source: "payload.checkout_context.presentment_country", target: "phone region" },
|
|
1446
|
+
{ source: "payload.metadata.utm[]", target: "utm.*", note: "a list of {name,value} pairs, not an object" },
|
|
1447
|
+
{ source: "payload.metadata.landing_page", target: "attribution.landingPage" },
|
|
1448
|
+
{ source: "store.shopify_domain", target: "storeUrl" },
|
|
1449
|
+
{ source: "store.name", target: "store.name" },
|
|
1450
|
+
{ source: "event_id", target: "eventId" },
|
|
1451
|
+
{ source: "event_time", target: "eventTime" }
|
|
1452
|
+
];
|
|
1453
|
+
var editableFields5 = [
|
|
1454
|
+
{ group: "Event", path: "event_id", label: "Event id" },
|
|
1455
|
+
{ group: "Event", path: "event_time", label: "Event time" },
|
|
1456
|
+
{ group: "Checkout", path: "payload.session_id", label: "Session id" },
|
|
1457
|
+
{ group: "Checkout", path: "payload.checkout_url", label: "Checkout URL", hint: "the link the shopper is sent back to" },
|
|
1458
|
+
{ group: "Checkout", path: "payload.session_state", label: "Session state" },
|
|
1459
|
+
{ group: "Customer", path: "payload.user.first_name", label: "First name" },
|
|
1460
|
+
{ group: "Customer", path: "payload.user.last_name", label: "Last name" },
|
|
1461
|
+
{ group: "Customer", path: "payload.user.email", label: "Email" },
|
|
1462
|
+
{ group: "Customer", path: "payload.user.phone_with_dial_code", label: "Phone", hint: "already E.164 shaped" },
|
|
1463
|
+
{ group: "Pricing", path: "payload.checkout_context.presentment_currency", label: "Currency" },
|
|
1464
|
+
{ group: "Pricing", path: "payload.coupons.0.code", label: "Coupon code", optional: true },
|
|
1465
|
+
{ group: "Store", path: "store.name", label: "Store name" },
|
|
1466
|
+
{ group: "Store", path: "store.shopify_domain", label: "Shopify domain" },
|
|
1467
|
+
{ group: "Attribution", path: "payload.metadata.landing_page", label: "Landing page", optional: true }
|
|
1468
|
+
];
|
|
1469
|
+
function buildPayload5(ctx) {
|
|
1470
|
+
const { config, items, phone } = ctx;
|
|
1471
|
+
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
1472
|
+
const currency = ctx.currency || config.defaults.currency;
|
|
1473
|
+
const domain = config.shopify.domain;
|
|
1474
|
+
const cust = config.customer;
|
|
1475
|
+
const { dialCode, national } = splitPhone(phone, cust.countryCode);
|
|
1476
|
+
const cartItems = (items ?? []).map(({ product, variant, quantity }) => {
|
|
1477
|
+
const unit = money2(variant?.price ?? 0);
|
|
1478
|
+
return {
|
|
1479
|
+
title: product.title,
|
|
1480
|
+
image: imageForVariant(product, variant),
|
|
1481
|
+
price: unit,
|
|
1482
|
+
total_price: money2(unit * quantity),
|
|
1483
|
+
total_discount: 0,
|
|
1484
|
+
quantity,
|
|
1485
|
+
variant_id: String(variant?.id ?? ""),
|
|
1486
|
+
product_id: String(product.id),
|
|
1487
|
+
sku: variant?.sku || null
|
|
1488
|
+
};
|
|
1489
|
+
});
|
|
1490
|
+
const checkoutUrl = cartPermalink(domain, (items ?? []).map(({ variant, quantity }) => ({ variantId: variant?.id, quantity })));
|
|
1491
|
+
const utm = Object.entries(config.defaults.utm ?? {}).map(([name, value]) => ({ name, value }));
|
|
1492
|
+
return {
|
|
1493
|
+
event_id: `fx-${now.getTime()}`,
|
|
1494
|
+
event_type: GATE_VALUE2,
|
|
1495
|
+
event_time: now.toISOString(),
|
|
1496
|
+
store: {
|
|
1497
|
+
id: 1,
|
|
1498
|
+
name: config.shopify.shop?.name ?? domain,
|
|
1499
|
+
shopify_domain: domain,
|
|
1500
|
+
main_domain: `https://${domain}`
|
|
1501
|
+
},
|
|
1502
|
+
payload: {
|
|
1503
|
+
session_id: `fx-sess-${now.getTime()}`,
|
|
1504
|
+
session_state: "ABANDONED",
|
|
1505
|
+
checkout_url: checkoutUrl,
|
|
1506
|
+
user: {
|
|
1507
|
+
first_name: cust.firstName,
|
|
1508
|
+
last_name: cust.lastName,
|
|
1509
|
+
full_name: `${cust.firstName} ${cust.lastName}`.trim(),
|
|
1510
|
+
email: cust.email,
|
|
1511
|
+
phone: national,
|
|
1512
|
+
dial_code: dialCode,
|
|
1513
|
+
phone_with_dial_code: phone
|
|
1514
|
+
},
|
|
1515
|
+
checkout_context: {
|
|
1516
|
+
presentment_currency: currency,
|
|
1517
|
+
store_currency: currency,
|
|
1518
|
+
presentment_country: cust.countryCode,
|
|
1519
|
+
store_country: cust.country
|
|
1520
|
+
},
|
|
1521
|
+
cart_items: cartItems,
|
|
1522
|
+
coupons: ctx.couponCode ? [{ code: ctx.couponCode }] : [],
|
|
1523
|
+
metadata: {
|
|
1524
|
+
landing_page: `https://${domain}/products/${items?.[0]?.product?.handle ?? ""}`,
|
|
1525
|
+
orig_referer: "",
|
|
1526
|
+
referer_host: "",
|
|
1527
|
+
utm
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
function sign5({ secret }) {
|
|
1533
|
+
return {
|
|
1534
|
+
signature: null,
|
|
1535
|
+
timestamp: null,
|
|
1536
|
+
headers: {
|
|
1537
|
+
"content-type": "application/json",
|
|
1538
|
+
"x-flexype-authorization": String(secret ?? "")
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
function webhookUrl5(config) {
|
|
1543
|
+
return String(targetFor(config, "flexype").webhookUrl ?? "").trim();
|
|
1544
|
+
}
|
|
1545
|
+
function webhookSecret5(config) {
|
|
1546
|
+
return String(targetFor(config, "flexype").webhookSecret ?? "");
|
|
1547
|
+
}
|
|
1548
|
+
function summarize5(payload) {
|
|
1549
|
+
const p = payload?.payload ?? {};
|
|
1550
|
+
const items = Array.isArray(p.cart_items) ? p.cart_items : [];
|
|
1551
|
+
return {
|
|
1552
|
+
event: "abandoned checkout",
|
|
1553
|
+
store: payload?.store?.shopify_domain,
|
|
1554
|
+
customer: `${p.user?.full_name ?? ""} \xB7 ${p.user?.phone_with_dial_code ?? ""}`.trim(),
|
|
1555
|
+
items: items.map((i) => `${i.title} x${i.quantity}`).join(", "),
|
|
1556
|
+
total: items.reduce((sum, i) => sum + Number(i.total_price ?? 0), 0),
|
|
1557
|
+
currency: p.checkout_context?.presentment_currency,
|
|
1558
|
+
extra: p.coupons?.[0]?.code ? `coupon ${p.coupons[0].code}` : "no coupon",
|
|
1559
|
+
link: p.checkout_url
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
var flexype_default = {
|
|
1563
|
+
id: "flexype",
|
|
1564
|
+
urlKey: "flexype",
|
|
1565
|
+
label: "FlexyPe",
|
|
1566
|
+
eventType: "flexype_abandoned_checkout",
|
|
1567
|
+
gate: { path: GATE_PATH3, value: GATE_VALUE2 },
|
|
1568
|
+
signatureScheme: "static shared secret in the header (no body signature)",
|
|
1569
|
+
signatureHeader: "x-flexype-authorization",
|
|
1570
|
+
fieldMap: fieldMap5,
|
|
1571
|
+
editableFields: editableFields5,
|
|
1572
|
+
buildPayload: buildPayload5,
|
|
1573
|
+
sign: sign5,
|
|
1574
|
+
webhookUrl: webhookUrl5,
|
|
1575
|
+
webhookSecret: webhookSecret5,
|
|
1576
|
+
summarize: summarize5
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
// src/providers/return-prime.mjs
|
|
1580
|
+
var STATUSES = ["requested", "approved", "received", "inspected", "rejected"];
|
|
1581
|
+
var titleCase = (v) => v.charAt(0).toUpperCase() + v.slice(1);
|
|
1582
|
+
var EVENTS3 = ["return", "exchange"].flatMap(
|
|
1583
|
+
(requestType) => STATUSES.map((status) => ({
|
|
1584
|
+
eventName: `${requestType}_${status}`,
|
|
1585
|
+
requestType,
|
|
1586
|
+
status,
|
|
1587
|
+
type: `return_prime_${requestType}_${status}`,
|
|
1588
|
+
label: `${titleCase(requestType)} ${titleCase(status)}`,
|
|
1589
|
+
selection: requestType === "exchange" ? "exchange" : "product",
|
|
1590
|
+
subject: requestType === "exchange" ? "the returned product and its replacement" : "the returned product"
|
|
1591
|
+
}))
|
|
1592
|
+
);
|
|
1593
|
+
var DEFAULT_EVENT3 = "return_requested";
|
|
1594
|
+
var eventDef2 = (eventName) => EVENTS3.find((e) => e.eventName === eventName) ?? EVENTS3.find((e) => e.eventName === DEFAULT_EVENT3);
|
|
1595
|
+
function eventFromPayload3(payload) {
|
|
1596
|
+
const request = payload?.request ?? payload ?? {};
|
|
1597
|
+
if (!request.request_type || !request.status) return void 0;
|
|
1598
|
+
return `${request.request_type}_${request.status}`;
|
|
1599
|
+
}
|
|
1600
|
+
function selectionFor3(eventName) {
|
|
1601
|
+
return eventDef2(eventName).selection;
|
|
1602
|
+
}
|
|
1603
|
+
var COMMON_FIELDS3 = [
|
|
1604
|
+
{ source: "request_type", target: "\xABgate\xBB + requestType", required: true, note: "return or exchange" },
|
|
1605
|
+
{ source: "status", target: "\xABgate\xBB + status", required: true, note: "requested, approved, received, inspected or rejected" },
|
|
1606
|
+
{ source: "customer.phone", target: "phone", required: true, note: "missing phone is rejected on every event" },
|
|
1607
|
+
{ source: "customer.address.country_code", target: "phone region" },
|
|
1608
|
+
{ source: "request_number", target: "requestNumber" },
|
|
1609
|
+
{ source: "order.name", target: "order.name" },
|
|
1610
|
+
{ source: "line_items[].original_product.title", target: "product.name", required: true, note: "the first PAID line wins; freebies rank last" },
|
|
1611
|
+
{ source: "line_items[].original_product.image.src", target: "product.image" },
|
|
1612
|
+
{ source: "line_items[].original_product.price", target: "product.price", note: "a zero price marks the line a freebie" },
|
|
1613
|
+
{ source: "line_items[].reason", target: "reason" },
|
|
1614
|
+
{ source: "line_items[].presentment_price.actual_amount", target: "pricing.totalPrice" },
|
|
1615
|
+
{ source: "line_items[].return_fee.price_set\u2026amount", target: "pricing.returnFee" },
|
|
1616
|
+
{ source: "line_items[].refund.status", target: "refund.status" },
|
|
1617
|
+
{ source: "line_items[].refund.meta.discount_code", target: "refund.discountCode", note: "only present once store credit is issued" },
|
|
1618
|
+
{ source: "line_items[].shipping[0].awb", target: "shipping.awb" },
|
|
1619
|
+
{ source: "approved/received/inspected/rejected.created_at", target: "timeline.*" }
|
|
1620
|
+
];
|
|
1621
|
+
var EXCHANGE_FIELDS = [
|
|
1622
|
+
{ source: "line_items[].exchange_product.title", target: "exchangeProduct.name", note: "exchanges only \u2014 returns never carry it" },
|
|
1623
|
+
{ source: "line_items[].exchange_product.price", target: "exchangeProduct.price + pricing.priceDifference", note: "difference is signed: positive means the shopper owes more" }
|
|
1624
|
+
];
|
|
1625
|
+
var fieldMap6 = COMMON_FIELDS3;
|
|
1626
|
+
function fieldMapFor(eventName) {
|
|
1627
|
+
return eventDef2(eventName).requestType === "exchange" ? [...COMMON_FIELDS3, ...EXCHANGE_FIELDS] : COMMON_FIELDS3;
|
|
1628
|
+
}
|
|
1629
|
+
function editableFieldsFor3(eventName) {
|
|
1630
|
+
const def = eventDef2(eventName);
|
|
1631
|
+
const p = (path6) => def.envelope === "root" ? path6 : `request.${path6}`;
|
|
1632
|
+
return [
|
|
1633
|
+
{ group: "Request", path: p("request_number"), label: "Request number" },
|
|
1634
|
+
{ group: "Request", path: p("created_at"), label: "Created at" },
|
|
1635
|
+
{ group: "Request", path: p("line_items.0.reason"), label: "Reason" },
|
|
1636
|
+
{ group: "Order", path: p("order.name"), label: "Order name" },
|
|
1637
|
+
{ group: "Customer", path: p("customer.name"), label: "Customer name" },
|
|
1638
|
+
{ group: "Customer", path: p("customer.email"), label: "Email" },
|
|
1639
|
+
{ group: "Customer", path: p("customer.phone"), label: "Phone", hint: "already E.164 shaped" },
|
|
1640
|
+
{ group: "Shipping", path: p("customer.address.address_line_1"), label: "Address line 1" },
|
|
1641
|
+
{ group: "Shipping", path: p("customer.address.city"), label: "City" },
|
|
1642
|
+
{ group: "Shipping", path: p("customer.address.province"), label: "Province / state" },
|
|
1643
|
+
{ group: "Shipping", path: p("customer.address.postal_code"), label: "Postal code" },
|
|
1644
|
+
{ group: "Shipping", path: p("customer.address.country_code"), label: "Country code", hint: "region used to parse the phone" },
|
|
1645
|
+
{ group: "Pricing", path: p("line_items.0.presentment_price.actual_amount"), label: "Item amount", type: "number" },
|
|
1646
|
+
{ group: "Pricing", path: p("line_items.0.presentment_price.currency"), label: "Currency" }
|
|
1647
|
+
];
|
|
1648
|
+
}
|
|
1649
|
+
var editableFields6 = editableFieldsFor3(DEFAULT_EVENT3);
|
|
1650
|
+
function statusBlock(reached, at, comment = null) {
|
|
1651
|
+
return { status: reached, comment, created_at: reached ? at : null };
|
|
1652
|
+
}
|
|
1653
|
+
function buildPayload6(ctx) {
|
|
1654
|
+
const { config, items, phone } = ctx;
|
|
1655
|
+
const eventName = ctx.eventName ?? DEFAULT_EVENT3;
|
|
1656
|
+
const def = eventDef2(eventName);
|
|
1657
|
+
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
1658
|
+
const currency = ctx.currency || config.defaults.currency;
|
|
1659
|
+
const cust = config.customer;
|
|
1660
|
+
const at = now.toISOString();
|
|
1661
|
+
const first = items?.[0];
|
|
1662
|
+
const second = items?.[1] ?? first;
|
|
1663
|
+
const originalPrice = money2(first?.variant?.price ?? 0);
|
|
1664
|
+
const exchangePrice = money2(second?.variant?.price ?? 0);
|
|
1665
|
+
const reachedIndex = STATUSES.indexOf(def.status);
|
|
1666
|
+
const reached = (name) => STATUSES.indexOf(name) <= reachedIndex && def.status !== "requested";
|
|
1667
|
+
const lineItem = {
|
|
1668
|
+
id: Number(first?.variant?.id ?? first?.product?.id ?? 0),
|
|
1669
|
+
refund: {
|
|
1670
|
+
requested_mode: "store_credit",
|
|
1671
|
+
actual_mode: def.status === "rejected" ? "store_credit" : null,
|
|
1672
|
+
meta: def.status === "rejected" && ctx.couponCode ? { discount_code: ctx.couponCode } : null,
|
|
1673
|
+
status: def.status === "rejected" ? "refunded" : "pending",
|
|
1674
|
+
refunded_amount: {
|
|
1675
|
+
shop_money: { ...def.status === "rejected" ? { amount: originalPrice } : {}, currency_code: currency },
|
|
1676
|
+
presentment_money: { ...def.status === "rejected" ? { amount: originalPrice } : {}, currency_code: currency }
|
|
1677
|
+
},
|
|
1678
|
+
refunded_at: def.status === "rejected" ? at : null,
|
|
1679
|
+
comment: null
|
|
1680
|
+
},
|
|
1681
|
+
return_fee: {
|
|
1682
|
+
price_set: {
|
|
1683
|
+
shop_money: { amount: ctx.returnFee ?? 0, currency_code: currency },
|
|
1684
|
+
presentment_money: { amount: ctx.returnFee ?? 0, currency_code: currency }
|
|
1685
|
+
},
|
|
1686
|
+
rule: "order"
|
|
1687
|
+
},
|
|
1688
|
+
exchange_fee: {
|
|
1689
|
+
price_set: {
|
|
1690
|
+
shop_money: { amount: null, currency_code: null },
|
|
1691
|
+
presentment_money: { amount: null, currency_code: null }
|
|
1692
|
+
}
|
|
1693
|
+
},
|
|
1694
|
+
exchange: { order: null },
|
|
1695
|
+
original_product: {
|
|
1696
|
+
title: first?.product?.title,
|
|
1697
|
+
variant_title: first?.variant?.title ?? null,
|
|
1698
|
+
product_id: Number(first?.product?.id ?? 0),
|
|
1699
|
+
variant_id: Number(first?.variant?.id ?? 0),
|
|
1700
|
+
image: { src: imageForVariant(first?.product, first?.variant) },
|
|
1701
|
+
price: originalPrice,
|
|
1702
|
+
sku: first?.variant?.sku || "",
|
|
1703
|
+
variant_deleted: false,
|
|
1704
|
+
product_deleted: false
|
|
1705
|
+
},
|
|
1706
|
+
...def.requestType === "exchange" ? {
|
|
1707
|
+
exchange_product: {
|
|
1708
|
+
product_id: Number(second?.product?.id ?? 0),
|
|
1709
|
+
title: second?.product?.title,
|
|
1710
|
+
variant_title: second?.variant?.title ?? "Default Title",
|
|
1711
|
+
variant_id: Number(second?.variant?.id ?? 0),
|
|
1712
|
+
image: { src: imageForVariant(second?.product, second?.variant) },
|
|
1713
|
+
price: exchangePrice,
|
|
1714
|
+
sku: second?.variant?.sku || "",
|
|
1715
|
+
variant_deleted: false,
|
|
1716
|
+
product_deleted: false
|
|
1717
|
+
}
|
|
1718
|
+
} : {},
|
|
1719
|
+
shipping: [
|
|
1720
|
+
def.status === "requested" ? { tracking_available: false, labels: [] } : {
|
|
1721
|
+
shipping_company: "bluedartV2",
|
|
1722
|
+
tracking_available: true,
|
|
1723
|
+
awb: String(now.getTime()).slice(-11),
|
|
1724
|
+
tracking_updated_at: null,
|
|
1725
|
+
labels: [],
|
|
1726
|
+
shipment_status: "Requested",
|
|
1727
|
+
tracking_url: `https://www.bluedart.com/trackdartresultthirdparty?trackFor=0&trackNo=${String(now.getTime()).slice(-11)}`
|
|
1728
|
+
}
|
|
1729
|
+
],
|
|
1730
|
+
quantity: first?.quantity ?? 1,
|
|
1731
|
+
reason: ctx.reason ?? "Size of Fit Issues",
|
|
1732
|
+
shop_price: {
|
|
1733
|
+
actual_amount: originalPrice,
|
|
1734
|
+
total_tax: 0,
|
|
1735
|
+
return_quantity: first?.quantity ?? 1,
|
|
1736
|
+
total_discount: 0,
|
|
1737
|
+
shipping_amount: 0,
|
|
1738
|
+
taxes_included: true,
|
|
1739
|
+
currency,
|
|
1740
|
+
do_not_carry_forward_discount: true
|
|
1741
|
+
},
|
|
1742
|
+
presentment_price: {
|
|
1743
|
+
actual_amount: originalPrice,
|
|
1744
|
+
total_tax: 0,
|
|
1745
|
+
return_quantity: first?.quantity ?? 1,
|
|
1746
|
+
total_discount: 0,
|
|
1747
|
+
shipping_amount: 0,
|
|
1748
|
+
taxes_included: true,
|
|
1749
|
+
currency,
|
|
1750
|
+
do_not_carry_forward_discount: true
|
|
1751
|
+
},
|
|
1752
|
+
shopify_order_fulfillment_location: null,
|
|
1753
|
+
return_location: def.status === "requested" ? null : {
|
|
1754
|
+
id: "rp-location-1",
|
|
1755
|
+
fullName: config.shopify.shop?.name ?? config.shopify.domain,
|
|
1756
|
+
mobileNumber: nationalNumber(phone, cust.countryCode),
|
|
1757
|
+
pinCode: cust.zip,
|
|
1758
|
+
streetAddress1: cust.address1,
|
|
1759
|
+
streetAddress2: cust.address2 ?? "",
|
|
1760
|
+
landmark: "",
|
|
1761
|
+
city: cust.city,
|
|
1762
|
+
state: cust.province,
|
|
1763
|
+
stateCode: cust.provinceCode,
|
|
1764
|
+
countryCode: cust.countryCode,
|
|
1765
|
+
country: cust.country,
|
|
1766
|
+
store: config.shopify.domain,
|
|
1767
|
+
facilityCode: "",
|
|
1768
|
+
isDefault: true,
|
|
1769
|
+
latitude: "",
|
|
1770
|
+
longitude: "",
|
|
1771
|
+
inStoreReturnExchange: false,
|
|
1772
|
+
external: false,
|
|
1773
|
+
createdAt: at,
|
|
1774
|
+
updatedAt: at
|
|
1775
|
+
},
|
|
1776
|
+
notes: null,
|
|
1777
|
+
tags: []
|
|
1778
|
+
};
|
|
1779
|
+
const request = {
|
|
1780
|
+
id: `rp-${now.getTime()}`,
|
|
1781
|
+
request_number: ctx.requestNumber ?? `${def.requestType === "exchange" ? "EXC" : "RET"}${String(now.getTime()).slice(-3)}`,
|
|
1782
|
+
request_type: def.requestType,
|
|
1783
|
+
status: def.status,
|
|
1784
|
+
manual_request: false,
|
|
1785
|
+
channel: 97426,
|
|
1786
|
+
smart_exchange: false,
|
|
1787
|
+
payment_details: null,
|
|
1788
|
+
order: {
|
|
1789
|
+
id: Number(ctx.orderId ?? String(now.getTime()).slice(-10)),
|
|
1790
|
+
name: ctx.orderName ?? `#${String(now.getTime()).slice(-5)}`,
|
|
1791
|
+
order_manual_payment: false,
|
|
1792
|
+
payment_gateways: [],
|
|
1793
|
+
fulfillments: [{ id: Number(String(now.getTime()).slice(-10)), line_items: [lineItem.id], delivery_status: null, delivery_date: null }],
|
|
1794
|
+
created_at: at
|
|
1795
|
+
},
|
|
1796
|
+
customer: {
|
|
1797
|
+
id: Number(String(now.getTime()).slice(-10)),
|
|
1798
|
+
name: `${cust.firstName} ${cust.lastName}`.trim(),
|
|
1799
|
+
email: cust.email,
|
|
1800
|
+
phone,
|
|
1801
|
+
address: {
|
|
1802
|
+
first_name: cust.firstName,
|
|
1803
|
+
last_name: cust.lastName || null,
|
|
1804
|
+
postal_code: cust.zip,
|
|
1805
|
+
city: cust.city,
|
|
1806
|
+
province: cust.province,
|
|
1807
|
+
country_code: cust.countryCode,
|
|
1808
|
+
province_code: cust.provinceCode,
|
|
1809
|
+
address_line_1: cust.address1,
|
|
1810
|
+
address_line_2: cust.address2 ?? "",
|
|
1811
|
+
country: cust.country,
|
|
1812
|
+
address_line_3: ""
|
|
1813
|
+
},
|
|
1814
|
+
bank: { account_holder_name: "", account_number: "", confirm_account_number: "", ifsc_code: "" }
|
|
1815
|
+
},
|
|
1816
|
+
approved: statusBlock(reached("approved"), at),
|
|
1817
|
+
received: statusBlock(reached("received"), at),
|
|
1818
|
+
inspected: statusBlock(reached("inspected"), at, def.status === "inspected" ? "quickreply test" : null),
|
|
1819
|
+
rejected: statusBlock(def.status === "rejected", at),
|
|
1820
|
+
archived: statusBlock(false, at),
|
|
1821
|
+
unarchived: statusBlock(false, at),
|
|
1822
|
+
incentive: null,
|
|
1823
|
+
line_items: [lineItem],
|
|
1824
|
+
created_at: at
|
|
1825
|
+
};
|
|
1826
|
+
return ctx.envelope === "root" ? request : { request };
|
|
1827
|
+
}
|
|
1828
|
+
function sign6() {
|
|
1829
|
+
return { signature: null, timestamp: null, headers: { "content-type": "application/json" } };
|
|
1830
|
+
}
|
|
1831
|
+
function webhookUrl6(config) {
|
|
1832
|
+
return String(targetFor(config, "return-prime").webhookUrl ?? "").trim();
|
|
1833
|
+
}
|
|
1834
|
+
function webhookSecret6(config) {
|
|
1835
|
+
return String(targetFor(config, "return-prime").webhookSecret ?? "");
|
|
1836
|
+
}
|
|
1837
|
+
function summarize6(payload) {
|
|
1838
|
+
const r = payload?.request ?? payload ?? {};
|
|
1839
|
+
const item = (Array.isArray(r.line_items) ? r.line_items : [])[0] ?? {};
|
|
1840
|
+
const original = item.original_product ?? {};
|
|
1841
|
+
const exchange = item.exchange_product;
|
|
1842
|
+
const difference = exchange ? money2(Number(exchange.price ?? 0) - Number(original.price ?? 0)) : void 0;
|
|
1843
|
+
return {
|
|
1844
|
+
event: `${r.request_type ?? "?"} ${r.status ?? "?"}`,
|
|
1845
|
+
store: item.return_location?.store ?? r.order?.name,
|
|
1846
|
+
customer: `${r.customer?.name ?? ""} \xB7 ${r.customer?.phone ?? ""}`.trim(),
|
|
1847
|
+
items: exchange ? `${original.title} \u2192 ${exchange.title}` : original.title,
|
|
1848
|
+
total: item.presentment_price?.actual_amount,
|
|
1849
|
+
currency: item.presentment_price?.currency,
|
|
1850
|
+
extra: difference === void 0 ? `${r.request_number ?? ""}` : `difference ${difference > 0 ? "+" : ""}${difference} (${difference > 0 ? "shopper pays" : "refund due"})`,
|
|
1851
|
+
link: null
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
var return_prime_default = {
|
|
1855
|
+
id: "return-prime",
|
|
1856
|
+
urlKey: "return_prime",
|
|
1857
|
+
label: "Return Prime",
|
|
1858
|
+
events: EVENTS3,
|
|
1859
|
+
defaultEvent: DEFAULT_EVENT3,
|
|
1860
|
+
eventType: "return_prime_return_requested",
|
|
1861
|
+
gate: { path: "request.request_type", value: "return" },
|
|
1862
|
+
gateFor: (eventName) => ({ path: "request.status", value: eventDef2(eventName).status }),
|
|
1863
|
+
signatureScheme: "none documented \u2014 every request is accepted",
|
|
1864
|
+
signatureHeader: null,
|
|
1865
|
+
fieldMap: fieldMap6,
|
|
1866
|
+
fieldMapFor,
|
|
1867
|
+
editableFields: editableFields6,
|
|
1868
|
+
editableFieldsFor: editableFieldsFor3,
|
|
1869
|
+
selectionFor: selectionFor3,
|
|
1870
|
+
eventFromPayload: eventFromPayload3,
|
|
1871
|
+
buildPayload: buildPayload6,
|
|
1872
|
+
sign: sign6,
|
|
1873
|
+
webhookUrl: webhookUrl6,
|
|
1874
|
+
webhookSecret: webhookSecret6,
|
|
1875
|
+
summarize: summarize6
|
|
1876
|
+
};
|
|
1877
|
+
|
|
1878
|
+
// src/providers/fastrr.mjs
|
|
1879
|
+
var GATE_PATH4 = "event_name";
|
|
1880
|
+
var GATE_VALUE3 = "ABANDON_CART";
|
|
1881
|
+
var fieldMap7 = [
|
|
1882
|
+
{ source: "event_name", target: "\xABgate\xBB", required: true, note: "must be ABANDON_CART or the event is dropped" },
|
|
1883
|
+
{ source: "event_id", target: "eventId" },
|
|
1884
|
+
{ source: "event_data.phone_number", target: "phone", required: true, note: "BARE national number \u2014 region comes from the address" },
|
|
1885
|
+
{ source: "event_data.shipping_address.country_code", target: "phone region", required: true },
|
|
1886
|
+
{ source: "event_data.checkout_url", target: "checkoutUrl", required: true },
|
|
1887
|
+
{ source: "event_data.items[].name", target: "cart.productName", required: true, note: "the first PAID line wins; freebies rank last" },
|
|
1888
|
+
{ source: "event_data.items[].img_url", target: "cart.image" },
|
|
1889
|
+
{ source: "event_data.items[].price", target: "\u2014 (ranking only)", note: "a zero price marks the line a freebie" },
|
|
1890
|
+
{ source: "event_data.items[].sku", target: "cart.sku" },
|
|
1891
|
+
{ source: "event_data.item_count", target: "cart.itemCount" },
|
|
1892
|
+
{ source: "event_data.total_price", target: "pricing.totalPrice" },
|
|
1893
|
+
{ source: "event_data.total_discount", target: "pricing.totalDiscount" },
|
|
1894
|
+
{ source: "event_data.shipping_price", target: "pricing.shippingPrice" },
|
|
1895
|
+
{ source: "event_data.tax", target: "pricing.tax" },
|
|
1896
|
+
{ source: "event_data.currency", target: "pricing.currency" },
|
|
1897
|
+
{ source: "event_data.discount_codes[0]", target: "pricing.discountCode" },
|
|
1898
|
+
{ source: "event_data.custom_attributes.landing_page_url", target: "attribution.landingPage + utm.*", note: "utm is PARSED from this query string" },
|
|
1899
|
+
{ source: "event_data.latest_stage", target: "latestStage" },
|
|
1900
|
+
{ source: "event_data.payment_status", target: "paymentStatus" },
|
|
1901
|
+
{ source: "event_data.rtoPredict", target: "rtoPredict" },
|
|
1902
|
+
{ source: "event_data.cart_id", target: "cartId" },
|
|
1903
|
+
{ source: "event_data.cart_token", target: "cartToken" }
|
|
1904
|
+
];
|
|
1905
|
+
var editableFields7 = [
|
|
1906
|
+
{ group: "Event", path: "event_id", label: "Event id" },
|
|
1907
|
+
{ group: "Cart", path: "event_data.cart_id", label: "Cart id" },
|
|
1908
|
+
{ group: "Cart", path: "event_data.cart_token", label: "Cart token" },
|
|
1909
|
+
{ group: "Cart", path: "event_data.checkout_url", label: "Checkout URL", hint: "the link the shopper is sent back to" },
|
|
1910
|
+
{ group: "Cart", path: "event_data.latest_stage", label: "Latest stage" },
|
|
1911
|
+
{ group: "Cart", path: "event_data.payment_status", label: "Payment status" },
|
|
1912
|
+
{ group: "Cart", path: "event_data.rtoPredict", label: "RTO prediction", optional: true },
|
|
1913
|
+
{ group: "Pricing", path: "event_data.total_price", label: "Total price", type: "number" },
|
|
1914
|
+
{ group: "Pricing", path: "event_data.total_discount", label: "Discount", type: "number" },
|
|
1915
|
+
{ group: "Pricing", path: "event_data.shipping_price", label: "Shipping", type: "number" },
|
|
1916
|
+
{ group: "Pricing", path: "event_data.tax", label: "Tax", type: "number" },
|
|
1917
|
+
{ group: "Pricing", path: "event_data.currency", label: "Currency" },
|
|
1918
|
+
{ group: "Customer", path: "event_data.first_name", label: "First name" },
|
|
1919
|
+
{ group: "Customer", path: "event_data.last_name", label: "Last name" },
|
|
1920
|
+
{ group: "Customer", path: "event_data.email", label: "Email" },
|
|
1921
|
+
{ group: "Customer", path: "event_data.phone_number", label: "Phone", hint: "bare national number, no country code" },
|
|
1922
|
+
{ group: "Shipping", path: "event_data.shipping_address.address1", label: "Address line 1" },
|
|
1923
|
+
{ group: "Shipping", path: "event_data.shipping_address.city", label: "City" },
|
|
1924
|
+
{ group: "Shipping", path: "event_data.shipping_address.state", label: "State" },
|
|
1925
|
+
{ group: "Shipping", path: "event_data.shipping_address.zip", label: "Zip / postcode" },
|
|
1926
|
+
{ group: "Shipping", path: "event_data.shipping_address.country_code", label: "Country code", hint: "region used to parse the phone" },
|
|
1927
|
+
{ group: "Attribution", path: "event_data.custom_attributes.landing_page_url", label: "Landing page URL", hint: "utm parameters are read out of this query string" }
|
|
1928
|
+
];
|
|
1929
|
+
function buildPayload7(ctx) {
|
|
1930
|
+
const { config, items, phone } = ctx;
|
|
1931
|
+
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
1932
|
+
const currency = ctx.currency || config.defaults.currency;
|
|
1933
|
+
const domain = config.shopify.domain;
|
|
1934
|
+
const cust = config.customer;
|
|
1935
|
+
const nationalPhone = nationalNumber(phone, cust.countryCode);
|
|
1936
|
+
const lineItems = (items ?? []).map(({ product, variant, quantity }) => ({
|
|
1937
|
+
sku: variant?.sku || "",
|
|
1938
|
+
name: product.title,
|
|
1939
|
+
title: product.title,
|
|
1940
|
+
price: money2(variant?.price ?? 0),
|
|
1941
|
+
quantity,
|
|
1942
|
+
product_id: Number(product.id),
|
|
1943
|
+
variant_id: Number(variant?.id ?? 0),
|
|
1944
|
+
img_url: imageForVariant(product, variant),
|
|
1945
|
+
custom_attributes: { contentId: String(product.id) }
|
|
1946
|
+
}));
|
|
1947
|
+
const subtotal = money2(lineItems.reduce((sum, li) => sum + li.price * li.quantity, 0));
|
|
1948
|
+
const discount = money2(Math.min(ctx.discount ?? 0, subtotal));
|
|
1949
|
+
const shippingPrice = ctx.shippingPrice ?? 0;
|
|
1950
|
+
const total = money2(subtotal - discount + shippingPrice);
|
|
1951
|
+
const landingPage = new URL(`https://${domain}/products/${items?.[0]?.product?.handle ?? ""}`);
|
|
1952
|
+
for (const [key, value] of Object.entries(config.defaults.utm ?? {})) {
|
|
1953
|
+
if (value) landingPage.searchParams.set(key, String(value));
|
|
1954
|
+
}
|
|
1955
|
+
const address = {
|
|
1956
|
+
zip: cust.zip,
|
|
1957
|
+
city: cust.city,
|
|
1958
|
+
state: cust.province,
|
|
1959
|
+
name: `${cust.firstName} ${cust.lastName}`.trim(),
|
|
1960
|
+
phone: nationalPhone,
|
|
1961
|
+
country: cust.country,
|
|
1962
|
+
address1: cust.address1,
|
|
1963
|
+
last_name: cust.lastName,
|
|
1964
|
+
first_name: cust.firstName,
|
|
1965
|
+
country_code: cust.countryCode,
|
|
1966
|
+
line_1: cust.address1,
|
|
1967
|
+
email: cust.email
|
|
1968
|
+
};
|
|
1969
|
+
const cartToken = `fastrr-${now.getTime()}`;
|
|
1970
|
+
return {
|
|
1971
|
+
event_id: `fr-${now.getTime()}`,
|
|
1972
|
+
event_name: GATE_VALUE3,
|
|
1973
|
+
event_data: {
|
|
1974
|
+
checkout_url: cartPermalink(domain, (items ?? []).map(({ variant, quantity }) => ({ variantId: variant?.id, quantity }))),
|
|
1975
|
+
total_discount: discount,
|
|
1976
|
+
latest_stage: "ORDER_SCREEN",
|
|
1977
|
+
product_id_list: lineItems.map((li) => String(li.product_id)),
|
|
1978
|
+
billing_address: address,
|
|
1979
|
+
custom_attributes: {
|
|
1980
|
+
landing_page_url: landingPage.toString(),
|
|
1981
|
+
ipv4_address: "192.168.1.1",
|
|
1982
|
+
shopifyCartToken: cartToken
|
|
1983
|
+
},
|
|
1984
|
+
cart_id: cartToken,
|
|
1985
|
+
updated_at: now.toISOString().replace("Z", ""),
|
|
1986
|
+
currency,
|
|
1987
|
+
shipping_address: address,
|
|
1988
|
+
first_name: cust.firstName,
|
|
1989
|
+
email: cust.email,
|
|
1990
|
+
source_name: "fastrr",
|
|
1991
|
+
item_count: lineItems.length,
|
|
1992
|
+
shipping_price: shippingPrice,
|
|
1993
|
+
variant_id_list: lineItems.map((li) => String(li.variant_id)),
|
|
1994
|
+
total_price: total,
|
|
1995
|
+
payment_status: "Pending",
|
|
1996
|
+
last_name: cust.lastName,
|
|
1997
|
+
tax: 0,
|
|
1998
|
+
item_title_list: lineItems.map((li) => li.title),
|
|
1999
|
+
item_name_list: lineItems.map((li) => li.name),
|
|
2000
|
+
img_url: lineItems[0]?.img_url,
|
|
2001
|
+
sku_list: lineItems.map((li) => li.sku),
|
|
2002
|
+
item_price_list: lineItems.map((li) => String(li.price)),
|
|
2003
|
+
cart_token: cartToken,
|
|
2004
|
+
phone_number: nationalPhone,
|
|
2005
|
+
items: lineItems,
|
|
2006
|
+
discount_codes: ctx.couponCode ? [ctx.couponCode] : [],
|
|
2007
|
+
rtoPredict: "low"
|
|
2008
|
+
}
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
function sign7() {
|
|
2012
|
+
return { signature: null, timestamp: null, headers: { "content-type": "application/json" } };
|
|
2013
|
+
}
|
|
2014
|
+
function webhookUrl7(config) {
|
|
2015
|
+
return String(targetFor(config, "fastrr").webhookUrl ?? "").trim();
|
|
2016
|
+
}
|
|
2017
|
+
function webhookSecret7(config) {
|
|
2018
|
+
return String(targetFor(config, "fastrr").webhookSecret ?? "");
|
|
2019
|
+
}
|
|
2020
|
+
function summarize7(payload) {
|
|
2021
|
+
const d = payload?.event_data ?? {};
|
|
2022
|
+
let store;
|
|
2023
|
+
try {
|
|
2024
|
+
store = d.checkout_url ? new URL(d.checkout_url).host : void 0;
|
|
2025
|
+
} catch {
|
|
2026
|
+
store = d.checkout_url;
|
|
2027
|
+
}
|
|
2028
|
+
const items = Array.isArray(d.items) ? d.items : [];
|
|
2029
|
+
return {
|
|
2030
|
+
event: "abandoned cart",
|
|
2031
|
+
store,
|
|
2032
|
+
customer: `${d.first_name ?? ""} ${d.last_name ?? ""} \xB7 ${d.phone_number ?? ""}`.trim(),
|
|
2033
|
+
items: items.map((i) => `${i.name} x${i.quantity}`).join(", "),
|
|
2034
|
+
total: d.total_price,
|
|
2035
|
+
currency: d.currency,
|
|
2036
|
+
extra: `stage ${d.latest_stage}, rto ${d.rtoPredict}`,
|
|
2037
|
+
link: d.checkout_url
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
var fastrr_default = {
|
|
2041
|
+
id: "fastrr",
|
|
2042
|
+
urlKey: "fastrr",
|
|
2043
|
+
label: "Fastrr",
|
|
2044
|
+
eventType: "fastrr_abandoned_cart",
|
|
2045
|
+
gate: { path: GATE_PATH4, value: GATE_VALUE3 },
|
|
2046
|
+
signatureScheme: "none documented \u2014 every request is accepted",
|
|
2047
|
+
signatureHeader: null,
|
|
2048
|
+
fieldMap: fieldMap7,
|
|
2049
|
+
editableFields: editableFields7,
|
|
2050
|
+
buildPayload: buildPayload7,
|
|
2051
|
+
sign: sign7,
|
|
2052
|
+
webhookUrl: webhookUrl7,
|
|
2053
|
+
webhookSecret: webhookSecret7,
|
|
2054
|
+
summarize: summarize7
|
|
2055
|
+
};
|
|
2056
|
+
|
|
1075
2057
|
// src/providers/index.mjs
|
|
1076
2058
|
var PROVIDER_META = [
|
|
1077
2059
|
{
|
|
@@ -1095,12 +2077,46 @@ var PROVIDER_META = [
|
|
|
1095
2077
|
header: "authorization",
|
|
1096
2078
|
available: true,
|
|
1097
2079
|
events: nitro_default.events
|
|
2080
|
+
},
|
|
2081
|
+
{
|
|
2082
|
+
id: "shopflo",
|
|
2083
|
+
label: "Shopflo",
|
|
2084
|
+
signature: "none documented \u2014 every request is accepted",
|
|
2085
|
+
header: null,
|
|
2086
|
+
available: true,
|
|
2087
|
+
events: shopflo_default.events
|
|
2088
|
+
},
|
|
2089
|
+
{
|
|
2090
|
+
id: "flexype",
|
|
2091
|
+
label: "FlexyPe",
|
|
2092
|
+
signature: "static shared secret in the header",
|
|
2093
|
+
header: "x-flexype-authorization",
|
|
2094
|
+
available: true
|
|
2095
|
+
},
|
|
2096
|
+
{
|
|
2097
|
+
id: "return-prime",
|
|
2098
|
+
label: "Return Prime",
|
|
2099
|
+
signature: "none documented \u2014 every request is accepted",
|
|
2100
|
+
header: null,
|
|
2101
|
+
available: true,
|
|
2102
|
+
events: return_prime_default.events
|
|
2103
|
+
},
|
|
2104
|
+
{
|
|
2105
|
+
id: "fastrr",
|
|
2106
|
+
label: "Fastrr",
|
|
2107
|
+
signature: "none documented \u2014 every request is accepted",
|
|
2108
|
+
header: null,
|
|
2109
|
+
available: true
|
|
1098
2110
|
}
|
|
1099
2111
|
];
|
|
1100
2112
|
var providers = {
|
|
1101
2113
|
[cashfree_occ_default.id]: cashfree_occ_default,
|
|
1102
2114
|
[razorpay_magic_default.id]: razorpay_magic_default,
|
|
1103
|
-
[nitro_default.id]: nitro_default
|
|
2115
|
+
[nitro_default.id]: nitro_default,
|
|
2116
|
+
[shopflo_default.id]: shopflo_default,
|
|
2117
|
+
[flexype_default.id]: flexype_default,
|
|
2118
|
+
[return_prime_default.id]: return_prime_default,
|
|
2119
|
+
[fastrr_default.id]: fastrr_default
|
|
1104
2120
|
};
|
|
1105
2121
|
function getProvider(id) {
|
|
1106
2122
|
const provider = providers[id];
|
|
@@ -1466,74 +2482,6 @@ function autoSelect(products, count = 1) {
|
|
|
1466
2482
|
}));
|
|
1467
2483
|
}
|
|
1468
2484
|
|
|
1469
|
-
// src/phone.mjs
|
|
1470
|
-
var CALLING_CODES = {
|
|
1471
|
-
IN: "91",
|
|
1472
|
-
US: "1",
|
|
1473
|
-
CA: "1",
|
|
1474
|
-
GB: "44",
|
|
1475
|
-
AE: "971",
|
|
1476
|
-
SG: "65",
|
|
1477
|
-
AU: "61",
|
|
1478
|
-
NZ: "64",
|
|
1479
|
-
DE: "49",
|
|
1480
|
-
FR: "33",
|
|
1481
|
-
IT: "39",
|
|
1482
|
-
ES: "34",
|
|
1483
|
-
NL: "31",
|
|
1484
|
-
SE: "46",
|
|
1485
|
-
RO: "40",
|
|
1486
|
-
PL: "48",
|
|
1487
|
-
ZA: "27",
|
|
1488
|
-
NG: "234",
|
|
1489
|
-
KE: "254",
|
|
1490
|
-
BD: "880",
|
|
1491
|
-
PK: "92",
|
|
1492
|
-
LK: "94",
|
|
1493
|
-
NP: "977",
|
|
1494
|
-
MY: "60",
|
|
1495
|
-
ID: "62",
|
|
1496
|
-
PH: "63",
|
|
1497
|
-
TH: "66",
|
|
1498
|
-
VN: "84",
|
|
1499
|
-
JP: "81",
|
|
1500
|
-
KR: "82",
|
|
1501
|
-
CN: "86",
|
|
1502
|
-
SA: "966",
|
|
1503
|
-
QA: "974",
|
|
1504
|
-
KW: "965",
|
|
1505
|
-
OM: "968",
|
|
1506
|
-
BH: "973",
|
|
1507
|
-
BR: "55",
|
|
1508
|
-
MX: "52"
|
|
1509
|
-
};
|
|
1510
|
-
function callingCode(regionCode) {
|
|
1511
|
-
return CALLING_CODES[String(regionCode || "").toUpperCase()] || null;
|
|
1512
|
-
}
|
|
1513
|
-
function toE164(raw, regionCode) {
|
|
1514
|
-
const cleaned = String(raw ?? "").replace(/\s+/g, "");
|
|
1515
|
-
if (!cleaned) return { ok: false, reason: "phone is empty" };
|
|
1516
|
-
if (cleaned.startsWith("+")) {
|
|
1517
|
-
const digits2 = cleaned.slice(1).replace(/\D/g, "");
|
|
1518
|
-
if (digits2.length < 8 || digits2.length > 15) return { ok: false, reason: `+${digits2} is not a plausible E.164 length` };
|
|
1519
|
-
return { ok: true, value: `+${digits2}` };
|
|
1520
|
-
}
|
|
1521
|
-
const cc = callingCode(regionCode);
|
|
1522
|
-
if (!cc) {
|
|
1523
|
-
return {
|
|
1524
|
-
ok: false,
|
|
1525
|
-
reason: `no country calling code known for region "${regionCode}" \u2014 give the phone in +E.164 form instead`
|
|
1526
|
-
};
|
|
1527
|
-
}
|
|
1528
|
-
let national = cleaned.replace(/\D/g, "").replace(/^0+/, "");
|
|
1529
|
-
if (national.startsWith(cc) && national.length > 10) national = national.slice(cc.length);
|
|
1530
|
-
const value = `+${cc}${national}`;
|
|
1531
|
-
const digits = value.slice(1);
|
|
1532
|
-
if (digits.length < 8 || digits.length > 15) return { ok: false, reason: `${value} is not a plausible E.164 length` };
|
|
1533
|
-
return { ok: true, value };
|
|
1534
|
-
}
|
|
1535
|
-
var knownRegions = Object.keys(CALLING_CODES);
|
|
1536
|
-
|
|
1537
2485
|
// src/core/paths.mjs
|
|
1538
2486
|
function getPath(obj, path6) {
|
|
1539
2487
|
return String(path6).replace(/\[(\d+)\]/g, ".$1").split(".").reduce((acc, key) => acc == null ? void 0 : acc[key], obj);
|
|
@@ -1701,7 +2649,19 @@ function locatePhone(payload) {
|
|
|
1701
2649
|
["phone", "customer.Shipping_address.Country_code"],
|
|
1702
2650
|
["customer.Shipping_address.Phone", "customer.Shipping_address.Country_code"],
|
|
1703
2651
|
// nitro
|
|
1704
|
-
["eventVal.customer.phone", "country"]
|
|
2652
|
+
["eventVal.customer.phone", "country"],
|
|
2653
|
+
// shopflo — one path per envelope, most specific first
|
|
2654
|
+
["eventPayload.userData.phone", "eventPayload.clientData.country"],
|
|
2655
|
+
["data.user_data.phone", "data.country_code"],
|
|
2656
|
+
["customer.phone", "customer.country_code"],
|
|
2657
|
+
// flexype
|
|
2658
|
+
["payload.user.phone_with_dial_code", "payload.checkout_context.presentment_country"],
|
|
2659
|
+
["payload.user.phone", "payload.checkout_context.presentment_country"],
|
|
2660
|
+
// return prime — wrapped and root envelopes
|
|
2661
|
+
["request.customer.phone", "request.customer.address.country_code"],
|
|
2662
|
+
// fastrr — a bare national number, so the region is what makes it parse
|
|
2663
|
+
["event_data.phone_number", "event_data.shipping_address.country_code"],
|
|
2664
|
+
["event_data.billing_address.phone", "event_data.billing_address.country_code"]
|
|
1705
2665
|
];
|
|
1706
2666
|
for (const [phonePath, regionPath] of candidates) {
|
|
1707
2667
|
const phone = getPath(payload, phonePath);
|
|
@@ -1736,8 +2696,8 @@ function checkAllowedPhone(payload, config) {
|
|
|
1736
2696
|
detail: ok ? `${normalized} is an approved test handset` : `${normalized} is NOT in allowedPhones \u2014 refusing to risk messaging a real shopper`
|
|
1737
2697
|
};
|
|
1738
2698
|
}
|
|
1739
|
-
function coverage(payload,
|
|
1740
|
-
return
|
|
2699
|
+
function coverage(payload, fieldMap8) {
|
|
2700
|
+
return fieldMap8.map((f) => {
|
|
1741
2701
|
const value = getPath(payload, f.source);
|
|
1742
2702
|
const present = value !== void 0 && value !== null && value !== "";
|
|
1743
2703
|
return {
|
|
@@ -1864,7 +2824,7 @@ function loadPayload(file) {
|
|
|
1864
2824
|
}
|
|
1865
2825
|
|
|
1866
2826
|
// src/core/build.mjs
|
|
1867
|
-
function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, phone, eventName, collection }) {
|
|
2827
|
+
function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, phone, eventName, collection, envelope }) {
|
|
1868
2828
|
const provider = getProvider(providerId);
|
|
1869
2829
|
const event = eventName ?? provider.defaultEvent;
|
|
1870
2830
|
const resolvedPhone = phone ?? cfg.customer.phone;
|
|
@@ -1875,6 +2835,7 @@ function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, p
|
|
|
1875
2835
|
discount,
|
|
1876
2836
|
eventName: event,
|
|
1877
2837
|
collection,
|
|
2838
|
+
envelope,
|
|
1878
2839
|
phone: parsed.ok ? parsed.value : String(resolvedPhone ?? "")
|
|
1879
2840
|
});
|
|
1880
2841
|
const editable = provider.editableFieldsFor ? provider.editableFieldsFor(event) : provider.editableFields;
|
|
@@ -1890,7 +2851,7 @@ function applyEdits(payload, fields, edits) {
|
|
|
1890
2851
|
}
|
|
1891
2852
|
return payload;
|
|
1892
2853
|
}
|
|
1893
|
-
async function
|
|
2854
|
+
async function buildPayload8({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope }) {
|
|
1894
2855
|
const provider0 = getProvider(providerId);
|
|
1895
2856
|
const needsItems = !provider0.selectionFor || ["cart", "product"].includes(provider0.selectionFor(eventName ?? provider0.defaultEvent));
|
|
1896
2857
|
if (needsItems && !items.length) throw new ConfigError("no products selected");
|
|
@@ -1899,7 +2860,7 @@ async function buildPayload4({ cfg, providerId = "cashfree-occ", items = [], dis
|
|
|
1899
2860
|
const parsed = toE164(resolvedPhone, cfg.customer.countryCode);
|
|
1900
2861
|
if (!parsed.ok) throw new ConfigError(`phone is unusable: ${parsed.reason}`);
|
|
1901
2862
|
const event = eventName ?? provider.defaultEvent;
|
|
1902
|
-
const payload = prebuilt ?? provider.buildPayload({ config: cfg, items, discount, phone: parsed.value, eventName: event, collection });
|
|
2863
|
+
const payload = prebuilt ?? provider.buildPayload({ config: cfg, items, discount, phone: parsed.value, eventName: event, collection, envelope });
|
|
1903
2864
|
const body = JSON.stringify(payload);
|
|
1904
2865
|
const report = await runAll({ payload, body, provider, config: cfg, checkImageUrls, eventName: event });
|
|
1905
2866
|
const summary = provider.summarize ? provider.summarize(payload) : {};
|
|
@@ -2169,7 +3130,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
2169
3130
|
return setStep(STEP.MODE);
|
|
2170
3131
|
case STEP.RESULT:
|
|
2171
3132
|
case STEP.ERROR:
|
|
2172
|
-
return onDone();
|
|
3133
|
+
return built ? setStep(STEP.REPORT) : onDone();
|
|
2173
3134
|
default:
|
|
2174
3135
|
return onDone();
|
|
2175
3136
|
}
|
|
@@ -2323,7 +3284,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
2323
3284
|
const onDiscount = (raw) => startReview(Math.max(0, Number.parseFloat(raw) || 0));
|
|
2324
3285
|
const finalise = (payload) => {
|
|
2325
3286
|
setStep(STEP.BUILDING);
|
|
2326
|
-
|
|
3287
|
+
buildPayload8({ cfg: config, providerId, items, discount: draft.discount, payload, eventName, collection }).then(async (result) => {
|
|
2327
3288
|
setBuilt(result);
|
|
2328
3289
|
let req = null;
|
|
2329
3290
|
let command = "";
|
|
@@ -2596,7 +3557,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
2596
3557
|
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "reproduce:" }),
|
|
2597
3558
|
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: sendResult.curl })
|
|
2598
3559
|
] }),
|
|
2599
|
-
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "
|
|
3560
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "enter returns to the menu \xB7 esc goes back to the report to retry" }) })
|
|
2600
3561
|
] }),
|
|
2601
3562
|
step === STEP.ERROR && error && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
2602
3563
|
/* @__PURE__ */ jsx8(Alert, { variant: "error", children: error.message }),
|
|
@@ -2606,7 +3567,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
2606
3567
|
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: f.detail })
|
|
2607
3568
|
] }, i)) }) : null,
|
|
2608
3569
|
error.hint ? /* @__PURE__ */ jsx8(Text8, { color: palette.warn, children: ` ${error.hint}` }) : null,
|
|
2609
|
-
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "
|
|
3570
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "enter returns to the menu \xB7 esc goes back to the report to retry" }) })
|
|
2610
3571
|
] })
|
|
2611
3572
|
] });
|
|
2612
3573
|
}
|
|
@@ -3567,11 +4528,12 @@ async function cmdBuild(args, config) {
|
|
|
3567
4528
|
} else {
|
|
3568
4529
|
log.ok(`${eventName} needs no product or collection`);
|
|
3569
4530
|
}
|
|
3570
|
-
const built = await
|
|
4531
|
+
const built = await buildPayload8({
|
|
3571
4532
|
cfg: config,
|
|
3572
4533
|
providerId,
|
|
3573
4534
|
eventName,
|
|
3574
4535
|
collection,
|
|
4536
|
+
envelope: typeof args.flags.envelope === "string" ? args.flags.envelope : void 0,
|
|
3575
4537
|
items,
|
|
3576
4538
|
discount,
|
|
3577
4539
|
phone: typeof args.flags.phone === "string" ? args.flags.phone : void 0,
|
|
@@ -3774,10 +4736,18 @@ ${c.bold("COMMANDS")}
|
|
|
3774
4736
|
help show this message
|
|
3775
4737
|
|
|
3776
4738
|
${c.bold("BUILD OPTIONS")}
|
|
3777
|
-
--provider <id> cashfree-occ
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
4739
|
+
--provider <id> cashfree-occ \xB7 razorpay-magic \xB7 nitro \xB7 shopflo
|
|
4740
|
+
flexype \xB7 return-prime \xB7 fastrr (default cashfree-occ)
|
|
4741
|
+
--event <name> multi-event providers only:
|
|
4742
|
+
nitro view \xB7 category_view \xB7 product_view \xB7 addtocart
|
|
4743
|
+
removefromcart \xB7 checkout \xB7 orders/create \xB7 orders/updated
|
|
4744
|
+
shopflo store_page_view \xB7 collection_page_viewed \xB7 product_page_viewed
|
|
4745
|
+
added_to_cart_ui \xB7 checkout_clicked \xB7 checkout_abandoned
|
|
4746
|
+
order_completed
|
|
4747
|
+
return-prime {return,exchange}_{requested,approved,received,
|
|
4748
|
+
inspected,rejected}
|
|
4749
|
+
--envelope <x> return-prime only: wrapped (default) or root
|
|
4750
|
+
--collection <x> category or collection view: collection id, handle or title
|
|
3781
4751
|
--items <n> how many products to put in the cart (default 1)
|
|
3782
4752
|
--search <text> only consider products matching a title
|
|
3783
4753
|
--discount <n> cart discount in major currency units (default 0)
|