@crediblemark/buayar 0.6.2 → 0.8.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/index.mjs CHANGED
@@ -123,6 +123,9 @@ var CANONICAL_TO_IPAYMU = {
123
123
  permata_va: { paymentMethod: "va", paymentChannel: "permata" },
124
124
  danamon_va: { paymentMethod: "va", paymentChannel: "danamon" },
125
125
  bsi_va: { paymentMethod: "va", paymentChannel: "bsi" },
126
+ bag_va: { paymentMethod: "va", paymentChannel: "bag" },
127
+ muamalat_va: { paymentMethod: "va", paymentChannel: "bmi" },
128
+ bmi_va: { paymentMethod: "va", paymentChannel: "bmi" },
126
129
  qris: { paymentMethod: "qris", paymentChannel: "mpm" },
127
130
  gopay_qris: { paymentMethod: "qris", paymentChannel: "mpm" },
128
131
  shopeepay_qris: { paymentMethod: "qris", paymentChannel: "mpm" },
@@ -1580,35 +1583,48 @@ var IpaymuProvider = class extends BasePaymentProvider {
1580
1583
  const baseUrl = this.getBaseUrl(sandbox);
1581
1584
  const endpoint = isDirect ? "/payment/direct" : "/payment";
1582
1585
  const url = `${baseUrl}${endpoint}`;
1586
+ const notifyUrl = callbackUrl || config.callbackUrl || "https://localhost/callback";
1587
+ const redirectUrl = returnUrl || config.returnUrl || "https://localhost/return";
1588
+ const feeDirection = params.feeDirection || params.extra?.feeDirection || config.extra?.feeDirection;
1589
+ const escrow = params.escrow !== void 0 ? params.escrow : params.extra?.escrow !== void 0 ? params.extra?.escrow : config.extra?.escrow;
1583
1590
  let payload;
1584
1591
  if (isDirect) {
1585
1592
  payload = {
1586
1593
  name: customer.name,
1587
1594
  email: customer.email,
1588
- phone: customer.phone || "",
1595
+ phone: customer.phone || "081234567890",
1589
1596
  amount: integerAmount,
1590
- notifyUrl: callbackUrl || config.callbackUrl || "",
1597
+ notifyUrl,
1591
1598
  expired: 24,
1592
1599
  expiredType: "hours",
1593
1600
  comments: productDetails,
1594
1601
  referenceId: orderId,
1595
1602
  paymentMethod: ipaymuMethod.paymentMethod,
1596
1603
  ...ipaymuMethod.paymentChannel ? { paymentChannel: ipaymuMethod.paymentChannel } : {},
1604
+ ...feeDirection ? { feeDirection } : {},
1605
+ ...escrow !== void 0 ? { escrow } : {},
1597
1606
  ...params.providerParams
1598
1607
  };
1599
1608
  } else {
1609
+ const hasItems = params.items && params.items.length > 0;
1610
+ const product = hasItems ? params.items.map((i) => i.name) : [productDetails.length > 50 ? productDetails.substring(0, 47) + "..." : productDetails];
1611
+ const qty = hasItems ? params.items.map((i) => i.quantity) : [1];
1612
+ const price = hasItems ? params.items.map((i) => Math.round(i.price)) : [integerAmount];
1613
+ const description = hasItems ? params.items.map((i) => i.description || i.name) : [productDetails];
1600
1614
  payload = {
1601
- product: [productDetails.length > 50 ? productDetails.substring(0, 47) + "..." : productDetails],
1602
- qty: [1],
1603
- price: [integerAmount],
1604
- description: [productDetails],
1605
- returnUrl: returnUrl || config.returnUrl || "",
1606
- notifyUrl: callbackUrl || config.callbackUrl || "",
1607
- cancelUrl: returnUrl || config.returnUrl || "",
1615
+ product,
1616
+ qty,
1617
+ price,
1618
+ description,
1619
+ returnUrl: redirectUrl,
1620
+ notifyUrl,
1621
+ cancelUrl: redirectUrl,
1608
1622
  referenceId: orderId,
1609
1623
  buyerName: customer.name,
1610
1624
  buyerEmail: customer.email,
1611
- buyerPhone: customer.phone || "",
1625
+ buyerPhone: customer.phone || "081234567890",
1626
+ ...feeDirection ? { feeDirection } : {},
1627
+ ...escrow !== void 0 ? { escrow } : {},
1612
1628
  ...params.providerParams
1613
1629
  };
1614
1630
  }
@@ -1648,8 +1664,8 @@ var IpaymuProvider = class extends BasePaymentProvider {
1648
1664
  provider: "ipaymu",
1649
1665
  orderId,
1650
1666
  amount: integerAmount,
1651
- reference: resData.TransactionId ? String(resData.TransactionId) : String(resData.SessionId || ""),
1652
- paymentUrl: resData.Url,
1667
+ reference: resData.TransactionId ? String(resData.TransactionId) : String(resData.SessionId || resData.SessionID || ""),
1668
+ paymentUrl: resData.Url || resData.url,
1653
1669
  rawResponse: data
1654
1670
  };
1655
1671
  if (resData.PaymentNo) {
@@ -1708,6 +1724,88 @@ var IpaymuProvider = class extends BasePaymentProvider {
1708
1724
  };
1709
1725
  }
1710
1726
  async getPaymentMethods(params, config) {
1727
+ const va = config.merchantCode || config.merchantId || "";
1728
+ const apiKey = config.apiKey || "";
1729
+ const sandbox = !!config.sandbox;
1730
+ if (va && apiKey) {
1731
+ try {
1732
+ const url = `${this.getBaseUrl(sandbox)}/payment-method-list`;
1733
+ const payload = { account: va };
1734
+ const { signature, timestamp } = generateIpaymuSignature("POST", va, apiKey, payload);
1735
+ const response = await fetch(url, {
1736
+ method: "POST",
1737
+ headers: {
1738
+ "Content-Type": "application/json",
1739
+ "Accept": "application/json",
1740
+ "va": va,
1741
+ "signature": signature,
1742
+ "timestamp": timestamp
1743
+ },
1744
+ body: JSON.stringify(payload)
1745
+ });
1746
+ const data = await response.json().catch(() => null);
1747
+ if (response.ok && data?.Data && Array.isArray(data.Data)) {
1748
+ const methods = [];
1749
+ const categories2 = {};
1750
+ for (const group of data.Data) {
1751
+ const groupCode = (group.Code || "").toLowerCase();
1752
+ const groupName = group.Name || group.Description || "Lainnya";
1753
+ const channels = group.Channels || [];
1754
+ let category = "Lainnya";
1755
+ if (groupCode === "va") category = "Virtual Account";
1756
+ else if (groupCode === "cstore") category = "Retail / Gerai";
1757
+ else if (groupCode === "qris") category = "QRIS";
1758
+ else if (groupCode === "cc") category = "Kartu Kredit";
1759
+ else if (groupCode === "paylater") category = "Paylater / Cicilan";
1760
+ else if (groupCode === "cod") category = "COD";
1761
+ else category = groupName;
1762
+ for (const ch of channels) {
1763
+ const chCode = (ch.Code || "").toLowerCase();
1764
+ let canonicalCode = chCode;
1765
+ if (groupCode === "va") {
1766
+ canonicalCode = chCode === "bag" ? "bag_va" : chCode === "bmi" ? "muamalat_va" : `${chCode}_va`;
1767
+ } else if (groupCode === "cc") {
1768
+ canonicalCode = "credit_card";
1769
+ }
1770
+ let totalFee = "-";
1771
+ if (ch.TransactionFee) {
1772
+ if (ch.TransactionFee.ActualFeeType === "PERCENT") {
1773
+ totalFee = `${ch.TransactionFee.ActualFee}%`;
1774
+ } else if (ch.TransactionFee.ActualFee !== void 0) {
1775
+ totalFee = `IDR ${Number(ch.TransactionFee.ActualFee).toLocaleString()}`;
1776
+ }
1777
+ }
1778
+ const pm = {
1779
+ paymentMethod: canonicalCode,
1780
+ code: canonicalCode,
1781
+ paymentName: ch.Name || ch.Description || canonicalCode,
1782
+ paymentImage: `https://my.ipaymu.com/images/banks/${chCode}.png`,
1783
+ totalFee,
1784
+ category,
1785
+ extra: {
1786
+ healthStatus: ch.HealthStatus,
1787
+ instructionsDoc: ch.PaymentInstructionsDoc,
1788
+ feeDetail: ch.TransactionFee
1789
+ }
1790
+ };
1791
+ methods.push(pm);
1792
+ if (!categories2[category]) categories2[category] = [];
1793
+ categories2[category].push(pm);
1794
+ }
1795
+ }
1796
+ if (methods.length > 0) {
1797
+ return {
1798
+ success: true,
1799
+ provider: "ipaymu",
1800
+ methods,
1801
+ categories: categories2,
1802
+ rawResponse: data
1803
+ };
1804
+ }
1805
+ }
1806
+ } catch (err) {
1807
+ }
1808
+ }
1711
1809
  const staticMethods = [
1712
1810
  {
1713
1811
  paymentMethod: "bca_va",
@@ -1773,6 +1871,22 @@ var IpaymuProvider = class extends BasePaymentProvider {
1773
1871
  totalFee: "IDR 3,500",
1774
1872
  category: "Virtual Account"
1775
1873
  },
1874
+ {
1875
+ paymentMethod: "bag_va",
1876
+ code: "bag_va",
1877
+ paymentName: "Bank Artha Graha Virtual Account",
1878
+ paymentImage: "https://my.ipaymu.com/images/banks/bag.png",
1879
+ totalFee: "IDR 3,500",
1880
+ category: "Virtual Account"
1881
+ },
1882
+ {
1883
+ paymentMethod: "muamalat_va",
1884
+ code: "muamalat_va",
1885
+ paymentName: "Bank Muamalat Virtual Account",
1886
+ paymentImage: "https://my.ipaymu.com/images/banks/bmi.png",
1887
+ totalFee: "IDR 3,500",
1888
+ category: "Virtual Account"
1889
+ },
1776
1890
  {
1777
1891
  paymentMethod: "qris",
1778
1892
  code: "qris",
@@ -1874,11 +1988,14 @@ var IpaymuProvider = class extends BasePaymentProvider {
1874
1988
  };
1875
1989
  }
1876
1990
  const txData = data.Data || {};
1877
- const statusText = (txData.Status || txData.status || "").toString().toLowerCase();
1878
- const isPaid = statusText === "berhasil" || statusText === "success" || txData.StatusCode === 1;
1879
- const isPending = statusText === "pending" || txData.StatusCode === 0;
1880
- const isFailed = !isPaid && !isPending;
1881
- const isExpired = statusText === "expired";
1991
+ const rawStatus = txData.Status !== void 0 ? txData.Status : txData.status;
1992
+ const statusDesc = (txData.StatusDesc || "").toString().toLowerCase();
1993
+ const paidStatus = (txData.PaidStatus || "").toString().toLowerCase();
1994
+ const statusCode = txData.StatusCode !== void 0 ? Number(txData.StatusCode) : rawStatus !== void 0 ? Number(rawStatus) : void 0;
1995
+ const isPaid = statusCode === 1 || paidStatus === "paid" || statusDesc.includes("berhasil") || statusDesc.includes("success");
1996
+ const isPending = statusCode === 0 || paidStatus === "unpaid" || statusDesc.includes("menunggu") || statusDesc.includes("pending");
1997
+ const isExpired = statusCode === 2 || statusDesc.includes("expired") || statusDesc.includes("kadaluarsa");
1998
+ const isFailed = !isPaid && !isPending && !isExpired;
1882
1999
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
1883
2000
  return {
1884
2001
  success: true,
@@ -2468,6 +2585,29 @@ function verifySnapWebhookSignature(headers, body, clientSecret, endpointUrl = "
2468
2585
  );
2469
2586
  return safeCompare(incoming, computed);
2470
2587
  }
2588
+ function snapErrorHint(message, code) {
2589
+ const m = (message || "").toLowerCase();
2590
+ const c = (code || "").toLowerCase();
2591
+ if (m.includes("unknown client") || c.includes("4017300") || c.includes("4017400")) {
2592
+ return "Client ID tidak dikenali DOKU. Pastikan clientId benar & kanal SNAP aktif untuk akun ini.";
2593
+ }
2594
+ if (m.includes("signature") || c.startsWith("401")) {
2595
+ return "Signature ditolak DOKU. Pastikan (a) Merchant Public Key yang di-upload sesuai dengan private key yang dipakai, dan (b) Get Token memakai timestamp UTC (Z).";
2596
+ }
2597
+ if (m.includes("bin") || m.includes("not configured") && m.includes("identifier")) {
2598
+ return "Akun belum punya BIN/partnerServiceId VA yang aktif. Sediakan nilai di config.extra.partnerServiceId (atau DOKU_PARTNER_SERVICE_ID) setelah di-assign di dashboard/sales.";
2599
+ }
2600
+ if (m.includes("merchantid") || m.includes("merchant id")) {
2601
+ return "QRIS/e-Wallet butuh merchantId. Isi config.extra.merchantId (atau DOKU_MERCHANT_ID) dari dashboard.";
2602
+ }
2603
+ if (m.includes("partner service id") || m.includes("partnerServiceId")) {
2604
+ return "partnerServiceId tidak valid. Harus 8 karakter left-padded (BIN/company code DOKU).";
2605
+ }
2606
+ if (m.includes("customer no") || m.includes("customerno")) {
2607
+ return "customerNo tidak valid (maks 20 digit unik). Cek config.extra.customerNo.";
2608
+ }
2609
+ return void 0;
2610
+ }
2471
2611
 
2472
2612
  // src/clients/snap.ts
2473
2613
  var SnapClient = class {
@@ -2524,7 +2664,16 @@ var SnapClient = class {
2524
2664
  } catch {
2525
2665
  }
2526
2666
  if (!response.ok || !data?.accessToken) {
2527
- throw new Error(data?.responseMessage || data?.message || `DOKU SNAP get-token failed: HTTP ${response.status} - ${text}`);
2667
+ const baseMessage = data?.responseMessage || data?.message || `DOKU SNAP get-token failed: HTTP ${response.status}`;
2668
+ const hint = snapErrorHint(baseMessage, data?.responseCode);
2669
+ const err = new SnapApiError(`${baseMessage}${data?.responseCode ? ` (${data.responseCode})` : ""}${hint ? ` \u2014 ${hint}` : ""}`, {
2670
+ status: response.status,
2671
+ code: data?.responseCode,
2672
+ raw: data,
2673
+ endpoint,
2674
+ method: "POST"
2675
+ });
2676
+ throw err;
2528
2677
  }
2529
2678
  if (!clientSecret) {
2530
2679
  }
@@ -2585,12 +2734,37 @@ var SnapClient = class {
2585
2734
  } catch {
2586
2735
  }
2587
2736
  if (!response.ok) {
2588
- const err = data?.responseMessage || data?.error?.message || data?.message || `HTTP ${response.status}`;
2589
- throw new Error(`${err}${data?.responseCode ? ` (${data.responseCode})` : ""}`);
2737
+ const baseMessage = data?.responseMessage || data?.error?.message || data?.message || `HTTP ${response.status}`;
2738
+ const hint = snapErrorHint(baseMessage, data?.responseCode);
2739
+ const message = `${baseMessage}${data?.responseCode ? ` (${data.responseCode})` : ""}${hint ? ` \u2014 ${hint}` : ""}`;
2740
+ const err = new SnapApiError(message, {
2741
+ status: response.status,
2742
+ code: data?.responseCode,
2743
+ raw: data,
2744
+ endpoint,
2745
+ method
2746
+ });
2747
+ throw err;
2590
2748
  }
2591
2749
  return data;
2592
2750
  }
2593
2751
  };
2752
+ var SnapApiError = class extends Error {
2753
+ status;
2754
+ responseCode;
2755
+ raw;
2756
+ endpoint;
2757
+ method;
2758
+ constructor(message, opts) {
2759
+ super(message);
2760
+ this.name = "SnapApiError";
2761
+ this.status = opts.status;
2762
+ this.responseCode = opts.code;
2763
+ this.raw = opts.raw;
2764
+ this.endpoint = opts.endpoint;
2765
+ this.method = opts.method;
2766
+ }
2767
+ };
2594
2768
 
2595
2769
  // src/providers/doku/provider.ts
2596
2770
  var DokuProvider = class extends BasePaymentProvider {
@@ -2867,8 +3041,8 @@ var DokuProvider = class extends BasePaymentProvider {
2867
3041
  provider: "doku",
2868
3042
  orderId,
2869
3043
  amount: integerAmount,
2870
- rawResponse: null,
2871
- error: e.message || "Failed to make SNAP request to DOKU API"
3044
+ rawResponse: e?.raw ?? e?.rawResponse ?? null,
3045
+ error: e?.message || "Failed to make SNAP request to DOKU API"
2872
3046
  };
2873
3047
  }
2874
3048
  }
@@ -2909,6 +3083,7 @@ var DokuProvider = class extends BasePaymentProvider {
2909
3083
  return {
2910
3084
  success: true,
2911
3085
  provider: "doku",
3086
+ mode: "va",
2912
3087
  orderId: vaData.trxId || orderId,
2913
3088
  amount: Number(vaData.totalAmount?.value || amount) || Math.round(amount),
2914
3089
  reference: vaData.virtualAccountNo || orderId,
@@ -2944,6 +3119,7 @@ var DokuProvider = class extends BasePaymentProvider {
2944
3119
  return {
2945
3120
  success: true,
2946
3121
  provider: "doku",
3122
+ mode: "qris",
2947
3123
  orderId: data.partnerReferenceNo || orderId,
2948
3124
  amount: Number(data.amount?.value || amount) || Math.round(amount),
2949
3125
  reference: data.referenceNo || orderId,
@@ -2989,10 +3165,12 @@ var DokuProvider = class extends BasePaymentProvider {
2989
3165
  return {
2990
3166
  success: true,
2991
3167
  provider: "doku",
3168
+ mode: "ewallet",
2992
3169
  orderId: data.partnerReferenceNo || orderId,
2993
3170
  amount: Number(data.amount?.value || amount) || Math.round(amount),
2994
3171
  reference: data.partnerReferenceNo || orderId,
2995
3172
  paymentUrl: data.webRedirectUrl || data.paymentUrl,
3173
+ checkoutUrl: data.webRedirectUrl || data.paymentUrl,
2996
3174
  rawResponse: data
2997
3175
  };
2998
3176
  }
@@ -8033,6 +8211,62 @@ var IpaymuClient = class {
8033
8211
  async checkTransaction(transactionId) {
8034
8212
  return this.request("POST", "/transaction", { transactionId });
8035
8213
  }
8214
+ /**
8215
+ * Ambil daftar channel pembayaran aktif milik merchant
8216
+ */
8217
+ async getPaymentMethods() {
8218
+ return this.request("POST", "/payment-method-list", { account: this.va });
8219
+ }
8220
+ /**
8221
+ * Ambil riwayat transaksi merchant berpaginasi
8222
+ */
8223
+ async getHistory(params) {
8224
+ const payload = {
8225
+ account: this.va,
8226
+ page: params?.page || 1,
8227
+ limit: params?.limit || 10,
8228
+ ...params
8229
+ };
8230
+ return this.request("POST", "/history", payload);
8231
+ }
8232
+ /**
8233
+ * Ambil daftar seluruh bank di Indonesia
8234
+ */
8235
+ async getBankList() {
8236
+ return this.request("POST", "/banklist", { account: this.va });
8237
+ }
8238
+ /**
8239
+ * Ambil jangkauan area pengiriman COD
8240
+ */
8241
+ async getCodArea(postalCode) {
8242
+ const payload = { account: this.va };
8243
+ if (postalCode) payload.postalCode = postalCode;
8244
+ return this.request("POST", "/cod/getarea", payload);
8245
+ }
8246
+ /**
8247
+ * Hitung tarif ongkir pengiriman COD
8248
+ */
8249
+ async getCodRate(params) {
8250
+ return this.request("POST", "/cod/getrate", { account: this.va, ...params });
8251
+ }
8252
+ /**
8253
+ * Request pickup kurir COD
8254
+ */
8255
+ async getCodPickup(params) {
8256
+ return this.request("POST", "/cod/pickup", { account: this.va, ...params });
8257
+ }
8258
+ /**
8259
+ * Ambil nomor resi / AWB pengiriman COD
8260
+ */
8261
+ async getCodAwb(transactionId) {
8262
+ return this.request("POST", "/cod/getawb", { account: this.va, transactionId });
8263
+ }
8264
+ /**
8265
+ * Lacak status pengiriman kurir berdasarkan no resi / AWB
8266
+ */
8267
+ async getCodTracking(awb) {
8268
+ return this.request("POST", "/cod/tracking", { account: this.va, awb });
8269
+ }
8036
8270
  };
8037
8271
 
8038
8272
  // src/clients/xendit.ts
@@ -9417,170 +9651,316 @@ var PaymentManager = class {
9417
9651
  };
9418
9652
  var paymentManager = new PaymentManager();
9419
9653
 
9654
+ // src/core/providerRegistry.ts
9655
+ var ProviderRegistry = class {
9656
+ descriptors = /* @__PURE__ */ new Map();
9657
+ constructor(initial) {
9658
+ for (const d of initial || []) this.register(d);
9659
+ }
9660
+ register(desc) {
9661
+ this.descriptors.set(desc.name.toLowerCase().trim(), desc);
9662
+ }
9663
+ unregister(name) {
9664
+ return this.descriptors.delete(name.toLowerCase().trim());
9665
+ }
9666
+ has(name) {
9667
+ return this.descriptors.has(name.toLowerCase().trim());
9668
+ }
9669
+ get(name) {
9670
+ return this.descriptors.get(name.toLowerCase().trim());
9671
+ }
9672
+ names() {
9673
+ return [...this.descriptors.keys()];
9674
+ }
9675
+ /**
9676
+ * Autodetect provider aktif dari variabel lingkungan.
9677
+ * Mengembalikan nama provider yang kredensial .env-nya terisi penuh,
9678
+ * atau undefined jika tidak ada / ambigu.
9679
+ */
9680
+ detectFromEnv(env) {
9681
+ const present = [];
9682
+ for (const [name, desc] of this.descriptors) {
9683
+ const filled = desc.envKeys.filter((k) => {
9684
+ const v = env[k];
9685
+ return typeof v === "string" && v.trim().length > 0;
9686
+ });
9687
+ if (filled.length > 0) present.push({ name, count: filled.length });
9688
+ }
9689
+ if (present.length === 0) return void 0;
9690
+ present.sort((a, b) => b.count - a.count);
9691
+ const top = present[0];
9692
+ const ties = present.filter((p) => p.count === top.count);
9693
+ return ties.length === 1 ? top.name : void 0;
9694
+ }
9695
+ /**
9696
+ * Autodetect provider dari struktur payload webhook.
9697
+ * Mengembalikan nama provider jika dikenali, else undefined.
9698
+ */
9699
+ detectFromWebhook(payload) {
9700
+ if (!payload) return void 0;
9701
+ const p = payload;
9702
+ if (p.signature_key && p.transaction_status) return "midtrans";
9703
+ if (p.merchantCode && p.merchantOrderId && p.resultCode) return "duitku";
9704
+ if (p.trx_id && (p.sid || p.reference_id || p.via)) return "ipaymu";
9705
+ if (p.service?.id || p.order?.invoice_number && p.transaction?.status) return "doku";
9706
+ if (p.bill_no && (p.payment_status_code !== void 0 || p.payment_status_desc)) return "faspay";
9707
+ if (p.merchant_id && p.order_id && p.payment_status) return "finpay";
9708
+ if (p.tXid && p.merchantToken && (p.referenceNo || p.amt)) return "nicepay";
9709
+ if (p.partner_tx_id || p.partner_trx_id) return "oy";
9710
+ if (p.merchant_id && p.order_id && p.signature) return "prismalink";
9711
+ if (p.object === "event" || p.type && p.data?.object && p.api_version) return "stripe";
9712
+ if (p.event && p.payload?.payment?.entity) return "razorpay";
9713
+ if (p.external_id || p.event?.startsWith("payment.") || p.event?.startsWith("qr.") || p.data?.reference_id) return "xendit";
9714
+ if (p.event_type && p.resource && (p.event_type.startsWith("PAYMENT.") || p.event_type.startsWith("CHECKOUT.ORDER."))) return "paypal";
9715
+ if (p.notificationItems || p.merchantAccountCode && p.pspReference && p.eventCode) return "adyen";
9716
+ if (p.type && p.data?._links && (p.type.startsWith("payment_") || p.type.startsWith("refund_"))) return "checkoutcom";
9717
+ if (p.type && p.data?.object?.status && p.merchant_id) return "square";
9718
+ if (p.order && p.order?.status && p.order?.extOrderId) return "payu";
9719
+ if (p.kind && p.subject?.transaction) return "braintree";
9720
+ if (p.HASH && p.REFNOEXT && p.IPN_PID) return "twocheckout";
9721
+ return void 0;
9722
+ }
9723
+ };
9724
+ var ENV_KEYS = {
9725
+ midtrans: ["MIDTRANS_SERVER_KEY", "MIDTRANS_CLIENT_KEY"],
9726
+ duitku: ["DUITKU_API_KEY", "DUITKU_MERCHANT_CODE"],
9727
+ ipaymu: ["IPAYMU_API_KEY", "IPAYMU_VA"],
9728
+ xendit: ["XENDIT_SECRET_KEY", "XENDIT_WEBHOOK_TOKEN"],
9729
+ doku: ["DOKU_CLIENT_ID", "DOKU_SECRET_KEY"],
9730
+ prismalink: ["PRISMALINK_MERCHANT_ID", "PRISMALINK_SECRET_KEY"],
9731
+ faspay: ["FASPAY_MERCHANT_ID", "FASPAY_USER_ID", "FASPAY_PASSWORD"],
9732
+ finpay: ["FINPAY_MERCHANT_ID", "FINPAY_MERCHANT_KEY"],
9733
+ nicepay: ["NICEPAY_IMID", "NICEPAY_KEY"],
9734
+ oy: ["OY_USERNAME", "OY_API_KEY"],
9735
+ stripe: ["STRIPE_SECRET_KEY", "STRIPE_PUBLIC_KEY", "STRIPE_WEBHOOK_SECRET"],
9736
+ paypal: ["PAYPAL_CLIENT_ID", "PAYPAL_CLIENT_SECRET", "PAYPAL_WEBHOOK_ID"],
9737
+ adyen: ["ADYEN_API_KEY", "ADYEN_MERCHANT_ACCOUNT", "ADYEN_HMAC_KEY"],
9738
+ checkoutcom: ["CHECKOUTCOM_SECRET_KEY", "CHECKOUTCOM_PUBLIC_KEY", "CHECKOUTCOM_WEBHOOK_SECRET"],
9739
+ razorpay: ["RAZORPAY_KEY_ID", "RAZORPAY_KEY_SECRET", "RAZORPAY_WEBHOOK_SECRET"],
9740
+ square: ["SQUARE_ACCESS_TOKEN", "SQUARE_LOCATION_ID", "SQUARE_WEBHOOK_SIGNATURE_KEY"],
9741
+ payu: ["PAYU_POS_ID", "PAYU_MD5_KEY"],
9742
+ braintree: ["BRAINTREE_MERCHANT_ID", "BRAINTREE_PUBLIC_KEY", "BRAINTREE_PRIVATE_KEY"],
9743
+ twocheckout: ["TWOCHECKOUT_MERCHANT_CODE", "TWOCHECKOUT_SECRET_KEY", "TWOCHECKOUT_SECRET_WORD"]
9744
+ };
9745
+ var WORKING_METHODS = {
9746
+ midtrans: Object.keys(CANONICAL_TO_MIDTRANS),
9747
+ duitku: Object.keys(CANONICAL_TO_DUITKU),
9748
+ ipaymu: Object.keys(CANONICAL_TO_IPAYMU),
9749
+ xendit: Object.keys(CANONICAL_TO_XENDIT),
9750
+ doku: Object.keys(CANONICAL_TO_DOKU),
9751
+ prismalink: Object.keys(CANONICAL_TO_PRISMALINK),
9752
+ faspay: Object.keys(CANONICAL_TO_FASPAY),
9753
+ finpay: Object.keys(CANONICAL_TO_FINPAY),
9754
+ nicepay: Object.keys(CANONICAL_TO_NICEPAY),
9755
+ oy: Object.keys(CANONICAL_TO_OY),
9756
+ stripe: Object.keys(CANONICAL_TO_STRIPE),
9757
+ paypal: ["credit_card", "paylater", "paypal", "bank_transfer"],
9758
+ adyen: ["credit_card", "paypal", "qris", "apple_pay", "google_pay", "klarna", "sepa"],
9759
+ checkoutcom: ["credit_card", "paypal", "apple_pay", "google_pay", "klarna", "sofort", "bank_transfer"],
9760
+ razorpay: ["credit_card", "wallet", "upi", "netbanking", "emi", "bank_transfer"],
9761
+ square: ["credit_card", "apple_pay", "google_pay", "afterpay", "cash_app"],
9762
+ payu: ["credit_card", "bank_transfer", "apple_pay", "google_pay", "blik", "installment"],
9763
+ braintree: ["credit_card", "paypal", "apple_pay", "google_pay", "venmo"],
9764
+ twocheckout: ["credit_card", "paypal", "paylater", "wire_transfer"]
9765
+ };
9766
+ var OPERATIONS = {
9767
+ midtrans: { refund: true, checkBalance: true, disburse: false },
9768
+ duitku: { refund: false, checkBalance: true, disburse: true },
9769
+ ipaymu: { refund: false, checkBalance: true, disburse: false },
9770
+ xendit: { refund: false, checkBalance: true, disburse: true },
9771
+ doku: { refund: false, checkBalance: false, disburse: false },
9772
+ prismalink: { refund: false, checkBalance: false, disburse: false },
9773
+ faspay: { refund: false, checkBalance: false, disburse: false },
9774
+ finpay: { refund: false, checkBalance: false, disburse: false },
9775
+ nicepay: { refund: false, checkBalance: false, disburse: false },
9776
+ oy: { refund: false, checkBalance: true, disburse: true },
9777
+ stripe: { refund: true, checkBalance: true, disburse: false },
9778
+ paypal: { refund: true, checkBalance: true, disburse: false },
9779
+ adyen: { refund: true, checkBalance: false, disburse: false },
9780
+ checkoutcom: { refund: true, checkBalance: true, disburse: false },
9781
+ razorpay: { refund: true, checkBalance: true, disburse: false },
9782
+ square: { refund: true, checkBalance: true, disburse: false },
9783
+ payu: { refund: true, checkBalance: false, disburse: false },
9784
+ braintree: { refund: true, checkBalance: false, disburse: false },
9785
+ twocheckout: { refund: true, checkBalance: false, disburse: false }
9786
+ };
9787
+ function buildDefaultDescriptors() {
9788
+ return Object.keys(ENV_KEYS).map((name) => ({
9789
+ name,
9790
+ envKeys: ENV_KEYS[name],
9791
+ methods: WORKING_METHODS[name] || [],
9792
+ operations: OPERATIONS[name] || { refund: false, checkBalance: false, disburse: false }
9793
+ }));
9794
+ }
9795
+ var providerRegistry = new ProviderRegistry(buildDefaultDescriptors());
9796
+
9420
9797
  // src/core/config.ts
9798
+ var UNIVERSAL = {
9799
+ apiKey: ["BUAYAR_API_KEY", "BUAYAR_SERVER_KEY", "PG_API_KEY", "PAYMENT_API_KEY"],
9800
+ clientKey: ["BUAYAR_CLIENT_KEY", "PG_CLIENT_KEY"],
9801
+ merchantCode: ["BUAYAR_MERCHANT_CODE", "PG_MERCHANT_CODE", "PAYMENT_MERCHANT_CODE"],
9802
+ merchantId: ["BUAYAR_MERCHANT_ID", "PG_MERCHANT_ID"],
9803
+ secretKey: ["BUAYAR_SECRET_KEY", "PG_SECRET_KEY", "SECRET_KEY"],
9804
+ serverKey: ["BUAYAR_SERVER_KEY", "PG_SECRET_KEY"],
9805
+ projectId: ["BUAYAR_PROJECT_ID", "PG_PROJECT_ID", "PROJECT_ID"]
9806
+ };
9807
+ var SPECIFIC = {
9808
+ midtrans: {
9809
+ apiKey: ["MIDTRANS_SERVER_KEY"],
9810
+ clientKey: ["MIDTRANS_CLIENT_KEY"],
9811
+ merchantId: ["MIDTRANS_MERCHANT_ID"]
9812
+ },
9813
+ duitku: {
9814
+ apiKey: ["DUITKU_API_KEY"],
9815
+ merchantCode: ["DUITKU_MERCHANT_CODE"]
9816
+ },
9817
+ ipaymu: {
9818
+ apiKey: ["IPAYMU_API_KEY"],
9819
+ merchantCode: ["IPAYMU_VA", "IPAYMU_MERCHANT_CODE"]
9820
+ },
9821
+ xendit: {
9822
+ apiKey: ["XENDIT_SECRET_KEY", "XENDIT_API_KEY"]
9823
+ },
9824
+ doku: {
9825
+ apiKey: ["DOKU_SECRET_KEY", "DOKU_API_KEY"],
9826
+ clientKey: ["DOKU_CLIENT_ID"],
9827
+ merchantCode: ["DOKU_CLIENT_ID", "DOKU_MERCHANT_ID"],
9828
+ merchantId: ["DOKU_MERCHANT_ID"]
9829
+ },
9830
+ prismalink: {
9831
+ apiKey: ["PRISMALINK_SECRET_KEY", "PRISMALINK_API_KEY"],
9832
+ merchantCode: ["PRISMALINK_MERCHANT_ID"],
9833
+ merchantId: ["PRISMALINK_MERCHANT_ID"]
9834
+ },
9835
+ faspay: {
9836
+ apiKey: ["FASPAY_PASSWORD", "FASPAY_API_KEY"],
9837
+ clientKey: ["FASPAY_USER_ID"],
9838
+ merchantCode: ["FASPAY_MERCHANT_ID"],
9839
+ merchantId: ["FASPAY_MERCHANT_ID"]
9840
+ },
9841
+ finpay: {
9842
+ apiKey: ["FINPAY_MERCHANT_KEY", "FINPAY_SECRET_KEY", "FINPAY_API_KEY"],
9843
+ merchantCode: ["FINPAY_MERCHANT_ID"],
9844
+ merchantId: ["FINPAY_MERCHANT_ID"]
9845
+ },
9846
+ nicepay: {
9847
+ apiKey: ["NICEPAY_KEY", "NICEPAY_SECRET_KEY", "NICEPAY_API_KEY"],
9848
+ merchantCode: ["NICEPAY_IMID", "NICEPAY_MERCHANT_ID"],
9849
+ merchantId: ["NICEPAY_IMID"]
9850
+ },
9851
+ oy: {
9852
+ apiKey: ["OY_API_KEY"],
9853
+ clientKey: ["OY_USERNAME"],
9854
+ merchantCode: ["OY_USERNAME"]
9855
+ },
9856
+ stripe: {
9857
+ apiKey: ["STRIPE_SECRET_KEY", "STRIPE_KEY"],
9858
+ clientKey: ["STRIPE_PUBLIC_KEY", "STRIPE_PUBLISHABLE_KEY"]
9859
+ },
9860
+ paypal: {
9861
+ apiKey: ["PAYPAL_CLIENT_SECRET"],
9862
+ clientKey: ["PAYPAL_CLIENT_ID"],
9863
+ merchantCode: ["PAYPAL_CLIENT_ID"]
9864
+ },
9865
+ adyen: {
9866
+ apiKey: ["ADYEN_API_KEY"],
9867
+ clientKey: ["ADYEN_CLIENT_KEY"],
9868
+ merchantCode: ["ADYEN_MERCHANT_ACCOUNT"],
9869
+ merchantId: ["ADYEN_MERCHANT_ACCOUNT"]
9870
+ },
9871
+ checkoutcom: {
9872
+ apiKey: ["CHECKOUTCOM_SECRET_KEY"],
9873
+ clientKey: ["CHECKOUTCOM_PUBLIC_KEY"]
9874
+ },
9875
+ razorpay: {
9876
+ apiKey: ["RAZORPAY_KEY_SECRET"],
9877
+ clientKey: ["RAZORPAY_KEY_ID"],
9878
+ merchantCode: ["RAZORPAY_KEY_ID"]
9879
+ },
9880
+ square: {
9881
+ apiKey: ["SQUARE_ACCESS_TOKEN"],
9882
+ clientKey: ["SQUARE_APPLICATION_ID"],
9883
+ merchantCode: ["SQUARE_APPLICATION_ID"],
9884
+ projectId: ["SQUARE_LOCATION_ID"]
9885
+ },
9886
+ payu: {
9887
+ apiKey: ["PAYU_MD5_KEY"],
9888
+ clientKey: ["PAYU_POS_ID"],
9889
+ merchantCode: ["PAYU_POS_ID"],
9890
+ merchantId: ["PAYU_POS_ID"]
9891
+ },
9892
+ braintree: {
9893
+ apiKey: ["BRAINTREE_PRIVATE_KEY"],
9894
+ clientKey: ["BRAINTREE_PUBLIC_KEY"],
9895
+ merchantCode: ["BRAINTREE_MERCHANT_ID"],
9896
+ merchantId: ["BRAINTREE_MERCHANT_ID"]
9897
+ },
9898
+ twocheckout: {
9899
+ apiKey: ["TWOCHECKOUT_SECRET_KEY"],
9900
+ merchantCode: ["TWOCHECKOUT_MERCHANT_CODE"],
9901
+ merchantId: ["TWOCHECKOUT_MERCHANT_CODE"]
9902
+ }
9903
+ };
9904
+ function firstDefined(env, keys) {
9905
+ for (const k of keys) {
9906
+ const v = env[k];
9907
+ if (typeof v === "string" && v.trim().length > 0) return v.trim();
9908
+ }
9909
+ return void 0;
9910
+ }
9911
+ function resolveSandbox(env, provider) {
9912
+ const universal = firstDefined(env, ["BUAYAR_SANDBOX", "PG_SANDBOX", "PAYMENT_SANDBOX"]);
9913
+ if (universal !== void 0) return universal === "true" || universal === "1";
9914
+ const specificMap = {
9915
+ midtrans: ["MIDTRANS_IS_PRODUCTION"],
9916
+ duitku: ["DUITKU_SANDBOX"],
9917
+ ipaymu: ["IPAYMU_SANDBOX"],
9918
+ doku: ["DOKU_SANDBOX"],
9919
+ prismalink: ["PRISMALINK_SANDBOX"],
9920
+ faspay: ["FASPAY_SANDBOX"],
9921
+ finpay: ["FINPAY_SANDBOX"],
9922
+ nicepay: ["NICEPAY_SANDBOX"],
9923
+ oy: ["OY_SANDBOX"],
9924
+ stripe: ["STRIPE_SANDBOX"],
9925
+ paypal: ["PAYPAL_SANDBOX"],
9926
+ adyen: ["ADYEN_SANDBOX"],
9927
+ checkoutcom: ["CHECKOUTCOM_SANDBOX"],
9928
+ razorpay: ["RAZORPAY_SANDBOX"],
9929
+ square: ["SQUARE_SANDBOX"],
9930
+ payu: ["PAYU_SANDBOX"],
9931
+ braintree: ["BRAINTREE_SANDBOX"],
9932
+ twocheckout: ["TWOCHECKOUT_SANDBOX"],
9933
+ xendit: ["XENDIT_SANDBOX"]
9934
+ };
9935
+ const specific = firstDefined(env, specificMap[provider]);
9936
+ if (specific !== void 0) {
9937
+ if (provider === "midtrans") return specific !== "true" && specific !== "1";
9938
+ return specific === "true" || specific === "1";
9939
+ }
9940
+ return env.NODE_ENV !== "production";
9941
+ }
9421
9942
  function resolveConfigFromEnv(customConfig) {
9422
9943
  const env = typeof process !== "undefined" && process?.env ? process.env : {};
9423
- const provider = (customConfig?.provider || env.PROVIDER_PG || env.PG_PROVIDER || env.BUAYAR_PROVIDER || env.PAYMENT_PROVIDER || "midtrans").toLowerCase().trim();
9424
- let sandbox;
9425
- if (customConfig?.sandbox !== void 0) {
9426
- sandbox = customConfig.sandbox;
9427
- } else if (env.BUAYAR_SANDBOX !== void 0) {
9428
- sandbox = env.BUAYAR_SANDBOX === "true" || env.BUAYAR_SANDBOX === "1";
9429
- } else if (env.PG_SANDBOX !== void 0) {
9430
- sandbox = env.PG_SANDBOX === "true" || env.PG_SANDBOX === "1";
9431
- } else if (env.PAYMENT_SANDBOX !== void 0) {
9432
- sandbox = env.PAYMENT_SANDBOX === "true" || env.PAYMENT_SANDBOX === "1";
9433
- } else if (env.MIDTRANS_IS_PRODUCTION !== void 0) {
9434
- sandbox = env.MIDTRANS_IS_PRODUCTION !== "true" && env.MIDTRANS_IS_PRODUCTION !== "1";
9435
- } else if (env.DUITKU_SANDBOX !== void 0) {
9436
- sandbox = env.DUITKU_SANDBOX === "true" || env.DUITKU_SANDBOX === "1";
9437
- } else if (env.IPAYMU_SANDBOX !== void 0) {
9438
- sandbox = env.IPAYMU_SANDBOX === "true" || env.IPAYMU_SANDBOX === "1";
9439
- } else if (env.DOKU_SANDBOX !== void 0) {
9440
- sandbox = env.DOKU_SANDBOX === "true" || env.DOKU_SANDBOX === "1";
9441
- } else if (env.PRISMALINK_SANDBOX !== void 0) {
9442
- sandbox = env.PRISMALINK_SANDBOX === "true" || env.PRISMALINK_SANDBOX === "1";
9443
- } else if (env.FASPAY_SANDBOX !== void 0) {
9444
- sandbox = env.FASPAY_SANDBOX === "true" || env.FASPAY_SANDBOX === "1";
9445
- } else if (env.FINPAY_SANDBOX !== void 0) {
9446
- sandbox = env.FINPAY_SANDBOX === "true" || env.FINPAY_SANDBOX === "1";
9447
- } else if (env.NICEPAY_SANDBOX !== void 0) {
9448
- sandbox = env.NICEPAY_SANDBOX === "true" || env.NICEPAY_SANDBOX === "1";
9449
- } else if (env.OY_SANDBOX !== void 0) {
9450
- sandbox = env.OY_SANDBOX === "true" || env.OY_SANDBOX === "1";
9451
- } else if (env.STRIPE_SANDBOX !== void 0) {
9452
- sandbox = env.STRIPE_SANDBOX === "true" || env.STRIPE_SANDBOX === "1";
9453
- } else if (env.PAYPAL_SANDBOX !== void 0) {
9454
- sandbox = env.PAYPAL_SANDBOX === "true" || env.PAYPAL_SANDBOX === "1";
9455
- } else if (env.ADYEN_SANDBOX !== void 0) {
9456
- sandbox = env.ADYEN_SANDBOX === "true" || env.ADYEN_SANDBOX === "1";
9457
- } else if (env.CHECKOUTCOM_SANDBOX !== void 0) {
9458
- sandbox = env.CHECKOUTCOM_SANDBOX === "true" || env.CHECKOUTCOM_SANDBOX === "1";
9459
- } else if (env.RAZORPAY_SANDBOX !== void 0) {
9460
- sandbox = env.RAZORPAY_SANDBOX === "true" || env.RAZORPAY_SANDBOX === "1";
9461
- } else if (env.SQUARE_SANDBOX !== void 0) {
9462
- sandbox = env.SQUARE_SANDBOX === "true" || env.SQUARE_SANDBOX === "1";
9463
- } else if (env.PAYU_SANDBOX !== void 0) {
9464
- sandbox = env.PAYU_SANDBOX === "true" || env.PAYU_SANDBOX === "1";
9465
- } else if (env.BRAINTREE_SANDBOX !== void 0) {
9466
- sandbox = env.BRAINTREE_SANDBOX === "true" || env.BRAINTREE_SANDBOX === "1";
9467
- } else if (env.TWOCHECKOUT_SANDBOX !== void 0) {
9468
- sandbox = env.TWOCHECKOUT_SANDBOX === "true" || env.TWOCHECKOUT_SANDBOX === "1";
9469
- } else {
9470
- sandbox = env.NODE_ENV !== "production";
9471
- }
9472
- let apiKey = customConfig?.apiKey || customConfig?.serverKey || customConfig?.secretKey;
9473
- if (!apiKey) {
9474
- if (provider === "midtrans") {
9475
- apiKey = env.MIDTRANS_SERVER_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.BUAYAR_SERVER_KEY;
9476
- } else if (provider === "duitku") {
9477
- apiKey = env.DUITKU_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9478
- } else if (provider === "ipaymu") {
9479
- apiKey = env.IPAYMU_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9480
- } else if (provider === "xendit") {
9481
- apiKey = env.XENDIT_SECRET_KEY || env.XENDIT_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9482
- } else if (provider === "doku") {
9483
- apiKey = env.DOKU_SECRET_KEY || env.DOKU_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9484
- } else if (provider === "prismalink") {
9485
- apiKey = env.PRISMALINK_SECRET_KEY || env.PRISMALINK_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9486
- } else if (provider === "faspay") {
9487
- apiKey = env.FASPAY_PASSWORD || env.FASPAY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9488
- } else if (provider === "finpay") {
9489
- apiKey = env.FINPAY_MERCHANT_KEY || env.FINPAY_SECRET_KEY || env.FINPAY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9490
- } else if (provider === "nicepay") {
9491
- apiKey = env.NICEPAY_KEY || env.NICEPAY_MERCHANT_KEY || env.NICEPAY_SECRET_KEY || env.NICEPAY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9492
- } else if (provider === "oy" || provider === "oyindonesia") {
9493
- apiKey = env.OY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9494
- } else if (provider === "stripe") {
9495
- apiKey = env.STRIPE_SECRET_KEY || env.STRIPE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9496
- } else if (provider === "paypal") {
9497
- apiKey = env.PAYPAL_CLIENT_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9498
- } else if (provider === "adyen") {
9499
- apiKey = env.ADYEN_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9500
- } else if (provider === "checkoutcom") {
9501
- apiKey = env.CHECKOUTCOM_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9502
- } else if (provider === "razorpay") {
9503
- apiKey = env.RAZORPAY_KEY_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9504
- } else if (provider === "square") {
9505
- apiKey = env.SQUARE_ACCESS_TOKEN || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9506
- } else if (provider === "payu") {
9507
- apiKey = env.PAYU_MD5_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9508
- } else if (provider === "braintree") {
9509
- apiKey = env.BRAINTREE_PRIVATE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9510
- } else if (provider === "twocheckout" || provider === "2checkout") {
9511
- apiKey = env.TWOCHECKOUT_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9512
- } else {
9513
- apiKey = env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.PG_SECRET_KEY || env.BUAYAR_SECRET_KEY;
9514
- }
9515
- }
9516
- let merchantCode = customConfig?.merchantCode;
9517
- let clientKey = customConfig?.clientKey;
9518
- let merchantId = customConfig?.merchantId;
9519
- if (provider === "midtrans") {
9520
- clientKey = clientKey || env.MIDTRANS_CLIENT_KEY || env.BUAYAR_CLIENT_KEY || env.PG_CLIENT_KEY;
9521
- merchantId = merchantId || env.MIDTRANS_MERCHANT_ID || env.BUAYAR_MERCHANT_ID || env.PG_MERCHANT_ID;
9522
- merchantCode = merchantCode || clientKey || merchantId || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE;
9523
- } else if (provider === "duitku") {
9524
- merchantCode = merchantCode || env.DUITKU_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9525
- } else if (provider === "ipaymu") {
9526
- merchantCode = merchantCode || env.IPAYMU_VA || env.IPAYMU_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9527
- } else if (provider === "doku") {
9528
- merchantCode = merchantCode || env.DOKU_CLIENT_ID || env.DOKU_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9529
- clientKey = clientKey || customConfig?.merchantCode || env.DOKU_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9530
- } else if (provider === "prismalink") {
9531
- merchantCode = merchantCode || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9532
- merchantId = merchantId || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
9533
- } else if (provider === "faspay") {
9534
- merchantCode = merchantCode || env.FASPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9535
- merchantId = merchantId || env.FASPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
9536
- clientKey = clientKey || env.FASPAY_USER_ID || env.BUAYAR_CLIENT_KEY;
9537
- } else if (provider === "finpay") {
9538
- merchantCode = merchantCode || env.FINPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9539
- merchantId = merchantId || env.FINPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
9540
- } else if (provider === "nicepay") {
9541
- merchantCode = merchantCode || env.NICEPAY_IMID || env.NICEPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9542
- merchantId = merchantId || env.NICEPAY_IMID || env.BUAYAR_MERCHANT_ID;
9543
- } else if (provider === "oy" || provider === "oyindonesia") {
9544
- merchantCode = merchantCode || env.OY_USERNAME || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9545
- clientKey = clientKey || customConfig?.merchantCode || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
9546
- } else if (provider === "stripe") {
9547
- clientKey = clientKey || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.BUAYAR_CLIENT_KEY || env.BUAYAR_PUBLIC_KEY;
9548
- merchantCode = merchantCode || clientKey || "stripe";
9549
- } else if (provider === "paypal") {
9550
- clientKey = clientKey || env.PAYPAL_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9551
- merchantCode = merchantCode || env.PAYPAL_CLIENT_ID || env.BUAYAR_MERCHANT_CODE;
9552
- } else if (provider === "adyen") {
9553
- clientKey = clientKey || env.ADYEN_CLIENT_KEY || env.BUAYAR_CLIENT_KEY;
9554
- merchantCode = merchantCode || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_CODE;
9555
- merchantId = merchantId || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_ID;
9556
- } else if (provider === "checkoutcom") {
9557
- clientKey = clientKey || env.CHECKOUTCOM_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9558
- merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE;
9559
- } else if (provider === "razorpay") {
9560
- clientKey = clientKey || env.RAZORPAY_KEY_ID || env.BUAYAR_CLIENT_KEY;
9561
- merchantCode = merchantCode || env.RAZORPAY_KEY_ID || env.BUAYAR_MERCHANT_CODE;
9562
- } else if (provider === "square") {
9563
- clientKey = clientKey || env.SQUARE_APPLICATION_ID || env.BUAYAR_CLIENT_KEY;
9564
- merchantCode = merchantCode || env.SQUARE_APPLICATION_ID || env.BUAYAR_MERCHANT_CODE;
9565
- } else if (provider === "payu") {
9566
- merchantCode = merchantCode || env.PAYU_POS_ID || env.BUAYAR_MERCHANT_CODE;
9567
- merchantId = merchantId || env.PAYU_POS_ID;
9568
- } else if (provider === "braintree") {
9569
- clientKey = clientKey || env.BRAINTREE_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9570
- merchantCode = merchantCode || env.BRAINTREE_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE;
9571
- merchantId = merchantId || env.BRAINTREE_MERCHANT_ID;
9572
- } else if (provider === "twocheckout" || provider === "2checkout") {
9573
- merchantCode = merchantCode || env.TWOCHECKOUT_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE;
9574
- merchantId = merchantId || env.TWOCHECKOUT_MERCHANT_CODE;
9575
- } else {
9576
- merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9577
- }
9578
- const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID || env.SQUARE_LOCATION_ID;
9579
- const publicKey = customConfig?.publicKey || env.BUAYAR_PUBLIC_KEY || env.PG_PUBLIC_KEY || env.PUBLIC_KEY || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.CHECKOUTCOM_PUBLIC_KEY;
9580
- const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY || env.BRAINTREE_PRIVATE_KEY;
9581
- const secretKey = customConfig?.secretKey || customConfig?.apiKey || customConfig?.serverKey || env.BUAYAR_SECRET_KEY || env.PG_SECRET_KEY || env.SECRET_KEY || env.XENDIT_SECRET_KEY || env.DOKU_SECRET_KEY || env.PRISMALINK_SECRET_KEY || env.FASPAY_PASSWORD || env.FINPAY_MERCHANT_KEY || env.NICEPAY_KEY || env.OY_API_KEY || env.STRIPE_SECRET_KEY || env.PAYPAL_CLIENT_SECRET || env.CHECKOUTCOM_SECRET_KEY || env.RAZORPAY_KEY_SECRET || env.SQUARE_ACCESS_TOKEN || env.BRAINTREE_PRIVATE_KEY || env.TWOCHECKOUT_SECRET_KEY;
9944
+ const explicit = (customConfig?.provider || env.PROVIDER_PG || env.PG_PROVIDER || env.BUAYAR_PROVIDER || env.PAYMENT_PROVIDER || "").toLowerCase().trim();
9945
+ let provider = explicit || providerRegistry.detectFromEnv(env) || "midtrans";
9946
+ provider = provider.replace("oyindonesia", "oy").replace("2checkout", "twocheckout");
9947
+ const sandbox = customConfig?.sandbox ?? resolveSandbox(env, provider);
9948
+ const spec = SPECIFIC[provider] || {};
9949
+ const cfg = {};
9950
+ const fields = ["apiKey", "clientKey", "merchantCode", "merchantId", "secretKey", "serverKey", "projectId"];
9951
+ for (const f of fields) {
9952
+ const universalKeys = UNIVERSAL[f] || [];
9953
+ const specificKeys = spec[f] || [];
9954
+ const universal = firstDefined(env, universalKeys);
9955
+ const specific = firstDefined(env, specificKeys);
9956
+ const value = universal || specific;
9957
+ const explicitValue = customConfig?.[f] || customConfig && (f === "apiKey" ? customConfig.secretKey || customConfig.serverKey : void 0);
9958
+ cfg[f] = explicitValue || value || "";
9959
+ }
9582
9960
  const callbackUrl = customConfig?.callbackUrl || env.BUAYAR_CALLBACK_URL || env.PG_CALLBACK_URL || env.PAYMENT_CALLBACK_URL;
9583
9961
  const returnUrl = customConfig?.returnUrl || env.BUAYAR_RETURN_URL || env.PG_RETURN_URL || env.PAYMENT_RETURN_URL;
9962
+ const publicKey = customConfig?.publicKey || firstDefined(env, ["BUAYAR_PUBLIC_KEY", "PG_PUBLIC_KEY", "PUBLIC_KEY"]) || cfg.clientKey;
9963
+ const privateKey = customConfig?.privateKey || firstDefined(env, ["BUAYAR_PRIVATE_KEY", "PG_PRIVATE_KEY", "PRIVATE_KEY"]) || (provider === "braintree" ? cfg.apiKey : void 0);
9584
9964
  const extra = {
9585
9965
  webhookToken: env.XENDIT_WEBHOOK_TOKEN || env.BUAYAR_WEBHOOK_TOKEN,
9586
9966
  webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.CHECKOUTCOM_WEBHOOK_SECRET || env.RAZORPAY_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
@@ -9601,15 +9981,16 @@ function resolveConfigFromEnv(customConfig) {
9601
9981
  secretWord: env.TWOCHECKOUT_SECRET_WORD,
9602
9982
  ...customConfig?.extra
9603
9983
  };
9984
+ const apiKey = cfg.apiKey || cfg.secretKey || cfg.serverKey;
9604
9985
  return {
9605
- provider: provider === "oyindonesia" ? "oy" : provider === "2checkout" ? "twocheckout" : provider,
9606
- apiKey: apiKey || "",
9986
+ provider,
9987
+ apiKey,
9607
9988
  serverKey: apiKey || "",
9608
- secretKey: secretKey || apiKey || "",
9609
- merchantCode: merchantCode || "",
9610
- clientKey: clientKey || "",
9611
- merchantId: merchantId || "",
9612
- projectId,
9989
+ secretKey: apiKey || "",
9990
+ merchantCode: cfg.merchantCode || "",
9991
+ clientKey: cfg.clientKey || "",
9992
+ merchantId: cfg.merchantId || "",
9993
+ projectId: cfg.projectId || "",
9613
9994
  publicKey,
9614
9995
  privateKey,
9615
9996
  sandbox,
@@ -9623,8 +10004,10 @@ function resolveConfigFromEnv(customConfig) {
9623
10004
  var Buayar = class {
9624
10005
  manager;
9625
10006
  config;
9626
- constructor(config, manager) {
10007
+ registry;
10008
+ constructor(config, manager, registry) {
9627
10009
  this.manager = manager || paymentManager;
10010
+ this.registry = registry || providerRegistry;
9628
10011
  this.config = resolveConfigFromEnv(config);
9629
10012
  }
9630
10013
  /**
@@ -9657,6 +10040,62 @@ var Buayar = class {
9657
10040
  getProvider(name) {
9658
10041
  return this.manager.getProvider(name || this.provider);
9659
10042
  }
10043
+ /**
10044
+ * Daftar nama provider yang terdaftar (bawaan + kustom).
10045
+ */
10046
+ listProviders() {
10047
+ return this.registry.names();
10048
+ }
10049
+ /**
10050
+ * Registrasi metadata provider kustom untuk deteksi & capability.
10051
+ * Contoh: buayar.registerProviderDescriptor({ name, envKeys, methods, operations })
10052
+ */
10053
+ registerProviderDescriptor(desc) {
10054
+ this.registry.register(desc);
10055
+ }
10056
+ /**
10057
+ * Cek capability (metode + operasi) provider tertentu — atau provider aktif bila kosong.
10058
+ * Jawab pertanyaan "provider ini dukung apa?" secara runtime, tanpa bongkar dokumen.
10059
+ */
10060
+ getCapabilities(name) {
10061
+ const n = name || this.provider;
10062
+ const desc = this.registry.get(n);
10063
+ if (!desc) return void 0;
10064
+ return { methods: desc.methods, operations: desc.operations };
10065
+ }
10066
+ /**
10067
+ * Deteksi nama provider dari struktur payload webhook.
10068
+ */
10069
+ detectProviderFromPayload(payload) {
10070
+ return this.registry.detectFromWebhook(payload);
10071
+ }
10072
+ /**
10073
+ * Deteksi nama provider aktif dari variabel lingkungan (kredensial yang terisi).
10074
+ */
10075
+ detectProviderFromEnv(env) {
10076
+ return this.registry.detectFromEnv(env || process.env);
10077
+ }
10078
+ /**
10079
+ * Logika "bisa pakai X dengan provider Y?" — helper untuk portabilitas.
10080
+ */
10081
+ supports(name, operation) {
10082
+ const desc = this.registry.get(name);
10083
+ return desc ? desc.operations[operation] : false;
10084
+ }
10085
+ /**
10086
+ * Daftar metode pembayaran yang benar2 tersedia untuk provider aktif.
10087
+ */
10088
+ getSupportedMethods(name) {
10089
+ const n = name || this.provider;
10090
+ return this.registry.get(n)?.methods || [];
10091
+ }
10092
+ /**
10093
+ * Iterasi CEPAT: apakah provider aktif mendukung method kanonik tertentu?
10094
+ */
10095
+ supportsMethod(method, name) {
10096
+ const n = name || this.provider;
10097
+ return this.registry.get(n)?.methods.includes(method) ?? false;
10098
+ }
9660
10099
  /**
9661
10100
  * Buat transaksi pembayaran baru (Mendukung Semi dan Full Integrasi)
9662
10101
  */
@@ -9731,47 +10170,8 @@ var Buayar = class {
9731
10170
  }
9732
10171
  }
9733
10172
  let providerName = configOverride?.provider || this.provider;
9734
- if (payload) {
9735
- if (payload.signature_key && payload.transaction_status) {
9736
- providerName = "midtrans";
9737
- } else if (payload.merchantCode && payload.merchantOrderId && payload.resultCode) {
9738
- providerName = "duitku";
9739
- } else if (payload.trx_id && (payload.sid || payload.reference_id || payload.via)) {
9740
- providerName = "ipaymu";
9741
- } else if (payload.service?.id || payload.order?.invoice_number && payload.transaction?.status) {
9742
- providerName = "doku";
9743
- } else if (payload.bill_no && (payload.payment_status_code !== void 0 || payload.payment_status_desc)) {
9744
- providerName = "faspay";
9745
- } else if (payload.merchant_id && payload.order_id && payload.payment_status) {
9746
- providerName = "finpay";
9747
- } else if (payload.tXid && payload.merchantToken && (payload.referenceNo || payload.amt)) {
9748
- providerName = "nicepay";
9749
- } else if (payload.partner_tx_id || payload.partner_trx_id) {
9750
- providerName = "oy";
9751
- } else if (payload.merchant_id && payload.order_id && payload.signature) {
9752
- providerName = "prismalink";
9753
- } else if (payload.object === "event" || payload.type && payload.data?.object && payload.api_version) {
9754
- providerName = "stripe";
9755
- } else if (payload.event && payload.payload?.payment?.entity) {
9756
- providerName = "razorpay";
9757
- } else if (payload.external_id || payload.event?.startsWith("payment.") || payload.event?.startsWith("qr.") || payload.data?.reference_id) {
9758
- providerName = "xendit";
9759
- } else if (payload.event_type && payload.resource && (payload.event_type.startsWith("PAYMENT.") || payload.event_type.startsWith("CHECKOUT.ORDER."))) {
9760
- providerName = "paypal";
9761
- } else if (payload.notificationItems || payload.merchantAccountCode && payload.pspReference && payload.eventCode) {
9762
- providerName = "adyen";
9763
- } else if (payload.type && payload.data?._links && (payload.type.startsWith("payment_") || payload.type.startsWith("refund_"))) {
9764
- providerName = "checkoutcom";
9765
- } else if (payload.type && payload.data?.object?.status && payload.merchant_id) {
9766
- providerName = "square";
9767
- } else if (payload.order && payload.order?.status && payload.order?.extOrderId) {
9768
- providerName = "payu";
9769
- } else if (payload.kind && payload.subject?.transaction) {
9770
- providerName = "braintree";
9771
- } else if (payload.HASH && payload.REFNOEXT && payload.IPN_PID) {
9772
- providerName = "twocheckout";
9773
- }
9774
- }
10173
+ const detected = this.registry.detectFromWebhook(payload);
10174
+ if (detected) providerName = detected;
9775
10175
  return this.manager.verifyCallback(providerName, payload, mergedConfig);
9776
10176
  }
9777
10177
  async handleWebhook(payload, headers, configOverride) {
@@ -9912,8 +10312,10 @@ export {
9912
10312
  PayuProvider,
9913
10313
  PrismalinkClient,
9914
10314
  PrismalinkProvider,
10315
+ ProviderRegistry,
9915
10316
  RazorpayClient,
9916
10317
  RazorpayProvider,
10318
+ SnapApiError,
9917
10319
  SnapClient,
9918
10320
  SquareClient,
9919
10321
  SquareProvider,
@@ -9926,6 +10328,7 @@ export {
9926
10328
  buayar,
9927
10329
  buildBraintreeBasicAuth,
9928
10330
  buildCoreChargePayload,
10331
+ buildDefaultDescriptors,
9929
10332
  buildPaypalBasicAuth,
9930
10333
  buildPayuBasicAuth,
9931
10334
  buildRazorpayBasicAuth,
@@ -9950,6 +10353,7 @@ export {
9950
10353
  minifyJson,
9951
10354
  parseCoreChargeResponse,
9952
10355
  paymentManager,
10356
+ providerRegistry,
9953
10357
  resolveConfigFromEnv,
9954
10358
  safeCompare,
9955
10359
  serializePaypalParams,
@@ -9957,6 +10361,7 @@ export {
9957
10361
  sha256,
9958
10362
  sha256Hex,
9959
10363
  sha512,
10364
+ snapErrorHint,
9960
10365
  snapExternalId,
9961
10366
  snapTimestamp,
9962
10367
  snapUtcTimestamp,