@misiki/gocommerce-connector 0.31.1 → 0.32.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/README.md +7 -6
- package/dist/{index-sPZh8NN4.d.cts → index-BAmkQfij.d.cts} +42 -4
- package/dist/{index-sPZh8NN4.d.ts → index-BAmkQfij.d.ts} +42 -4
- package/dist/index.cjs +90 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +90 -34
- package/dist/index.js.map +1 -1
- package/dist/services/index.cjs +90 -33
- package/dist/services/index.cjs.map +1 -1
- package/dist/services/index.d.cts +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +90 -34
- package/dist/services/index.js.map +1 -1
- package/package.json +1 -1
package/dist/services/index.cjs
CHANGED
|
@@ -2196,9 +2196,9 @@ var CheckoutService = class extends BaseService {
|
|
|
2196
2196
|
}
|
|
2197
2197
|
// The family's other gateway flows. GoCommerce's Stripe is a Payment
|
|
2198
2198
|
// Element (a client secret, not a hosted page) — `checkout('stripe')` returns
|
|
2199
|
-
// that secret for a storefront that mounts the element.
|
|
2200
|
-
//
|
|
2201
|
-
//
|
|
2199
|
+
// that secret for a storefront that mounts the element. PhonePe and Affirm are
|
|
2200
|
+
// not engine gateways at all. paymentMethodService never offers these codes,
|
|
2201
|
+
// so they are reached only by a storefront that hard-codes one.
|
|
2202
2202
|
async checkoutStripe() {
|
|
2203
2203
|
throw unsupported(
|
|
2204
2204
|
"checkoutStripe",
|
|
@@ -2221,7 +2221,7 @@ var CheckoutService = class extends BaseService {
|
|
|
2221
2221
|
const gateway = await this.redirectGateway();
|
|
2222
2222
|
if (!gateway) throw unsupported("checkoutPaypal", "this store has no hosted-page payment gateway switched on");
|
|
2223
2223
|
const id2 = cartId || storedCartId() || "";
|
|
2224
|
-
const back = origin ?
|
|
2224
|
+
const back = origin ? successUrl(origin, id2) : void 0;
|
|
2225
2225
|
const result = await this.place(gateway, id2, back ? { return_url: back } : {});
|
|
2226
2226
|
const url = result.payment.client_data?.url;
|
|
2227
2227
|
if (!url) throw new GoCommerceError("The payment page did not open. Please try again.", 502);
|
|
@@ -2237,11 +2237,40 @@ var CheckoutService = class extends BaseService {
|
|
|
2237
2237
|
} = {}) {
|
|
2238
2238
|
return { order_no: order_no ?? null, status: "processing" };
|
|
2239
2239
|
}
|
|
2240
|
-
|
|
2241
|
-
|
|
2240
|
+
/**
|
|
2241
|
+
* Cashfree's JavaScript checkout. The engine has already created the Cashfree
|
|
2242
|
+
* order; this hands the storefront the session its modal opens. `order_no` is
|
|
2243
|
+
* the store's number, which the storefront prefers over `order_id`, Cashfree's.
|
|
2244
|
+
*
|
|
2245
|
+
* The return URL is for the one case the modal cannot open, an in-app browser,
|
|
2246
|
+
* when Cashfree sends the shopper back to it instead. Only https is sent: every
|
|
2247
|
+
* Cashfree example is, and a plain-http dev origin should not risk the order.
|
|
2248
|
+
*/
|
|
2249
|
+
async checkoutCashfree({ cartId, origin } = {}) {
|
|
2250
|
+
const { id: id2, extras, address } = await this.storedCheckout(cartId);
|
|
2251
|
+
if (!extras.phone && !address.phone) throw new GoCommerceError("Add a phone number to pay with Cashfree.", 400);
|
|
2252
|
+
const result = await this.place("cashfree", id2, origin?.startsWith("https:") ? { return_url: successUrl(origin, id2) } : {});
|
|
2253
|
+
const data = result.payment.client_data ?? {};
|
|
2254
|
+
if (result.payment.kind !== "client_action" || !data.payment_session_id) {
|
|
2255
|
+
throw new GoCommerceError("The payment page did not open. Please try again.", 502);
|
|
2256
|
+
}
|
|
2257
|
+
cashfreeEnvironment = data.environment;
|
|
2258
|
+
return {
|
|
2259
|
+
order_no: result.order.number,
|
|
2260
|
+
payment_session_id: data.payment_session_id,
|
|
2261
|
+
order_id: data.order_id,
|
|
2262
|
+
environment: data.environment
|
|
2263
|
+
};
|
|
2242
2264
|
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2265
|
+
/**
|
|
2266
|
+
* Nothing to capture: the signed webhook tells the engine the order is paid.
|
|
2267
|
+
* The storefront calls this on the server, after Cashfree's modal resolves
|
|
2268
|
+
* with any outcome, so it can neither claim the payment nor, without the
|
|
2269
|
+
* browser's order token, check it. Answering sends the shopper to the success
|
|
2270
|
+
* page; throwing would call a payment that may have gone through failed.
|
|
2271
|
+
*/
|
|
2272
|
+
async captureCashfreePayment({ order_no } = {}) {
|
|
2273
|
+
return { order_no: order_no ?? null, status: "processing" };
|
|
2245
2274
|
}
|
|
2246
2275
|
async checkoutPhonepe() {
|
|
2247
2276
|
throw unsupported("checkoutPhonepe", "the engine has no PhonePe gateway");
|
|
@@ -2307,7 +2336,7 @@ var CheckoutService = class extends BaseService {
|
|
|
2307
2336
|
}
|
|
2308
2337
|
/**
|
|
2309
2338
|
* What checkout would charge for the cart now, by the storefront's method
|
|
2310
|
-
* code (`COD`, `RAZORPAY`, `PAYPAL`) or none yet (D185). Null until the
|
|
2339
|
+
* code (`COD`, `RAZORPAY`, `CASHFREE`, `PAYPAL`) or none yet (D185). Null until the
|
|
2311
2340
|
* address step has stored an address, and null from an engine before D185.
|
|
2312
2341
|
*
|
|
2313
2342
|
* A refusal is checkout's own: the same GoCommerceError, with the same
|
|
@@ -2315,7 +2344,7 @@ var CheckoutService = class extends BaseService {
|
|
|
2315
2344
|
*/
|
|
2316
2345
|
async getQuote({ cartId, method = "" } = {}) {
|
|
2317
2346
|
const id2 = cartId || storedCartId();
|
|
2318
|
-
if (!id2 || !cartExtras(id2).shippingAddress) return null;
|
|
2347
|
+
if (!id2 || !cartExtras(id2).shippingAddress || cartExtras(id2).attempt?.placed) return null;
|
|
2319
2348
|
const { extras, email, address } = await this.storedCheckout(id2);
|
|
2320
2349
|
const code = method.toLowerCase() === "paypal" ? await this.redirectGateway() : method.toLowerCase();
|
|
2321
2350
|
try {
|
|
@@ -2376,6 +2405,11 @@ var CheckoutService = class extends BaseService {
|
|
|
2376
2405
|
* key resumes that order, and without one the shopper is stuck. A changed
|
|
2377
2406
|
* request — a different address, a different method — gets a new key, since
|
|
2378
2407
|
* the engine refuses a key replayed with a different body.
|
|
2408
|
+
*
|
|
2409
|
+
* A gateway's modal keeps the key after the order is placed, along with exactly
|
|
2410
|
+
* what placed it. The cart is converted by then, so a shopper who closes the
|
|
2411
|
+
* window can pay again only under this key, and the engine then reopens the same
|
|
2412
|
+
* gateway order rather than risk a second charge on a new one (D232).
|
|
2379
2413
|
*/
|
|
2380
2414
|
async place(code, cartId, extra = {}) {
|
|
2381
2415
|
const { id: id2, extras, email, address, currency } = await this.storedCheckout(cartId);
|
|
@@ -2392,23 +2426,27 @@ var CheckoutService = class extends BaseService {
|
|
|
2392
2426
|
const serialised = JSON.stringify(body);
|
|
2393
2427
|
const retry = extras.attempt?.body === `${code}:${serialised}`;
|
|
2394
2428
|
const key = retry ? extras.attempt.key : newKey();
|
|
2429
|
+
const placed = retry ? extras.attempt?.placed : void 0;
|
|
2395
2430
|
const meta = retry ? extras.attempt?.meta : metaBrowser();
|
|
2396
2431
|
const attribution = retry ? extras.attempt?.attribution : landingAttribution();
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2432
|
+
if (!placed) {
|
|
2433
|
+
saveCartExtras(id2, {
|
|
2434
|
+
attempt: { key, body: `${code}:${serialised}`, ...meta ? { meta } : {}, ...attribution ? { attribution } : {} }
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2400
2437
|
const metadata = {
|
|
2401
2438
|
...extra.metadata,
|
|
2402
2439
|
...meta ? { meta_capi: meta } : {},
|
|
2403
2440
|
...attribution ? { attribution } : {}
|
|
2404
2441
|
};
|
|
2405
2442
|
const expected = this.expected.get(id2);
|
|
2443
|
+
const sent = placed ?? {
|
|
2444
|
+
...Object.keys(metadata).length ? { ...body, metadata } : body,
|
|
2445
|
+
...expected ? { quoted_total_minor: toMinor(expected.total, currency) } : {}
|
|
2446
|
+
};
|
|
2406
2447
|
const result = await this.data(`/api/checkout/${encodeURIComponent(code)}`, {
|
|
2407
2448
|
method: "POST",
|
|
2408
|
-
body:
|
|
2409
|
-
...Object.keys(metadata).length ? { ...body, metadata } : body,
|
|
2410
|
-
...expected ? { quoted_total_minor: toMinor(expected.total, currency) } : {}
|
|
2411
|
-
},
|
|
2449
|
+
body: sent,
|
|
2412
2450
|
headers: { "Idempotency-Key": key }
|
|
2413
2451
|
}).catch((err) => {
|
|
2414
2452
|
if (keyAlreadyUsed(err)) {
|
|
@@ -2435,11 +2473,18 @@ var CheckoutService = class extends BaseService {
|
|
|
2435
2473
|
}).catch(() => void 0);
|
|
2436
2474
|
}
|
|
2437
2475
|
}
|
|
2438
|
-
|
|
2476
|
+
const reopenable = result.payment.kind === "client_action";
|
|
2477
|
+
saveCartExtras(id2, { attempt: reopenable ? { key, body: `${code}:${serialised}`, placed: sent } : null });
|
|
2478
|
+
if (reopenable && result.order.payment_status === "paid") {
|
|
2479
|
+
throw new GoCommerceError(`Order ${result.order.number} is already paid, so there is nothing more to pay.`, 409, "already_paid");
|
|
2480
|
+
}
|
|
2439
2481
|
return result;
|
|
2440
2482
|
}
|
|
2441
2483
|
};
|
|
2442
2484
|
var REDIRECT_GATEWAYS = /* @__PURE__ */ new Set(["paypal", "adyen", "paddle", "lemonsqueezy", "creem", "hyperswitch", "revenuecat"]);
|
|
2485
|
+
var cashfreeEnvironment;
|
|
2486
|
+
var cashfreeIsTest = () => cashfreeEnvironment === "sandbox";
|
|
2487
|
+
var successUrl = (origin, cartId) => `${origin.replace(/\/+$/, "")}/checkout/success?cart_id=${encodeURIComponent(cartId)}`;
|
|
2443
2488
|
var unsupported = (method, why) => new NotSupportedError("CheckoutService", method, why);
|
|
2444
2489
|
function keyAlreadyUsed(err) {
|
|
2445
2490
|
return err instanceof GoCommerceError && err.status === 400 && err.message.includes("Idempotency-Key was already used");
|
|
@@ -2466,7 +2511,8 @@ var checkoutService = new CheckoutService();
|
|
|
2466
2511
|
// src/services/payment-method-service.ts
|
|
2467
2512
|
var DRIVABLE = {
|
|
2468
2513
|
cod: { code: "COD", img: "/payment/cod.svg" },
|
|
2469
|
-
razorpay: { code: "RAZORPAY" }
|
|
2514
|
+
razorpay: { code: "RAZORPAY" },
|
|
2515
|
+
cashfree: { code: "CASHFREE", img: "/payment/card.svg" }
|
|
2470
2516
|
};
|
|
2471
2517
|
var reported2 = /* @__PURE__ */ new Set();
|
|
2472
2518
|
var PaymentMethodService = class extends BaseService {
|
|
@@ -2475,7 +2521,12 @@ var PaymentMethodService = class extends BaseService {
|
|
|
2475
2521
|
const options = await this.facts.checkoutOptions();
|
|
2476
2522
|
const methods = options.methods ?? [];
|
|
2477
2523
|
const redirect = methods.find((m) => REDIRECT_GATEWAYS.has(m.code))?.code;
|
|
2478
|
-
const drive = (code) =>
|
|
2524
|
+
const drive = (code) => {
|
|
2525
|
+
if (code === "cashfree" && options.currency !== "INR") return void 0;
|
|
2526
|
+
if (DRIVABLE[code]) return DRIVABLE[code];
|
|
2527
|
+
if (code === redirect) return { code: "PAYPAL", img: "/payment/card.svg" };
|
|
2528
|
+
return REDIRECT_GATEWAYS.has(code) ? { code: code.toUpperCase(), img: "/payment/card.svg" } : void 0;
|
|
2529
|
+
};
|
|
2479
2530
|
const data = methods.filter((m) => {
|
|
2480
2531
|
if (drive(m.code)) return true;
|
|
2481
2532
|
if (!reported2.has(m.code)) {
|
|
@@ -2485,19 +2536,24 @@ var PaymentMethodService = class extends BaseService {
|
|
|
2485
2536
|
);
|
|
2486
2537
|
}
|
|
2487
2538
|
return false;
|
|
2488
|
-
}).map((m, i) =>
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2539
|
+
}).map((m, i) => {
|
|
2540
|
+
const method = {
|
|
2541
|
+
id: m.code,
|
|
2542
|
+
code: drive(m.code).code,
|
|
2543
|
+
engineCode: m.code,
|
|
2544
|
+
name: m.name,
|
|
2545
|
+
title: m.name,
|
|
2546
|
+
description: "",
|
|
2547
|
+
img: drive(m.code).img ?? null,
|
|
2548
|
+
fee: toMajor(m.fee),
|
|
2549
|
+
rank: i,
|
|
2550
|
+
active: true,
|
|
2551
|
+
isActive: true
|
|
2552
|
+
};
|
|
2553
|
+
if (REDIRECT_GATEWAYS.has(m.code) && m.code !== redirect) Object.assign(method, { redirects: true });
|
|
2554
|
+
if (m.code === "cashfree") Object.defineProperty(method, "isTest", { get: cashfreeIsTest, enumerable: true });
|
|
2555
|
+
return method;
|
|
2556
|
+
});
|
|
2501
2557
|
return { data, count: data.length, pageSize: data.length, noOfPage: 1, page: 1 };
|
|
2502
2558
|
}
|
|
2503
2559
|
};
|
|
@@ -4326,6 +4382,7 @@ exports.b2bService = b2bService;
|
|
|
4326
4382
|
exports.bannerService = bannerService;
|
|
4327
4383
|
exports.blogService = blogService;
|
|
4328
4384
|
exports.cartService = cartService;
|
|
4385
|
+
exports.cashfreeIsTest = cashfreeIsTest;
|
|
4329
4386
|
exports.categoryService = categoryService;
|
|
4330
4387
|
exports.chatService = chatService;
|
|
4331
4388
|
exports.checkoutService = checkoutService;
|