hookwright 1.12.1 → 1.13.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 +453 -8
- 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.13.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",
|
|
@@ -178,7 +178,9 @@ var DEFAULT_CONFIG = {
|
|
|
178
178
|
shopflo: { webhookUrl: "", webhookSecret: "" },
|
|
179
179
|
flexype: { webhookUrl: "", webhookSecret: "" },
|
|
180
180
|
"return-prime": { webhookUrl: "", webhookSecret: "" },
|
|
181
|
-
fastrr: { webhookUrl: "", webhookSecret: "" }
|
|
181
|
+
fastrr: { webhookUrl: "", webhookSecret: "" },
|
|
182
|
+
gokwik: { webhookUrl: "", webhookSecret: "" },
|
|
183
|
+
ecom360: { webhookUrl: "", webhookSecret: "" }
|
|
182
184
|
},
|
|
183
185
|
customer: {
|
|
184
186
|
firstName: "",
|
|
@@ -381,6 +383,7 @@ function normalizeProduct(product) {
|
|
|
381
383
|
title: v.title,
|
|
382
384
|
sku: v.sku || "",
|
|
383
385
|
price: v.price != null ? Number(v.price) : null,
|
|
386
|
+
compareAtPrice: v.compare_at_price != null ? Number(v.compare_at_price) : null,
|
|
384
387
|
available: v.inventory_quantity == null ? true : v.inventory_quantity > 0,
|
|
385
388
|
imageId: v.image_id ? String(v.image_id) : null
|
|
386
389
|
}));
|
|
@@ -2257,6 +2260,423 @@ var fastrr_default = {
|
|
|
2257
2260
|
summarize: summarize7
|
|
2258
2261
|
};
|
|
2259
2262
|
|
|
2263
|
+
// src/providers/gokwik.mjs
|
|
2264
|
+
var GATE_PATH5 = "abc_url";
|
|
2265
|
+
var GATE_VALUE4 = "";
|
|
2266
|
+
var fieldMap8 = [
|
|
2267
|
+
{ source: "abc_url", target: "\xABgate\xBB + checkout_link", required: true, note: "absent and the event is dropped; its origin builds every other link" },
|
|
2268
|
+
{ source: "customer.phone / address.phone", target: "customer.phone", required: true },
|
|
2269
|
+
{ source: "sa_localization", target: "phone region", required: true, note: 'address.country says "India", which the parser cannot use' },
|
|
2270
|
+
{ source: "customer.firstname", target: "customer.firstName" },
|
|
2271
|
+
{ source: "customer.lastname", target: "customer.lastName" },
|
|
2272
|
+
{ source: "customer.email / address.email", target: "customer.email" },
|
|
2273
|
+
{ source: "items[].title", target: "product_details", required: true, note: "the first PAID line wins; freebies rank last" },
|
|
2274
|
+
{ source: "items[].product_title", target: "product_name" },
|
|
2275
|
+
{ source: "items[].image", target: "product_image_url", note: "read off the featured line only" },
|
|
2276
|
+
{ source: "items[].url", target: "product_url", note: "relative \u2014 resolved against the abc_url origin" },
|
|
2277
|
+
{ source: "items[].final_price", target: "product_price", note: "PAISE \u2014 the consumer divides by 100" },
|
|
2278
|
+
{ source: "items[].sku", target: "product_sku" },
|
|
2279
|
+
{ source: "items[].product_type", target: "product_type" },
|
|
2280
|
+
{ source: "items[].variant_id", target: "cart_link", note: "joined as variant:quantity" },
|
|
2281
|
+
{ source: "items[].quantity", target: "total_quantity", note: "summed across the cart" },
|
|
2282
|
+
{ source: "item_count", target: "item_count", note: "gokwik's own count is kept over the line count" },
|
|
2283
|
+
{ source: "total_price", target: "total_price", note: "RUPEE string, unlike the line prices" },
|
|
2284
|
+
{ source: "original_total_price", target: "original_total_price" },
|
|
2285
|
+
{ source: "items_subtotal_price", target: "subtotal_price" },
|
|
2286
|
+
{ source: "total_discount", target: "total_discount" },
|
|
2287
|
+
{ source: "currency", target: "currency" },
|
|
2288
|
+
{ source: "request_id", target: "request_id" },
|
|
2289
|
+
{ source: "token", target: "token" },
|
|
2290
|
+
{ source: "drop_stage", target: "drop_stage" },
|
|
2291
|
+
{ source: "rto_risk_flag", target: "rto_risk_flag" },
|
|
2292
|
+
{ source: "brand_order_count", target: "brand_order_count" },
|
|
2293
|
+
{ source: "mkt_source", target: "mkt_source" },
|
|
2294
|
+
{ source: "mkt_medium", target: "mkt_medium" },
|
|
2295
|
+
{ source: "mkt_campaign", target: "mkt_campaign" },
|
|
2296
|
+
{ source: "mkt_content", target: "mkt_content" },
|
|
2297
|
+
{ source: "mkt_term", target: "mkt_term" },
|
|
2298
|
+
{ source: "mkt_fbclid", target: "mkt_fbclid" },
|
|
2299
|
+
{ source: "landing_page", target: "landing_page" },
|
|
2300
|
+
{ source: "orig_referrer", target: "orig_referrer" },
|
|
2301
|
+
{ source: "address.city", target: "address.city" },
|
|
2302
|
+
{ source: "address.state", target: "address.state" },
|
|
2303
|
+
{ source: "address.pincode", target: "address.pincode" },
|
|
2304
|
+
{ source: "address.country", target: "address.country" },
|
|
2305
|
+
{ source: "address.address", target: "address.address" },
|
|
2306
|
+
{ source: "shipping.price", target: "shipping.price" },
|
|
2307
|
+
{ source: "city", target: "city", note: "the ip city, not the delivery city" },
|
|
2308
|
+
{ source: "isp", target: "isp" },
|
|
2309
|
+
{ source: "user_agent", target: "user_agent" },
|
|
2310
|
+
{ source: "updated_at", target: "eventTime" }
|
|
2311
|
+
];
|
|
2312
|
+
var editableFields8 = [
|
|
2313
|
+
{ group: "Checkout", path: "request_id", label: "Request id" },
|
|
2314
|
+
{ group: "Checkout", path: "token", label: "Token" },
|
|
2315
|
+
{ group: "Checkout", path: "abc_url", label: "Recovery URL", hint: "gates the event; its origin builds the product and cart links" },
|
|
2316
|
+
{ group: "Checkout", path: "drop_stage", label: "Drop stage" },
|
|
2317
|
+
{ group: "Checkout", path: "rto_risk_flag", label: "RTO risk flag" },
|
|
2318
|
+
{ group: "Checkout", path: "gokwik_source_channel", label: "Source channel" },
|
|
2319
|
+
{ group: "Pricing", path: "total_price", label: "Total price", hint: "rupee string, unlike the line prices" },
|
|
2320
|
+
{ group: "Pricing", path: "total_discount", label: "Discount" },
|
|
2321
|
+
{ group: "Pricing", path: "currency", label: "Currency" },
|
|
2322
|
+
{ group: "Customer", path: "customer.firstname", label: "First name" },
|
|
2323
|
+
{ group: "Customer", path: "customer.lastname", label: "Last name" },
|
|
2324
|
+
{ group: "Customer", path: "customer.email", label: "Email" },
|
|
2325
|
+
{ group: "Customer", path: "customer.phone", label: "Phone" },
|
|
2326
|
+
{ group: "Customer", path: "brand_order_count", label: "Brand order count", type: "number" },
|
|
2327
|
+
{ group: "Customer", path: "sa_localization", label: "Localization", hint: "two letter region used to parse the phone" },
|
|
2328
|
+
{ group: "Shipping", path: "address.address", label: "Address line" },
|
|
2329
|
+
{ group: "Shipping", path: "address.city", label: "City" },
|
|
2330
|
+
{ group: "Shipping", path: "address.state", label: "State" },
|
|
2331
|
+
{ group: "Shipping", path: "address.pincode", label: "Pincode", type: "number" },
|
|
2332
|
+
{ group: "Attribution", path: "mkt_source", label: "UTM source" },
|
|
2333
|
+
{ group: "Attribution", path: "mkt_medium", label: "UTM medium" },
|
|
2334
|
+
{ group: "Attribution", path: "mkt_campaign", label: "UTM campaign" },
|
|
2335
|
+
{ group: "Attribution", path: "landing_page", label: "Landing page" },
|
|
2336
|
+
{ group: "Attribution", path: "orig_referrer", label: "Referrer" }
|
|
2337
|
+
];
|
|
2338
|
+
function paise(rupees) {
|
|
2339
|
+
return Math.round(money2(rupees) * 100);
|
|
2340
|
+
}
|
|
2341
|
+
function buildPayload8(ctx) {
|
|
2342
|
+
const { config, items, phone } = ctx;
|
|
2343
|
+
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
2344
|
+
const currency = ctx.currency || config.defaults.currency;
|
|
2345
|
+
const domain = config.shopify.domain;
|
|
2346
|
+
const cust = config.customer;
|
|
2347
|
+
const utm = config.defaults.utm ?? {};
|
|
2348
|
+
const lineItems = (items ?? []).map(({ product, variant, quantity }) => {
|
|
2349
|
+
const unit = money2(variant?.price ?? 0);
|
|
2350
|
+
return {
|
|
2351
|
+
id: Number(variant?.id ?? 0),
|
|
2352
|
+
sku: variant?.sku || "",
|
|
2353
|
+
url: `/products/${product.handle}?variant=${variant?.id ?? ""}`,
|
|
2354
|
+
grams: 500,
|
|
2355
|
+
image: imageForVariant(product, variant),
|
|
2356
|
+
price: paise(unit),
|
|
2357
|
+
title: `${product.title}${variant?.title ? ` - ${variant.title}` : ""}`,
|
|
2358
|
+
vendor: product.vendor ?? "",
|
|
2359
|
+
taxable: true,
|
|
2360
|
+
quantity,
|
|
2361
|
+
gift_card: false,
|
|
2362
|
+
line_price: paise(unit * quantity),
|
|
2363
|
+
product_id: Number(product.id),
|
|
2364
|
+
variant_id: Number(variant?.id ?? 0),
|
|
2365
|
+
final_price: paise(unit),
|
|
2366
|
+
product_type: product.productType ?? "",
|
|
2367
|
+
product_title: product.title,
|
|
2368
|
+
original_price: paise(unit),
|
|
2369
|
+
total_discount: 0,
|
|
2370
|
+
final_line_price: paise(unit * quantity),
|
|
2371
|
+
requires_shipping: true
|
|
2372
|
+
};
|
|
2373
|
+
});
|
|
2374
|
+
const subtotal = money2(lineItems.reduce((sum, li) => sum + li.final_line_price / 100, 0));
|
|
2375
|
+
const discount = money2(Math.min(ctx.discount ?? 0, subtotal));
|
|
2376
|
+
const total = money2(subtotal - discount);
|
|
2377
|
+
const requestId = ctx.requestId ?? `gk-${now.getTime()}`;
|
|
2378
|
+
const abcUrl = `https://${domain}?mrid=${requestId}`;
|
|
2379
|
+
return {
|
|
2380
|
+
request_id: requestId,
|
|
2381
|
+
token: `${requestId}?key=${now.getTime().toString(36)}`,
|
|
2382
|
+
note: null,
|
|
2383
|
+
attributes: "{}",
|
|
2384
|
+
original_total_price: subtotal.toFixed(4),
|
|
2385
|
+
total_price: total.toFixed(4),
|
|
2386
|
+
total_discount: discount.toFixed(4),
|
|
2387
|
+
total_weight: "500.0000",
|
|
2388
|
+
is_abandoned: true,
|
|
2389
|
+
item_count: lineItems.length,
|
|
2390
|
+
items: lineItems,
|
|
2391
|
+
requires_shipping: true,
|
|
2392
|
+
currency,
|
|
2393
|
+
items_subtotal_price: String(subtotal),
|
|
2394
|
+
cart_level_discount_applications: [],
|
|
2395
|
+
discount: null,
|
|
2396
|
+
shipping: {
|
|
2397
|
+
id: 1,
|
|
2398
|
+
name: "Shipping",
|
|
2399
|
+
price: ctx.shippingPrice ?? 0,
|
|
2400
|
+
title: "Shipping",
|
|
2401
|
+
base_price: 0,
|
|
2402
|
+
cod_charges: 0,
|
|
2403
|
+
prepaid_price: 0,
|
|
2404
|
+
payment_options: "all",
|
|
2405
|
+
discounted_price: 0
|
|
2406
|
+
},
|
|
2407
|
+
abc_url: abcUrl,
|
|
2408
|
+
created_at: now.toISOString(),
|
|
2409
|
+
updated_at: now.toISOString(),
|
|
2410
|
+
city: cust.city,
|
|
2411
|
+
isp: "Test ISP",
|
|
2412
|
+
ip: "203.0.113.10",
|
|
2413
|
+
mkt_source: utm.utm_source ?? "direct",
|
|
2414
|
+
mkt_medium: utm.utm_medium ?? null,
|
|
2415
|
+
mkt_campaign: utm.utm_campaign ?? null,
|
|
2416
|
+
mkt_content: utm.utm_content ?? null,
|
|
2417
|
+
mkt_term: utm.utm_term ?? null,
|
|
2418
|
+
mkt_fbclid: utm.fbclid ?? null,
|
|
2419
|
+
gift_card_total: "0",
|
|
2420
|
+
payment_methods: ["upi", "cc", "dc", "netbanking"],
|
|
2421
|
+
drop_stage: "Payment Page",
|
|
2422
|
+
checkout_url: null,
|
|
2423
|
+
note_text: "",
|
|
2424
|
+
landing_page: "/",
|
|
2425
|
+
orig_referrer: `https://${domain}/`,
|
|
2426
|
+
gokwik_source_channel: "shopify_checkout",
|
|
2427
|
+
store_source: "web",
|
|
2428
|
+
store_platform: null,
|
|
2429
|
+
rto_risk_flag: "Control",
|
|
2430
|
+
sa_localization: cust.countryCode,
|
|
2431
|
+
shopifysessionid: `gk-session-${now.getTime()}`,
|
|
2432
|
+
user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/151.0.0.0 Safari/537.36",
|
|
2433
|
+
notify_customer: false,
|
|
2434
|
+
brand_order_count: 2,
|
|
2435
|
+
address: {
|
|
2436
|
+
firstname: cust.firstName,
|
|
2437
|
+
lastname: cust.lastName,
|
|
2438
|
+
city: cust.city,
|
|
2439
|
+
pincode: Number(cust.zip) || 0,
|
|
2440
|
+
state: cust.province,
|
|
2441
|
+
country: cust.country,
|
|
2442
|
+
email: cust.email,
|
|
2443
|
+
phone,
|
|
2444
|
+
default_address: 0,
|
|
2445
|
+
addresstype: "home",
|
|
2446
|
+
partial_address: false,
|
|
2447
|
+
total_order_count: 1,
|
|
2448
|
+
deliver_order_count: 0,
|
|
2449
|
+
address: cust.address1
|
|
2450
|
+
},
|
|
2451
|
+
customer: {
|
|
2452
|
+
firstname: cust.firstName,
|
|
2453
|
+
lastname: cust.lastName,
|
|
2454
|
+
email: cust.email,
|
|
2455
|
+
phone
|
|
2456
|
+
}
|
|
2457
|
+
};
|
|
2458
|
+
}
|
|
2459
|
+
function sign8() {
|
|
2460
|
+
return { signature: null, timestamp: null, headers: { "content-type": "application/json" } };
|
|
2461
|
+
}
|
|
2462
|
+
function webhookUrl8(config) {
|
|
2463
|
+
return String(targetFor(config, "gokwik").webhookUrl ?? "").trim();
|
|
2464
|
+
}
|
|
2465
|
+
function webhookSecret8(config) {
|
|
2466
|
+
return String(targetFor(config, "gokwik").webhookSecret ?? "");
|
|
2467
|
+
}
|
|
2468
|
+
function summarize8(payload) {
|
|
2469
|
+
const items = Array.isArray(payload?.items) ? payload.items : [];
|
|
2470
|
+
let store;
|
|
2471
|
+
try {
|
|
2472
|
+
store = payload?.abc_url ? new URL(payload.abc_url).host : void 0;
|
|
2473
|
+
} catch {
|
|
2474
|
+
store = payload?.abc_url;
|
|
2475
|
+
}
|
|
2476
|
+
return {
|
|
2477
|
+
event: "abandoned checkout",
|
|
2478
|
+
store,
|
|
2479
|
+
customer: `${payload?.customer?.firstname ?? ""} ${payload?.customer?.lastname ?? ""} \xB7 ${payload?.customer?.phone ?? ""}`.trim(),
|
|
2480
|
+
items: items.map((i) => `${i.title} x${i.quantity}`).join(", "),
|
|
2481
|
+
total: payload?.total_price,
|
|
2482
|
+
currency: payload?.currency,
|
|
2483
|
+
extra: `stage ${payload?.drop_stage}, rto ${payload?.rto_risk_flag}`,
|
|
2484
|
+
link: payload?.abc_url
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
var gokwik_default = {
|
|
2488
|
+
id: "gokwik",
|
|
2489
|
+
urlKey: "gokwik",
|
|
2490
|
+
label: "GoKwik",
|
|
2491
|
+
eventType: "gokwik_abandoned_checkout",
|
|
2492
|
+
gate: { path: GATE_PATH5, value: GATE_VALUE4 },
|
|
2493
|
+
signatureScheme: "none documented \u2014 every request is accepted",
|
|
2494
|
+
signatureHeader: null,
|
|
2495
|
+
fieldMap: fieldMap8,
|
|
2496
|
+
editableFields: editableFields8,
|
|
2497
|
+
buildPayload: buildPayload8,
|
|
2498
|
+
sign: sign8,
|
|
2499
|
+
webhookUrl: webhookUrl8,
|
|
2500
|
+
webhookSecret: webhookSecret8,
|
|
2501
|
+
summarize: summarize8
|
|
2502
|
+
};
|
|
2503
|
+
|
|
2504
|
+
// src/providers/ecom360.mjs
|
|
2505
|
+
import crypto4 from "crypto";
|
|
2506
|
+
var GATE_PATH6 = "event";
|
|
2507
|
+
var GATE_VALUE5 = "ABANDONED_CHECKOUT";
|
|
2508
|
+
var fieldMap9 = [
|
|
2509
|
+
{ source: "event", target: "\xABgate\xBB", required: true, note: "must be ABANDONED_CHECKOUT or the event is dropped" },
|
|
2510
|
+
{ source: "data.phone / data.customer.shipping_address.phone", target: "customer.phone", required: true },
|
|
2511
|
+
{ source: "data.customer.shipping_address.country_code", target: "phone region" },
|
|
2512
|
+
{ source: "data.customer.first_name", target: "customer.firstName" },
|
|
2513
|
+
{ source: "data.customer.last_name", target: "customer.lastName" },
|
|
2514
|
+
{ source: "data.email / data.customer.email", target: "customer.email" },
|
|
2515
|
+
{ source: "data.abandoned_checkout_url", target: "checkout_link", required: true },
|
|
2516
|
+
{ source: "data.store_url", target: "store_url + cart_link", required: true, note: "the cart link is built from it; no lookup needed" },
|
|
2517
|
+
{ source: "data.line_items[].title", target: "product_details", required: true, note: "the first PAID line wins; freebies rank last" },
|
|
2518
|
+
{ source: "data.line_items[].sku", target: "product_sku" },
|
|
2519
|
+
{ source: "data.line_items[].price", target: "product_price", note: "also ranks the lines; a zero marks a freebie" },
|
|
2520
|
+
{ source: "data.line_items[].variant_id", target: "cart_link", note: "joined as variant:quantity" },
|
|
2521
|
+
{ source: "data.line_items[].quantity", target: "total_quantity", note: "summed across the cart" },
|
|
2522
|
+
{ source: "data.line_items[]", target: "item_count", note: "the line count" },
|
|
2523
|
+
{ source: "\u2014 (no handle is sent)", target: "product_url", note: "the consumer builds none, by design" },
|
|
2524
|
+
{ source: "data.total_price", target: "total_price" },
|
|
2525
|
+
{ source: "data.original_total_price", target: "original_total_price" },
|
|
2526
|
+
{ source: "data.total_discount", target: "total_discount" },
|
|
2527
|
+
{ source: "data.promotions[0].code", target: "coupon_code" },
|
|
2528
|
+
{ source: "data.promotions[0].value", target: "coupon_value" },
|
|
2529
|
+
{ source: "data.cart_id", target: "cart_id" },
|
|
2530
|
+
{ source: "data.cart_token", target: "cart_token" },
|
|
2531
|
+
{ source: "data.platform", target: "platform" },
|
|
2532
|
+
{ source: "data.utm_parameters.utm_source", target: "utm_parameters.utm_source" },
|
|
2533
|
+
{ source: "data.utm_parameters.utm_medium", target: "utm_parameters.utm_medium" },
|
|
2534
|
+
{ source: "data.utm_parameters.utm_campaign", target: "utm_parameters.utm_campaign" },
|
|
2535
|
+
{ source: "data.utm_parameters.fbclid", target: "utm_parameters.fbclid" },
|
|
2536
|
+
{ source: "data.customer.shipping_address.city", target: "shipping_address.city" },
|
|
2537
|
+
{ source: "data.customer.shipping_address.province", target: "shipping_address.province" },
|
|
2538
|
+
{ source: "data.customer.shipping_address.zip", target: "shipping_address.zip" },
|
|
2539
|
+
{ source: "data.customer.shipping_address.country", target: "shipping_address.country" }
|
|
2540
|
+
];
|
|
2541
|
+
var editableFields9 = [
|
|
2542
|
+
{ group: "Checkout", path: "data.cart_id", label: "Cart id" },
|
|
2543
|
+
{ group: "Checkout", path: "data.cart_token", label: "Cart token" },
|
|
2544
|
+
{ group: "Checkout", path: "data.abandoned_checkout_url", label: "Checkout URL", hint: "the link the shopper is sent back to" },
|
|
2545
|
+
{ group: "Checkout", path: "data.store_url", label: "Store domain", hint: "the cart link is built from this" },
|
|
2546
|
+
{ group: "Checkout", path: "data.platform", label: "Platform" },
|
|
2547
|
+
{ group: "Pricing", path: "data.total_price", label: "Total price", type: "number" },
|
|
2548
|
+
{ group: "Pricing", path: "data.original_total_price", label: "Original total", type: "number" },
|
|
2549
|
+
{ group: "Pricing", path: "data.total_discount", label: "Discount", type: "number" },
|
|
2550
|
+
{ group: "Customer", path: "data.customer.first_name", label: "First name" },
|
|
2551
|
+
{ group: "Customer", path: "data.customer.last_name", label: "Last name" },
|
|
2552
|
+
{ group: "Customer", path: "data.email", label: "Email" },
|
|
2553
|
+
{ group: "Customer", path: "data.phone", label: "Phone" },
|
|
2554
|
+
{ group: "Shipping", path: "data.customer.shipping_address.address1", label: "Address line 1" },
|
|
2555
|
+
{ group: "Shipping", path: "data.customer.shipping_address.city", label: "City" },
|
|
2556
|
+
{ group: "Shipping", path: "data.customer.shipping_address.province", label: "State" },
|
|
2557
|
+
{ group: "Shipping", path: "data.customer.shipping_address.zip", label: "Zip / postcode" },
|
|
2558
|
+
{ group: "Shipping", path: "data.customer.shipping_address.country_code", label: "Country code", hint: "region used to parse the phone" },
|
|
2559
|
+
{ group: "Attribution", path: "data.utm_parameters.utm_source", label: "UTM source" },
|
|
2560
|
+
{ group: "Attribution", path: "data.utm_parameters.utm_campaign", label: "UTM campaign" },
|
|
2561
|
+
{ group: "Attribution", path: "data.utm_parameters.fbclid", label: "FBCLID" }
|
|
2562
|
+
];
|
|
2563
|
+
function buildPayload9(ctx) {
|
|
2564
|
+
const { config, items, phone } = ctx;
|
|
2565
|
+
const now = ctx.now ?? /* @__PURE__ */ new Date();
|
|
2566
|
+
const domain = config.shopify.domain;
|
|
2567
|
+
const cust = config.customer;
|
|
2568
|
+
const utm = config.defaults.utm ?? {};
|
|
2569
|
+
const lineItems = (items ?? []).map(({ product, variant, quantity }) => ({
|
|
2570
|
+
product_id: String(product.id),
|
|
2571
|
+
variant_id: String(variant?.id ?? ""),
|
|
2572
|
+
sku: variant?.sku || "",
|
|
2573
|
+
price: money2(variant?.price ?? 0),
|
|
2574
|
+
quantity,
|
|
2575
|
+
gram: 200,
|
|
2576
|
+
title: `${product.title}${variant?.title ? ` - ${variant.title}` : ""}`
|
|
2577
|
+
}));
|
|
2578
|
+
const subtotal = money2(lineItems.reduce((sum, li) => sum + li.price * li.quantity, 0));
|
|
2579
|
+
const discount = money2(Math.min(ctx.discount ?? 0, subtotal));
|
|
2580
|
+
const total = money2(subtotal - discount);
|
|
2581
|
+
const cartToken = ctx.cartToken ?? `ec-${now.getTime()}`;
|
|
2582
|
+
const shippingAddress = {
|
|
2583
|
+
first_name: cust.firstName,
|
|
2584
|
+
last_name: cust.lastName,
|
|
2585
|
+
address1: cust.address1,
|
|
2586
|
+
address2: "",
|
|
2587
|
+
city: cust.city,
|
|
2588
|
+
province: cust.province,
|
|
2589
|
+
country: cust.country,
|
|
2590
|
+
zip: cust.zip,
|
|
2591
|
+
phone,
|
|
2592
|
+
name: `${cust.firstName} ${cust.lastName}`.trim(),
|
|
2593
|
+
province_code: cust.provinceCode ?? "",
|
|
2594
|
+
country_code: cust.countryCode
|
|
2595
|
+
};
|
|
2596
|
+
return {
|
|
2597
|
+
event: GATE_VALUE5,
|
|
2598
|
+
data: {
|
|
2599
|
+
cart_id: `cart_${now.getTime()}`,
|
|
2600
|
+
store_url: domain,
|
|
2601
|
+
platform: "SHOPIFY",
|
|
2602
|
+
cart_token: cartToken,
|
|
2603
|
+
email: cust.email,
|
|
2604
|
+
phone,
|
|
2605
|
+
abandoned_checkout_url: `https://${domain}/checkouts/${cartToken}`,
|
|
2606
|
+
original_total_price: subtotal,
|
|
2607
|
+
total_price: total,
|
|
2608
|
+
total_discount: discount,
|
|
2609
|
+
utm_parameters: {
|
|
2610
|
+
fbclid: utm.fbclid ?? void 0,
|
|
2611
|
+
utm_source: utm.utm_source ?? void 0,
|
|
2612
|
+
utm_medium: utm.utm_medium ?? void 0,
|
|
2613
|
+
utm_campaign: utm.utm_campaign ?? void 0,
|
|
2614
|
+
utm_content: utm.utm_content ?? void 0,
|
|
2615
|
+
utm_term: utm.utm_term ?? void 0
|
|
2616
|
+
},
|
|
2617
|
+
line_items: lineItems,
|
|
2618
|
+
promotions: ctx.couponCode ? [{ code: ctx.couponCode, value: discount }] : [],
|
|
2619
|
+
customer: {
|
|
2620
|
+
email: cust.email,
|
|
2621
|
+
first_name: cust.firstName,
|
|
2622
|
+
last_name: cust.lastName,
|
|
2623
|
+
shipping_address: shippingAddress
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
};
|
|
2627
|
+
}
|
|
2628
|
+
function sign9({ body, secret }) {
|
|
2629
|
+
const signature = crypto4.createHmac("sha256", String(secret)).update(body).digest("base64");
|
|
2630
|
+
return {
|
|
2631
|
+
timestamp: null,
|
|
2632
|
+
signature,
|
|
2633
|
+
headers: {
|
|
2634
|
+
"content-type": "application/json",
|
|
2635
|
+
"x-webhook-signature": signature,
|
|
2636
|
+
"x-webhook-topic": "abandonedCheckout",
|
|
2637
|
+
"x-webhook-version": "v1",
|
|
2638
|
+
"user-agent": "Ecom360-v1"
|
|
2639
|
+
}
|
|
2640
|
+
};
|
|
2641
|
+
}
|
|
2642
|
+
function webhookUrl9(config) {
|
|
2643
|
+
return String(targetFor(config, "ecom360").webhookUrl ?? "").trim();
|
|
2644
|
+
}
|
|
2645
|
+
function webhookSecret9(config) {
|
|
2646
|
+
return String(targetFor(config, "ecom360").webhookSecret ?? "");
|
|
2647
|
+
}
|
|
2648
|
+
function summarize9(payload) {
|
|
2649
|
+
const d = payload?.data ?? {};
|
|
2650
|
+
const items = Array.isArray(d.line_items) ? d.line_items : [];
|
|
2651
|
+
const c2 = d.customer ?? {};
|
|
2652
|
+
return {
|
|
2653
|
+
event: "abandoned checkout",
|
|
2654
|
+
store: d.store_url,
|
|
2655
|
+
customer: `${c2.first_name ?? ""} ${c2.last_name ?? ""} \xB7 ${d.phone ?? ""}`.trim(),
|
|
2656
|
+
items: items.map((i) => `${i.title} x${i.quantity}`).join(", "),
|
|
2657
|
+
total: d.total_price,
|
|
2658
|
+
currency: void 0,
|
|
2659
|
+
extra: `platform ${d.platform}`,
|
|
2660
|
+
link: d.abandoned_checkout_url
|
|
2661
|
+
};
|
|
2662
|
+
}
|
|
2663
|
+
var ecom360_default = {
|
|
2664
|
+
id: "ecom360",
|
|
2665
|
+
urlKey: "ecom360",
|
|
2666
|
+
label: "Ecom 360",
|
|
2667
|
+
eventType: "ecom360_abandoned_checkout",
|
|
2668
|
+
gate: { path: GATE_PATH6, value: GATE_VALUE5 },
|
|
2669
|
+
signatureScheme: "base64 HMAC-SHA256 over the body",
|
|
2670
|
+
signatureHeader: "x-webhook-signature",
|
|
2671
|
+
fieldMap: fieldMap9,
|
|
2672
|
+
editableFields: editableFields9,
|
|
2673
|
+
buildPayload: buildPayload9,
|
|
2674
|
+
sign: sign9,
|
|
2675
|
+
webhookUrl: webhookUrl9,
|
|
2676
|
+
webhookSecret: webhookSecret9,
|
|
2677
|
+
summarize: summarize9
|
|
2678
|
+
};
|
|
2679
|
+
|
|
2260
2680
|
// src/providers/index.mjs
|
|
2261
2681
|
var PROVIDER_META = [
|
|
2262
2682
|
{
|
|
@@ -2310,6 +2730,20 @@ var PROVIDER_META = [
|
|
|
2310
2730
|
signature: "none documented \u2014 every request is accepted",
|
|
2311
2731
|
header: null,
|
|
2312
2732
|
available: true
|
|
2733
|
+
},
|
|
2734
|
+
{
|
|
2735
|
+
id: "gokwik",
|
|
2736
|
+
label: "GoKwik",
|
|
2737
|
+
signature: "none documented \u2014 every request is accepted",
|
|
2738
|
+
header: null,
|
|
2739
|
+
available: true
|
|
2740
|
+
},
|
|
2741
|
+
{
|
|
2742
|
+
id: "ecom360",
|
|
2743
|
+
label: "Ecom 360",
|
|
2744
|
+
signature: "base64 HMAC-SHA256 over the body",
|
|
2745
|
+
header: "x-webhook-signature",
|
|
2746
|
+
available: true
|
|
2313
2747
|
}
|
|
2314
2748
|
];
|
|
2315
2749
|
var providers = {
|
|
@@ -2319,7 +2753,9 @@ var providers = {
|
|
|
2319
2753
|
[shopflo_default.id]: shopflo_default,
|
|
2320
2754
|
[flexype_default.id]: flexype_default,
|
|
2321
2755
|
[return_prime_default.id]: return_prime_default,
|
|
2322
|
-
[fastrr_default.id]: fastrr_default
|
|
2756
|
+
[fastrr_default.id]: fastrr_default,
|
|
2757
|
+
[gokwik_default.id]: gokwik_default,
|
|
2758
|
+
[ecom360_default.id]: ecom360_default
|
|
2323
2759
|
};
|
|
2324
2760
|
function getProvider(id) {
|
|
2325
2761
|
const provider = providers[id];
|
|
@@ -2979,8 +3415,8 @@ function resolveSource(payload, source) {
|
|
|
2979
3415
|
}
|
|
2980
3416
|
return void 0;
|
|
2981
3417
|
}
|
|
2982
|
-
function coverage(payload,
|
|
2983
|
-
return
|
|
3418
|
+
function coverage(payload, fieldMap10) {
|
|
3419
|
+
return fieldMap10.map((f) => {
|
|
2984
3420
|
const value = resolveSource(payload, f.source);
|
|
2985
3421
|
const present = value !== void 0 && value !== null && value !== "";
|
|
2986
3422
|
return {
|
|
@@ -3032,6 +3468,15 @@ async function runAll({ payload, body, provider, config, checkImageUrls = true,
|
|
|
3032
3468
|
ok: missing.length === 0,
|
|
3033
3469
|
detail: missing.length === 0 ? `all ${cov.length} mapped fields resolved` : `missing: ${missing.map((m) => m.field).join(", ")}`
|
|
3034
3470
|
});
|
|
3471
|
+
const empty = cov.filter((c2) => c2.status === "empty");
|
|
3472
|
+
if (empty.length) {
|
|
3473
|
+
checks.push({
|
|
3474
|
+
name: "Empty optional fields",
|
|
3475
|
+
ok: true,
|
|
3476
|
+
warn: true,
|
|
3477
|
+
detail: `${empty.map((e) => e.maps_to).join(", ")} \u2014 a journey param bound to one of these needs a fallback, or the send fails`
|
|
3478
|
+
});
|
|
3479
|
+
}
|
|
3035
3480
|
return {
|
|
3036
3481
|
checks,
|
|
3037
3482
|
coverage: cov,
|
|
@@ -3136,7 +3581,7 @@ function applyEdits(payload, fields, edits) {
|
|
|
3136
3581
|
}
|
|
3137
3582
|
return payload;
|
|
3138
3583
|
}
|
|
3139
|
-
async function
|
|
3584
|
+
async function buildPayload10({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live, delta }) {
|
|
3140
3585
|
const provider0 = getProvider(providerId);
|
|
3141
3586
|
const needsItems = !provider0.selectionFor || ["cart", "product"].includes(provider0.selectionFor(eventName ?? provider0.defaultEvent));
|
|
3142
3587
|
if (needsItems && !items.length) throw new ConfigError("no products selected");
|
|
@@ -3683,7 +4128,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
3683
4128
|
const onDiscount = (raw) => startReview(Math.max(0, Number.parseFloat(raw) || 0));
|
|
3684
4129
|
const finalise = (payload) => {
|
|
3685
4130
|
setStep(STEP.BUILDING);
|
|
3686
|
-
|
|
4131
|
+
buildPayload10({ cfg: config, providerId, items, discount: draft.discount, payload, eventName, collection, live: draft.live, delta: draft.delta }).then(async (result) => {
|
|
3687
4132
|
setBuilt(result);
|
|
3688
4133
|
let req = null;
|
|
3689
4134
|
let command = "";
|
|
@@ -4954,7 +5399,7 @@ async function cmdBuild(args, config) {
|
|
|
4954
5399
|
else if (live?.kind === "order") log.ok(`order ${live.name} (${live.id})`);
|
|
4955
5400
|
else log.warn("no live record available \u2014 falling back to a generated one");
|
|
4956
5401
|
}
|
|
4957
|
-
const built = await
|
|
5402
|
+
const built = await buildPayload10({
|
|
4958
5403
|
cfg: config,
|
|
4959
5404
|
providerId,
|
|
4960
5405
|
eventName,
|