@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.js CHANGED
@@ -76,8 +76,10 @@ __export(index_exports, {
76
76
  PayuProvider: () => PayuProvider,
77
77
  PrismalinkClient: () => PrismalinkClient,
78
78
  PrismalinkProvider: () => PrismalinkProvider,
79
+ ProviderRegistry: () => ProviderRegistry,
79
80
  RazorpayClient: () => RazorpayClient,
80
81
  RazorpayProvider: () => RazorpayProvider,
82
+ SnapApiError: () => SnapApiError,
81
83
  SnapClient: () => SnapClient,
82
84
  SquareClient: () => SquareClient,
83
85
  SquareProvider: () => SquareProvider,
@@ -90,6 +92,7 @@ __export(index_exports, {
90
92
  buayar: () => buayar,
91
93
  buildBraintreeBasicAuth: () => buildBraintreeBasicAuth,
92
94
  buildCoreChargePayload: () => buildCoreChargePayload,
95
+ buildDefaultDescriptors: () => buildDefaultDescriptors,
93
96
  buildPaypalBasicAuth: () => buildPaypalBasicAuth,
94
97
  buildPayuBasicAuth: () => buildPayuBasicAuth,
95
98
  buildRazorpayBasicAuth: () => buildRazorpayBasicAuth,
@@ -114,6 +117,7 @@ __export(index_exports, {
114
117
  minifyJson: () => minifyJson,
115
118
  parseCoreChargeResponse: () => parseCoreChargeResponse,
116
119
  paymentManager: () => paymentManager,
120
+ providerRegistry: () => providerRegistry,
117
121
  resolveConfigFromEnv: () => resolveConfigFromEnv,
118
122
  safeCompare: () => safeCompare,
119
123
  serializePaypalParams: () => serializePaypalParams,
@@ -121,6 +125,7 @@ __export(index_exports, {
121
125
  sha256: () => sha256,
122
126
  sha256Hex: () => sha256Hex,
123
127
  sha512: () => sha512,
128
+ snapErrorHint: () => snapErrorHint,
124
129
  snapExternalId: () => snapExternalId,
125
130
  snapTimestamp: () => snapTimestamp,
126
131
  snapUtcTimestamp: () => snapUtcTimestamp,
@@ -282,6 +287,9 @@ var CANONICAL_TO_IPAYMU = {
282
287
  permata_va: { paymentMethod: "va", paymentChannel: "permata" },
283
288
  danamon_va: { paymentMethod: "va", paymentChannel: "danamon" },
284
289
  bsi_va: { paymentMethod: "va", paymentChannel: "bsi" },
290
+ bag_va: { paymentMethod: "va", paymentChannel: "bag" },
291
+ muamalat_va: { paymentMethod: "va", paymentChannel: "bmi" },
292
+ bmi_va: { paymentMethod: "va", paymentChannel: "bmi" },
285
293
  qris: { paymentMethod: "qris", paymentChannel: "mpm" },
286
294
  gopay_qris: { paymentMethod: "qris", paymentChannel: "mpm" },
287
295
  shopeepay_qris: { paymentMethod: "qris", paymentChannel: "mpm" },
@@ -1739,35 +1747,48 @@ var IpaymuProvider = class extends BasePaymentProvider {
1739
1747
  const baseUrl = this.getBaseUrl(sandbox);
1740
1748
  const endpoint = isDirect ? "/payment/direct" : "/payment";
1741
1749
  const url = `${baseUrl}${endpoint}`;
1750
+ const notifyUrl = callbackUrl || config.callbackUrl || "https://localhost/callback";
1751
+ const redirectUrl = returnUrl || config.returnUrl || "https://localhost/return";
1752
+ const feeDirection = params.feeDirection || params.extra?.feeDirection || config.extra?.feeDirection;
1753
+ const escrow = params.escrow !== void 0 ? params.escrow : params.extra?.escrow !== void 0 ? params.extra?.escrow : config.extra?.escrow;
1742
1754
  let payload;
1743
1755
  if (isDirect) {
1744
1756
  payload = {
1745
1757
  name: customer.name,
1746
1758
  email: customer.email,
1747
- phone: customer.phone || "",
1759
+ phone: customer.phone || "081234567890",
1748
1760
  amount: integerAmount,
1749
- notifyUrl: callbackUrl || config.callbackUrl || "",
1761
+ notifyUrl,
1750
1762
  expired: 24,
1751
1763
  expiredType: "hours",
1752
1764
  comments: productDetails,
1753
1765
  referenceId: orderId,
1754
1766
  paymentMethod: ipaymuMethod.paymentMethod,
1755
1767
  ...ipaymuMethod.paymentChannel ? { paymentChannel: ipaymuMethod.paymentChannel } : {},
1768
+ ...feeDirection ? { feeDirection } : {},
1769
+ ...escrow !== void 0 ? { escrow } : {},
1756
1770
  ...params.providerParams
1757
1771
  };
1758
1772
  } else {
1773
+ const hasItems = params.items && params.items.length > 0;
1774
+ const product = hasItems ? params.items.map((i) => i.name) : [productDetails.length > 50 ? productDetails.substring(0, 47) + "..." : productDetails];
1775
+ const qty = hasItems ? params.items.map((i) => i.quantity) : [1];
1776
+ const price = hasItems ? params.items.map((i) => Math.round(i.price)) : [integerAmount];
1777
+ const description = hasItems ? params.items.map((i) => i.description || i.name) : [productDetails];
1759
1778
  payload = {
1760
- product: [productDetails.length > 50 ? productDetails.substring(0, 47) + "..." : productDetails],
1761
- qty: [1],
1762
- price: [integerAmount],
1763
- description: [productDetails],
1764
- returnUrl: returnUrl || config.returnUrl || "",
1765
- notifyUrl: callbackUrl || config.callbackUrl || "",
1766
- cancelUrl: returnUrl || config.returnUrl || "",
1779
+ product,
1780
+ qty,
1781
+ price,
1782
+ description,
1783
+ returnUrl: redirectUrl,
1784
+ notifyUrl,
1785
+ cancelUrl: redirectUrl,
1767
1786
  referenceId: orderId,
1768
1787
  buyerName: customer.name,
1769
1788
  buyerEmail: customer.email,
1770
- buyerPhone: customer.phone || "",
1789
+ buyerPhone: customer.phone || "081234567890",
1790
+ ...feeDirection ? { feeDirection } : {},
1791
+ ...escrow !== void 0 ? { escrow } : {},
1771
1792
  ...params.providerParams
1772
1793
  };
1773
1794
  }
@@ -1807,8 +1828,8 @@ var IpaymuProvider = class extends BasePaymentProvider {
1807
1828
  provider: "ipaymu",
1808
1829
  orderId,
1809
1830
  amount: integerAmount,
1810
- reference: resData.TransactionId ? String(resData.TransactionId) : String(resData.SessionId || ""),
1811
- paymentUrl: resData.Url,
1831
+ reference: resData.TransactionId ? String(resData.TransactionId) : String(resData.SessionId || resData.SessionID || ""),
1832
+ paymentUrl: resData.Url || resData.url,
1812
1833
  rawResponse: data
1813
1834
  };
1814
1835
  if (resData.PaymentNo) {
@@ -1867,6 +1888,88 @@ var IpaymuProvider = class extends BasePaymentProvider {
1867
1888
  };
1868
1889
  }
1869
1890
  async getPaymentMethods(params, config) {
1891
+ const va = config.merchantCode || config.merchantId || "";
1892
+ const apiKey = config.apiKey || "";
1893
+ const sandbox = !!config.sandbox;
1894
+ if (va && apiKey) {
1895
+ try {
1896
+ const url = `${this.getBaseUrl(sandbox)}/payment-method-list`;
1897
+ const payload = { account: va };
1898
+ const { signature, timestamp } = generateIpaymuSignature("POST", va, apiKey, payload);
1899
+ const response = await fetch(url, {
1900
+ method: "POST",
1901
+ headers: {
1902
+ "Content-Type": "application/json",
1903
+ "Accept": "application/json",
1904
+ "va": va,
1905
+ "signature": signature,
1906
+ "timestamp": timestamp
1907
+ },
1908
+ body: JSON.stringify(payload)
1909
+ });
1910
+ const data = await response.json().catch(() => null);
1911
+ if (response.ok && data?.Data && Array.isArray(data.Data)) {
1912
+ const methods = [];
1913
+ const categories2 = {};
1914
+ for (const group of data.Data) {
1915
+ const groupCode = (group.Code || "").toLowerCase();
1916
+ const groupName = group.Name || group.Description || "Lainnya";
1917
+ const channels = group.Channels || [];
1918
+ let category = "Lainnya";
1919
+ if (groupCode === "va") category = "Virtual Account";
1920
+ else if (groupCode === "cstore") category = "Retail / Gerai";
1921
+ else if (groupCode === "qris") category = "QRIS";
1922
+ else if (groupCode === "cc") category = "Kartu Kredit";
1923
+ else if (groupCode === "paylater") category = "Paylater / Cicilan";
1924
+ else if (groupCode === "cod") category = "COD";
1925
+ else category = groupName;
1926
+ for (const ch of channels) {
1927
+ const chCode = (ch.Code || "").toLowerCase();
1928
+ let canonicalCode = chCode;
1929
+ if (groupCode === "va") {
1930
+ canonicalCode = chCode === "bag" ? "bag_va" : chCode === "bmi" ? "muamalat_va" : `${chCode}_va`;
1931
+ } else if (groupCode === "cc") {
1932
+ canonicalCode = "credit_card";
1933
+ }
1934
+ let totalFee = "-";
1935
+ if (ch.TransactionFee) {
1936
+ if (ch.TransactionFee.ActualFeeType === "PERCENT") {
1937
+ totalFee = `${ch.TransactionFee.ActualFee}%`;
1938
+ } else if (ch.TransactionFee.ActualFee !== void 0) {
1939
+ totalFee = `IDR ${Number(ch.TransactionFee.ActualFee).toLocaleString()}`;
1940
+ }
1941
+ }
1942
+ const pm = {
1943
+ paymentMethod: canonicalCode,
1944
+ code: canonicalCode,
1945
+ paymentName: ch.Name || ch.Description || canonicalCode,
1946
+ paymentImage: `https://my.ipaymu.com/images/banks/${chCode}.png`,
1947
+ totalFee,
1948
+ category,
1949
+ extra: {
1950
+ healthStatus: ch.HealthStatus,
1951
+ instructionsDoc: ch.PaymentInstructionsDoc,
1952
+ feeDetail: ch.TransactionFee
1953
+ }
1954
+ };
1955
+ methods.push(pm);
1956
+ if (!categories2[category]) categories2[category] = [];
1957
+ categories2[category].push(pm);
1958
+ }
1959
+ }
1960
+ if (methods.length > 0) {
1961
+ return {
1962
+ success: true,
1963
+ provider: "ipaymu",
1964
+ methods,
1965
+ categories: categories2,
1966
+ rawResponse: data
1967
+ };
1968
+ }
1969
+ }
1970
+ } catch (err) {
1971
+ }
1972
+ }
1870
1973
  const staticMethods = [
1871
1974
  {
1872
1975
  paymentMethod: "bca_va",
@@ -1932,6 +2035,22 @@ var IpaymuProvider = class extends BasePaymentProvider {
1932
2035
  totalFee: "IDR 3,500",
1933
2036
  category: "Virtual Account"
1934
2037
  },
2038
+ {
2039
+ paymentMethod: "bag_va",
2040
+ code: "bag_va",
2041
+ paymentName: "Bank Artha Graha Virtual Account",
2042
+ paymentImage: "https://my.ipaymu.com/images/banks/bag.png",
2043
+ totalFee: "IDR 3,500",
2044
+ category: "Virtual Account"
2045
+ },
2046
+ {
2047
+ paymentMethod: "muamalat_va",
2048
+ code: "muamalat_va",
2049
+ paymentName: "Bank Muamalat Virtual Account",
2050
+ paymentImage: "https://my.ipaymu.com/images/banks/bmi.png",
2051
+ totalFee: "IDR 3,500",
2052
+ category: "Virtual Account"
2053
+ },
1935
2054
  {
1936
2055
  paymentMethod: "qris",
1937
2056
  code: "qris",
@@ -2033,11 +2152,14 @@ var IpaymuProvider = class extends BasePaymentProvider {
2033
2152
  };
2034
2153
  }
2035
2154
  const txData = data.Data || {};
2036
- const statusText = (txData.Status || txData.status || "").toString().toLowerCase();
2037
- const isPaid = statusText === "berhasil" || statusText === "success" || txData.StatusCode === 1;
2038
- const isPending = statusText === "pending" || txData.StatusCode === 0;
2039
- const isFailed = !isPaid && !isPending;
2040
- const isExpired = statusText === "expired";
2155
+ const rawStatus = txData.Status !== void 0 ? txData.Status : txData.status;
2156
+ const statusDesc = (txData.StatusDesc || "").toString().toLowerCase();
2157
+ const paidStatus = (txData.PaidStatus || "").toString().toLowerCase();
2158
+ const statusCode = txData.StatusCode !== void 0 ? Number(txData.StatusCode) : rawStatus !== void 0 ? Number(rawStatus) : void 0;
2159
+ const isPaid = statusCode === 1 || paidStatus === "paid" || statusDesc.includes("berhasil") || statusDesc.includes("success");
2160
+ const isPending = statusCode === 0 || paidStatus === "unpaid" || statusDesc.includes("menunggu") || statusDesc.includes("pending");
2161
+ const isExpired = statusCode === 2 || statusDesc.includes("expired") || statusDesc.includes("kadaluarsa");
2162
+ const isFailed = !isPaid && !isPending && !isExpired;
2041
2163
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
2042
2164
  return {
2043
2165
  success: true,
@@ -2627,6 +2749,29 @@ function verifySnapWebhookSignature(headers, body, clientSecret, endpointUrl = "
2627
2749
  );
2628
2750
  return safeCompare(incoming, computed);
2629
2751
  }
2752
+ function snapErrorHint(message, code) {
2753
+ const m = (message || "").toLowerCase();
2754
+ const c = (code || "").toLowerCase();
2755
+ if (m.includes("unknown client") || c.includes("4017300") || c.includes("4017400")) {
2756
+ return "Client ID tidak dikenali DOKU. Pastikan clientId benar & kanal SNAP aktif untuk akun ini.";
2757
+ }
2758
+ if (m.includes("signature") || c.startsWith("401")) {
2759
+ 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).";
2760
+ }
2761
+ if (m.includes("bin") || m.includes("not configured") && m.includes("identifier")) {
2762
+ 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.";
2763
+ }
2764
+ if (m.includes("merchantid") || m.includes("merchant id")) {
2765
+ return "QRIS/e-Wallet butuh merchantId. Isi config.extra.merchantId (atau DOKU_MERCHANT_ID) dari dashboard.";
2766
+ }
2767
+ if (m.includes("partner service id") || m.includes("partnerServiceId")) {
2768
+ return "partnerServiceId tidak valid. Harus 8 karakter left-padded (BIN/company code DOKU).";
2769
+ }
2770
+ if (m.includes("customer no") || m.includes("customerno")) {
2771
+ return "customerNo tidak valid (maks 20 digit unik). Cek config.extra.customerNo.";
2772
+ }
2773
+ return void 0;
2774
+ }
2630
2775
 
2631
2776
  // src/clients/snap.ts
2632
2777
  var SnapClient = class {
@@ -2683,7 +2828,16 @@ var SnapClient = class {
2683
2828
  } catch {
2684
2829
  }
2685
2830
  if (!response.ok || !data?.accessToken) {
2686
- throw new Error(data?.responseMessage || data?.message || `DOKU SNAP get-token failed: HTTP ${response.status} - ${text}`);
2831
+ const baseMessage = data?.responseMessage || data?.message || `DOKU SNAP get-token failed: HTTP ${response.status}`;
2832
+ const hint = snapErrorHint(baseMessage, data?.responseCode);
2833
+ const err = new SnapApiError(`${baseMessage}${data?.responseCode ? ` (${data.responseCode})` : ""}${hint ? ` \u2014 ${hint}` : ""}`, {
2834
+ status: response.status,
2835
+ code: data?.responseCode,
2836
+ raw: data,
2837
+ endpoint,
2838
+ method: "POST"
2839
+ });
2840
+ throw err;
2687
2841
  }
2688
2842
  if (!clientSecret) {
2689
2843
  }
@@ -2744,12 +2898,37 @@ var SnapClient = class {
2744
2898
  } catch {
2745
2899
  }
2746
2900
  if (!response.ok) {
2747
- const err = data?.responseMessage || data?.error?.message || data?.message || `HTTP ${response.status}`;
2748
- throw new Error(`${err}${data?.responseCode ? ` (${data.responseCode})` : ""}`);
2901
+ const baseMessage = data?.responseMessage || data?.error?.message || data?.message || `HTTP ${response.status}`;
2902
+ const hint = snapErrorHint(baseMessage, data?.responseCode);
2903
+ const message = `${baseMessage}${data?.responseCode ? ` (${data.responseCode})` : ""}${hint ? ` \u2014 ${hint}` : ""}`;
2904
+ const err = new SnapApiError(message, {
2905
+ status: response.status,
2906
+ code: data?.responseCode,
2907
+ raw: data,
2908
+ endpoint,
2909
+ method
2910
+ });
2911
+ throw err;
2749
2912
  }
2750
2913
  return data;
2751
2914
  }
2752
2915
  };
2916
+ var SnapApiError = class extends Error {
2917
+ status;
2918
+ responseCode;
2919
+ raw;
2920
+ endpoint;
2921
+ method;
2922
+ constructor(message, opts) {
2923
+ super(message);
2924
+ this.name = "SnapApiError";
2925
+ this.status = opts.status;
2926
+ this.responseCode = opts.code;
2927
+ this.raw = opts.raw;
2928
+ this.endpoint = opts.endpoint;
2929
+ this.method = opts.method;
2930
+ }
2931
+ };
2753
2932
 
2754
2933
  // src/providers/doku/provider.ts
2755
2934
  var DokuProvider = class extends BasePaymentProvider {
@@ -3026,8 +3205,8 @@ var DokuProvider = class extends BasePaymentProvider {
3026
3205
  provider: "doku",
3027
3206
  orderId,
3028
3207
  amount: integerAmount,
3029
- rawResponse: null,
3030
- error: e.message || "Failed to make SNAP request to DOKU API"
3208
+ rawResponse: e?.raw ?? e?.rawResponse ?? null,
3209
+ error: e?.message || "Failed to make SNAP request to DOKU API"
3031
3210
  };
3032
3211
  }
3033
3212
  }
@@ -3068,6 +3247,7 @@ var DokuProvider = class extends BasePaymentProvider {
3068
3247
  return {
3069
3248
  success: true,
3070
3249
  provider: "doku",
3250
+ mode: "va",
3071
3251
  orderId: vaData.trxId || orderId,
3072
3252
  amount: Number(vaData.totalAmount?.value || amount) || Math.round(amount),
3073
3253
  reference: vaData.virtualAccountNo || orderId,
@@ -3103,6 +3283,7 @@ var DokuProvider = class extends BasePaymentProvider {
3103
3283
  return {
3104
3284
  success: true,
3105
3285
  provider: "doku",
3286
+ mode: "qris",
3106
3287
  orderId: data.partnerReferenceNo || orderId,
3107
3288
  amount: Number(data.amount?.value || amount) || Math.round(amount),
3108
3289
  reference: data.referenceNo || orderId,
@@ -3148,10 +3329,12 @@ var DokuProvider = class extends BasePaymentProvider {
3148
3329
  return {
3149
3330
  success: true,
3150
3331
  provider: "doku",
3332
+ mode: "ewallet",
3151
3333
  orderId: data.partnerReferenceNo || orderId,
3152
3334
  amount: Number(data.amount?.value || amount) || Math.round(amount),
3153
3335
  reference: data.partnerReferenceNo || orderId,
3154
3336
  paymentUrl: data.webRedirectUrl || data.paymentUrl,
3337
+ checkoutUrl: data.webRedirectUrl || data.paymentUrl,
3155
3338
  rawResponse: data
3156
3339
  };
3157
3340
  }
@@ -8192,6 +8375,62 @@ var IpaymuClient = class {
8192
8375
  async checkTransaction(transactionId) {
8193
8376
  return this.request("POST", "/transaction", { transactionId });
8194
8377
  }
8378
+ /**
8379
+ * Ambil daftar channel pembayaran aktif milik merchant
8380
+ */
8381
+ async getPaymentMethods() {
8382
+ return this.request("POST", "/payment-method-list", { account: this.va });
8383
+ }
8384
+ /**
8385
+ * Ambil riwayat transaksi merchant berpaginasi
8386
+ */
8387
+ async getHistory(params) {
8388
+ const payload = {
8389
+ account: this.va,
8390
+ page: params?.page || 1,
8391
+ limit: params?.limit || 10,
8392
+ ...params
8393
+ };
8394
+ return this.request("POST", "/history", payload);
8395
+ }
8396
+ /**
8397
+ * Ambil daftar seluruh bank di Indonesia
8398
+ */
8399
+ async getBankList() {
8400
+ return this.request("POST", "/banklist", { account: this.va });
8401
+ }
8402
+ /**
8403
+ * Ambil jangkauan area pengiriman COD
8404
+ */
8405
+ async getCodArea(postalCode) {
8406
+ const payload = { account: this.va };
8407
+ if (postalCode) payload.postalCode = postalCode;
8408
+ return this.request("POST", "/cod/getarea", payload);
8409
+ }
8410
+ /**
8411
+ * Hitung tarif ongkir pengiriman COD
8412
+ */
8413
+ async getCodRate(params) {
8414
+ return this.request("POST", "/cod/getrate", { account: this.va, ...params });
8415
+ }
8416
+ /**
8417
+ * Request pickup kurir COD
8418
+ */
8419
+ async getCodPickup(params) {
8420
+ return this.request("POST", "/cod/pickup", { account: this.va, ...params });
8421
+ }
8422
+ /**
8423
+ * Ambil nomor resi / AWB pengiriman COD
8424
+ */
8425
+ async getCodAwb(transactionId) {
8426
+ return this.request("POST", "/cod/getawb", { account: this.va, transactionId });
8427
+ }
8428
+ /**
8429
+ * Lacak status pengiriman kurir berdasarkan no resi / AWB
8430
+ */
8431
+ async getCodTracking(awb) {
8432
+ return this.request("POST", "/cod/tracking", { account: this.va, awb });
8433
+ }
8195
8434
  };
8196
8435
 
8197
8436
  // src/clients/xendit.ts
@@ -9576,170 +9815,316 @@ var PaymentManager = class {
9576
9815
  };
9577
9816
  var paymentManager = new PaymentManager();
9578
9817
 
9818
+ // src/core/providerRegistry.ts
9819
+ var ProviderRegistry = class {
9820
+ descriptors = /* @__PURE__ */ new Map();
9821
+ constructor(initial) {
9822
+ for (const d of initial || []) this.register(d);
9823
+ }
9824
+ register(desc) {
9825
+ this.descriptors.set(desc.name.toLowerCase().trim(), desc);
9826
+ }
9827
+ unregister(name) {
9828
+ return this.descriptors.delete(name.toLowerCase().trim());
9829
+ }
9830
+ has(name) {
9831
+ return this.descriptors.has(name.toLowerCase().trim());
9832
+ }
9833
+ get(name) {
9834
+ return this.descriptors.get(name.toLowerCase().trim());
9835
+ }
9836
+ names() {
9837
+ return [...this.descriptors.keys()];
9838
+ }
9839
+ /**
9840
+ * Autodetect provider aktif dari variabel lingkungan.
9841
+ * Mengembalikan nama provider yang kredensial .env-nya terisi penuh,
9842
+ * atau undefined jika tidak ada / ambigu.
9843
+ */
9844
+ detectFromEnv(env) {
9845
+ const present = [];
9846
+ for (const [name, desc] of this.descriptors) {
9847
+ const filled = desc.envKeys.filter((k) => {
9848
+ const v = env[k];
9849
+ return typeof v === "string" && v.trim().length > 0;
9850
+ });
9851
+ if (filled.length > 0) present.push({ name, count: filled.length });
9852
+ }
9853
+ if (present.length === 0) return void 0;
9854
+ present.sort((a, b) => b.count - a.count);
9855
+ const top = present[0];
9856
+ const ties = present.filter((p) => p.count === top.count);
9857
+ return ties.length === 1 ? top.name : void 0;
9858
+ }
9859
+ /**
9860
+ * Autodetect provider dari struktur payload webhook.
9861
+ * Mengembalikan nama provider jika dikenali, else undefined.
9862
+ */
9863
+ detectFromWebhook(payload) {
9864
+ if (!payload) return void 0;
9865
+ const p = payload;
9866
+ if (p.signature_key && p.transaction_status) return "midtrans";
9867
+ if (p.merchantCode && p.merchantOrderId && p.resultCode) return "duitku";
9868
+ if (p.trx_id && (p.sid || p.reference_id || p.via)) return "ipaymu";
9869
+ if (p.service?.id || p.order?.invoice_number && p.transaction?.status) return "doku";
9870
+ if (p.bill_no && (p.payment_status_code !== void 0 || p.payment_status_desc)) return "faspay";
9871
+ if (p.merchant_id && p.order_id && p.payment_status) return "finpay";
9872
+ if (p.tXid && p.merchantToken && (p.referenceNo || p.amt)) return "nicepay";
9873
+ if (p.partner_tx_id || p.partner_trx_id) return "oy";
9874
+ if (p.merchant_id && p.order_id && p.signature) return "prismalink";
9875
+ if (p.object === "event" || p.type && p.data?.object && p.api_version) return "stripe";
9876
+ if (p.event && p.payload?.payment?.entity) return "razorpay";
9877
+ if (p.external_id || p.event?.startsWith("payment.") || p.event?.startsWith("qr.") || p.data?.reference_id) return "xendit";
9878
+ if (p.event_type && p.resource && (p.event_type.startsWith("PAYMENT.") || p.event_type.startsWith("CHECKOUT.ORDER."))) return "paypal";
9879
+ if (p.notificationItems || p.merchantAccountCode && p.pspReference && p.eventCode) return "adyen";
9880
+ if (p.type && p.data?._links && (p.type.startsWith("payment_") || p.type.startsWith("refund_"))) return "checkoutcom";
9881
+ if (p.type && p.data?.object?.status && p.merchant_id) return "square";
9882
+ if (p.order && p.order?.status && p.order?.extOrderId) return "payu";
9883
+ if (p.kind && p.subject?.transaction) return "braintree";
9884
+ if (p.HASH && p.REFNOEXT && p.IPN_PID) return "twocheckout";
9885
+ return void 0;
9886
+ }
9887
+ };
9888
+ var ENV_KEYS = {
9889
+ midtrans: ["MIDTRANS_SERVER_KEY", "MIDTRANS_CLIENT_KEY"],
9890
+ duitku: ["DUITKU_API_KEY", "DUITKU_MERCHANT_CODE"],
9891
+ ipaymu: ["IPAYMU_API_KEY", "IPAYMU_VA"],
9892
+ xendit: ["XENDIT_SECRET_KEY", "XENDIT_WEBHOOK_TOKEN"],
9893
+ doku: ["DOKU_CLIENT_ID", "DOKU_SECRET_KEY"],
9894
+ prismalink: ["PRISMALINK_MERCHANT_ID", "PRISMALINK_SECRET_KEY"],
9895
+ faspay: ["FASPAY_MERCHANT_ID", "FASPAY_USER_ID", "FASPAY_PASSWORD"],
9896
+ finpay: ["FINPAY_MERCHANT_ID", "FINPAY_MERCHANT_KEY"],
9897
+ nicepay: ["NICEPAY_IMID", "NICEPAY_KEY"],
9898
+ oy: ["OY_USERNAME", "OY_API_KEY"],
9899
+ stripe: ["STRIPE_SECRET_KEY", "STRIPE_PUBLIC_KEY", "STRIPE_WEBHOOK_SECRET"],
9900
+ paypal: ["PAYPAL_CLIENT_ID", "PAYPAL_CLIENT_SECRET", "PAYPAL_WEBHOOK_ID"],
9901
+ adyen: ["ADYEN_API_KEY", "ADYEN_MERCHANT_ACCOUNT", "ADYEN_HMAC_KEY"],
9902
+ checkoutcom: ["CHECKOUTCOM_SECRET_KEY", "CHECKOUTCOM_PUBLIC_KEY", "CHECKOUTCOM_WEBHOOK_SECRET"],
9903
+ razorpay: ["RAZORPAY_KEY_ID", "RAZORPAY_KEY_SECRET", "RAZORPAY_WEBHOOK_SECRET"],
9904
+ square: ["SQUARE_ACCESS_TOKEN", "SQUARE_LOCATION_ID", "SQUARE_WEBHOOK_SIGNATURE_KEY"],
9905
+ payu: ["PAYU_POS_ID", "PAYU_MD5_KEY"],
9906
+ braintree: ["BRAINTREE_MERCHANT_ID", "BRAINTREE_PUBLIC_KEY", "BRAINTREE_PRIVATE_KEY"],
9907
+ twocheckout: ["TWOCHECKOUT_MERCHANT_CODE", "TWOCHECKOUT_SECRET_KEY", "TWOCHECKOUT_SECRET_WORD"]
9908
+ };
9909
+ var WORKING_METHODS = {
9910
+ midtrans: Object.keys(CANONICAL_TO_MIDTRANS),
9911
+ duitku: Object.keys(CANONICAL_TO_DUITKU),
9912
+ ipaymu: Object.keys(CANONICAL_TO_IPAYMU),
9913
+ xendit: Object.keys(CANONICAL_TO_XENDIT),
9914
+ doku: Object.keys(CANONICAL_TO_DOKU),
9915
+ prismalink: Object.keys(CANONICAL_TO_PRISMALINK),
9916
+ faspay: Object.keys(CANONICAL_TO_FASPAY),
9917
+ finpay: Object.keys(CANONICAL_TO_FINPAY),
9918
+ nicepay: Object.keys(CANONICAL_TO_NICEPAY),
9919
+ oy: Object.keys(CANONICAL_TO_OY),
9920
+ stripe: Object.keys(CANONICAL_TO_STRIPE),
9921
+ paypal: ["credit_card", "paylater", "paypal", "bank_transfer"],
9922
+ adyen: ["credit_card", "paypal", "qris", "apple_pay", "google_pay", "klarna", "sepa"],
9923
+ checkoutcom: ["credit_card", "paypal", "apple_pay", "google_pay", "klarna", "sofort", "bank_transfer"],
9924
+ razorpay: ["credit_card", "wallet", "upi", "netbanking", "emi", "bank_transfer"],
9925
+ square: ["credit_card", "apple_pay", "google_pay", "afterpay", "cash_app"],
9926
+ payu: ["credit_card", "bank_transfer", "apple_pay", "google_pay", "blik", "installment"],
9927
+ braintree: ["credit_card", "paypal", "apple_pay", "google_pay", "venmo"],
9928
+ twocheckout: ["credit_card", "paypal", "paylater", "wire_transfer"]
9929
+ };
9930
+ var OPERATIONS = {
9931
+ midtrans: { refund: true, checkBalance: true, disburse: false },
9932
+ duitku: { refund: false, checkBalance: true, disburse: true },
9933
+ ipaymu: { refund: false, checkBalance: true, disburse: false },
9934
+ xendit: { refund: false, checkBalance: true, disburse: true },
9935
+ doku: { refund: false, checkBalance: false, disburse: false },
9936
+ prismalink: { refund: false, checkBalance: false, disburse: false },
9937
+ faspay: { refund: false, checkBalance: false, disburse: false },
9938
+ finpay: { refund: false, checkBalance: false, disburse: false },
9939
+ nicepay: { refund: false, checkBalance: false, disburse: false },
9940
+ oy: { refund: false, checkBalance: true, disburse: true },
9941
+ stripe: { refund: true, checkBalance: true, disburse: false },
9942
+ paypal: { refund: true, checkBalance: true, disburse: false },
9943
+ adyen: { refund: true, checkBalance: false, disburse: false },
9944
+ checkoutcom: { refund: true, checkBalance: true, disburse: false },
9945
+ razorpay: { refund: true, checkBalance: true, disburse: false },
9946
+ square: { refund: true, checkBalance: true, disburse: false },
9947
+ payu: { refund: true, checkBalance: false, disburse: false },
9948
+ braintree: { refund: true, checkBalance: false, disburse: false },
9949
+ twocheckout: { refund: true, checkBalance: false, disburse: false }
9950
+ };
9951
+ function buildDefaultDescriptors() {
9952
+ return Object.keys(ENV_KEYS).map((name) => ({
9953
+ name,
9954
+ envKeys: ENV_KEYS[name],
9955
+ methods: WORKING_METHODS[name] || [],
9956
+ operations: OPERATIONS[name] || { refund: false, checkBalance: false, disburse: false }
9957
+ }));
9958
+ }
9959
+ var providerRegistry = new ProviderRegistry(buildDefaultDescriptors());
9960
+
9579
9961
  // src/core/config.ts
9962
+ var UNIVERSAL = {
9963
+ apiKey: ["BUAYAR_API_KEY", "BUAYAR_SERVER_KEY", "PG_API_KEY", "PAYMENT_API_KEY"],
9964
+ clientKey: ["BUAYAR_CLIENT_KEY", "PG_CLIENT_KEY"],
9965
+ merchantCode: ["BUAYAR_MERCHANT_CODE", "PG_MERCHANT_CODE", "PAYMENT_MERCHANT_CODE"],
9966
+ merchantId: ["BUAYAR_MERCHANT_ID", "PG_MERCHANT_ID"],
9967
+ secretKey: ["BUAYAR_SECRET_KEY", "PG_SECRET_KEY", "SECRET_KEY"],
9968
+ serverKey: ["BUAYAR_SERVER_KEY", "PG_SECRET_KEY"],
9969
+ projectId: ["BUAYAR_PROJECT_ID", "PG_PROJECT_ID", "PROJECT_ID"]
9970
+ };
9971
+ var SPECIFIC = {
9972
+ midtrans: {
9973
+ apiKey: ["MIDTRANS_SERVER_KEY"],
9974
+ clientKey: ["MIDTRANS_CLIENT_KEY"],
9975
+ merchantId: ["MIDTRANS_MERCHANT_ID"]
9976
+ },
9977
+ duitku: {
9978
+ apiKey: ["DUITKU_API_KEY"],
9979
+ merchantCode: ["DUITKU_MERCHANT_CODE"]
9980
+ },
9981
+ ipaymu: {
9982
+ apiKey: ["IPAYMU_API_KEY"],
9983
+ merchantCode: ["IPAYMU_VA", "IPAYMU_MERCHANT_CODE"]
9984
+ },
9985
+ xendit: {
9986
+ apiKey: ["XENDIT_SECRET_KEY", "XENDIT_API_KEY"]
9987
+ },
9988
+ doku: {
9989
+ apiKey: ["DOKU_SECRET_KEY", "DOKU_API_KEY"],
9990
+ clientKey: ["DOKU_CLIENT_ID"],
9991
+ merchantCode: ["DOKU_CLIENT_ID", "DOKU_MERCHANT_ID"],
9992
+ merchantId: ["DOKU_MERCHANT_ID"]
9993
+ },
9994
+ prismalink: {
9995
+ apiKey: ["PRISMALINK_SECRET_KEY", "PRISMALINK_API_KEY"],
9996
+ merchantCode: ["PRISMALINK_MERCHANT_ID"],
9997
+ merchantId: ["PRISMALINK_MERCHANT_ID"]
9998
+ },
9999
+ faspay: {
10000
+ apiKey: ["FASPAY_PASSWORD", "FASPAY_API_KEY"],
10001
+ clientKey: ["FASPAY_USER_ID"],
10002
+ merchantCode: ["FASPAY_MERCHANT_ID"],
10003
+ merchantId: ["FASPAY_MERCHANT_ID"]
10004
+ },
10005
+ finpay: {
10006
+ apiKey: ["FINPAY_MERCHANT_KEY", "FINPAY_SECRET_KEY", "FINPAY_API_KEY"],
10007
+ merchantCode: ["FINPAY_MERCHANT_ID"],
10008
+ merchantId: ["FINPAY_MERCHANT_ID"]
10009
+ },
10010
+ nicepay: {
10011
+ apiKey: ["NICEPAY_KEY", "NICEPAY_SECRET_KEY", "NICEPAY_API_KEY"],
10012
+ merchantCode: ["NICEPAY_IMID", "NICEPAY_MERCHANT_ID"],
10013
+ merchantId: ["NICEPAY_IMID"]
10014
+ },
10015
+ oy: {
10016
+ apiKey: ["OY_API_KEY"],
10017
+ clientKey: ["OY_USERNAME"],
10018
+ merchantCode: ["OY_USERNAME"]
10019
+ },
10020
+ stripe: {
10021
+ apiKey: ["STRIPE_SECRET_KEY", "STRIPE_KEY"],
10022
+ clientKey: ["STRIPE_PUBLIC_KEY", "STRIPE_PUBLISHABLE_KEY"]
10023
+ },
10024
+ paypal: {
10025
+ apiKey: ["PAYPAL_CLIENT_SECRET"],
10026
+ clientKey: ["PAYPAL_CLIENT_ID"],
10027
+ merchantCode: ["PAYPAL_CLIENT_ID"]
10028
+ },
10029
+ adyen: {
10030
+ apiKey: ["ADYEN_API_KEY"],
10031
+ clientKey: ["ADYEN_CLIENT_KEY"],
10032
+ merchantCode: ["ADYEN_MERCHANT_ACCOUNT"],
10033
+ merchantId: ["ADYEN_MERCHANT_ACCOUNT"]
10034
+ },
10035
+ checkoutcom: {
10036
+ apiKey: ["CHECKOUTCOM_SECRET_KEY"],
10037
+ clientKey: ["CHECKOUTCOM_PUBLIC_KEY"]
10038
+ },
10039
+ razorpay: {
10040
+ apiKey: ["RAZORPAY_KEY_SECRET"],
10041
+ clientKey: ["RAZORPAY_KEY_ID"],
10042
+ merchantCode: ["RAZORPAY_KEY_ID"]
10043
+ },
10044
+ square: {
10045
+ apiKey: ["SQUARE_ACCESS_TOKEN"],
10046
+ clientKey: ["SQUARE_APPLICATION_ID"],
10047
+ merchantCode: ["SQUARE_APPLICATION_ID"],
10048
+ projectId: ["SQUARE_LOCATION_ID"]
10049
+ },
10050
+ payu: {
10051
+ apiKey: ["PAYU_MD5_KEY"],
10052
+ clientKey: ["PAYU_POS_ID"],
10053
+ merchantCode: ["PAYU_POS_ID"],
10054
+ merchantId: ["PAYU_POS_ID"]
10055
+ },
10056
+ braintree: {
10057
+ apiKey: ["BRAINTREE_PRIVATE_KEY"],
10058
+ clientKey: ["BRAINTREE_PUBLIC_KEY"],
10059
+ merchantCode: ["BRAINTREE_MERCHANT_ID"],
10060
+ merchantId: ["BRAINTREE_MERCHANT_ID"]
10061
+ },
10062
+ twocheckout: {
10063
+ apiKey: ["TWOCHECKOUT_SECRET_KEY"],
10064
+ merchantCode: ["TWOCHECKOUT_MERCHANT_CODE"],
10065
+ merchantId: ["TWOCHECKOUT_MERCHANT_CODE"]
10066
+ }
10067
+ };
10068
+ function firstDefined(env, keys) {
10069
+ for (const k of keys) {
10070
+ const v = env[k];
10071
+ if (typeof v === "string" && v.trim().length > 0) return v.trim();
10072
+ }
10073
+ return void 0;
10074
+ }
10075
+ function resolveSandbox(env, provider) {
10076
+ const universal = firstDefined(env, ["BUAYAR_SANDBOX", "PG_SANDBOX", "PAYMENT_SANDBOX"]);
10077
+ if (universal !== void 0) return universal === "true" || universal === "1";
10078
+ const specificMap = {
10079
+ midtrans: ["MIDTRANS_IS_PRODUCTION"],
10080
+ duitku: ["DUITKU_SANDBOX"],
10081
+ ipaymu: ["IPAYMU_SANDBOX"],
10082
+ doku: ["DOKU_SANDBOX"],
10083
+ prismalink: ["PRISMALINK_SANDBOX"],
10084
+ faspay: ["FASPAY_SANDBOX"],
10085
+ finpay: ["FINPAY_SANDBOX"],
10086
+ nicepay: ["NICEPAY_SANDBOX"],
10087
+ oy: ["OY_SANDBOX"],
10088
+ stripe: ["STRIPE_SANDBOX"],
10089
+ paypal: ["PAYPAL_SANDBOX"],
10090
+ adyen: ["ADYEN_SANDBOX"],
10091
+ checkoutcom: ["CHECKOUTCOM_SANDBOX"],
10092
+ razorpay: ["RAZORPAY_SANDBOX"],
10093
+ square: ["SQUARE_SANDBOX"],
10094
+ payu: ["PAYU_SANDBOX"],
10095
+ braintree: ["BRAINTREE_SANDBOX"],
10096
+ twocheckout: ["TWOCHECKOUT_SANDBOX"],
10097
+ xendit: ["XENDIT_SANDBOX"]
10098
+ };
10099
+ const specific = firstDefined(env, specificMap[provider]);
10100
+ if (specific !== void 0) {
10101
+ if (provider === "midtrans") return specific !== "true" && specific !== "1";
10102
+ return specific === "true" || specific === "1";
10103
+ }
10104
+ return env.NODE_ENV !== "production";
10105
+ }
9580
10106
  function resolveConfigFromEnv(customConfig) {
9581
10107
  const env = typeof process !== "undefined" && process?.env ? process.env : {};
9582
- const provider = (customConfig?.provider || env.PROVIDER_PG || env.PG_PROVIDER || env.BUAYAR_PROVIDER || env.PAYMENT_PROVIDER || "midtrans").toLowerCase().trim();
9583
- let sandbox;
9584
- if (customConfig?.sandbox !== void 0) {
9585
- sandbox = customConfig.sandbox;
9586
- } else if (env.BUAYAR_SANDBOX !== void 0) {
9587
- sandbox = env.BUAYAR_SANDBOX === "true" || env.BUAYAR_SANDBOX === "1";
9588
- } else if (env.PG_SANDBOX !== void 0) {
9589
- sandbox = env.PG_SANDBOX === "true" || env.PG_SANDBOX === "1";
9590
- } else if (env.PAYMENT_SANDBOX !== void 0) {
9591
- sandbox = env.PAYMENT_SANDBOX === "true" || env.PAYMENT_SANDBOX === "1";
9592
- } else if (env.MIDTRANS_IS_PRODUCTION !== void 0) {
9593
- sandbox = env.MIDTRANS_IS_PRODUCTION !== "true" && env.MIDTRANS_IS_PRODUCTION !== "1";
9594
- } else if (env.DUITKU_SANDBOX !== void 0) {
9595
- sandbox = env.DUITKU_SANDBOX === "true" || env.DUITKU_SANDBOX === "1";
9596
- } else if (env.IPAYMU_SANDBOX !== void 0) {
9597
- sandbox = env.IPAYMU_SANDBOX === "true" || env.IPAYMU_SANDBOX === "1";
9598
- } else if (env.DOKU_SANDBOX !== void 0) {
9599
- sandbox = env.DOKU_SANDBOX === "true" || env.DOKU_SANDBOX === "1";
9600
- } else if (env.PRISMALINK_SANDBOX !== void 0) {
9601
- sandbox = env.PRISMALINK_SANDBOX === "true" || env.PRISMALINK_SANDBOX === "1";
9602
- } else if (env.FASPAY_SANDBOX !== void 0) {
9603
- sandbox = env.FASPAY_SANDBOX === "true" || env.FASPAY_SANDBOX === "1";
9604
- } else if (env.FINPAY_SANDBOX !== void 0) {
9605
- sandbox = env.FINPAY_SANDBOX === "true" || env.FINPAY_SANDBOX === "1";
9606
- } else if (env.NICEPAY_SANDBOX !== void 0) {
9607
- sandbox = env.NICEPAY_SANDBOX === "true" || env.NICEPAY_SANDBOX === "1";
9608
- } else if (env.OY_SANDBOX !== void 0) {
9609
- sandbox = env.OY_SANDBOX === "true" || env.OY_SANDBOX === "1";
9610
- } else if (env.STRIPE_SANDBOX !== void 0) {
9611
- sandbox = env.STRIPE_SANDBOX === "true" || env.STRIPE_SANDBOX === "1";
9612
- } else if (env.PAYPAL_SANDBOX !== void 0) {
9613
- sandbox = env.PAYPAL_SANDBOX === "true" || env.PAYPAL_SANDBOX === "1";
9614
- } else if (env.ADYEN_SANDBOX !== void 0) {
9615
- sandbox = env.ADYEN_SANDBOX === "true" || env.ADYEN_SANDBOX === "1";
9616
- } else if (env.CHECKOUTCOM_SANDBOX !== void 0) {
9617
- sandbox = env.CHECKOUTCOM_SANDBOX === "true" || env.CHECKOUTCOM_SANDBOX === "1";
9618
- } else if (env.RAZORPAY_SANDBOX !== void 0) {
9619
- sandbox = env.RAZORPAY_SANDBOX === "true" || env.RAZORPAY_SANDBOX === "1";
9620
- } else if (env.SQUARE_SANDBOX !== void 0) {
9621
- sandbox = env.SQUARE_SANDBOX === "true" || env.SQUARE_SANDBOX === "1";
9622
- } else if (env.PAYU_SANDBOX !== void 0) {
9623
- sandbox = env.PAYU_SANDBOX === "true" || env.PAYU_SANDBOX === "1";
9624
- } else if (env.BRAINTREE_SANDBOX !== void 0) {
9625
- sandbox = env.BRAINTREE_SANDBOX === "true" || env.BRAINTREE_SANDBOX === "1";
9626
- } else if (env.TWOCHECKOUT_SANDBOX !== void 0) {
9627
- sandbox = env.TWOCHECKOUT_SANDBOX === "true" || env.TWOCHECKOUT_SANDBOX === "1";
9628
- } else {
9629
- sandbox = env.NODE_ENV !== "production";
9630
- }
9631
- let apiKey = customConfig?.apiKey || customConfig?.serverKey || customConfig?.secretKey;
9632
- if (!apiKey) {
9633
- if (provider === "midtrans") {
9634
- apiKey = env.MIDTRANS_SERVER_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.BUAYAR_SERVER_KEY;
9635
- } else if (provider === "duitku") {
9636
- apiKey = env.DUITKU_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9637
- } else if (provider === "ipaymu") {
9638
- apiKey = env.IPAYMU_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9639
- } else if (provider === "xendit") {
9640
- apiKey = env.XENDIT_SECRET_KEY || env.XENDIT_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9641
- } else if (provider === "doku") {
9642
- apiKey = env.DOKU_SECRET_KEY || env.DOKU_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9643
- } else if (provider === "prismalink") {
9644
- apiKey = env.PRISMALINK_SECRET_KEY || env.PRISMALINK_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9645
- } else if (provider === "faspay") {
9646
- apiKey = env.FASPAY_PASSWORD || env.FASPAY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9647
- } else if (provider === "finpay") {
9648
- 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;
9649
- } else if (provider === "nicepay") {
9650
- 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;
9651
- } else if (provider === "oy" || provider === "oyindonesia") {
9652
- apiKey = env.OY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9653
- } else if (provider === "stripe") {
9654
- apiKey = env.STRIPE_SECRET_KEY || env.STRIPE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9655
- } else if (provider === "paypal") {
9656
- apiKey = env.PAYPAL_CLIENT_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9657
- } else if (provider === "adyen") {
9658
- apiKey = env.ADYEN_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9659
- } else if (provider === "checkoutcom") {
9660
- apiKey = env.CHECKOUTCOM_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9661
- } else if (provider === "razorpay") {
9662
- apiKey = env.RAZORPAY_KEY_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9663
- } else if (provider === "square") {
9664
- apiKey = env.SQUARE_ACCESS_TOKEN || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9665
- } else if (provider === "payu") {
9666
- apiKey = env.PAYU_MD5_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9667
- } else if (provider === "braintree") {
9668
- apiKey = env.BRAINTREE_PRIVATE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9669
- } else if (provider === "twocheckout" || provider === "2checkout") {
9670
- apiKey = env.TWOCHECKOUT_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9671
- } else {
9672
- apiKey = env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.PG_SECRET_KEY || env.BUAYAR_SECRET_KEY;
9673
- }
9674
- }
9675
- let merchantCode = customConfig?.merchantCode;
9676
- let clientKey = customConfig?.clientKey;
9677
- let merchantId = customConfig?.merchantId;
9678
- if (provider === "midtrans") {
9679
- clientKey = clientKey || env.MIDTRANS_CLIENT_KEY || env.BUAYAR_CLIENT_KEY || env.PG_CLIENT_KEY;
9680
- merchantId = merchantId || env.MIDTRANS_MERCHANT_ID || env.BUAYAR_MERCHANT_ID || env.PG_MERCHANT_ID;
9681
- merchantCode = merchantCode || clientKey || merchantId || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE;
9682
- } else if (provider === "duitku") {
9683
- merchantCode = merchantCode || env.DUITKU_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9684
- } else if (provider === "ipaymu") {
9685
- merchantCode = merchantCode || env.IPAYMU_VA || env.IPAYMU_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9686
- } else if (provider === "doku") {
9687
- merchantCode = merchantCode || env.DOKU_CLIENT_ID || env.DOKU_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9688
- clientKey = clientKey || customConfig?.merchantCode || env.DOKU_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9689
- } else if (provider === "prismalink") {
9690
- merchantCode = merchantCode || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9691
- merchantId = merchantId || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
9692
- } else if (provider === "faspay") {
9693
- merchantCode = merchantCode || env.FASPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9694
- merchantId = merchantId || env.FASPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
9695
- clientKey = clientKey || env.FASPAY_USER_ID || env.BUAYAR_CLIENT_KEY;
9696
- } else if (provider === "finpay") {
9697
- merchantCode = merchantCode || env.FINPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9698
- merchantId = merchantId || env.FINPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
9699
- } else if (provider === "nicepay") {
9700
- merchantCode = merchantCode || env.NICEPAY_IMID || env.NICEPAY_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9701
- merchantId = merchantId || env.NICEPAY_IMID || env.BUAYAR_MERCHANT_ID;
9702
- } else if (provider === "oy" || provider === "oyindonesia") {
9703
- merchantCode = merchantCode || env.OY_USERNAME || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9704
- clientKey = clientKey || customConfig?.merchantCode || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
9705
- } else if (provider === "stripe") {
9706
- clientKey = clientKey || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.BUAYAR_CLIENT_KEY || env.BUAYAR_PUBLIC_KEY;
9707
- merchantCode = merchantCode || clientKey || "stripe";
9708
- } else if (provider === "paypal") {
9709
- clientKey = clientKey || env.PAYPAL_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9710
- merchantCode = merchantCode || env.PAYPAL_CLIENT_ID || env.BUAYAR_MERCHANT_CODE;
9711
- } else if (provider === "adyen") {
9712
- clientKey = clientKey || env.ADYEN_CLIENT_KEY || env.BUAYAR_CLIENT_KEY;
9713
- merchantCode = merchantCode || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_CODE;
9714
- merchantId = merchantId || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_ID;
9715
- } else if (provider === "checkoutcom") {
9716
- clientKey = clientKey || env.CHECKOUTCOM_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9717
- merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE;
9718
- } else if (provider === "razorpay") {
9719
- clientKey = clientKey || env.RAZORPAY_KEY_ID || env.BUAYAR_CLIENT_KEY;
9720
- merchantCode = merchantCode || env.RAZORPAY_KEY_ID || env.BUAYAR_MERCHANT_CODE;
9721
- } else if (provider === "square") {
9722
- clientKey = clientKey || env.SQUARE_APPLICATION_ID || env.BUAYAR_CLIENT_KEY;
9723
- merchantCode = merchantCode || env.SQUARE_APPLICATION_ID || env.BUAYAR_MERCHANT_CODE;
9724
- } else if (provider === "payu") {
9725
- merchantCode = merchantCode || env.PAYU_POS_ID || env.BUAYAR_MERCHANT_CODE;
9726
- merchantId = merchantId || env.PAYU_POS_ID;
9727
- } else if (provider === "braintree") {
9728
- clientKey = clientKey || env.BRAINTREE_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9729
- merchantCode = merchantCode || env.BRAINTREE_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE;
9730
- merchantId = merchantId || env.BRAINTREE_MERCHANT_ID;
9731
- } else if (provider === "twocheckout" || provider === "2checkout") {
9732
- merchantCode = merchantCode || env.TWOCHECKOUT_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE;
9733
- merchantId = merchantId || env.TWOCHECKOUT_MERCHANT_CODE;
9734
- } else {
9735
- merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
9736
- }
9737
- const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID || env.SQUARE_LOCATION_ID;
9738
- 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;
9739
- const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY || env.BRAINTREE_PRIVATE_KEY;
9740
- 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;
10108
+ const explicit = (customConfig?.provider || env.PROVIDER_PG || env.PG_PROVIDER || env.BUAYAR_PROVIDER || env.PAYMENT_PROVIDER || "").toLowerCase().trim();
10109
+ let provider = explicit || providerRegistry.detectFromEnv(env) || "midtrans";
10110
+ provider = provider.replace("oyindonesia", "oy").replace("2checkout", "twocheckout");
10111
+ const sandbox = customConfig?.sandbox ?? resolveSandbox(env, provider);
10112
+ const spec = SPECIFIC[provider] || {};
10113
+ const cfg = {};
10114
+ const fields = ["apiKey", "clientKey", "merchantCode", "merchantId", "secretKey", "serverKey", "projectId"];
10115
+ for (const f of fields) {
10116
+ const universalKeys = UNIVERSAL[f] || [];
10117
+ const specificKeys = spec[f] || [];
10118
+ const universal = firstDefined(env, universalKeys);
10119
+ const specific = firstDefined(env, specificKeys);
10120
+ const value = universal || specific;
10121
+ const explicitValue = customConfig?.[f] || customConfig && (f === "apiKey" ? customConfig.secretKey || customConfig.serverKey : void 0);
10122
+ cfg[f] = explicitValue || value || "";
10123
+ }
9741
10124
  const callbackUrl = customConfig?.callbackUrl || env.BUAYAR_CALLBACK_URL || env.PG_CALLBACK_URL || env.PAYMENT_CALLBACK_URL;
9742
10125
  const returnUrl = customConfig?.returnUrl || env.BUAYAR_RETURN_URL || env.PG_RETURN_URL || env.PAYMENT_RETURN_URL;
10126
+ const publicKey = customConfig?.publicKey || firstDefined(env, ["BUAYAR_PUBLIC_KEY", "PG_PUBLIC_KEY", "PUBLIC_KEY"]) || cfg.clientKey;
10127
+ const privateKey = customConfig?.privateKey || firstDefined(env, ["BUAYAR_PRIVATE_KEY", "PG_PRIVATE_KEY", "PRIVATE_KEY"]) || (provider === "braintree" ? cfg.apiKey : void 0);
9743
10128
  const extra = {
9744
10129
  webhookToken: env.XENDIT_WEBHOOK_TOKEN || env.BUAYAR_WEBHOOK_TOKEN,
9745
10130
  webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.CHECKOUTCOM_WEBHOOK_SECRET || env.RAZORPAY_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
@@ -9760,15 +10145,16 @@ function resolveConfigFromEnv(customConfig) {
9760
10145
  secretWord: env.TWOCHECKOUT_SECRET_WORD,
9761
10146
  ...customConfig?.extra
9762
10147
  };
10148
+ const apiKey = cfg.apiKey || cfg.secretKey || cfg.serverKey;
9763
10149
  return {
9764
- provider: provider === "oyindonesia" ? "oy" : provider === "2checkout" ? "twocheckout" : provider,
9765
- apiKey: apiKey || "",
10150
+ provider,
10151
+ apiKey,
9766
10152
  serverKey: apiKey || "",
9767
- secretKey: secretKey || apiKey || "",
9768
- merchantCode: merchantCode || "",
9769
- clientKey: clientKey || "",
9770
- merchantId: merchantId || "",
9771
- projectId,
10153
+ secretKey: apiKey || "",
10154
+ merchantCode: cfg.merchantCode || "",
10155
+ clientKey: cfg.clientKey || "",
10156
+ merchantId: cfg.merchantId || "",
10157
+ projectId: cfg.projectId || "",
9772
10158
  publicKey,
9773
10159
  privateKey,
9774
10160
  sandbox,
@@ -9782,8 +10168,10 @@ function resolveConfigFromEnv(customConfig) {
9782
10168
  var Buayar = class {
9783
10169
  manager;
9784
10170
  config;
9785
- constructor(config, manager) {
10171
+ registry;
10172
+ constructor(config, manager, registry) {
9786
10173
  this.manager = manager || paymentManager;
10174
+ this.registry = registry || providerRegistry;
9787
10175
  this.config = resolveConfigFromEnv(config);
9788
10176
  }
9789
10177
  /**
@@ -9816,6 +10204,62 @@ var Buayar = class {
9816
10204
  getProvider(name) {
9817
10205
  return this.manager.getProvider(name || this.provider);
9818
10206
  }
10207
+ /**
10208
+ * Daftar nama provider yang terdaftar (bawaan + kustom).
10209
+ */
10210
+ listProviders() {
10211
+ return this.registry.names();
10212
+ }
10213
+ /**
10214
+ * Registrasi metadata provider kustom untuk deteksi & capability.
10215
+ * Contoh: buayar.registerProviderDescriptor({ name, envKeys, methods, operations })
10216
+ */
10217
+ registerProviderDescriptor(desc) {
10218
+ this.registry.register(desc);
10219
+ }
10220
+ /**
10221
+ * Cek capability (metode + operasi) provider tertentu — atau provider aktif bila kosong.
10222
+ * Jawab pertanyaan "provider ini dukung apa?" secara runtime, tanpa bongkar dokumen.
10223
+ */
10224
+ getCapabilities(name) {
10225
+ const n = name || this.provider;
10226
+ const desc = this.registry.get(n);
10227
+ if (!desc) return void 0;
10228
+ return { methods: desc.methods, operations: desc.operations };
10229
+ }
10230
+ /**
10231
+ * Deteksi nama provider dari struktur payload webhook.
10232
+ */
10233
+ detectProviderFromPayload(payload) {
10234
+ return this.registry.detectFromWebhook(payload);
10235
+ }
10236
+ /**
10237
+ * Deteksi nama provider aktif dari variabel lingkungan (kredensial yang terisi).
10238
+ */
10239
+ detectProviderFromEnv(env) {
10240
+ return this.registry.detectFromEnv(env || process.env);
10241
+ }
10242
+ /**
10243
+ * Logika "bisa pakai X dengan provider Y?" — helper untuk portabilitas.
10244
+ */
10245
+ supports(name, operation) {
10246
+ const desc = this.registry.get(name);
10247
+ return desc ? desc.operations[operation] : false;
10248
+ }
10249
+ /**
10250
+ * Daftar metode pembayaran yang benar2 tersedia untuk provider aktif.
10251
+ */
10252
+ getSupportedMethods(name) {
10253
+ const n = name || this.provider;
10254
+ return this.registry.get(n)?.methods || [];
10255
+ }
10256
+ /**
10257
+ * Iterasi CEPAT: apakah provider aktif mendukung method kanonik tertentu?
10258
+ */
10259
+ supportsMethod(method, name) {
10260
+ const n = name || this.provider;
10261
+ return this.registry.get(n)?.methods.includes(method) ?? false;
10262
+ }
9819
10263
  /**
9820
10264
  * Buat transaksi pembayaran baru (Mendukung Semi dan Full Integrasi)
9821
10265
  */
@@ -9890,47 +10334,8 @@ var Buayar = class {
9890
10334
  }
9891
10335
  }
9892
10336
  let providerName = configOverride?.provider || this.provider;
9893
- if (payload) {
9894
- if (payload.signature_key && payload.transaction_status) {
9895
- providerName = "midtrans";
9896
- } else if (payload.merchantCode && payload.merchantOrderId && payload.resultCode) {
9897
- providerName = "duitku";
9898
- } else if (payload.trx_id && (payload.sid || payload.reference_id || payload.via)) {
9899
- providerName = "ipaymu";
9900
- } else if (payload.service?.id || payload.order?.invoice_number && payload.transaction?.status) {
9901
- providerName = "doku";
9902
- } else if (payload.bill_no && (payload.payment_status_code !== void 0 || payload.payment_status_desc)) {
9903
- providerName = "faspay";
9904
- } else if (payload.merchant_id && payload.order_id && payload.payment_status) {
9905
- providerName = "finpay";
9906
- } else if (payload.tXid && payload.merchantToken && (payload.referenceNo || payload.amt)) {
9907
- providerName = "nicepay";
9908
- } else if (payload.partner_tx_id || payload.partner_trx_id) {
9909
- providerName = "oy";
9910
- } else if (payload.merchant_id && payload.order_id && payload.signature) {
9911
- providerName = "prismalink";
9912
- } else if (payload.object === "event" || payload.type && payload.data?.object && payload.api_version) {
9913
- providerName = "stripe";
9914
- } else if (payload.event && payload.payload?.payment?.entity) {
9915
- providerName = "razorpay";
9916
- } else if (payload.external_id || payload.event?.startsWith("payment.") || payload.event?.startsWith("qr.") || payload.data?.reference_id) {
9917
- providerName = "xendit";
9918
- } else if (payload.event_type && payload.resource && (payload.event_type.startsWith("PAYMENT.") || payload.event_type.startsWith("CHECKOUT.ORDER."))) {
9919
- providerName = "paypal";
9920
- } else if (payload.notificationItems || payload.merchantAccountCode && payload.pspReference && payload.eventCode) {
9921
- providerName = "adyen";
9922
- } else if (payload.type && payload.data?._links && (payload.type.startsWith("payment_") || payload.type.startsWith("refund_"))) {
9923
- providerName = "checkoutcom";
9924
- } else if (payload.type && payload.data?.object?.status && payload.merchant_id) {
9925
- providerName = "square";
9926
- } else if (payload.order && payload.order?.status && payload.order?.extOrderId) {
9927
- providerName = "payu";
9928
- } else if (payload.kind && payload.subject?.transaction) {
9929
- providerName = "braintree";
9930
- } else if (payload.HASH && payload.REFNOEXT && payload.IPN_PID) {
9931
- providerName = "twocheckout";
9932
- }
9933
- }
10337
+ const detected = this.registry.detectFromWebhook(payload);
10338
+ if (detected) providerName = detected;
9934
10339
  return this.manager.verifyCallback(providerName, payload, mergedConfig);
9935
10340
  }
9936
10341
  async handleWebhook(payload, headers, configOverride) {
@@ -10072,8 +10477,10 @@ var buayar = new Buayar();
10072
10477
  PayuProvider,
10073
10478
  PrismalinkClient,
10074
10479
  PrismalinkProvider,
10480
+ ProviderRegistry,
10075
10481
  RazorpayClient,
10076
10482
  RazorpayProvider,
10483
+ SnapApiError,
10077
10484
  SnapClient,
10078
10485
  SquareClient,
10079
10486
  SquareProvider,
@@ -10086,6 +10493,7 @@ var buayar = new Buayar();
10086
10493
  buayar,
10087
10494
  buildBraintreeBasicAuth,
10088
10495
  buildCoreChargePayload,
10496
+ buildDefaultDescriptors,
10089
10497
  buildPaypalBasicAuth,
10090
10498
  buildPayuBasicAuth,
10091
10499
  buildRazorpayBasicAuth,
@@ -10110,6 +10518,7 @@ var buayar = new Buayar();
10110
10518
  minifyJson,
10111
10519
  parseCoreChargeResponse,
10112
10520
  paymentManager,
10521
+ providerRegistry,
10113
10522
  resolveConfigFromEnv,
10114
10523
  safeCompare,
10115
10524
  serializePaypalParams,
@@ -10117,6 +10526,7 @@ var buayar = new Buayar();
10117
10526
  sha256,
10118
10527
  sha256Hex,
10119
10528
  sha512,
10529
+ snapErrorHint,
10120
10530
  snapExternalId,
10121
10531
  snapTimestamp,
10122
10532
  snapUtcTimestamp,