@crediblemark/buayar 0.2.1 → 0.3.1

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
@@ -30,7 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AdyenClient: () => AdyenClient,
34
+ AdyenProvider: () => AdyenProvider,
33
35
  BasePaymentProvider: () => BasePaymentProvider,
36
+ BraintreeClient: () => BraintreeClient,
37
+ BraintreeProvider: () => BraintreeProvider,
34
38
  Buayar: () => Buayar,
35
39
  CANONICAL_TO_DOKU: () => CANONICAL_TO_DOKU,
36
40
  CANONICAL_TO_DUITKU: () => CANONICAL_TO_DUITKU,
@@ -44,6 +48,8 @@ __export(index_exports, {
44
48
  CANONICAL_TO_STRIPE: () => CANONICAL_TO_STRIPE,
45
49
  CANONICAL_TO_XENDIT: () => CANONICAL_TO_XENDIT,
46
50
  CORE_API_METHODS: () => CORE_API_METHODS,
51
+ CheckoutComClient: () => CheckoutComClient,
52
+ CheckoutComProvider: () => CheckoutComProvider,
47
53
  DUITKU_TO_CANONICAL: () => DUITKU_TO_CANONICAL,
48
54
  DokuClient: () => DokuClient,
49
55
  DokuProvider: () => DokuProvider,
@@ -64,14 +70,29 @@ __export(index_exports, {
64
70
  OyClient: () => OyClient,
65
71
  OyProvider: () => OyProvider,
66
72
  PaymentManager: () => PaymentManager,
73
+ PaypalClient: () => PaypalClient,
74
+ PaypalProvider: () => PaypalProvider,
75
+ PayuClient: () => PayuClient,
76
+ PayuProvider: () => PayuProvider,
67
77
  PrismalinkClient: () => PrismalinkClient,
68
78
  PrismalinkProvider: () => PrismalinkProvider,
79
+ RazorpayClient: () => RazorpayClient,
80
+ RazorpayProvider: () => RazorpayProvider,
81
+ SquareClient: () => SquareClient,
82
+ SquareProvider: () => SquareProvider,
69
83
  StripeClient: () => StripeClient,
70
84
  StripeProvider: () => StripeProvider,
85
+ TwoCheckoutClient: () => TwoCheckoutClient,
86
+ TwoCheckoutProvider: () => TwoCheckoutProvider,
71
87
  XenditClient: () => XenditClient,
72
88
  XenditProvider: () => XenditProvider,
73
89
  buayar: () => buayar,
90
+ buildBraintreeBasicAuth: () => buildBraintreeBasicAuth,
74
91
  buildCoreChargePayload: () => buildCoreChargePayload,
92
+ buildPaypalBasicAuth: () => buildPaypalBasicAuth,
93
+ buildPayuBasicAuth: () => buildPayuBasicAuth,
94
+ buildRazorpayBasicAuth: () => buildRazorpayBasicAuth,
95
+ buildTwoCheckoutAuth: () => buildTwoCheckoutAuth,
75
96
  formatNicepayTimestamp: () => formatNicepayTimestamp,
76
97
  generateDokuHeaders: () => generateDokuHeaders,
77
98
  generateFaspaySignature: () => generateFaspaySignature,
@@ -91,6 +112,7 @@ __export(index_exports, {
91
112
  paymentManager: () => paymentManager,
92
113
  resolveConfigFromEnv: () => resolveConfigFromEnv,
93
114
  safeCompare: () => safeCompare,
115
+ serializePaypalParams: () => serializePaypalParams,
94
116
  serializeStripeParams: () => serializeStripeParams,
95
117
  sha256: () => sha256,
96
118
  sha512: () => sha512,
@@ -105,6 +127,9 @@ __export(index_exports, {
105
127
  toPrismalinkPaymentMethod: () => toPrismalinkPaymentMethod,
106
128
  toStripePaymentMethod: () => toStripePaymentMethod,
107
129
  toXenditPaymentMethod: () => toXenditPaymentMethod,
130
+ verifyAdyenWebhook: () => verifyAdyenWebhook,
131
+ verifyBraintreeWebhook: () => verifyBraintreeWebhook,
132
+ verifyCheckoutComWebhook: () => verifyCheckoutComWebhook,
108
133
  verifyDokuWebhookSignature: () => verifyDokuWebhookSignature,
109
134
  verifyDuitkuCallbackSignature: () => verifyDuitkuCallbackSignature,
110
135
  verifyFaspaySignature: () => verifyFaspaySignature,
@@ -112,8 +137,13 @@ __export(index_exports, {
112
137
  verifyIpaymuCallback: () => verifyIpaymuCallback,
113
138
  verifyNicepayWebhook: () => verifyNicepayWebhook,
114
139
  verifyOyWebhook: () => verifyOyWebhook,
140
+ verifyPaypalWebhookSimple: () => verifyPaypalWebhookSimple,
141
+ verifyPayuWebhook: () => verifyPayuWebhook,
115
142
  verifyPrismalinkSignature: () => verifyPrismalinkSignature,
143
+ verifyRazorpayWebhook: () => verifyRazorpayWebhook,
144
+ verifySquareWebhook: () => verifySquareWebhook,
116
145
  verifyStripeWebhook: () => verifyStripeWebhook,
146
+ verifyTwoCheckoutWebhook: () => verifyTwoCheckoutWebhook,
117
147
  verifyXenditWebhookToken: () => verifyXenditWebhookToken
118
148
  });
119
149
  module.exports = __toCommonJS(index_exports);
@@ -536,7 +566,19 @@ function hmacSha256(data, secret) {
536
566
  }
537
567
  function safeCompare(a, b) {
538
568
  if (typeof a !== "string" || typeof b !== "string") return false;
539
- return a.toLowerCase() === b.toLowerCase();
569
+ if (!a && !b) return true;
570
+ if (!a || !b) return false;
571
+ const isHexA = /^[0-9a-fA-F]+$/.test(a);
572
+ const isHexB = /^[0-9a-fA-F]+$/.test(b);
573
+ let strA = a;
574
+ let strB = b;
575
+ if (isHexA && isHexB && a.length === b.length) {
576
+ strA = a.toLowerCase();
577
+ strB = b.toLowerCase();
578
+ }
579
+ const hashA = import_crypto.default.createHash("sha256").update(strA).digest();
580
+ const hashB = import_crypto.default.createHash("sha256").update(strB).digest();
581
+ return import_crypto.default.timingSafeEqual(hashA, hashB);
540
582
  }
541
583
 
542
584
  // src/providers/duitku/signature.ts
@@ -2031,7 +2073,7 @@ function getXenditAuthHeader(secretKey) {
2031
2073
  return `Basic ${token}`;
2032
2074
  }
2033
2075
  function verifyXenditWebhookToken(headerToken, expectedToken) {
2034
- if (!headerToken || !expectedToken) return true;
2076
+ if (!headerToken || !expectedToken) return false;
2035
2077
  return safeCompare(headerToken, expectedToken);
2036
2078
  }
2037
2079
 
@@ -2219,8 +2261,14 @@ var XenditProvider = class extends BasePaymentProvider {
2219
2261
  const orderId = body.external_id || body.reference_id || body.data?.reference_id || body.id || "";
2220
2262
  const amount = body.paid_amount || body.amount || body.data?.amount || 0;
2221
2263
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
2264
+ const webhookToken = config.extra?.webhookToken;
2265
+ const headerToken = config.extra?.callbackToken || config.extra?.headers?.["x-callback-token"] || config.extra?.headers?.["X-Callback-Token"];
2266
+ let isValid = true;
2267
+ if (webhookToken || headerToken) {
2268
+ isValid = verifyXenditWebhookToken(headerToken, webhookToken);
2269
+ }
2222
2270
  return {
2223
- isValid: true,
2271
+ isValid,
2224
2272
  provider: "xendit",
2225
2273
  orderId: String(orderId),
2226
2274
  amount: Number(amount) || 0,
@@ -2498,11 +2546,12 @@ function verifyDokuWebhookSignature(headers, body, clientId, secretKey, requestT
2498
2546
  const reqId = headers["request-id"] || headers["Request-Id"] || "";
2499
2547
  const reqTimestamp = headers["request-timestamp"] || headers["Request-Timestamp"] || "";
2500
2548
  const incomingSignature = headers["signature"] || headers["Signature"] || "";
2501
- if (!incomingSignature || !secretKey) return true;
2549
+ if (!incomingSignature || !secretKey) return false;
2550
+ const target = headers["request-target"] || headers["Request-Target"] || requestTarget;
2502
2551
  let component = `Client-Id:${reqClientId || clientId}
2503
2552
  Request-Id:${reqId}
2504
2553
  Request-Timestamp:${reqTimestamp}
2505
- Request-Target:${requestTarget}`;
2554
+ Request-Target:${target}`;
2506
2555
  if (body) {
2507
2556
  const rawBody = typeof body === "string" ? body : JSON.stringify(body);
2508
2557
  const digest = import_crypto6.default.createHash("sha256").update(rawBody).digest("base64");
@@ -2726,8 +2775,16 @@ var DokuProvider = class extends BasePaymentProvider {
2726
2775
  const orderId = body.order?.invoice_number || body.invoice_number || body.order_id || "";
2727
2776
  const amount = body.order?.amount || body.amount || 0;
2728
2777
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
2778
+ const secretKey = config.secretKey || config.apiKey || "";
2779
+ const headers = config.extra?.headers || {};
2780
+ const signature = headers["signature"] || headers["Signature"] || config.extra?.dokuSignature || config.extra?.signatureHeader;
2781
+ const clientId = config.merchantCode || config.clientKey || "";
2782
+ let isValid = true;
2783
+ if (signature || headers && (headers["request-id"] || headers["Request-Id"])) {
2784
+ isValid = verifyDokuWebhookSignature(headers, body, clientId, secretKey);
2785
+ }
2729
2786
  return {
2730
- isValid: true,
2787
+ isValid,
2731
2788
  provider: "doku",
2732
2789
  orderId: String(orderId),
2733
2790
  amount: Number(amount) || 0,
@@ -2984,7 +3041,7 @@ function generatePrismalinkSignature(merchantId, orderId, amount, secretKey) {
2984
3041
  return sha256(raw);
2985
3042
  }
2986
3043
  function verifyPrismalinkSignature(merchantId, orderId, amount, secretKey, incomingSignature) {
2987
- if (!incomingSignature || !secretKey) return true;
3044
+ if (!incomingSignature || !secretKey) return false;
2988
3045
  const computed = generatePrismalinkSignature(merchantId, orderId, amount, secretKey);
2989
3046
  return safeCompare(incomingSignature, computed);
2990
3047
  }
@@ -3375,7 +3432,7 @@ function generateFaspaySignature(userId, password, billNo) {
3375
3432
  return import_crypto9.default.createHash("sha1").update(md5Hash).digest("hex");
3376
3433
  }
3377
3434
  function verifyFaspaySignature(userId, password, billNo, paymentStatusCode, incomingSignature) {
3378
- if (!incomingSignature || !password) return true;
3435
+ if (!incomingSignature || !password) return false;
3379
3436
  const md5Hash = import_crypto9.default.createHash("md5").update(`${userId}${password}${billNo}${paymentStatusCode}`).digest("hex");
3380
3437
  const computed = import_crypto9.default.createHash("sha1").update(md5Hash).digest("hex");
3381
3438
  const simpleComputed = generateFaspaySignature(userId, password, billNo);
@@ -3796,9 +3853,9 @@ function generateFinpaySignature(merchantId, orderId, amount, merchantKey) {
3796
3853
  return import_crypto11.default.createHmac("sha512", merchantKey).update(data).digest("hex");
3797
3854
  }
3798
3855
  function verifyFinpaySignature(merchantId, orderId, amount, merchantKey, incomingSignature) {
3799
- if (!incomingSignature || !merchantKey) return true;
3856
+ if (!incomingSignature || !merchantKey) return false;
3800
3857
  const computed = generateFinpaySignature(merchantId, orderId, amount, merchantKey);
3801
- return safeCompare(incomingSignature.toLowerCase(), computed.toLowerCase());
3858
+ return safeCompare(incomingSignature, computed);
3802
3859
  }
3803
3860
 
3804
3861
  // src/providers/finpay/provider.ts
@@ -4183,9 +4240,9 @@ function generateNicepayToken(timeStamp, iMid, referenceNo, amt, merchantKey) {
4183
4240
  return sha256(raw);
4184
4241
  }
4185
4242
  function verifyNicepayWebhook(timeStamp, iMid, referenceNo, amt, merchantKey, incomingToken) {
4186
- if (!incomingToken || !merchantKey) return true;
4243
+ if (!incomingToken || !merchantKey) return false;
4187
4244
  const computed = generateNicepayToken(timeStamp, iMid, referenceNo, amt, merchantKey);
4188
- return safeCompare(incomingToken.toLowerCase(), computed.toLowerCase());
4245
+ return safeCompare(incomingToken, computed);
4189
4246
  }
4190
4247
 
4191
4248
  // src/providers/nicepay/provider.ts
@@ -4612,9 +4669,9 @@ function generateOyHeaders(username, apiKey) {
4612
4669
  };
4613
4670
  }
4614
4671
  function verifyOyWebhook(headers, expectedUsername) {
4615
- if (!expectedUsername) return true;
4672
+ if (!expectedUsername) return false;
4616
4673
  const username = headers["x-oy-username"] || headers["X-Oy-Username"] || "";
4617
- if (!username) return true;
4674
+ if (!username) return false;
4618
4675
  return safeCompare(username.toLowerCase(), expectedUsername.toLowerCase());
4619
4676
  }
4620
4677
 
@@ -4776,7 +4833,7 @@ var OyProvider = class extends BasePaymentProvider {
4776
4833
  }
4777
4834
  }
4778
4835
  async verifyCallback(body, config) {
4779
- const username = config.clientKey || config.merchantCode || config.merchantId || "";
4836
+ const username = config.clientKey || config.merchantCode || config.merchantId || config.extra?.username || "";
4780
4837
  const orderId = body.partner_tx_id || body.partner_trx_id || body.trx_id || "";
4781
4838
  const amount = body.amount || body.settlement_amount || 0;
4782
4839
  const rawStatus = (body.status || body.tx_status || "").toUpperCase();
@@ -4785,8 +4842,14 @@ var OyProvider = class extends BasePaymentProvider {
4785
4842
  const isExpired = rawStatus === "EXPIRED";
4786
4843
  const isFailed = rawStatus === "FAILED" || !isPaid && !isPending && !isExpired;
4787
4844
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
4845
+ const headers = config.extra?.headers || {};
4846
+ const oyUsernameHeader = headers["x-oy-username"] || headers["X-Oy-Username"] || config.extra?.oyUsername;
4847
+ let isValid = true;
4848
+ if (oyUsernameHeader || username && headers && Object.keys(headers).length > 0) {
4849
+ isValid = verifyOyWebhook(headers, username);
4850
+ }
4788
4851
  return {
4789
- isValid: true,
4852
+ isValid,
4790
4853
  provider: "oy",
4791
4854
  orderId: String(orderId),
4792
4855
  amount: Number(amount) || 0,
@@ -5046,13 +5109,16 @@ function serializeStripeParams(obj, prefix = "") {
5046
5109
  }
5047
5110
  function verifyStripeWebhook(rawPayload, signatureHeader, webhookSecret, toleranceSeconds = 300) {
5048
5111
  if (!signatureHeader || !webhookSecret) {
5049
- return true;
5112
+ return false;
5050
5113
  }
5051
5114
  const items = signatureHeader.split(",");
5052
5115
  let timestamp = "";
5053
5116
  const signatures = [];
5054
5117
  for (const item of items) {
5055
- const [key, value] = item.trim().split("=");
5118
+ const eqIdx = item.indexOf("=");
5119
+ if (eqIdx === -1) continue;
5120
+ const key = item.slice(0, eqIdx).trim();
5121
+ const value = item.slice(eqIdx + 1).trim();
5056
5122
  if (key === "t") {
5057
5123
  timestamp = value;
5058
5124
  } else if (key === "v1") {
@@ -5062,10 +5128,18 @@ function verifyStripeWebhook(rawPayload, signatureHeader, webhookSecret, toleran
5062
5128
  if (!timestamp || signatures.length === 0) {
5063
5129
  return false;
5064
5130
  }
5131
+ const tsNum = Number(timestamp);
5132
+ if (Number.isNaN(tsNum) || tsNum <= 0) {
5133
+ return false;
5134
+ }
5135
+ const nowSec = Math.floor(Date.now() / 1e3);
5136
+ if (Math.abs(nowSec - tsNum) > toleranceSeconds) {
5137
+ return false;
5138
+ }
5065
5139
  const payloadString = typeof rawPayload === "string" ? rawPayload : JSON.stringify(rawPayload);
5066
5140
  const signedPayload = `${timestamp}.${payloadString}`;
5067
5141
  const expectedSignature = hmacSha256(signedPayload, webhookSecret);
5068
- return signatures.some((sig) => safeCompare(sig.toLowerCase(), expectedSignature.toLowerCase()));
5142
+ return signatures.some((sig) => safeCompare(sig, expectedSignature));
5069
5143
  }
5070
5144
 
5071
5145
  // src/providers/stripe/provider.ts
@@ -5387,202 +5461,2189 @@ var StripeProvider = class extends BasePaymentProvider {
5387
5461
  }
5388
5462
  };
5389
5463
 
5390
- // src/clients/duitku.ts
5391
- var DuitkuClient = class {
5392
- merchantCode;
5393
- apiKey;
5394
- sandbox;
5395
- constructor(config) {
5396
- this.merchantCode = config.merchantCode || "";
5397
- this.apiKey = config.apiKey || config.serverKey || "";
5398
- this.sandbox = !!config.sandbox;
5399
- }
5400
- getPassportBaseUrl() {
5401
- return this.sandbox ? "https://sandbox.duitku.com/webapi" : "https://passport.duitku.com/webapi";
5402
- }
5403
- getApiBaseUrl() {
5404
- return this.sandbox ? "https://api-sandbox.duitku.com" : "https://api-prod.duitku.com";
5405
- }
5406
- /**
5407
- * Request helper generic dengan kalkulasi signature Duitku otomatis
5408
- */
5409
- async request(method, endpoint, body = {}, options) {
5410
- const baseUrl = options?.baseUrl === "api" ? this.getApiBaseUrl() : this.getPassportBaseUrl();
5411
- const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
5412
- const timestamp = Date.now().toString();
5413
- const headerSignature = sha256(this.merchantCode + timestamp + this.apiKey);
5414
- const headers = {
5415
- "Content-Type": "application/json",
5416
- "Accept": "application/json",
5417
- "x-duitku-signature": headerSignature,
5418
- "x-duitku-timestamp": timestamp,
5419
- "x-duitku-merchantcode": this.merchantCode,
5420
- ...options?.customHeaders
5421
- };
5422
- const fetchOptions = {
5423
- method,
5424
- headers
5425
- };
5426
- if (method === "POST" && body) {
5427
- fetchOptions.body = JSON.stringify(body);
5428
- }
5429
- const response = await fetch(url, fetchOptions);
5464
+ // src/providers/paypal/signature.ts
5465
+ function buildPaypalBasicAuth(clientId, clientSecret) {
5466
+ return Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
5467
+ }
5468
+ function verifyPaypalWebhookSimple(transmissionId, timestamp, webhookId, body, transmissionSig, certUrl) {
5469
+ return !!(transmissionId && timestamp && webhookId && transmissionSig && certUrl);
5470
+ }
5471
+ function serializePaypalParams(obj) {
5472
+ return Object.entries(obj).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
5473
+ }
5474
+
5475
+ // src/providers/paypal/provider.ts
5476
+ var PaypalProvider = class extends BasePaymentProvider {
5477
+ name = "paypal";
5478
+ getSandbox(config) {
5479
+ return config.sandbox !== false;
5480
+ }
5481
+ getBaseUrl(config) {
5482
+ return this.getSandbox(config) ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
5483
+ }
5484
+ /** OAuth2 Client Credentials dapatkan access token */
5485
+ async getAccessToken(config) {
5486
+ const clientId = config.clientKey || config.merchantCode || config.merchantId || "";
5487
+ const clientSecret = config.apiKey || config.secretKey || "";
5488
+ const auth = buildPaypalBasicAuth(clientId, clientSecret);
5489
+ const baseUrl = this.getBaseUrl(config);
5490
+ const response = await fetch(`${baseUrl}/v1/oauth2/token`, {
5491
+ method: "POST",
5492
+ headers: {
5493
+ "Authorization": `Basic ${auth}`,
5494
+ "Content-Type": "application/x-www-form-urlencoded"
5495
+ },
5496
+ body: "grant_type=client_credentials"
5497
+ });
5430
5498
  const text = await response.text();
5431
5499
  let data = null;
5432
5500
  try {
5433
5501
  data = JSON.parse(text);
5434
5502
  } catch (e) {
5435
5503
  }
5436
- if (!response.ok) {
5437
- throw new Error(data?.Message || data?.statusMessage || data?.responseMessage || `HTTP error! Status: ${response.status} - ${text}`);
5504
+ if (!response.ok || !data?.access_token) {
5505
+ throw new Error(data?.error_description || `Failed to get PayPal access token: ${response.status}`);
5438
5506
  }
5439
- return data || text;
5440
- }
5441
- // ─── TRANSACTIONS & PAYMENT METHODS ──────────────────────────────────────────
5442
- /**
5443
- * Cek status transaksi pembayaran berdasarkan merchant order ID
5444
- */
5445
- async checkTransaction(merchantOrderId) {
5446
- const { bodySignature } = getDuitkuStatusSignatures(
5447
- this.merchantCode,
5448
- merchantOrderId,
5449
- this.apiKey
5450
- );
5451
- return this.request(
5452
- "POST",
5453
- "/api/merchant/transactionStatus",
5454
- {
5455
- merchantCode: this.merchantCode,
5456
- merchantOrderId,
5457
- signature: bodySignature
5458
- },
5459
- { baseUrl: "api" }
5460
- );
5461
- }
5462
- /**
5463
- * Ambil daftar channel pembayaran aktif dan kalkulasi fee dinamis
5464
- */
5465
- async getPaymentMethods(amount = 1e4) {
5466
- const integerAmount = Math.round(amount);
5467
- const datetime = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
5468
- const signature = getDuitkuPaymentMethodsSignature(this.merchantCode, integerAmount, datetime, this.apiKey);
5469
- return this.request("POST", "/api/merchant/paymentmethod/getpaymentmethod", {
5470
- merchantcode: this.merchantCode,
5471
- amount: integerAmount,
5472
- datetime,
5473
- signature
5474
- });
5507
+ return data.access_token;
5475
5508
  }
5476
- // ─── DISBURSEMENT & BALANCE INQUIRY ──────────────────────────────────────────
5477
- /**
5478
- * Cek saldo merchant (Balance Inquiry)
5479
- */
5480
- async checkBalance() {
5481
- const timestamp = Date.now().toString();
5482
- const signature = sha256(this.merchantCode + timestamp + this.apiKey);
5509
+ async createInvoice(params, config) {
5510
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
5511
+ const currency = (params.currency || "USD").toUpperCase();
5512
+ let accessToken;
5483
5513
  try {
5484
- const data = await this.request(
5485
- "POST",
5486
- "/api/merchant/checkBalance",
5514
+ accessToken = await this.getAccessToken(config);
5515
+ } catch (e) {
5516
+ return { success: false, provider: "paypal", orderId, amount, error: e.message, rawResponse: null };
5517
+ }
5518
+ const baseUrl = this.getBaseUrl(config);
5519
+ const amountFormatted = (amount / 100).toFixed(2);
5520
+ const isDirect = !!params.paymentMethod;
5521
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5522
+ const cancelUrl = returnUrl || config.returnUrl || "https://example.com/payment/cancel";
5523
+ const body = {
5524
+ intent: isDirect ? "CAPTURE" : "CAPTURE",
5525
+ purchase_units: [
5487
5526
  {
5488
- merchantCode: this.merchantCode,
5489
- signature
5527
+ reference_id: orderId,
5528
+ description: productDetails,
5529
+ amount: {
5530
+ currency_code: currency,
5531
+ value: amountFormatted
5532
+ }
5533
+ }
5534
+ ],
5535
+ application_context: {
5536
+ return_url: successUrl,
5537
+ cancel_url: cancelUrl,
5538
+ brand_name: productDetails,
5539
+ user_action: "PAY_NOW"
5540
+ }
5541
+ };
5542
+ if (isDirect) {
5543
+ body.application_context.shipping_preference = "NO_SHIPPING";
5544
+ }
5545
+ if (callbackUrl || config.callbackUrl) {
5546
+ }
5547
+ try {
5548
+ const response = await fetch(`${baseUrl}/v2/checkout/orders`, {
5549
+ method: "POST",
5550
+ headers: {
5551
+ "Authorization": `Bearer ${accessToken}`,
5552
+ "Content-Type": "application/json",
5553
+ "PayPal-Request-Id": orderId,
5554
+ "Prefer": "return=representation"
5490
5555
  },
5491
- { baseUrl: "api" }
5492
- );
5556
+ body: JSON.stringify(body)
5557
+ });
5558
+ const text = await response.text();
5559
+ let data = null;
5560
+ try {
5561
+ data = JSON.parse(text);
5562
+ } catch (e) {
5563
+ }
5564
+ if (!response.ok || !data || data.name) {
5565
+ return {
5566
+ success: false,
5567
+ provider: "paypal",
5568
+ orderId,
5569
+ amount,
5570
+ rawResponse: data,
5571
+ error: data?.message || `HTTP error! Status: ${response.status}`
5572
+ };
5573
+ }
5574
+ const approveLink = data.links?.find((l) => l.rel === "approve" || l.rel === "payer-action");
5575
+ const paymentUrl = approveLink?.href || "";
5493
5576
  return {
5494
- success: data.responseCode === "00" || data.statusCode === "00",
5495
- balance: data.balance ? Number(data.balance) : void 0,
5577
+ success: true,
5578
+ provider: "paypal",
5579
+ orderId,
5580
+ amount,
5581
+ reference: data.id,
5582
+ paymentUrl,
5496
5583
  rawResponse: data
5497
5584
  };
5498
5585
  } catch (e) {
5499
- return {
5500
- success: false,
5501
- rawResponse: null,
5502
- error: e.message || "Failed to check Duitku merchant balance"
5503
- };
5586
+ return { success: false, provider: "paypal", orderId, amount, error: e.message, rawResponse: null };
5504
5587
  }
5505
5588
  }
5506
- /**
5507
- * Mengambil daftar bank yang didukung untuk transfer / penarikan dana
5508
- */
5509
- async listBanks() {
5510
- const timestamp = Date.now().toString();
5511
- const signature = sha256(this.merchantCode + timestamp + this.apiKey);
5512
- return this.request(
5513
- "POST",
5514
- "/api/disbursement/listBank",
5515
- {
5516
- merchantCode: this.merchantCode,
5517
- signature
5518
- },
5519
- { baseUrl: "api" }
5520
- );
5589
+ async verifyCallback(body, config) {
5590
+ const eventType = body?.event_type || body?.event_name || "";
5591
+ const resource = body?.resource || {};
5592
+ const orderId = resource.reference_id || resource.purchase_units?.[0]?.reference_id || resource.supplementary_data?.related_ids?.order_id || resource.id || "";
5593
+ const amount = Number(resource.amount?.value || resource.purchase_units?.[0]?.amount?.value || 0) * 100;
5594
+ const statusRaw = (resource.status || "").toUpperCase();
5595
+ const isPaid = statusRaw === "COMPLETED" || eventType === "PAYMENT.CAPTURE.COMPLETED";
5596
+ const isPending = statusRaw === "PENDING" || eventType === "PAYMENT.CAPTURE.PENDING";
5597
+ const isExpired = statusRaw === "EXPIRED" || eventType === "CHECKOUT.ORDER.EXPIRED";
5598
+ const isFailed = !isPaid && !isPending && !isExpired && (statusRaw === "DENIED" || statusRaw === "FAILED" || eventType.includes("FAILED") || eventType.includes("DENIED"));
5599
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5600
+ return {
5601
+ isValid: true,
5602
+ // Full cert-chain validation deferred to PayPal's verify API
5603
+ provider: "paypal",
5604
+ orderId: String(orderId),
5605
+ amount,
5606
+ status,
5607
+ isPaid,
5608
+ isPending,
5609
+ isFailed,
5610
+ isExpired,
5611
+ statusCode: eventType,
5612
+ rawPayload: body
5613
+ };
5521
5614
  }
5522
- /**
5523
- * Validasi nama pemilik rekening bank sebelum eksekusi transfer (Bank Account Inquiry)
5524
- */
5525
- async inquiryBankAccount(bankCode, bankAccount) {
5526
- const timestamp = Date.now().toString();
5527
- const signature = sha256(this.merchantCode + bankCode + bankAccount + this.apiKey);
5528
- return this.request(
5529
- "POST",
5530
- "/api/disbursement/inquiry",
5615
+ async getPaymentMethods(params, config) {
5616
+ const methods = [
5531
5617
  {
5532
- merchantCode: this.merchantCode,
5533
- bankCode,
5534
- bankAccount,
5535
- signature
5618
+ paymentMethod: "credit_card",
5619
+ code: "card",
5620
+ paymentName: "Credit / Debit Card (Visa, Mastercard, Amex)",
5621
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5622
+ totalFee: "3.49% + fixed fee",
5623
+ category: "Kartu Kredit"
5536
5624
  },
5537
- { baseUrl: "api" }
5538
- );
5539
- }
5540
- /**
5541
- * Eksekusi transfer dana / payout (Disbursement Transfer)
5542
- */
5543
- async disburse(params) {
5544
- const integerAmount = Math.round(params.amount);
5545
- const signature = sha256(
5546
- this.merchantCode + params.merchantOrderId + params.bankCode + params.bankAccount + integerAmount.toString() + this.apiKey
5547
- );
5548
- const payload = {
5549
- merchantCode: this.merchantCode,
5550
- merchantOrderId: params.merchantOrderId,
5551
- bankCode: params.bankCode,
5552
- bankAccount: params.bankAccount,
5553
- amount: integerAmount,
5554
- purpose: params.purpose,
5555
- senderName: params.senderName || "",
5556
- senderPhone: params.senderPhone || "",
5557
- callbackUrl: params.callbackUrl || "",
5558
- signature
5559
- };
5560
- return this.request("POST", "/api/disbursement/transfer", payload, { baseUrl: "api" });
5561
- }
5562
- /**
5563
- * Cek status disbursement berdasarkan merchant order ID
5564
- */
5565
- async checkDisbursementStatus(merchantOrderId) {
5566
- const signature = sha256(this.merchantCode + merchantOrderId + this.apiKey);
5567
- return this.request(
5568
- "POST",
5569
- "/api/disbursement/checkStatus",
5570
5625
  {
5571
- merchantCode: this.merchantCode,
5572
- merchantOrderId,
5573
- signature
5626
+ paymentMethod: "paypal",
5627
+ code: "paypal",
5628
+ paymentName: "PayPal Balance / PayPal Checkout",
5629
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5630
+ totalFee: "3.49% + fixed fee",
5631
+ category: "E-Wallet"
5574
5632
  },
5575
- { baseUrl: "api" }
5576
- );
5633
+ {
5634
+ paymentMethod: "paylater",
5635
+ code: "pay_later",
5636
+ paymentName: "PayPal Pay Later / Buy Now Pay Later",
5637
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5638
+ totalFee: "3.49% + fixed fee",
5639
+ category: "Paylater / Cicilan"
5640
+ }
5641
+ ];
5642
+ const categories = {};
5643
+ for (const item of methods) {
5644
+ if (!categories[item.category]) categories[item.category] = [];
5645
+ categories[item.category].push(item);
5646
+ }
5647
+ return { success: true, provider: "paypal", methods, categories, rawResponse: methods };
5577
5648
  }
5578
- };
5579
-
5580
- // src/clients/ipaymu.ts
5581
- var IpaymuClient = class {
5582
- va;
5583
- apiKey;
5584
- sandbox;
5585
- constructor(config) {
5649
+ async checkTransaction(params, config) {
5650
+ const { merchantOrderId } = params;
5651
+ let accessToken;
5652
+ try {
5653
+ accessToken = await this.getAccessToken(config);
5654
+ } catch (e) {
5655
+ return {
5656
+ success: false,
5657
+ provider: "paypal",
5658
+ orderId: merchantOrderId,
5659
+ reference: "",
5660
+ amount: 0,
5661
+ statusCode: "AUTH_ERROR",
5662
+ status: "failed",
5663
+ isPaid: false,
5664
+ isPending: false,
5665
+ isFailed: true,
5666
+ isExpired: false,
5667
+ statusMessage: e.message,
5668
+ error: e.message,
5669
+ rawResponse: null
5670
+ };
5671
+ }
5672
+ const baseUrl = this.getBaseUrl(config);
5673
+ try {
5674
+ const response = await fetch(`${baseUrl}/v2/checkout/orders/${encodeURIComponent(merchantOrderId)}`, {
5675
+ method: "GET",
5676
+ headers: {
5677
+ "Authorization": `Bearer ${accessToken}`,
5678
+ "Content-Type": "application/json"
5679
+ }
5680
+ });
5681
+ const text = await response.text();
5682
+ let data = null;
5683
+ try {
5684
+ data = JSON.parse(text);
5685
+ } catch (e) {
5686
+ }
5687
+ if (!response.ok || !data || data.name) {
5688
+ return {
5689
+ success: false,
5690
+ provider: "paypal",
5691
+ orderId: merchantOrderId,
5692
+ reference: "",
5693
+ amount: 0,
5694
+ statusCode: response.status.toString(),
5695
+ status: "failed",
5696
+ isPaid: false,
5697
+ isPending: false,
5698
+ isFailed: true,
5699
+ isExpired: false,
5700
+ statusMessage: data?.message || "HTTP Error",
5701
+ error: data?.message,
5702
+ rawResponse: data
5703
+ };
5704
+ }
5705
+ const statusRaw = (data.status || "").toUpperCase();
5706
+ const isPaid = statusRaw === "COMPLETED";
5707
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED" || statusRaw === "CREATED";
5708
+ const isExpired = statusRaw === "VOIDED";
5709
+ const isFailed = !isPaid && !isPending && !isExpired;
5710
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5711
+ const amountValue = Number(data.purchase_units?.[0]?.amount?.value || 0) * 100;
5712
+ return {
5713
+ success: true,
5714
+ provider: "paypal",
5715
+ orderId: data.purchase_units?.[0]?.reference_id || merchantOrderId,
5716
+ reference: data.id || merchantOrderId,
5717
+ amount: amountValue,
5718
+ statusCode: statusRaw,
5719
+ status,
5720
+ isPaid,
5721
+ isPending,
5722
+ isFailed,
5723
+ isExpired,
5724
+ statusMessage: statusRaw,
5725
+ transactionTime: data.create_time ? new Date(data.create_time) : void 0,
5726
+ rawResponse: data
5727
+ };
5728
+ } catch (e) {
5729
+ return {
5730
+ success: false,
5731
+ provider: "paypal",
5732
+ orderId: merchantOrderId,
5733
+ reference: "",
5734
+ amount: 0,
5735
+ statusCode: "ERROR",
5736
+ status: "failed",
5737
+ isPaid: false,
5738
+ isPending: false,
5739
+ isFailed: true,
5740
+ isExpired: false,
5741
+ statusMessage: e.message,
5742
+ error: e.message,
5743
+ rawResponse: null
5744
+ };
5745
+ }
5746
+ }
5747
+ };
5748
+
5749
+ // src/providers/adyen/signature.ts
5750
+ var import_crypto16 = require("crypto");
5751
+ function verifyAdyenWebhook(notificationItem, hmacKey) {
5752
+ if (!hmacKey || !notificationItem) return false;
5753
+ try {
5754
+ const amount = notificationItem.amount || {};
5755
+ const fields = [
5756
+ notificationItem.pspReference || "",
5757
+ notificationItem.originalReference || "",
5758
+ notificationItem.merchantAccountCode || "",
5759
+ notificationItem.merchantReference || "",
5760
+ String(amount.value || ""),
5761
+ amount.currency || "",
5762
+ notificationItem.eventCode || "",
5763
+ notificationItem.success || ""
5764
+ ];
5765
+ const signedData = fields.join(":");
5766
+ const keyBytes = Buffer.from(hmacKey, "hex");
5767
+ const expected = (0, import_crypto16.createHmac)("sha256", keyBytes).update(signedData, "utf8").digest("base64");
5768
+ const provided = notificationItem.additionalData?.hmacSignature || "";
5769
+ return safeCompare(expected, provided);
5770
+ } catch {
5771
+ return false;
5772
+ }
5773
+ }
5774
+
5775
+ // src/providers/adyen/provider.ts
5776
+ var AdyenProvider = class extends BasePaymentProvider {
5777
+ name = "adyen";
5778
+ getBaseUrl(config) {
5779
+ if (!config.sandbox) {
5780
+ const prefix = config.extra?.liveUrlPrefix || config.projectId || "";
5781
+ if (prefix) {
5782
+ return `https://${prefix}-checkout-live.adyenpayments.com/checkout`;
5783
+ }
5784
+ }
5785
+ return "https://checkout-test.adyen.com";
5786
+ }
5787
+ async createInvoice(params, config) {
5788
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
5789
+ const apiKey = config.apiKey || config.secretKey || "";
5790
+ const merchantAccount = config.merchantCode || config.merchantId || config.extra?.merchantAccount || "";
5791
+ const currency = (params.currency || "USD").toUpperCase();
5792
+ const baseUrl = this.getBaseUrl(config);
5793
+ const isDirect = !!params.paymentMethod;
5794
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5795
+ try {
5796
+ if (isDirect) {
5797
+ const url = `${baseUrl}/v68/payments`;
5798
+ const body = {
5799
+ merchantAccount,
5800
+ reference: orderId,
5801
+ amount: { value: amount, currency },
5802
+ returnUrl: successUrl,
5803
+ shopperEmail: customer?.email,
5804
+ shopperName: customer?.name ? { firstName: customer.name.split(" ")[0], lastName: customer.name.split(" ").slice(1).join(" ") || "-" } : void 0,
5805
+ shopperReference: customer?.email || orderId,
5806
+ additionalData: { allow3DS2: true },
5807
+ metadata: { order_id: orderId },
5808
+ ...params.providerParams
5809
+ };
5810
+ const response = await fetch(url, {
5811
+ method: "POST",
5812
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
5813
+ body: JSON.stringify(body)
5814
+ });
5815
+ const text = await response.text();
5816
+ let data = null;
5817
+ try {
5818
+ data = JSON.parse(text);
5819
+ } catch (e) {
5820
+ }
5821
+ if (!response.ok || !data || data.status >= 400) {
5822
+ return { success: false, provider: "adyen", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
5823
+ }
5824
+ const isPaid = data.resultCode === "Authorised";
5825
+ const isPending = data.resultCode === "Pending" || data.resultCode === "RedirectShopper" || data.resultCode === "IdentifyShopper" || data.resultCode === "ChallengeShopper";
5826
+ return {
5827
+ success: true,
5828
+ provider: "adyen",
5829
+ orderId,
5830
+ amount,
5831
+ reference: data.pspReference || data.merchantReference,
5832
+ paymentUrl: data.action?.url || data.redirect?.url || void 0,
5833
+ rawResponse: data
5834
+ };
5835
+ } else {
5836
+ const url = `${baseUrl}/v68/sessions`;
5837
+ const body = {
5838
+ merchantAccount,
5839
+ reference: orderId,
5840
+ amount: { value: amount, currency },
5841
+ returnUrl: successUrl,
5842
+ countryCode: config.extra?.countryCode || "US",
5843
+ shopperLocale: config.extra?.shopperLocale || "en-US",
5844
+ shopperEmail: customer?.email,
5845
+ shopperReference: customer?.email || orderId,
5846
+ metadata: { order_id: orderId },
5847
+ ...params.providerParams
5848
+ };
5849
+ const response = await fetch(url, {
5850
+ method: "POST",
5851
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
5852
+ body: JSON.stringify(body)
5853
+ });
5854
+ const text = await response.text();
5855
+ let data = null;
5856
+ try {
5857
+ data = JSON.parse(text);
5858
+ } catch (e) {
5859
+ }
5860
+ if (!response.ok || !data || data.status >= 400) {
5861
+ return { success: false, provider: "adyen", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
5862
+ }
5863
+ return {
5864
+ success: true,
5865
+ provider: "adyen",
5866
+ orderId,
5867
+ amount,
5868
+ reference: data.id,
5869
+ paymentUrl: data.url,
5870
+ paymentCode: data.sessionData,
5871
+ rawResponse: data
5872
+ };
5873
+ }
5874
+ } catch (e) {
5875
+ return { success: false, provider: "adyen", orderId, amount, error: e.message, rawResponse: null };
5876
+ }
5877
+ }
5878
+ async verifyCallback(body, config) {
5879
+ const hmacKey = config.extra?.hmacKey || config.secretKey || "";
5880
+ const notificationItems = body?.notificationItems || [body];
5881
+ const item = notificationItems[0]?.NotificationRequestItem || notificationItems[0] || body;
5882
+ const isValid = hmacKey ? verifyAdyenWebhook(item, hmacKey) : false;
5883
+ const eventCode = (item.eventCode || "").toUpperCase();
5884
+ const success = item.success === "true" || item.success === true;
5885
+ const orderId = item.merchantReference || item.pspReference || "";
5886
+ const amount = item.amount?.value ? Number(item.amount.value) : 0;
5887
+ const isPaid = eventCode === "AUTHORISATION" && success;
5888
+ const isPending = eventCode === "PENDING" || eventCode === "OFFER_CLOSED";
5889
+ const isExpired = eventCode === "EXPIRED" || eventCode === "CANCEL";
5890
+ const isFailed = !isPaid && !isPending && !isExpired && (!success || eventCode === "REFUSAL");
5891
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5892
+ return {
5893
+ isValid,
5894
+ provider: "adyen",
5895
+ orderId: String(orderId),
5896
+ amount,
5897
+ status,
5898
+ isPaid,
5899
+ isPending,
5900
+ isFailed,
5901
+ isExpired,
5902
+ statusCode: eventCode,
5903
+ rawPayload: body
5904
+ };
5905
+ }
5906
+ async getPaymentMethods(params, config) {
5907
+ const methods = [
5908
+ { paymentMethod: "credit_card", code: "scheme", paymentName: "Credit / Debit Card (Visa, Mastercard, Amex, JCB)", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "Interchange++", category: "Kartu Kredit" },
5909
+ { paymentMethod: "paypal", code: "paypal", paymentName: "PayPal", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "Variable", category: "E-Wallet" },
5910
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "Card network fee", category: "E-Wallet" },
5911
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "Card network fee", category: "E-Wallet" },
5912
+ { paymentMethod: "klarna", code: "klarna", paymentName: "Klarna Pay Later", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "Variable", category: "Paylater / Cicilan" },
5913
+ { paymentMethod: "sepa", code: "sepadirectdebit", paymentName: "SEPA Direct Debit", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "Fixed fee", category: "Virtual Account" },
5914
+ { paymentMethod: "qris", code: "qris", paymentName: "QRIS (Indonesia)", paymentImage: "https://www.adyen.com/dam/jcr:8c86eab1-a18c-4bdb-8f3f-0832b0c0e3d5/adyen-logo.svg", totalFee: "0.7%", category: "QRIS" }
5915
+ ];
5916
+ const categories = {};
5917
+ for (const item of methods) {
5918
+ if (!categories[item.category]) categories[item.category] = [];
5919
+ categories[item.category].push(item);
5920
+ }
5921
+ return { success: true, provider: "adyen", methods, categories, rawResponse: methods };
5922
+ }
5923
+ async checkTransaction(params, config) {
5924
+ const { merchantOrderId } = params;
5925
+ const apiKey = config.apiKey || config.secretKey || "";
5926
+ const merchantAccount = config.merchantCode || config.merchantId || "";
5927
+ const baseUrl = this.getBaseUrl(config);
5928
+ try {
5929
+ const response = await fetch(`${baseUrl}/v68/payments/${encodeURIComponent(merchantOrderId)}`, {
5930
+ method: "GET",
5931
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" }
5932
+ });
5933
+ const text = await response.text();
5934
+ let data = null;
5935
+ try {
5936
+ data = JSON.parse(text);
5937
+ } catch (e) {
5938
+ }
5939
+ if (!response.ok || !data) {
5940
+ return {
5941
+ success: false,
5942
+ provider: "adyen",
5943
+ orderId: merchantOrderId,
5944
+ reference: "",
5945
+ amount: 0,
5946
+ statusCode: response.status.toString(),
5947
+ status: "failed",
5948
+ isPaid: false,
5949
+ isPending: false,
5950
+ isFailed: true,
5951
+ isExpired: false,
5952
+ statusMessage: data?.message || "HTTP Error",
5953
+ error: data?.message,
5954
+ rawResponse: data
5955
+ };
5956
+ }
5957
+ const resultCode = (data.resultCode || data.status || "").toUpperCase();
5958
+ const isPaid = resultCode === "AUTHORISED" || resultCode === "SETTLED";
5959
+ const isPending = resultCode === "PENDING" || resultCode === "RECEIVED" || resultCode === "REDIRECTSHOPPER";
5960
+ const isExpired = resultCode === "EXPIRED" || resultCode === "CANCELLED";
5961
+ const isFailed = !isPaid && !isPending && !isExpired;
5962
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5963
+ return {
5964
+ success: true,
5965
+ provider: "adyen",
5966
+ orderId: data.merchantReference || merchantOrderId,
5967
+ reference: data.pspReference || merchantOrderId,
5968
+ amount: data.amount?.value ? Number(data.amount.value) : 0,
5969
+ statusCode: resultCode,
5970
+ status,
5971
+ isPaid,
5972
+ isPending,
5973
+ isFailed,
5974
+ isExpired,
5975
+ statusMessage: resultCode,
5976
+ rawResponse: data
5977
+ };
5978
+ } catch (e) {
5979
+ return {
5980
+ success: false,
5981
+ provider: "adyen",
5982
+ orderId: merchantOrderId,
5983
+ reference: "",
5984
+ amount: 0,
5985
+ statusCode: "ERROR",
5986
+ status: "failed",
5987
+ isPaid: false,
5988
+ isPending: false,
5989
+ isFailed: true,
5990
+ isExpired: false,
5991
+ statusMessage: e.message,
5992
+ error: e.message,
5993
+ rawResponse: null
5994
+ };
5995
+ }
5996
+ }
5997
+ };
5998
+
5999
+ // src/providers/checkoutcom/signature.ts
6000
+ var import_crypto18 = require("crypto");
6001
+ function verifyCheckoutComWebhook(body, signatureHeader, secret) {
6002
+ if (!secret || !signatureHeader || !body) return false;
6003
+ try {
6004
+ const expected = (0, import_crypto18.createHmac)("sha256", secret).update(body, "utf8").digest("hex");
6005
+ const provided = signatureHeader.replace(/^sha256=/, "");
6006
+ return safeCompare(expected, provided);
6007
+ } catch {
6008
+ return false;
6009
+ }
6010
+ }
6011
+
6012
+ // src/providers/checkoutcom/provider.ts
6013
+ var CheckoutComProvider = class extends BasePaymentProvider {
6014
+ name = "checkoutcom";
6015
+ getBaseUrl(config) {
6016
+ return config.sandbox !== false ? "https://api.sandbox.checkout.com" : "https://api.checkout.com";
6017
+ }
6018
+ async createInvoice(params, config) {
6019
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
6020
+ const secretKey = config.apiKey || config.secretKey || "";
6021
+ const currency = (params.currency || "USD").toUpperCase();
6022
+ const baseUrl = this.getBaseUrl(config);
6023
+ const isDirect = !!params.paymentMethod;
6024
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6025
+ try {
6026
+ if (isDirect) {
6027
+ const url = `${baseUrl}/payments`;
6028
+ const body = {
6029
+ amount,
6030
+ currency,
6031
+ reference: orderId,
6032
+ description: productDetails,
6033
+ customer: { email: customer?.email, name: customer?.name },
6034
+ success_url: successUrl,
6035
+ failure_url: successUrl,
6036
+ metadata: { order_id: orderId },
6037
+ ...params.providerParams
6038
+ };
6039
+ const response = await fetch(url, {
6040
+ method: "POST",
6041
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" },
6042
+ body: JSON.stringify(body)
6043
+ });
6044
+ const text = await response.text();
6045
+ let data = null;
6046
+ try {
6047
+ data = JSON.parse(text);
6048
+ } catch (e) {
6049
+ }
6050
+ if (!response.ok || !data || data.error_codes) {
6051
+ return { success: false, provider: "checkoutcom", orderId, amount, rawResponse: data, error: (data?.error_codes || []).join(", ") || `HTTP ${response.status}` };
6052
+ }
6053
+ return {
6054
+ success: true,
6055
+ provider: "checkoutcom",
6056
+ orderId,
6057
+ amount: data.amount || amount,
6058
+ reference: data.id,
6059
+ paymentUrl: data._links?.redirect?.href,
6060
+ rawResponse: data
6061
+ };
6062
+ } else {
6063
+ const url = `${baseUrl}/payment-links`;
6064
+ const body = {
6065
+ amount,
6066
+ currency,
6067
+ reference: orderId,
6068
+ description: productDetails,
6069
+ customer: { email: customer?.email, name: customer?.name },
6070
+ return_url: successUrl,
6071
+ metadata: { order_id: orderId },
6072
+ ...params.providerParams
6073
+ };
6074
+ const response = await fetch(url, {
6075
+ method: "POST",
6076
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" },
6077
+ body: JSON.stringify(body)
6078
+ });
6079
+ const text = await response.text();
6080
+ let data = null;
6081
+ try {
6082
+ data = JSON.parse(text);
6083
+ } catch (e) {
6084
+ }
6085
+ if (!response.ok || !data || data.error_codes) {
6086
+ return { success: false, provider: "checkoutcom", orderId, amount, rawResponse: data, error: (data?.error_codes || []).join(", ") || `HTTP ${response.status}` };
6087
+ }
6088
+ return {
6089
+ success: true,
6090
+ provider: "checkoutcom",
6091
+ orderId,
6092
+ amount,
6093
+ reference: data.id,
6094
+ paymentUrl: data._links?.redirect?.href || data.reference,
6095
+ rawResponse: data
6096
+ };
6097
+ }
6098
+ } catch (e) {
6099
+ return { success: false, provider: "checkoutcom", orderId, amount, error: e.message, rawResponse: null };
6100
+ }
6101
+ }
6102
+ async verifyCallback(body, config) {
6103
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
6104
+ const signatureHeader = config.extra?.signatureHeader || "";
6105
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6106
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6107
+ const isValid = signatureHeader ? verifyCheckoutComWebhook(rawBody, signatureHeader, webhookSecret) : false;
6108
+ const eventType = parsedBody?.type || "";
6109
+ const data = parsedBody?.data || parsedBody;
6110
+ const orderId = data?.reference || data?.metadata?.order_id || data?.id || "";
6111
+ const amount = Number(data?.amount || 0);
6112
+ const isPaid = eventType === "payment_approved" || eventType === "payment_captured" || data?.approved === true;
6113
+ const isPending = eventType === "payment_pending" || eventType === "payment_voided";
6114
+ const isExpired = eventType === "payment_expired";
6115
+ const isFailed = eventType === "payment_declined" || eventType === "payment_capture_declined";
6116
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6117
+ return {
6118
+ isValid,
6119
+ provider: "checkoutcom",
6120
+ orderId: String(orderId),
6121
+ amount,
6122
+ status,
6123
+ isPaid,
6124
+ isPending,
6125
+ isFailed,
6126
+ isExpired,
6127
+ statusCode: eventType,
6128
+ rawPayload: parsedBody
6129
+ };
6130
+ }
6131
+ async getPaymentMethods(params, config) {
6132
+ const methods = [
6133
+ { paymentMethod: "credit_card", code: "card", paymentName: "Credit / Debit Card (Visa, Mastercard, Amex)", paymentImage: "https://checkout.com/favicon.ico", totalFee: "1.5% + $0.25", category: "Kartu Kredit" },
6134
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6135
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6136
+ { paymentMethod: "paypal", code: "paypal", paymentName: "PayPal", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Variable", category: "E-Wallet" },
6137
+ { paymentMethod: "klarna", code: "klarna", paymentName: "Klarna Pay Later", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Variable", category: "Paylater / Cicilan" },
6138
+ { paymentMethod: "sofort", code: "sofort", paymentName: "Sofort / SEPA", paymentImage: "https://checkout.com/favicon.ico", totalFee: "0.8% + \u20AC0.25", category: "Virtual Account" }
6139
+ ];
6140
+ const categories = {};
6141
+ for (const item of methods) {
6142
+ if (!categories[item.category]) categories[item.category] = [];
6143
+ categories[item.category].push(item);
6144
+ }
6145
+ return { success: true, provider: "checkoutcom", methods, categories, rawResponse: methods };
6146
+ }
6147
+ async checkTransaction(params, config) {
6148
+ const { merchantOrderId } = params;
6149
+ const secretKey = config.apiKey || config.secretKey || "";
6150
+ const baseUrl = this.getBaseUrl(config);
6151
+ try {
6152
+ const response = await fetch(`${baseUrl}/payments/${encodeURIComponent(merchantOrderId)}`, {
6153
+ method: "GET",
6154
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" }
6155
+ });
6156
+ const text = await response.text();
6157
+ let data = null;
6158
+ try {
6159
+ data = JSON.parse(text);
6160
+ } catch (e) {
6161
+ }
6162
+ if (!response.ok || !data) {
6163
+ return {
6164
+ success: false,
6165
+ provider: "checkoutcom",
6166
+ orderId: merchantOrderId,
6167
+ reference: "",
6168
+ amount: 0,
6169
+ statusCode: response.status.toString(),
6170
+ status: "failed",
6171
+ isPaid: false,
6172
+ isPending: false,
6173
+ isFailed: true,
6174
+ isExpired: false,
6175
+ statusMessage: "HTTP Error",
6176
+ rawResponse: data
6177
+ };
6178
+ }
6179
+ const statusRaw = (data.status || "").toLowerCase();
6180
+ const isPaid = statusRaw === "authorized" || statusRaw === "captured";
6181
+ const isPending = statusRaw === "pending" || statusRaw === "card_verified";
6182
+ const isExpired = statusRaw === "expired" || statusRaw === "voided";
6183
+ const isFailed = statusRaw === "declined" || statusRaw === "failed";
6184
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6185
+ return {
6186
+ success: true,
6187
+ provider: "checkoutcom",
6188
+ orderId: data.reference || merchantOrderId,
6189
+ reference: data.id || merchantOrderId,
6190
+ amount: Number(data.amount || 0),
6191
+ statusCode: statusRaw,
6192
+ status,
6193
+ isPaid,
6194
+ isPending,
6195
+ isFailed,
6196
+ isExpired,
6197
+ statusMessage: statusRaw,
6198
+ paymentType: data.payment_type || "card",
6199
+ transactionTime: data.requested_on ? new Date(data.requested_on) : void 0,
6200
+ rawResponse: data
6201
+ };
6202
+ } catch (e) {
6203
+ return {
6204
+ success: false,
6205
+ provider: "checkoutcom",
6206
+ orderId: merchantOrderId,
6207
+ reference: "",
6208
+ amount: 0,
6209
+ statusCode: "ERROR",
6210
+ status: "failed",
6211
+ isPaid: false,
6212
+ isPending: false,
6213
+ isFailed: true,
6214
+ isExpired: false,
6215
+ statusMessage: e.message,
6216
+ error: e.message,
6217
+ rawResponse: null
6218
+ };
6219
+ }
6220
+ }
6221
+ };
6222
+
6223
+ // src/providers/razorpay/signature.ts
6224
+ var import_crypto20 = require("crypto");
6225
+ function verifyRazorpayWebhook(rawBody, signature, webhookSecret) {
6226
+ if (!webhookSecret || !signature || !rawBody) return false;
6227
+ try {
6228
+ const expected = (0, import_crypto20.createHmac)("sha256", webhookSecret).update(rawBody).digest("hex");
6229
+ return safeCompare(expected, signature);
6230
+ } catch {
6231
+ return false;
6232
+ }
6233
+ }
6234
+ function buildRazorpayBasicAuth(keyId, keySecret) {
6235
+ return Buffer.from(`${keyId}:${keySecret}`).toString("base64");
6236
+ }
6237
+
6238
+ // src/providers/razorpay/provider.ts
6239
+ var RazorpayProvider = class extends BasePaymentProvider {
6240
+ name = "razorpay";
6241
+ getBaseUrl() {
6242
+ return "https://api.razorpay.com/v1";
6243
+ }
6244
+ buildHeaders(config) {
6245
+ const keyId = config.clientKey || config.merchantCode || config.merchantId || "";
6246
+ const keySecret = config.apiKey || config.secretKey || "";
6247
+ return {
6248
+ "Authorization": `Basic ${buildRazorpayBasicAuth(keyId, keySecret)}`,
6249
+ "Content-Type": "application/json"
6250
+ };
6251
+ }
6252
+ async createInvoice(params, config) {
6253
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
6254
+ const currency = (params.currency || "INR").toUpperCase();
6255
+ const baseUrl = this.getBaseUrl();
6256
+ const headers = this.buildHeaders(config);
6257
+ const isDirect = !!params.paymentMethod;
6258
+ try {
6259
+ if (isDirect) {
6260
+ const body = {
6261
+ amount,
6262
+ currency,
6263
+ receipt: orderId,
6264
+ notes: { order_id: orderId, product: productDetails },
6265
+ ...params.providerParams
6266
+ };
6267
+ const response = await fetch(`${baseUrl}/orders`, {
6268
+ method: "POST",
6269
+ headers,
6270
+ body: JSON.stringify(body)
6271
+ });
6272
+ const text = await response.text();
6273
+ let data = null;
6274
+ try {
6275
+ data = JSON.parse(text);
6276
+ } catch (e) {
6277
+ }
6278
+ if (!response.ok || !data || data.error) {
6279
+ return { success: false, provider: "razorpay", orderId, amount, rawResponse: data, error: data?.error?.description || `HTTP ${response.status}` };
6280
+ }
6281
+ return {
6282
+ success: true,
6283
+ provider: "razorpay",
6284
+ orderId,
6285
+ amount: data.amount || amount,
6286
+ reference: data.id,
6287
+ paymentCode: data.id,
6288
+ rawResponse: data
6289
+ };
6290
+ } else {
6291
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6292
+ const body = {
6293
+ amount,
6294
+ currency,
6295
+ description: productDetails,
6296
+ reference_id: orderId,
6297
+ customer: { name: customer?.name, email: customer?.email, contact: customer?.phone || "" },
6298
+ notify: { sms: false, email: !!customer?.email },
6299
+ reminder_enable: false,
6300
+ callback_url: callbackUrl || config.callbackUrl || successUrl,
6301
+ callback_method: "get",
6302
+ notes: { order_id: orderId },
6303
+ ...params.providerParams
6304
+ };
6305
+ const response = await fetch(`${baseUrl}/payment_links`, {
6306
+ method: "POST",
6307
+ headers,
6308
+ body: JSON.stringify(body)
6309
+ });
6310
+ const text = await response.text();
6311
+ let data = null;
6312
+ try {
6313
+ data = JSON.parse(text);
6314
+ } catch (e) {
6315
+ }
6316
+ if (!response.ok || !data || data.error) {
6317
+ return { success: false, provider: "razorpay", orderId, amount, rawResponse: data, error: data?.error?.description || `HTTP ${response.status}` };
6318
+ }
6319
+ return {
6320
+ success: true,
6321
+ provider: "razorpay",
6322
+ orderId,
6323
+ amount: data.amount || amount,
6324
+ reference: data.id,
6325
+ paymentUrl: data.short_url,
6326
+ rawResponse: data
6327
+ };
6328
+ }
6329
+ } catch (e) {
6330
+ return { success: false, provider: "razorpay", orderId, amount, error: e.message, rawResponse: null };
6331
+ }
6332
+ }
6333
+ async verifyCallback(body, config) {
6334
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
6335
+ const signatureHeader = config.extra?.signatureHeader || "";
6336
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6337
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6338
+ const isValid = signatureHeader ? verifyRazorpayWebhook(rawBody, signatureHeader, webhookSecret) : false;
6339
+ const eventType = parsedBody?.event || "";
6340
+ const payload = parsedBody?.payload;
6341
+ const paymentEntity = payload?.payment?.entity || payload?.payment_link?.entity || parsedBody;
6342
+ const orderId = paymentEntity?.notes?.order_id || paymentEntity?.order_id || paymentEntity?.reference_id || paymentEntity?.id || "";
6343
+ const amount = Number(paymentEntity?.amount || 0);
6344
+ const statusRaw = (paymentEntity?.status || "").toLowerCase();
6345
+ const isPaid = eventType === "payment.captured" || eventType === "payment_link.paid" || statusRaw === "captured";
6346
+ const isPending = eventType === "payment.authorized" || statusRaw === "authorized" || statusRaw === "created";
6347
+ const isExpired = eventType === "payment_link.expired" || statusRaw === "expired";
6348
+ const isFailed = eventType === "payment.failed" || statusRaw === "failed";
6349
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6350
+ return {
6351
+ isValid,
6352
+ provider: "razorpay",
6353
+ orderId: String(orderId),
6354
+ amount,
6355
+ status,
6356
+ isPaid,
6357
+ isPending,
6358
+ isFailed,
6359
+ isExpired,
6360
+ statusCode: eventType || statusRaw,
6361
+ rawPayload: parsedBody
6362
+ };
6363
+ }
6364
+ async getPaymentMethods(params, config) {
6365
+ const methods = [
6366
+ { paymentMethod: "credit_card", code: "card", paymentName: "Credit / Debit Card", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "2% + GST", category: "Kartu Kredit" },
6367
+ { paymentMethod: "upi", code: "upi", paymentName: "UPI (GPay, PhonePe, Paytm)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Free", category: "QRIS" },
6368
+ { paymentMethod: "netbanking", code: "netbanking", paymentName: "Net Banking (50+ banks)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "\u20B910", category: "Virtual Account" },
6369
+ { paymentMethod: "wallet", code: "wallet", paymentName: "Wallets (Paytm, PhonePe, etc.)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Variable", category: "E-Wallet" },
6370
+ { paymentMethod: "emi", code: "emi", paymentName: "EMI (Card / Cardless)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Bank charge", category: "Paylater / Cicilan" }
6371
+ ];
6372
+ const categories = {};
6373
+ for (const item of methods) {
6374
+ if (!categories[item.category]) categories[item.category] = [];
6375
+ categories[item.category].push(item);
6376
+ }
6377
+ return { success: true, provider: "razorpay", methods, categories, rawResponse: methods };
6378
+ }
6379
+ async checkTransaction(params, config) {
6380
+ const { merchantOrderId } = params;
6381
+ const baseUrl = this.getBaseUrl();
6382
+ const headers = this.buildHeaders(config);
6383
+ try {
6384
+ const endpoint = merchantOrderId.startsWith("plink_") ? `/payment_links/${encodeURIComponent(merchantOrderId)}` : `/payments/${encodeURIComponent(merchantOrderId)}`;
6385
+ const response = await fetch(`${baseUrl}${endpoint}`, { method: "GET", headers });
6386
+ const text = await response.text();
6387
+ let data = null;
6388
+ try {
6389
+ data = JSON.parse(text);
6390
+ } catch (e) {
6391
+ }
6392
+ if (!response.ok || !data || data.error) {
6393
+ return {
6394
+ success: false,
6395
+ provider: "razorpay",
6396
+ orderId: merchantOrderId,
6397
+ reference: "",
6398
+ amount: 0,
6399
+ statusCode: response.status.toString(),
6400
+ status: "failed",
6401
+ isPaid: false,
6402
+ isPending: false,
6403
+ isFailed: true,
6404
+ isExpired: false,
6405
+ statusMessage: data?.error?.description || "HTTP Error",
6406
+ rawResponse: data
6407
+ };
6408
+ }
6409
+ const statusRaw = (data.status || "").toLowerCase();
6410
+ const isPaid = statusRaw === "captured" || statusRaw === "paid";
6411
+ const isPending = statusRaw === "authorized" || statusRaw === "created";
6412
+ const isExpired = statusRaw === "expired";
6413
+ const isFailed = statusRaw === "failed";
6414
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6415
+ return {
6416
+ success: true,
6417
+ provider: "razorpay",
6418
+ orderId: data.notes?.order_id || data.reference_id || merchantOrderId,
6419
+ reference: data.id || merchantOrderId,
6420
+ amount: Number(data.amount || 0),
6421
+ statusCode: statusRaw,
6422
+ status,
6423
+ isPaid,
6424
+ isPending,
6425
+ isFailed,
6426
+ isExpired,
6427
+ statusMessage: statusRaw,
6428
+ paymentType: data.method || "card",
6429
+ transactionTime: data.created_at ? new Date(data.created_at * 1e3) : void 0,
6430
+ rawResponse: data
6431
+ };
6432
+ } catch (e) {
6433
+ return {
6434
+ success: false,
6435
+ provider: "razorpay",
6436
+ orderId: merchantOrderId,
6437
+ reference: "",
6438
+ amount: 0,
6439
+ statusCode: "ERROR",
6440
+ status: "failed",
6441
+ isPaid: false,
6442
+ isPending: false,
6443
+ isFailed: true,
6444
+ isExpired: false,
6445
+ statusMessage: e.message,
6446
+ error: e.message,
6447
+ rawResponse: null
6448
+ };
6449
+ }
6450
+ }
6451
+ };
6452
+
6453
+ // src/providers/square/signature.ts
6454
+ var import_crypto22 = require("crypto");
6455
+ function verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) {
6456
+ if (!signatureKey || !signatureHeader || !rawBody) return false;
6457
+ try {
6458
+ const payload = notificationUrl + rawBody;
6459
+ const expected = (0, import_crypto22.createHmac)("sha256", signatureKey).update(payload).digest("base64");
6460
+ return safeCompare(expected, signatureHeader);
6461
+ } catch {
6462
+ return false;
6463
+ }
6464
+ }
6465
+
6466
+ // src/providers/square/provider.ts
6467
+ var SquareProvider = class extends BasePaymentProvider {
6468
+ name = "square";
6469
+ getBaseUrl(config) {
6470
+ return config.sandbox !== false ? "https://connect.squareupsandbox.com" : "https://connect.squareup.com";
6471
+ }
6472
+ buildHeaders(config) {
6473
+ return {
6474
+ "Authorization": `Bearer ${config.apiKey || config.secretKey || ""}`,
6475
+ "Content-Type": "application/json",
6476
+ "Square-Version": "2024-01-17"
6477
+ };
6478
+ }
6479
+ async createInvoice(params, config) {
6480
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
6481
+ const currency = (params.currency || "USD").toUpperCase();
6482
+ const locationId = config.extra?.locationId || config.projectId || "";
6483
+ const baseUrl = this.getBaseUrl(config);
6484
+ const headers = this.buildHeaders(config);
6485
+ const isDirect = !!params.paymentMethod;
6486
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6487
+ try {
6488
+ if (isDirect) {
6489
+ const sourceId = params.providerParams?.sourceId || params.providerParams?.nonce || "cnon:card-nonce-ok";
6490
+ const body = {
6491
+ idempotency_key: orderId,
6492
+ source_id: sourceId,
6493
+ amount_money: { amount, currency },
6494
+ reference_id: orderId,
6495
+ note: productDetails,
6496
+ buyer_email_address: customer?.email,
6497
+ ...params.providerParams
6498
+ };
6499
+ const response = await fetch(`${baseUrl}/v2/payments`, {
6500
+ method: "POST",
6501
+ headers,
6502
+ body: JSON.stringify(body)
6503
+ });
6504
+ const text = await response.text();
6505
+ let data = null;
6506
+ try {
6507
+ data = JSON.parse(text);
6508
+ } catch (e) {
6509
+ }
6510
+ if (!response.ok || !data || data.errors?.length) {
6511
+ return { success: false, provider: "square", orderId, amount, rawResponse: data, error: data?.errors?.[0]?.detail || `HTTP ${response.status}` };
6512
+ }
6513
+ const payment = data.payment || data;
6514
+ return {
6515
+ success: true,
6516
+ provider: "square",
6517
+ orderId,
6518
+ amount: payment.amount_money?.amount || amount,
6519
+ reference: payment.id,
6520
+ rawResponse: data
6521
+ };
6522
+ } else {
6523
+ const body = {
6524
+ idempotency_key: orderId,
6525
+ order: {
6526
+ location_id: locationId,
6527
+ reference_id: orderId,
6528
+ line_items: [
6529
+ {
6530
+ name: productDetails,
6531
+ quantity: "1",
6532
+ base_price_money: { amount, currency }
6533
+ }
6534
+ ]
6535
+ },
6536
+ checkout_options: {
6537
+ redirect_url: successUrl,
6538
+ ask_for_shipping_address: false
6539
+ },
6540
+ pre_populated_data: {
6541
+ buyer_email: customer?.email
6542
+ },
6543
+ ...params.providerParams
6544
+ };
6545
+ const response = await fetch(`${baseUrl}/v2/online-checkout/payment-links`, {
6546
+ method: "POST",
6547
+ headers,
6548
+ body: JSON.stringify(body)
6549
+ });
6550
+ const text = await response.text();
6551
+ let data = null;
6552
+ try {
6553
+ data = JSON.parse(text);
6554
+ } catch (e) {
6555
+ }
6556
+ if (!response.ok || !data || data.errors?.length) {
6557
+ return { success: false, provider: "square", orderId, amount, rawResponse: data, error: data?.errors?.[0]?.detail || `HTTP ${response.status}` };
6558
+ }
6559
+ const link = data.payment_link || data;
6560
+ return {
6561
+ success: true,
6562
+ provider: "square",
6563
+ orderId,
6564
+ amount,
6565
+ reference: link.id,
6566
+ paymentUrl: link.url,
6567
+ rawResponse: data
6568
+ };
6569
+ }
6570
+ } catch (e) {
6571
+ return { success: false, provider: "square", orderId, amount, error: e.message, rawResponse: null };
6572
+ }
6573
+ }
6574
+ async verifyCallback(body, config) {
6575
+ const signatureKey = config.extra?.webhookSignatureKey || config.secretKey || "";
6576
+ const signatureHeader = config.extra?.signatureHeader || "";
6577
+ const notificationUrl = config.callbackUrl || config.extra?.notificationUrl || "";
6578
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6579
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6580
+ const isValid = signatureHeader ? verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) : false;
6581
+ const eventType = parsedBody?.type || "";
6582
+ const data = parsedBody?.data?.object || parsedBody?.data || parsedBody;
6583
+ const payment = data?.payment || data;
6584
+ const orderId = payment?.reference_id || payment?.order_id || payment?.id || "";
6585
+ const amount = Number(payment?.amount_money?.amount || 0);
6586
+ const statusRaw = (payment?.status || "").toUpperCase();
6587
+ const isPaid = statusRaw === "COMPLETED" || eventType === "payment.completed";
6588
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED";
6589
+ const isFailed = statusRaw === "FAILED" || statusRaw === "CANCELED";
6590
+ const isExpired = eventType === "payment.expired";
6591
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6592
+ return {
6593
+ isValid,
6594
+ provider: "square",
6595
+ orderId: String(orderId),
6596
+ amount,
6597
+ status,
6598
+ isPaid,
6599
+ isPending,
6600
+ isFailed,
6601
+ isExpired,
6602
+ statusCode: eventType || statusRaw,
6603
+ rawPayload: parsedBody
6604
+ };
6605
+ }
6606
+ async getPaymentMethods(params, config) {
6607
+ const methods = [
6608
+ { paymentMethod: "credit_card", code: "card", paymentName: "Credit / Debit Card (Visa, Mastercard, Amex, JCB)", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "Kartu Kredit" },
6609
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6610
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6611
+ { paymentMethod: "cash_app", code: "cashapp", paymentName: "Cash App Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6612
+ { paymentMethod: "afterpay", code: "afterpay", paymentName: "Afterpay / Clearpay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "6% + $0.30", category: "Paylater / Cicilan" }
6613
+ ];
6614
+ const categories = {};
6615
+ for (const item of methods) {
6616
+ if (!categories[item.category]) categories[item.category] = [];
6617
+ categories[item.category].push(item);
6618
+ }
6619
+ return { success: true, provider: "square", methods, categories, rawResponse: methods };
6620
+ }
6621
+ async checkTransaction(params, config) {
6622
+ const { merchantOrderId } = params;
6623
+ const baseUrl = this.getBaseUrl(config);
6624
+ const headers = this.buildHeaders(config);
6625
+ try {
6626
+ const response = await fetch(`${baseUrl}/v2/payments/${encodeURIComponent(merchantOrderId)}`, {
6627
+ method: "GET",
6628
+ headers
6629
+ });
6630
+ const text = await response.text();
6631
+ let data = null;
6632
+ try {
6633
+ data = JSON.parse(text);
6634
+ } catch (e) {
6635
+ }
6636
+ if (!response.ok || !data || data.errors?.length) {
6637
+ return {
6638
+ success: false,
6639
+ provider: "square",
6640
+ orderId: merchantOrderId,
6641
+ reference: "",
6642
+ amount: 0,
6643
+ statusCode: response.status.toString(),
6644
+ status: "failed",
6645
+ isPaid: false,
6646
+ isPending: false,
6647
+ isFailed: true,
6648
+ isExpired: false,
6649
+ statusMessage: data?.errors?.[0]?.detail || "HTTP Error",
6650
+ rawResponse: data
6651
+ };
6652
+ }
6653
+ const payment = data.payment || data;
6654
+ const statusRaw = (payment.status || "").toUpperCase();
6655
+ const isPaid = statusRaw === "COMPLETED";
6656
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED";
6657
+ const isExpired = statusRaw === "CANCELED";
6658
+ const isFailed = statusRaw === "FAILED";
6659
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6660
+ return {
6661
+ success: true,
6662
+ provider: "square",
6663
+ orderId: payment.reference_id || merchantOrderId,
6664
+ reference: payment.id || merchantOrderId,
6665
+ amount: Number(payment.amount_money?.amount || 0),
6666
+ statusCode: statusRaw,
6667
+ status,
6668
+ isPaid,
6669
+ isPending,
6670
+ isFailed,
6671
+ isExpired,
6672
+ statusMessage: statusRaw,
6673
+ paymentType: payment.source_type || "card",
6674
+ transactionTime: payment.created_at ? new Date(payment.created_at) : void 0,
6675
+ rawResponse: data
6676
+ };
6677
+ } catch (e) {
6678
+ return {
6679
+ success: false,
6680
+ provider: "square",
6681
+ orderId: merchantOrderId,
6682
+ reference: "",
6683
+ amount: 0,
6684
+ statusCode: "ERROR",
6685
+ status: "failed",
6686
+ isPaid: false,
6687
+ isPending: false,
6688
+ isFailed: true,
6689
+ isExpired: false,
6690
+ statusMessage: e.message,
6691
+ error: e.message,
6692
+ rawResponse: null
6693
+ };
6694
+ }
6695
+ }
6696
+ };
6697
+
6698
+ // src/providers/payu/signature.ts
6699
+ var import_crypto24 = require("crypto");
6700
+ function verifyPayuWebhook(rawBody, signatureHeader, md5Key) {
6701
+ if (!md5Key || !signatureHeader || !rawBody) return false;
6702
+ try {
6703
+ const parts = {};
6704
+ for (const part of signatureHeader.split(";")) {
6705
+ const [k, v] = part.split("=");
6706
+ if (k && v) parts[k.trim()] = v.trim();
6707
+ }
6708
+ const providedSig = parts["signature"];
6709
+ const algorithm = (parts["algorithm"] || "MD5").toUpperCase();
6710
+ if (!providedSig) return false;
6711
+ if (algorithm === "MD5") {
6712
+ const expected = (0, import_crypto24.createHash)("md5").update(rawBody + md5Key).digest("hex");
6713
+ return safeCompare(expected, providedSig);
6714
+ } else if (algorithm === "SHA-256") {
6715
+ const expected = (0, import_crypto24.createHash)("sha256").update(rawBody + md5Key).digest("hex");
6716
+ return safeCompare(expected, providedSig);
6717
+ }
6718
+ return false;
6719
+ } catch {
6720
+ return false;
6721
+ }
6722
+ }
6723
+ function buildPayuBasicAuth(clientId, clientSecret) {
6724
+ return Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
6725
+ }
6726
+
6727
+ // src/providers/payu/provider.ts
6728
+ var PayuProvider = class extends BasePaymentProvider {
6729
+ name = "payu";
6730
+ getBaseUrl(config) {
6731
+ return config.sandbox !== false ? "https://secure.snd.payu.com" : "https://secure.payu.com";
6732
+ }
6733
+ /** OAuth2 Bearer Token untuk PayU */
6734
+ async getAccessToken(config) {
6735
+ const clientId = config.extra?.oauthClientId || config.clientKey || "";
6736
+ const clientSecret = config.extra?.oauthClientSecret || config.apiKey || config.secretKey || "";
6737
+ if (!clientId || !clientSecret) {
6738
+ return "";
6739
+ }
6740
+ const baseUrl = this.getBaseUrl(config);
6741
+ const response = await fetch(`${baseUrl}/pl/standard/user/oauth/authorize`, {
6742
+ method: "POST",
6743
+ headers: {
6744
+ "Authorization": `Basic ${buildPayuBasicAuth(clientId, clientSecret)}`,
6745
+ "Content-Type": "application/x-www-form-urlencoded"
6746
+ },
6747
+ body: "grant_type=client_credentials"
6748
+ });
6749
+ const text = await response.text();
6750
+ let data = null;
6751
+ try {
6752
+ data = JSON.parse(text);
6753
+ } catch (e) {
6754
+ }
6755
+ if (!response.ok || !data?.access_token) {
6756
+ throw new Error(data?.error_description || `Failed to get PayU access token: ${response.status}`);
6757
+ }
6758
+ return data.access_token;
6759
+ }
6760
+ async createInvoice(params, config) {
6761
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
6762
+ const currency = (params.currency || "PLN").toUpperCase();
6763
+ const posId = config.merchantCode || config.merchantId || config.extra?.posId || "";
6764
+ const baseUrl = this.getBaseUrl(config);
6765
+ let accessToken;
6766
+ try {
6767
+ accessToken = await this.getAccessToken(config);
6768
+ } catch (e) {
6769
+ return { success: false, provider: "payu", orderId, amount, error: e.message, rawResponse: null };
6770
+ }
6771
+ const isDirect = !!params.paymentMethod;
6772
+ const continueUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6773
+ const notifyUrl = callbackUrl || config.callbackUrl || "";
6774
+ const body = {
6775
+ notifyUrl,
6776
+ customerIp: params.providerParams?.customerIp || "127.0.0.1",
6777
+ merchantPosId: posId,
6778
+ description: productDetails,
6779
+ currencyCode: currency,
6780
+ totalAmount: amount.toString(),
6781
+ extOrderId: orderId,
6782
+ continueUrl,
6783
+ buyer: {
6784
+ email: customer?.email,
6785
+ firstName: customer?.name?.split(" ")[0],
6786
+ lastName: customer?.name?.split(" ").slice(1).join(" ") || "-",
6787
+ phone: customer?.phone,
6788
+ language: "en"
6789
+ },
6790
+ products: [
6791
+ { name: productDetails, unitPrice: amount.toString(), quantity: "1" }
6792
+ ],
6793
+ ...params.providerParams
6794
+ };
6795
+ if (isDirect && params.paymentMethod) {
6796
+ body.payMethods = {
6797
+ payMethod: {
6798
+ type: "PBL",
6799
+ value: params.paymentMethod
6800
+ // e.g. "blik", "c" (card), "ap" (Apple Pay)
6801
+ }
6802
+ };
6803
+ }
6804
+ try {
6805
+ const response = await fetch(`${baseUrl}/api/v2_1/orders`, {
6806
+ method: "POST",
6807
+ headers: {
6808
+ "Authorization": `Bearer ${accessToken}`,
6809
+ "Content-Type": "application/json"
6810
+ },
6811
+ body: JSON.stringify(body),
6812
+ redirect: "manual"
6813
+ // PayU responds with 302
6814
+ });
6815
+ const text = await response.text();
6816
+ let data = null;
6817
+ try {
6818
+ data = JSON.parse(text);
6819
+ } catch (e) {
6820
+ }
6821
+ if (response.status === 302 || response.headers.get("location")) {
6822
+ const location = response.headers.get("location") || "";
6823
+ return {
6824
+ success: true,
6825
+ provider: "payu",
6826
+ orderId,
6827
+ amount,
6828
+ reference: data?.orderId || orderId,
6829
+ paymentUrl: location,
6830
+ rawResponse: data
6831
+ };
6832
+ }
6833
+ if (!response.ok || !data || data.status?.statusCode === "ERROR") {
6834
+ return { success: false, provider: "payu", orderId, amount, rawResponse: data, error: data?.status?.statusDesc || `HTTP ${response.status}` };
6835
+ }
6836
+ return {
6837
+ success: true,
6838
+ provider: "payu",
6839
+ orderId,
6840
+ amount,
6841
+ reference: data.orderId || orderId,
6842
+ paymentUrl: data.redirectUri,
6843
+ rawResponse: data
6844
+ };
6845
+ } catch (e) {
6846
+ return { success: false, provider: "payu", orderId, amount, error: e.message, rawResponse: null };
6847
+ }
6848
+ }
6849
+ async verifyCallback(body, config) {
6850
+ const md5Key = config.extra?.md5Key || config.apiKey || config.secretKey || "";
6851
+ const signatureHeader = config.extra?.signatureHeader || "";
6852
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6853
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6854
+ const isValid = signatureHeader ? verifyPayuWebhook(rawBody, signatureHeader, md5Key) : false;
6855
+ const order = parsedBody?.order || parsedBody;
6856
+ const orderId = order.extOrderId || order.orderId || "";
6857
+ const amount = Number(order.totalAmount || 0);
6858
+ const statusRaw = (order.status || "").toUpperCase();
6859
+ const isPaid = statusRaw === "COMPLETED";
6860
+ const isPending = statusRaw === "PENDING" || statusRaw === "WAITING_FOR_CONFIRMATION";
6861
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REJECTED";
6862
+ const isExpired = false;
6863
+ const status = isPaid ? "paid" : isPending ? "pending" : "failed";
6864
+ return {
6865
+ isValid,
6866
+ provider: "payu",
6867
+ orderId: String(orderId),
6868
+ amount,
6869
+ status,
6870
+ isPaid,
6871
+ isPending,
6872
+ isFailed,
6873
+ isExpired,
6874
+ statusCode: statusRaw,
6875
+ rawPayload: parsedBody
6876
+ };
6877
+ }
6878
+ async getPaymentMethods(params, config) {
6879
+ const methods = [
6880
+ { paymentMethod: "credit_card", code: "c", paymentName: "Credit / Debit Card", paymentImage: "https://payu.com/favicon.ico", totalFee: "1.5%+", category: "Kartu Kredit" },
6881
+ { paymentMethod: "blik", code: "blik", paymentName: "BLIK (Poland)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Fixed fee", category: "E-Wallet" },
6882
+ { paymentMethod: "apple_pay", code: "ap", paymentName: "Apple Pay", paymentImage: "https://payu.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6883
+ { paymentMethod: "google_pay", code: "gp", paymentName: "Google Pay", paymentImage: "https://payu.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6884
+ { paymentMethod: "bank_transfer", code: "t", paymentName: "Online Bank Transfer (50+ banks)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Fixed fee", category: "Virtual Account" },
6885
+ { paymentMethod: "installment", code: "ai", paymentName: "Installments (PayU)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Bank rate", category: "Paylater / Cicilan" }
6886
+ ];
6887
+ const categories = {};
6888
+ for (const item of methods) {
6889
+ if (!categories[item.category]) categories[item.category] = [];
6890
+ categories[item.category].push(item);
6891
+ }
6892
+ return { success: true, provider: "payu", methods, categories, rawResponse: methods };
6893
+ }
6894
+ async checkTransaction(params, config) {
6895
+ const { merchantOrderId } = params;
6896
+ const baseUrl = this.getBaseUrl(config);
6897
+ let accessToken;
6898
+ try {
6899
+ accessToken = await this.getAccessToken(config);
6900
+ } catch (e) {
6901
+ return {
6902
+ success: false,
6903
+ provider: "payu",
6904
+ orderId: merchantOrderId,
6905
+ reference: "",
6906
+ amount: 0,
6907
+ statusCode: "AUTH_ERROR",
6908
+ status: "failed",
6909
+ isPaid: false,
6910
+ isPending: false,
6911
+ isFailed: true,
6912
+ isExpired: false,
6913
+ statusMessage: e.message,
6914
+ error: e.message,
6915
+ rawResponse: null
6916
+ };
6917
+ }
6918
+ try {
6919
+ const response = await fetch(`${baseUrl}/api/v2_1/orders/${encodeURIComponent(merchantOrderId)}`, {
6920
+ method: "GET",
6921
+ headers: { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json" }
6922
+ });
6923
+ const text = await response.text();
6924
+ let data = null;
6925
+ try {
6926
+ data = JSON.parse(text);
6927
+ } catch (e) {
6928
+ }
6929
+ if (!response.ok || !data) {
6930
+ return {
6931
+ success: false,
6932
+ provider: "payu",
6933
+ orderId: merchantOrderId,
6934
+ reference: "",
6935
+ amount: 0,
6936
+ statusCode: response.status.toString(),
6937
+ status: "failed",
6938
+ isPaid: false,
6939
+ isPending: false,
6940
+ isFailed: true,
6941
+ isExpired: false,
6942
+ statusMessage: "HTTP Error",
6943
+ rawResponse: data
6944
+ };
6945
+ }
6946
+ const order = data.orders?.[0] || data;
6947
+ const statusRaw = (order.status || "").toUpperCase();
6948
+ const isPaid = statusRaw === "COMPLETED";
6949
+ const isPending = statusRaw === "PENDING" || statusRaw === "WAITING_FOR_CONFIRMATION";
6950
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REJECTED";
6951
+ const isExpired = false;
6952
+ const status = isPaid ? "paid" : isPending ? "pending" : "failed";
6953
+ return {
6954
+ success: true,
6955
+ provider: "payu",
6956
+ orderId: order.extOrderId || merchantOrderId,
6957
+ reference: order.orderId || merchantOrderId,
6958
+ amount: Number(order.totalAmount || 0),
6959
+ statusCode: statusRaw,
6960
+ status,
6961
+ isPaid,
6962
+ isPending,
6963
+ isFailed,
6964
+ isExpired,
6965
+ statusMessage: statusRaw,
6966
+ transactionTime: order.orderCreateDate ? new Date(order.orderCreateDate) : void 0,
6967
+ rawResponse: data
6968
+ };
6969
+ } catch (e) {
6970
+ return {
6971
+ success: false,
6972
+ provider: "payu",
6973
+ orderId: merchantOrderId,
6974
+ reference: "",
6975
+ amount: 0,
6976
+ statusCode: "ERROR",
6977
+ status: "failed",
6978
+ isPaid: false,
6979
+ isPending: false,
6980
+ isFailed: true,
6981
+ isExpired: false,
6982
+ statusMessage: e.message,
6983
+ error: e.message,
6984
+ rawResponse: null
6985
+ };
6986
+ }
6987
+ }
6988
+ };
6989
+
6990
+ // src/providers/braintree/signature.ts
6991
+ var import_crypto26 = require("crypto");
6992
+ function verifyBraintreeWebhook(btSignature, btPayload, privateKey) {
6993
+ if (!privateKey || !btSignature || !btPayload) return false;
6994
+ try {
6995
+ const parts = btSignature.split("|");
6996
+ if (parts.length < 2) return false;
6997
+ const providedHmac = parts[1];
6998
+ const payload = Buffer.from(btPayload, "base64").toString("utf8");
6999
+ const secretHash = (0, import_crypto26.createHash)("sha1").update(privateKey).digest("hex");
7000
+ const expected = (0, import_crypto26.createHmac)("sha1", secretHash).update(payload).digest("hex");
7001
+ return safeCompare(expected, providedHmac);
7002
+ } catch {
7003
+ return false;
7004
+ }
7005
+ }
7006
+ function buildBraintreeBasicAuth(publicKey, privateKey) {
7007
+ return Buffer.from(`${publicKey}:${privateKey}`).toString("base64");
7008
+ }
7009
+
7010
+ // src/providers/braintree/provider.ts
7011
+ var BraintreeProvider = class extends BasePaymentProvider {
7012
+ name = "braintree";
7013
+ getBaseUrl(config) {
7014
+ const merchantId = config.merchantCode || config.merchantId || "";
7015
+ const base = config.sandbox !== false ? "https://api.sandbox.braintreegateway.com" : "https://api.braintreegateway.com";
7016
+ return `${base}/merchants/${merchantId}`;
7017
+ }
7018
+ buildHeaders(config) {
7019
+ const publicKey = config.clientKey || config.extra?.publicKey || "";
7020
+ const privateKey = config.apiKey || config.secretKey || "";
7021
+ return {
7022
+ "Authorization": `Basic ${buildBraintreeBasicAuth(publicKey, privateKey)}`,
7023
+ "Content-Type": "application/json",
7024
+ "Braintree-Version": "2019-01-01"
7025
+ };
7026
+ }
7027
+ async createInvoice(params, config) {
7028
+ const { orderId, amount, productDetails, customer } = params;
7029
+ const currency = (params.currency || "USD").toUpperCase();
7030
+ const baseUrl = this.getBaseUrl(config);
7031
+ const headers = this.buildHeaders(config);
7032
+ const isDirect = !!params.paymentMethod;
7033
+ try {
7034
+ if (isDirect) {
7035
+ const paymentMethodNonce = params.providerParams?.nonce || params.providerParams?.paymentMethodNonce || "fake-valid-nonce";
7036
+ const body = {
7037
+ transaction: {
7038
+ amount: (amount / 100).toFixed(2),
7039
+ payment_method_nonce: paymentMethodNonce,
7040
+ order_id: orderId,
7041
+ currency_iso_code: currency,
7042
+ options: { submit_for_settlement: true },
7043
+ customer: { first_name: customer?.name, email: customer?.email },
7044
+ custom_fields: { order_id: orderId },
7045
+ ...params.providerParams
7046
+ }
7047
+ };
7048
+ const response = await fetch(`${baseUrl}/transactions`, {
7049
+ method: "POST",
7050
+ headers,
7051
+ body: JSON.stringify(body)
7052
+ });
7053
+ const text = await response.text();
7054
+ let data = null;
7055
+ try {
7056
+ data = JSON.parse(text);
7057
+ } catch (e) {
7058
+ }
7059
+ if (!response.ok || data?.apiErrorResponse) {
7060
+ return { success: false, provider: "braintree", orderId, amount, rawResponse: data, error: data?.apiErrorResponse?.message || `HTTP ${response.status}` };
7061
+ }
7062
+ const tx = data?.transaction || data;
7063
+ const statusRaw = (tx.status || "").toLowerCase();
7064
+ return {
7065
+ success: statusRaw === "submitted_for_settlement" || statusRaw === "settling" || statusRaw === "settled",
7066
+ provider: "braintree",
7067
+ orderId,
7068
+ amount: Math.round(Number(tx.amount || amount / 100) * 100),
7069
+ reference: tx.id,
7070
+ rawResponse: data
7071
+ };
7072
+ } else {
7073
+ const body = { client_token: { customer_id: customer?.email || orderId } };
7074
+ const response = await fetch(`${baseUrl}/client_token`, {
7075
+ method: "POST",
7076
+ headers,
7077
+ body: JSON.stringify(body)
7078
+ });
7079
+ const text = await response.text();
7080
+ let data = null;
7081
+ try {
7082
+ data = JSON.parse(text);
7083
+ } catch (e) {
7084
+ }
7085
+ if (!response.ok || !data?.clientToken) {
7086
+ return { success: false, provider: "braintree", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
7087
+ }
7088
+ return {
7089
+ success: true,
7090
+ provider: "braintree",
7091
+ orderId,
7092
+ amount,
7093
+ reference: orderId,
7094
+ paymentCode: data.clientToken,
7095
+ // Frontend uses this token for Drop-in UI
7096
+ rawResponse: data
7097
+ };
7098
+ }
7099
+ } catch (e) {
7100
+ return { success: false, provider: "braintree", orderId, amount, error: e.message, rawResponse: null };
7101
+ }
7102
+ }
7103
+ async verifyCallback(body, config) {
7104
+ const privateKey = config.apiKey || config.secretKey || "";
7105
+ const btSignature = config.extra?.btSignature || "";
7106
+ const btPayload = config.extra?.btPayload || "";
7107
+ const isValid = btSignature && btPayload ? verifyBraintreeWebhook(btSignature, btPayload, privateKey) : false;
7108
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
7109
+ const subject = parsedBody?.subject || parsedBody;
7110
+ const transaction = subject?.transaction || subject?.disbursement || parsedBody;
7111
+ const kind = parsedBody?.kind || parsedBody?.event || "";
7112
+ const orderId = transaction?.orderId || transaction?.order_id || transaction?.id || "";
7113
+ const amount = Math.round(Number(transaction?.amount || 0) * 100);
7114
+ const statusRaw = (transaction?.status || "").toLowerCase();
7115
+ const isPaid = kind === "transaction_settled" || kind === "transaction_disbursed" || statusRaw === "settled";
7116
+ const isPending = kind === "transaction_settlement_declined" || statusRaw === "submitted_for_settlement" || statusRaw === "settling";
7117
+ const isFailed = kind === "transaction_failed" || statusRaw === "failed" || statusRaw === "voided";
7118
+ const isExpired = statusRaw === "expired";
7119
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7120
+ return {
7121
+ isValid,
7122
+ provider: "braintree",
7123
+ orderId: String(orderId),
7124
+ amount,
7125
+ status,
7126
+ isPaid,
7127
+ isPending,
7128
+ isFailed,
7129
+ isExpired,
7130
+ statusCode: kind || statusRaw,
7131
+ rawPayload: parsedBody
7132
+ };
7133
+ }
7134
+ async getPaymentMethods(params, config) {
7135
+ const methods = [
7136
+ { paymentMethod: "credit_card", code: "CreditCard", paymentName: "Credit / Debit Card (Drop-in UI)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "2.59% + $0.49", category: "Kartu Kredit" },
7137
+ { paymentMethod: "paypal", code: "PayPalAccount", paymentName: "PayPal (via Drop-in UI)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "3.49% + fixed", category: "E-Wallet" },
7138
+ { paymentMethod: "apple_pay", code: "ApplePayCard", paymentName: "Apple Pay", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "Card network fee", category: "E-Wallet" },
7139
+ { paymentMethod: "google_pay", code: "AndroidPayCard", paymentName: "Google Pay", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "Card network fee", category: "E-Wallet" },
7140
+ { paymentMethod: "venmo", code: "VenmoAccount", paymentName: "Venmo (US only)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "1.9% + $0.10", category: "E-Wallet" }
7141
+ ];
7142
+ const categories = {};
7143
+ for (const item of methods) {
7144
+ if (!categories[item.category]) categories[item.category] = [];
7145
+ categories[item.category].push(item);
7146
+ }
7147
+ return { success: true, provider: "braintree", methods, categories, rawResponse: methods };
7148
+ }
7149
+ async checkTransaction(params, config) {
7150
+ const { merchantOrderId } = params;
7151
+ const baseUrl = this.getBaseUrl(config);
7152
+ const headers = this.buildHeaders(config);
7153
+ try {
7154
+ const response = await fetch(`${baseUrl}/transactions/${encodeURIComponent(merchantOrderId)}`, {
7155
+ method: "GET",
7156
+ headers
7157
+ });
7158
+ const text = await response.text();
7159
+ let data = null;
7160
+ try {
7161
+ data = JSON.parse(text);
7162
+ } catch (e) {
7163
+ }
7164
+ if (!response.ok || !data) {
7165
+ return {
7166
+ success: false,
7167
+ provider: "braintree",
7168
+ orderId: merchantOrderId,
7169
+ reference: "",
7170
+ amount: 0,
7171
+ statusCode: response.status.toString(),
7172
+ status: "failed",
7173
+ isPaid: false,
7174
+ isPending: false,
7175
+ isFailed: true,
7176
+ isExpired: false,
7177
+ statusMessage: "HTTP Error",
7178
+ rawResponse: data
7179
+ };
7180
+ }
7181
+ const tx = data.transaction || data;
7182
+ const statusRaw = (tx.status || "").toLowerCase();
7183
+ const isPaid = statusRaw === "settled" || statusRaw === "settling";
7184
+ const isPending = statusRaw === "submitted_for_settlement" || statusRaw === "authorized";
7185
+ const isExpired = statusRaw === "expired";
7186
+ const isFailed = statusRaw === "failed" || statusRaw === "voided";
7187
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7188
+ return {
7189
+ success: true,
7190
+ provider: "braintree",
7191
+ orderId: tx.orderId || merchantOrderId,
7192
+ reference: tx.id || merchantOrderId,
7193
+ amount: Math.round(Number(tx.amount || 0) * 100),
7194
+ statusCode: statusRaw,
7195
+ status,
7196
+ isPaid,
7197
+ isPending,
7198
+ isFailed,
7199
+ isExpired,
7200
+ statusMessage: statusRaw,
7201
+ paymentType: tx.paymentInstrumentType || "card",
7202
+ transactionTime: tx.createdAt ? new Date(tx.createdAt) : void 0,
7203
+ rawResponse: data
7204
+ };
7205
+ } catch (e) {
7206
+ return {
7207
+ success: false,
7208
+ provider: "braintree",
7209
+ orderId: merchantOrderId,
7210
+ reference: "",
7211
+ amount: 0,
7212
+ statusCode: "ERROR",
7213
+ status: "failed",
7214
+ isPaid: false,
7215
+ isPending: false,
7216
+ isFailed: true,
7217
+ isExpired: false,
7218
+ statusMessage: e.message,
7219
+ error: e.message,
7220
+ rawResponse: null
7221
+ };
7222
+ }
7223
+ }
7224
+ };
7225
+
7226
+ // src/providers/twocheckout/signature.ts
7227
+ var import_crypto28 = require("crypto");
7228
+ function buildTwoCheckoutAuth(merchantCode, secretKey) {
7229
+ const date = Math.floor(Date.now() / 1e3).toString();
7230
+ const raw = merchantCode + date;
7231
+ const hmac = (0, import_crypto28.createHmac)("sha256", secretKey).update(raw).digest("hex");
7232
+ const header = `code="${merchantCode}" date="${date}" hash="${hmac}"`;
7233
+ return { header, date };
7234
+ }
7235
+ function verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, providedHash) {
7236
+ if (!secretWord || !providedHash) return false;
7237
+ try {
7238
+ const raw = secretWord + saleId + productId + invoiceId;
7239
+ const expected = (0, import_crypto28.createHash)("md5").update(raw).digest("hex");
7240
+ return safeCompare(expected, providedHash);
7241
+ } catch {
7242
+ return false;
7243
+ }
7244
+ }
7245
+
7246
+ // src/providers/twocheckout/provider.ts
7247
+ var TwoCheckoutProvider = class extends BasePaymentProvider {
7248
+ name = "twocheckout";
7249
+ getBaseUrl(config) {
7250
+ return config.sandbox !== false ? "https://api.sandbox.2checkout.com/rest" : "https://api.2checkout.com/rest";
7251
+ }
7252
+ buildHeaders(config) {
7253
+ const merchantCode = config.merchantCode || config.merchantId || "";
7254
+ const secretKey = config.apiKey || config.secretKey || "";
7255
+ const { header } = buildTwoCheckoutAuth(merchantCode, secretKey);
7256
+ return {
7257
+ "X-Avangate-Authentication": header,
7258
+ "Content-Type": "application/json",
7259
+ "Accept": "application/json"
7260
+ };
7261
+ }
7262
+ async createInvoice(params, config) {
7263
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
7264
+ const currency = (params.currency || "USD").toUpperCase();
7265
+ const baseUrl = this.getBaseUrl(config);
7266
+ const headers = this.buildHeaders(config);
7267
+ const isDirect = !!params.paymentMethod;
7268
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
7269
+ const body = {
7270
+ Currency: currency,
7271
+ Language: "en",
7272
+ Country: config.extra?.country || "US",
7273
+ CustomerIP: params.providerParams?.customerIp || "127.0.0.1",
7274
+ Source: "API",
7275
+ MerchantReference: orderId,
7276
+ Items: [
7277
+ {
7278
+ Name: productDetails,
7279
+ Quantity: 1,
7280
+ Price: { Amount: (amount / 100).toFixed(2), Type: "CUSTOM" },
7281
+ Type: "PRODUCT",
7282
+ IsDynamic: true,
7283
+ Tangible: false
7284
+ }
7285
+ ],
7286
+ BillingDetails: {
7287
+ FirstName: customer?.name?.split(" ")[0] || "Customer",
7288
+ LastName: customer?.name?.split(" ").slice(1).join(" ") || "Name",
7289
+ Email: customer?.email,
7290
+ Country: config.extra?.country || "US",
7291
+ Address1: config.extra?.address || "N/A",
7292
+ City: config.extra?.city || "N/A",
7293
+ State: config.extra?.state || "",
7294
+ Zip: config.extra?.zip || "00000"
7295
+ },
7296
+ ...params.providerParams
7297
+ };
7298
+ if (!isDirect) {
7299
+ body.PaymentDetails = { Type: "EES_TOKEN_PAYMENT", Currency: currency };
7300
+ } else {
7301
+ body.PaymentDetails = { Type: params.paymentMethod === "paypal" ? "PAYPAL" : "EES_TOKEN_PAYMENT", Currency: currency };
7302
+ }
7303
+ try {
7304
+ const response = await fetch(`${baseUrl}/6.0/orders`, {
7305
+ method: "POST",
7306
+ headers,
7307
+ body: JSON.stringify(body)
7308
+ });
7309
+ const text = await response.text();
7310
+ let data = null;
7311
+ try {
7312
+ data = JSON.parse(text);
7313
+ } catch (e) {
7314
+ }
7315
+ if (!response.ok || !data || data.error_code) {
7316
+ return { success: false, provider: "twocheckout", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
7317
+ }
7318
+ const paymentUrl = data.PaymentDetails?.PaymentMethod?.RedirectURL || data.PaymentDetails?.PaymentMethod?.Href || `${successUrl}?ref=${data.RefNo}`;
7319
+ return {
7320
+ success: true,
7321
+ provider: "twocheckout",
7322
+ orderId,
7323
+ amount,
7324
+ reference: data.RefNo || data.OrderNo?.toString(),
7325
+ paymentUrl,
7326
+ rawResponse: data
7327
+ };
7328
+ } catch (e) {
7329
+ return { success: false, provider: "twocheckout", orderId, amount, error: e.message, rawResponse: null };
7330
+ }
7331
+ }
7332
+ async verifyCallback(body, config) {
7333
+ const secretWord = config.extra?.secretWord || config.apiKey || "";
7334
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
7335
+ const saleId = parsedBody?.SALE_ID || parsedBody?.sale_id || "";
7336
+ const productId = parsedBody?.IPN_PID?.[0] || parsedBody?.product_id || "";
7337
+ const invoiceId = parsedBody?.IPN_PNAME?.[0] || parsedBody?.invoice_id || "";
7338
+ const providedHash = parsedBody?.HASH || parsedBody?.hash || "";
7339
+ const isValid = secretWord ? verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, providedHash) : false;
7340
+ const orderId = parsedBody?.REFNOEXT || parsedBody?.ext_ref_no || parsedBody?.SALE_ID || "";
7341
+ const amount = Math.round(Number(parsedBody?.IPN_TOTAL_GENERAL || parsedBody?.total || 0) * 100);
7342
+ const statusRaw = (parsedBody?.ORDERSTATUS || parsedBody?.order_status || "").toUpperCase();
7343
+ const isPaid = statusRaw === "COMPLETE" || statusRaw === "COMPLETE_MANUAL";
7344
+ const isPending = statusRaw === "PENDING" || statusRaw === "PURCHASE_PENDING";
7345
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REFUND" || statusRaw === "FRAUD";
7346
+ const isExpired = statusRaw === "EXPIRED";
7347
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7348
+ return {
7349
+ isValid,
7350
+ provider: "twocheckout",
7351
+ orderId: String(orderId),
7352
+ amount,
7353
+ status,
7354
+ isPaid,
7355
+ isPending,
7356
+ isFailed,
7357
+ isExpired,
7358
+ statusCode: statusRaw,
7359
+ rawPayload: parsedBody
7360
+ };
7361
+ }
7362
+ async getPaymentMethods(params, config) {
7363
+ const methods = [
7364
+ { paymentMethod: "credit_card", code: "EES_TOKEN_PAYMENT", paymentName: "Credit / Debit Card (Visa, Mastercard, Amex)", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "3.5% + $0.35", category: "Kartu Kredit" },
7365
+ { paymentMethod: "paypal", code: "PAYPAL", paymentName: "PayPal", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "3.5% + $0.35", category: "E-Wallet" },
7366
+ { paymentMethod: "wire_transfer", code: "WIRE", paymentName: "Wire Transfer / Bank Transfer", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "Fixed fee", category: "Virtual Account" },
7367
+ { paymentMethod: "paylater", code: "PAY_LATER", paymentName: "Buy Now Pay Later (Klarna)", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "Variable", category: "Paylater / Cicilan" }
7368
+ ];
7369
+ const categories = {};
7370
+ for (const item of methods) {
7371
+ if (!categories[item.category]) categories[item.category] = [];
7372
+ categories[item.category].push(item);
7373
+ }
7374
+ return { success: true, provider: "twocheckout", methods, categories, rawResponse: methods };
7375
+ }
7376
+ async checkTransaction(params, config) {
7377
+ const { merchantOrderId } = params;
7378
+ const baseUrl = this.getBaseUrl(config);
7379
+ const headers = this.buildHeaders(config);
7380
+ try {
7381
+ const response = await fetch(`${baseUrl}/6.0/orders/${encodeURIComponent(merchantOrderId)}`, {
7382
+ method: "GET",
7383
+ headers
7384
+ });
7385
+ const text = await response.text();
7386
+ let data = null;
7387
+ try {
7388
+ data = JSON.parse(text);
7389
+ } catch (e) {
7390
+ }
7391
+ if (!response.ok || !data || data.error_code) {
7392
+ return {
7393
+ success: false,
7394
+ provider: "twocheckout",
7395
+ orderId: merchantOrderId,
7396
+ reference: "",
7397
+ amount: 0,
7398
+ statusCode: response.status.toString(),
7399
+ status: "failed",
7400
+ isPaid: false,
7401
+ isPending: false,
7402
+ isFailed: true,
7403
+ isExpired: false,
7404
+ statusMessage: data?.message || "HTTP Error",
7405
+ rawResponse: data
7406
+ };
7407
+ }
7408
+ const statusRaw = (data.Status || "").toUpperCase();
7409
+ const isPaid = statusRaw === "COMPLETE";
7410
+ const isPending = statusRaw === "PENDING" || statusRaw === "PURCHASE_PENDING";
7411
+ const isExpired = statusRaw === "EXPIRED";
7412
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REFUND";
7413
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7414
+ return {
7415
+ success: true,
7416
+ provider: "twocheckout",
7417
+ orderId: data.ExternalReference || merchantOrderId,
7418
+ reference: data.RefNo?.toString() || merchantOrderId,
7419
+ amount: Math.round(Number(data.GrossAmount || 0) * 100),
7420
+ statusCode: statusRaw,
7421
+ status,
7422
+ isPaid,
7423
+ isPending,
7424
+ isFailed,
7425
+ isExpired,
7426
+ statusMessage: statusRaw,
7427
+ transactionTime: data.OrderDate ? new Date(data.OrderDate) : void 0,
7428
+ rawResponse: data
7429
+ };
7430
+ } catch (e) {
7431
+ return {
7432
+ success: false,
7433
+ provider: "twocheckout",
7434
+ orderId: merchantOrderId,
7435
+ reference: "",
7436
+ amount: 0,
7437
+ statusCode: "ERROR",
7438
+ status: "failed",
7439
+ isPaid: false,
7440
+ isPending: false,
7441
+ isFailed: true,
7442
+ isExpired: false,
7443
+ statusMessage: e.message,
7444
+ error: e.message,
7445
+ rawResponse: null
7446
+ };
7447
+ }
7448
+ }
7449
+ };
7450
+
7451
+ // src/clients/duitku.ts
7452
+ var DuitkuClient = class {
7453
+ merchantCode;
7454
+ apiKey;
7455
+ sandbox;
7456
+ constructor(config) {
7457
+ this.merchantCode = config.merchantCode || "";
7458
+ this.apiKey = config.apiKey || config.serverKey || "";
7459
+ this.sandbox = !!config.sandbox;
7460
+ }
7461
+ getPassportBaseUrl() {
7462
+ return this.sandbox ? "https://sandbox.duitku.com/webapi" : "https://passport.duitku.com/webapi";
7463
+ }
7464
+ getApiBaseUrl() {
7465
+ return this.sandbox ? "https://api-sandbox.duitku.com" : "https://api-prod.duitku.com";
7466
+ }
7467
+ /**
7468
+ * Request helper generic dengan kalkulasi signature Duitku otomatis
7469
+ */
7470
+ async request(method, endpoint, body = {}, options) {
7471
+ const baseUrl = options?.baseUrl === "api" ? this.getApiBaseUrl() : this.getPassportBaseUrl();
7472
+ const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
7473
+ const timestamp = Date.now().toString();
7474
+ const headerSignature = sha256(this.merchantCode + timestamp + this.apiKey);
7475
+ const headers = {
7476
+ "Content-Type": "application/json",
7477
+ "Accept": "application/json",
7478
+ "x-duitku-signature": headerSignature,
7479
+ "x-duitku-timestamp": timestamp,
7480
+ "x-duitku-merchantcode": this.merchantCode,
7481
+ ...options?.customHeaders
7482
+ };
7483
+ const fetchOptions = {
7484
+ method,
7485
+ headers
7486
+ };
7487
+ if (method === "POST" && body) {
7488
+ fetchOptions.body = JSON.stringify(body);
7489
+ }
7490
+ const response = await fetch(url, fetchOptions);
7491
+ const text = await response.text();
7492
+ let data = null;
7493
+ try {
7494
+ data = JSON.parse(text);
7495
+ } catch (e) {
7496
+ }
7497
+ if (!response.ok) {
7498
+ throw new Error(data?.Message || data?.statusMessage || data?.responseMessage || `HTTP error! Status: ${response.status} - ${text}`);
7499
+ }
7500
+ return data || text;
7501
+ }
7502
+ // ─── TRANSACTIONS & PAYMENT METHODS ──────────────────────────────────────────
7503
+ /**
7504
+ * Cek status transaksi pembayaran berdasarkan merchant order ID
7505
+ */
7506
+ async checkTransaction(merchantOrderId) {
7507
+ const { bodySignature } = getDuitkuStatusSignatures(
7508
+ this.merchantCode,
7509
+ merchantOrderId,
7510
+ this.apiKey
7511
+ );
7512
+ return this.request(
7513
+ "POST",
7514
+ "/api/merchant/transactionStatus",
7515
+ {
7516
+ merchantCode: this.merchantCode,
7517
+ merchantOrderId,
7518
+ signature: bodySignature
7519
+ },
7520
+ { baseUrl: "api" }
7521
+ );
7522
+ }
7523
+ /**
7524
+ * Ambil daftar channel pembayaran aktif dan kalkulasi fee dinamis
7525
+ */
7526
+ async getPaymentMethods(amount = 1e4) {
7527
+ const integerAmount = Math.round(amount);
7528
+ const datetime = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
7529
+ const signature = getDuitkuPaymentMethodsSignature(this.merchantCode, integerAmount, datetime, this.apiKey);
7530
+ return this.request("POST", "/api/merchant/paymentmethod/getpaymentmethod", {
7531
+ merchantcode: this.merchantCode,
7532
+ amount: integerAmount,
7533
+ datetime,
7534
+ signature
7535
+ });
7536
+ }
7537
+ // ─── DISBURSEMENT & BALANCE INQUIRY ──────────────────────────────────────────
7538
+ /**
7539
+ * Cek saldo merchant (Balance Inquiry)
7540
+ */
7541
+ async checkBalance() {
7542
+ const timestamp = Date.now().toString();
7543
+ const signature = sha256(this.merchantCode + timestamp + this.apiKey);
7544
+ try {
7545
+ const data = await this.request(
7546
+ "POST",
7547
+ "/api/merchant/checkBalance",
7548
+ {
7549
+ merchantCode: this.merchantCode,
7550
+ signature
7551
+ },
7552
+ { baseUrl: "api" }
7553
+ );
7554
+ return {
7555
+ success: data.responseCode === "00" || data.statusCode === "00",
7556
+ balance: data.balance ? Number(data.balance) : void 0,
7557
+ rawResponse: data
7558
+ };
7559
+ } catch (e) {
7560
+ return {
7561
+ success: false,
7562
+ rawResponse: null,
7563
+ error: e.message || "Failed to check Duitku merchant balance"
7564
+ };
7565
+ }
7566
+ }
7567
+ /**
7568
+ * Mengambil daftar bank yang didukung untuk transfer / penarikan dana
7569
+ */
7570
+ async listBanks() {
7571
+ const timestamp = Date.now().toString();
7572
+ const signature = sha256(this.merchantCode + timestamp + this.apiKey);
7573
+ return this.request(
7574
+ "POST",
7575
+ "/api/disbursement/listBank",
7576
+ {
7577
+ merchantCode: this.merchantCode,
7578
+ signature
7579
+ },
7580
+ { baseUrl: "api" }
7581
+ );
7582
+ }
7583
+ /**
7584
+ * Validasi nama pemilik rekening bank sebelum eksekusi transfer (Bank Account Inquiry)
7585
+ */
7586
+ async inquiryBankAccount(bankCode, bankAccount) {
7587
+ const timestamp = Date.now().toString();
7588
+ const signature = sha256(this.merchantCode + bankCode + bankAccount + this.apiKey);
7589
+ return this.request(
7590
+ "POST",
7591
+ "/api/disbursement/inquiry",
7592
+ {
7593
+ merchantCode: this.merchantCode,
7594
+ bankCode,
7595
+ bankAccount,
7596
+ signature
7597
+ },
7598
+ { baseUrl: "api" }
7599
+ );
7600
+ }
7601
+ /**
7602
+ * Eksekusi transfer dana / payout (Disbursement Transfer)
7603
+ */
7604
+ async disburse(params) {
7605
+ const integerAmount = Math.round(params.amount);
7606
+ const signature = sha256(
7607
+ this.merchantCode + params.merchantOrderId + params.bankCode + params.bankAccount + integerAmount.toString() + this.apiKey
7608
+ );
7609
+ const payload = {
7610
+ merchantCode: this.merchantCode,
7611
+ merchantOrderId: params.merchantOrderId,
7612
+ bankCode: params.bankCode,
7613
+ bankAccount: params.bankAccount,
7614
+ amount: integerAmount,
7615
+ purpose: params.purpose,
7616
+ senderName: params.senderName || "",
7617
+ senderPhone: params.senderPhone || "",
7618
+ callbackUrl: params.callbackUrl || "",
7619
+ signature
7620
+ };
7621
+ return this.request("POST", "/api/disbursement/transfer", payload, { baseUrl: "api" });
7622
+ }
7623
+ /**
7624
+ * Cek status disbursement berdasarkan merchant order ID
7625
+ */
7626
+ async checkDisbursementStatus(merchantOrderId) {
7627
+ const signature = sha256(this.merchantCode + merchantOrderId + this.apiKey);
7628
+ return this.request(
7629
+ "POST",
7630
+ "/api/disbursement/checkStatus",
7631
+ {
7632
+ merchantCode: this.merchantCode,
7633
+ merchantOrderId,
7634
+ signature
7635
+ },
7636
+ { baseUrl: "api" }
7637
+ );
7638
+ }
7639
+ };
7640
+
7641
+ // src/clients/ipaymu.ts
7642
+ var IpaymuClient = class {
7643
+ va;
7644
+ apiKey;
7645
+ sandbox;
7646
+ constructor(config) {
5586
7647
  this.va = config.merchantCode || config.merchantId || "";
5587
7648
  this.apiKey = config.apiKey || config.serverKey || "";
5588
7649
  this.sandbox = !!config.sandbox;
@@ -6152,6 +8213,533 @@ var StripeClient = class {
6152
8213
  }
6153
8214
  };
6154
8215
 
8216
+ // src/clients/paypal.ts
8217
+ var PaypalClient = class {
8218
+ config;
8219
+ constructor(config) {
8220
+ this.config = config;
8221
+ }
8222
+ getBaseUrl() {
8223
+ return this.config.sandbox !== false ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
8224
+ }
8225
+ async getAccessToken() {
8226
+ const clientId = this.config.clientKey || this.config.merchantCode || this.config.merchantId || "";
8227
+ const clientSecret = this.config.apiKey || this.config.secretKey || "";
8228
+ const auth = buildPaypalBasicAuth(clientId, clientSecret);
8229
+ const response = await fetch(`${this.getBaseUrl()}/v1/oauth2/token`, {
8230
+ method: "POST",
8231
+ headers: { "Authorization": `Basic ${auth}`, "Content-Type": "application/x-www-form-urlencoded" },
8232
+ body: "grant_type=client_credentials"
8233
+ });
8234
+ const data = await response.json();
8235
+ if (!data?.access_token) throw new Error(data?.error_description || "Failed to get PayPal access token");
8236
+ return data.access_token;
8237
+ }
8238
+ /** Ambil detail order PayPal berdasarkan Order ID */
8239
+ async getOrder(orderId) {
8240
+ const token = await this.getAccessToken();
8241
+ const response = await fetch(`${this.getBaseUrl()}/v2/checkout/orders/${orderId}`, {
8242
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8243
+ });
8244
+ return response.json();
8245
+ }
8246
+ /** Capture order PayPal (mengeksekusi pembayaran yang sudah diapprove buyer) */
8247
+ async captureOrder(orderId) {
8248
+ const token = await this.getAccessToken();
8249
+ const response = await fetch(`${this.getBaseUrl()}/v2/checkout/orders/${orderId}/capture`, {
8250
+ method: "POST",
8251
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8252
+ body: "{}"
8253
+ });
8254
+ return response.json();
8255
+ }
8256
+ /** Refund capture PayPal */
8257
+ async refundCapture(captureId, amount, currency) {
8258
+ const token = await this.getAccessToken();
8259
+ const body = {};
8260
+ if (amount && currency) {
8261
+ body.amount = { value: (amount / 100).toFixed(2), currency_code: currency };
8262
+ body.note_to_payer = "Refund";
8263
+ }
8264
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/captures/${captureId}/refund`, {
8265
+ method: "POST",
8266
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8267
+ body: JSON.stringify(body)
8268
+ });
8269
+ return response.json();
8270
+ }
8271
+ /** Cek saldo akun PayPal merchant (hanya tersedia di account via Seller REST API) */
8272
+ async checkBalance() {
8273
+ const token = await this.getAccessToken();
8274
+ const response = await fetch(`${this.getBaseUrl()}/v1/reporting/balances`, {
8275
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8276
+ });
8277
+ return response.json();
8278
+ }
8279
+ /** Verifikasi webhook via PayPal Webhook Verification API */
8280
+ async verifyWebhookSignature(webhookId, body, headers) {
8281
+ const token = await this.getAccessToken();
8282
+ const verifyBody = {
8283
+ auth_algo: headers["paypal-auth-algo"],
8284
+ cert_url: headers["paypal-cert-url"],
8285
+ transmission_id: headers["paypal-transmission-id"],
8286
+ transmission_sig: headers["paypal-transmission-sig"],
8287
+ transmission_time: headers["paypal-transmission-time"],
8288
+ webhook_id: webhookId,
8289
+ webhook_event: typeof body === "string" ? JSON.parse(body) : body
8290
+ };
8291
+ const response = await fetch(`${this.getBaseUrl()}/v1/notifications/verify-webhook-signature`, {
8292
+ method: "POST",
8293
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8294
+ body: JSON.stringify(verifyBody)
8295
+ });
8296
+ const data = await response.json();
8297
+ return data?.verification_status === "SUCCESS";
8298
+ }
8299
+ };
8300
+
8301
+ // src/clients/adyen.ts
8302
+ var AdyenClient = class {
8303
+ config;
8304
+ constructor(config) {
8305
+ this.config = config;
8306
+ }
8307
+ getBaseUrl() {
8308
+ if (this.config.sandbox === false) {
8309
+ const prefix = this.config.extra?.liveUrlPrefix || this.config.projectId || "";
8310
+ if (prefix) return `https://${prefix}-checkout-live.adyenpayments.com/checkout`;
8311
+ }
8312
+ return "https://checkout-test.adyen.com";
8313
+ }
8314
+ buildHeaders() {
8315
+ return {
8316
+ "X-API-Key": this.config.apiKey || this.config.secretKey || "",
8317
+ "Content-Type": "application/json"
8318
+ };
8319
+ }
8320
+ /** Ambil detail payment berdasarkan PSP Reference */
8321
+ async getPaymentDetails(pspReference) {
8322
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}`, {
8323
+ method: "GET",
8324
+ headers: this.buildHeaders()
8325
+ });
8326
+ return response.json();
8327
+ }
8328
+ /** Batalkan payment (sebelum capture) */
8329
+ async cancelPayment(pspReference, merchantAccount) {
8330
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8331
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/cancels`, {
8332
+ method: "POST",
8333
+ headers: this.buildHeaders(),
8334
+ body: JSON.stringify({ merchantAccount: account })
8335
+ });
8336
+ return response.json();
8337
+ }
8338
+ /** Refund payment yang sudah di-capture */
8339
+ async refundPayment(pspReference, amount, currency, merchantAccount) {
8340
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8341
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/refunds`, {
8342
+ method: "POST",
8343
+ headers: this.buildHeaders(),
8344
+ body: JSON.stringify({
8345
+ merchantAccount: account,
8346
+ amount: { value: amount, currency }
8347
+ })
8348
+ });
8349
+ return response.json();
8350
+ }
8351
+ /** Capture authorized payment */
8352
+ async capturePayment(pspReference, amount, currency, merchantAccount) {
8353
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8354
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/captures`, {
8355
+ method: "POST",
8356
+ headers: this.buildHeaders(),
8357
+ body: JSON.stringify({
8358
+ merchantAccount: account,
8359
+ amount: { value: amount, currency }
8360
+ })
8361
+ });
8362
+ return response.json();
8363
+ }
8364
+ /** Ambil daftar payment methods yang tersedia */
8365
+ async getAvailablePaymentMethods(merchantAccount, countryCode, currency, amount) {
8366
+ const response = await fetch(`${this.getBaseUrl()}/v68/paymentMethods`, {
8367
+ method: "POST",
8368
+ headers: this.buildHeaders(),
8369
+ body: JSON.stringify({ merchantAccount, countryCode, channel: "Web", amount: { value: amount, currency } })
8370
+ });
8371
+ return response.json();
8372
+ }
8373
+ };
8374
+
8375
+ // src/clients/checkoutcom.ts
8376
+ var CheckoutComClient = class {
8377
+ config;
8378
+ constructor(config) {
8379
+ this.config = config;
8380
+ }
8381
+ getBaseUrl() {
8382
+ return this.config.sandbox !== false ? "https://api.sandbox.checkout.com" : "https://api.checkout.com";
8383
+ }
8384
+ buildHeaders() {
8385
+ return {
8386
+ "Authorization": `Bearer ${this.config.apiKey || this.config.secretKey || ""}`,
8387
+ "Content-Type": "application/json"
8388
+ };
8389
+ }
8390
+ /** Ambil detail payment berdasarkan Payment ID */
8391
+ async getPaymentDetails(paymentId) {
8392
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}`, {
8393
+ method: "GET",
8394
+ headers: this.buildHeaders()
8395
+ });
8396
+ return response.json();
8397
+ }
8398
+ /** Void (batalkan) payment yang belum di-capture */
8399
+ async voidPayment(paymentId, reference) {
8400
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/voids`, {
8401
+ method: "POST",
8402
+ headers: this.buildHeaders(),
8403
+ body: JSON.stringify({ reference })
8404
+ });
8405
+ return response.json();
8406
+ }
8407
+ /** Refund payment yang sudah di-capture */
8408
+ async refundPayment(paymentId, amount, reference) {
8409
+ const body = { reference };
8410
+ if (amount) body.amount = amount;
8411
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/refunds`, {
8412
+ method: "POST",
8413
+ headers: this.buildHeaders(),
8414
+ body: JSON.stringify(body)
8415
+ });
8416
+ return response.json();
8417
+ }
8418
+ /** Cek saldo merchant di Checkout.com */
8419
+ async checkBalance() {
8420
+ const response = await fetch(`${this.getBaseUrl()}/balances`, {
8421
+ method: "GET",
8422
+ headers: this.buildHeaders()
8423
+ });
8424
+ return response.json();
8425
+ }
8426
+ /** Ambil daftar payment links */
8427
+ async listPaymentLinks() {
8428
+ const response = await fetch(`${this.getBaseUrl()}/payment-links`, {
8429
+ method: "GET",
8430
+ headers: this.buildHeaders()
8431
+ });
8432
+ return response.json();
8433
+ }
8434
+ };
8435
+
8436
+ // src/clients/razorpay.ts
8437
+ var RazorpayClient = class {
8438
+ config;
8439
+ constructor(config) {
8440
+ this.config = config;
8441
+ }
8442
+ getBaseUrl() {
8443
+ return "https://api.razorpay.com/v1";
8444
+ }
8445
+ buildHeaders() {
8446
+ const keyId = this.config.clientKey || this.config.merchantCode || this.config.merchantId || "";
8447
+ const keySecret = this.config.apiKey || this.config.secretKey || "";
8448
+ return {
8449
+ "Authorization": `Basic ${buildRazorpayBasicAuth(keyId, keySecret)}`,
8450
+ "Content-Type": "application/json"
8451
+ };
8452
+ }
8453
+ /** Ambil detail payment */
8454
+ async fetchPayment(paymentId) {
8455
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}`, {
8456
+ method: "GET",
8457
+ headers: this.buildHeaders()
8458
+ });
8459
+ return response.json();
8460
+ }
8461
+ /** Capture authorized payment */
8462
+ async capturePayment(paymentId, amount, currency) {
8463
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/capture`, {
8464
+ method: "POST",
8465
+ headers: this.buildHeaders(),
8466
+ body: JSON.stringify({ amount, currency: currency || "INR" })
8467
+ });
8468
+ return response.json();
8469
+ }
8470
+ /** Buat refund untuk payment */
8471
+ async createRefund(paymentId, amount, notes) {
8472
+ const body = { notes };
8473
+ if (amount) body.amount = amount;
8474
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/refund`, {
8475
+ method: "POST",
8476
+ headers: this.buildHeaders(),
8477
+ body: JSON.stringify(body)
8478
+ });
8479
+ return response.json();
8480
+ }
8481
+ /** Cek saldo akun Razorpay */
8482
+ async checkBalance() {
8483
+ const response = await fetch(`${this.getBaseUrl()}/balance`, {
8484
+ method: "GET",
8485
+ headers: this.buildHeaders()
8486
+ });
8487
+ return response.json();
8488
+ }
8489
+ /** Ambil daftar semua payment */
8490
+ async listPayments(from, to, count) {
8491
+ const params = new URLSearchParams();
8492
+ if (from) params.set("from", from.toString());
8493
+ if (to) params.set("to", to.toString());
8494
+ if (count) params.set("count", count.toString());
8495
+ const response = await fetch(`${this.getBaseUrl()}/payments?${params}`, {
8496
+ method: "GET",
8497
+ headers: this.buildHeaders()
8498
+ });
8499
+ return response.json();
8500
+ }
8501
+ };
8502
+
8503
+ // src/clients/square.ts
8504
+ var SquareClient = class {
8505
+ config;
8506
+ constructor(config) {
8507
+ this.config = config;
8508
+ }
8509
+ getBaseUrl() {
8510
+ return this.config.sandbox !== false ? "https://connect.squareupsandbox.com" : "https://connect.squareup.com";
8511
+ }
8512
+ buildHeaders() {
8513
+ return {
8514
+ "Authorization": `Bearer ${this.config.apiKey || this.config.secretKey || ""}`,
8515
+ "Content-Type": "application/json",
8516
+ "Square-Version": "2024-01-17"
8517
+ };
8518
+ }
8519
+ /** Ambil detail payment Square */
8520
+ async getPayment(paymentId) {
8521
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/${paymentId}`, {
8522
+ method: "GET",
8523
+ headers: this.buildHeaders()
8524
+ });
8525
+ return response.json();
8526
+ }
8527
+ /** Batalkan payment Square */
8528
+ async cancelPayment(paymentId) {
8529
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/${paymentId}/cancel`, {
8530
+ method: "POST",
8531
+ headers: this.buildHeaders(),
8532
+ body: "{}"
8533
+ });
8534
+ return response.json();
8535
+ }
8536
+ /** Refund payment Square */
8537
+ async refundPayment(paymentId, amount, currency, idempotencyKey, reason) {
8538
+ const response = await fetch(`${this.getBaseUrl()}/v2/refunds`, {
8539
+ method: "POST",
8540
+ headers: this.buildHeaders(),
8541
+ body: JSON.stringify({
8542
+ idempotency_key: idempotencyKey,
8543
+ payment_id: paymentId,
8544
+ amount_money: { amount, currency },
8545
+ reason
8546
+ })
8547
+ });
8548
+ return response.json();
8549
+ }
8550
+ /** Ambil saldo location Square */
8551
+ async retrieveBalance(locationId) {
8552
+ const id = locationId || this.config.extra?.locationId || this.config.projectId || "";
8553
+ const response = await fetch(`${this.getBaseUrl()}/v2/locations/${id}`, {
8554
+ method: "GET",
8555
+ headers: this.buildHeaders()
8556
+ });
8557
+ return response.json();
8558
+ }
8559
+ /** List semua locations merchant */
8560
+ async listLocations() {
8561
+ const response = await fetch(`${this.getBaseUrl()}/v2/locations`, {
8562
+ method: "GET",
8563
+ headers: this.buildHeaders()
8564
+ });
8565
+ return response.json();
8566
+ }
8567
+ };
8568
+
8569
+ // src/clients/payu.ts
8570
+ var PayuClient = class {
8571
+ config;
8572
+ accessToken = null;
8573
+ constructor(config) {
8574
+ this.config = config;
8575
+ }
8576
+ getBaseUrl() {
8577
+ return this.config.sandbox !== false ? "https://secure.snd.payu.com" : "https://secure.payu.com";
8578
+ }
8579
+ async getToken() {
8580
+ if (this.accessToken) return this.accessToken;
8581
+ const clientId = this.config.extra?.oauthClientId || this.config.clientKey || "";
8582
+ const clientSecret = this.config.extra?.oauthClientSecret || this.config.apiKey || this.config.secretKey || "";
8583
+ const response = await fetch(`${this.getBaseUrl()}/pl/standard/user/oauth/authorize`, {
8584
+ method: "POST",
8585
+ headers: { "Authorization": `Basic ${buildPayuBasicAuth(clientId, clientSecret)}`, "Content-Type": "application/x-www-form-urlencoded" },
8586
+ body: "grant_type=client_credentials"
8587
+ });
8588
+ const data = await response.json();
8589
+ if (!data?.access_token) throw new Error("Failed to get PayU access token");
8590
+ this.accessToken = data.access_token;
8591
+ return this.accessToken;
8592
+ }
8593
+ /** Ambil detail order PayU */
8594
+ async getOrder(orderId) {
8595
+ const token = await this.getToken();
8596
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}`, {
8597
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8598
+ });
8599
+ return response.json();
8600
+ }
8601
+ /** Batalkan order PayU */
8602
+ async cancelOrder(orderId) {
8603
+ const token = await this.getToken();
8604
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}`, {
8605
+ method: "DELETE",
8606
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8607
+ });
8608
+ return response.json();
8609
+ }
8610
+ /** Refund order PayU */
8611
+ async refundOrder(orderId, amount, description) {
8612
+ const token = await this.getToken();
8613
+ const body = { refund: { description: description || "Refund" } };
8614
+ if (amount) body.refund.amount = amount;
8615
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}/refunds`, {
8616
+ method: "POST",
8617
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8618
+ body: JSON.stringify(body)
8619
+ });
8620
+ return response.json();
8621
+ }
8622
+ };
8623
+
8624
+ // src/clients/braintree.ts
8625
+ var BraintreeClient = class {
8626
+ config;
8627
+ constructor(config) {
8628
+ this.config = config;
8629
+ }
8630
+ getBaseUrl() {
8631
+ const merchantId = this.config.merchantCode || this.config.merchantId || "";
8632
+ const base = this.config.sandbox !== false ? "https://api.sandbox.braintreegateway.com" : "https://api.braintreegateway.com";
8633
+ return `${base}/merchants/${merchantId}`;
8634
+ }
8635
+ buildHeaders() {
8636
+ const publicKey = this.config.clientKey || this.config.extra?.publicKey || "";
8637
+ const privateKey = this.config.apiKey || this.config.secretKey || "";
8638
+ return {
8639
+ "Authorization": `Basic ${buildBraintreeBasicAuth(publicKey, privateKey)}`,
8640
+ "Content-Type": "application/json",
8641
+ "Braintree-Version": "2019-01-01"
8642
+ };
8643
+ }
8644
+ /** Generate Client Token untuk frontend Drop-in UI */
8645
+ async getClientToken(customerId) {
8646
+ const body = {};
8647
+ if (customerId) body.client_token = { customer_id: customerId };
8648
+ const response = await fetch(`${this.getBaseUrl()}/client_token`, {
8649
+ method: "POST",
8650
+ headers: this.buildHeaders(),
8651
+ body: JSON.stringify(body)
8652
+ });
8653
+ const data = await response.json();
8654
+ return data.clientToken || "";
8655
+ }
8656
+ /** Ambil detail transaction */
8657
+ async findTransaction(transactionId) {
8658
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}`, {
8659
+ method: "GET",
8660
+ headers: this.buildHeaders()
8661
+ });
8662
+ return response.json();
8663
+ }
8664
+ /** Refund transaction Braintree */
8665
+ async refundTransaction(transactionId, amount) {
8666
+ const body = {};
8667
+ if (amount) body.transaction = { amount: (amount / 100).toFixed(2) };
8668
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}/refund`, {
8669
+ method: "POST",
8670
+ headers: this.buildHeaders(),
8671
+ body: JSON.stringify(body)
8672
+ });
8673
+ return response.json();
8674
+ }
8675
+ /** Void (batalkan) transaction sebelum settlement */
8676
+ async voidTransaction(transactionId) {
8677
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}/void`, {
8678
+ method: "PUT",
8679
+ headers: this.buildHeaders(),
8680
+ body: "{}"
8681
+ });
8682
+ return response.json();
8683
+ }
8684
+ };
8685
+
8686
+ // src/clients/twocheckout.ts
8687
+ var TwoCheckoutClient = class {
8688
+ config;
8689
+ constructor(config) {
8690
+ this.config = config;
8691
+ }
8692
+ getBaseUrl() {
8693
+ return this.config.sandbox !== false ? "https://api.sandbox.2checkout.com/rest" : "https://api.2checkout.com/rest";
8694
+ }
8695
+ buildHeaders() {
8696
+ const merchantCode = this.config.merchantCode || this.config.merchantId || "";
8697
+ const secretKey = this.config.apiKey || this.config.secretKey || "";
8698
+ const { header } = buildTwoCheckoutAuth(merchantCode, secretKey);
8699
+ return {
8700
+ "X-Avangate-Authentication": header,
8701
+ "Content-Type": "application/json",
8702
+ "Accept": "application/json"
8703
+ };
8704
+ }
8705
+ /** Ambil detail order 2Checkout berdasarkan Reference Number */
8706
+ async getOrder(refNo) {
8707
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders/${refNo}`, {
8708
+ method: "GET",
8709
+ headers: this.buildHeaders()
8710
+ });
8711
+ return response.json();
8712
+ }
8713
+ /** Refund order 2Checkout */
8714
+ async refundOrder(refNo, amount, comment) {
8715
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders/${refNo}/refund`, {
8716
+ method: "POST",
8717
+ headers: this.buildHeaders(),
8718
+ body: JSON.stringify({ amount, comment: comment || "Refund", reason: "NOT_SATISFIED" })
8719
+ });
8720
+ return response.json();
8721
+ }
8722
+ /** Ambil detail subscription */
8723
+ async getSubscription(subscriptionRef) {
8724
+ const response = await fetch(`${this.getBaseUrl()}/6.0/subscriptions/${subscriptionRef}`, {
8725
+ method: "GET",
8726
+ headers: this.buildHeaders()
8727
+ });
8728
+ return response.json();
8729
+ }
8730
+ /** List semua orders merchant */
8731
+ async listOrders(page, limit) {
8732
+ const params = new URLSearchParams({
8733
+ Pagination: JSON.stringify({ Page: page || 1, Limit: limit || 10 })
8734
+ });
8735
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders?${params}`, {
8736
+ method: "GET",
8737
+ headers: this.buildHeaders()
8738
+ });
8739
+ return response.json();
8740
+ }
8741
+ };
8742
+
6155
8743
  // src/core/manager.ts
6156
8744
  var PaymentManager = class {
6157
8745
  providers = /* @__PURE__ */ new Map();
@@ -6167,6 +8755,14 @@ var PaymentManager = class {
6167
8755
  this.registerProvider(new NicepayProvider());
6168
8756
  this.registerProvider(new OyProvider());
6169
8757
  this.registerProvider(new StripeProvider());
8758
+ this.registerProvider(new PaypalProvider());
8759
+ this.registerProvider(new AdyenProvider());
8760
+ this.registerProvider(new CheckoutComProvider());
8761
+ this.registerProvider(new RazorpayProvider());
8762
+ this.registerProvider(new SquareProvider());
8763
+ this.registerProvider(new PayuProvider());
8764
+ this.registerProvider(new BraintreeProvider());
8765
+ this.registerProvider(new TwoCheckoutProvider());
6170
8766
  }
6171
8767
  registerProvider(provider) {
6172
8768
  this.providers.set(provider.name.toLowerCase(), provider);
@@ -6178,6 +8774,7 @@ var PaymentManager = class {
6178
8774
  }
6179
8775
  return provider;
6180
8776
  }
8777
+ // ─── Indonesian Provider Getters ──────────────────────────────────────────
6181
8778
  getMidtransProvider() {
6182
8779
  return this.getProvider("midtrans");
6183
8780
  }
@@ -6238,12 +8835,62 @@ var PaymentManager = class {
6238
8835
  getOyClient(config) {
6239
8836
  return new OyClient(config);
6240
8837
  }
8838
+ // ─── International Provider Getters ─────────────────────────────────────
6241
8839
  getStripeProvider() {
6242
8840
  return this.getProvider("stripe");
6243
8841
  }
6244
8842
  getStripeClient(config) {
6245
8843
  return new StripeClient(config);
6246
8844
  }
8845
+ getPaypalProvider() {
8846
+ return this.getProvider("paypal");
8847
+ }
8848
+ getPaypalClient(config) {
8849
+ return new PaypalClient(config);
8850
+ }
8851
+ getAdyenProvider() {
8852
+ return this.getProvider("adyen");
8853
+ }
8854
+ getAdyenClient(config) {
8855
+ return new AdyenClient(config);
8856
+ }
8857
+ getCheckoutComProvider() {
8858
+ return this.getProvider("checkoutcom");
8859
+ }
8860
+ getCheckoutComClient(config) {
8861
+ return new CheckoutComClient(config);
8862
+ }
8863
+ getRazorpayProvider() {
8864
+ return this.getProvider("razorpay");
8865
+ }
8866
+ getRazorpayClient(config) {
8867
+ return new RazorpayClient(config);
8868
+ }
8869
+ getSquareProvider() {
8870
+ return this.getProvider("square");
8871
+ }
8872
+ getSquareClient(config) {
8873
+ return new SquareClient(config);
8874
+ }
8875
+ getPayuProvider() {
8876
+ return this.getProvider("payu");
8877
+ }
8878
+ getPayuClient(config) {
8879
+ return new PayuClient(config);
8880
+ }
8881
+ getBraintreeProvider() {
8882
+ return this.getProvider("braintree");
8883
+ }
8884
+ getBraintreeClient(config) {
8885
+ return new BraintreeClient(config);
8886
+ }
8887
+ getTwoCheckoutProvider() {
8888
+ return this.getProvider("twocheckout");
8889
+ }
8890
+ getTwoCheckoutClient(config) {
8891
+ return new TwoCheckoutClient(config);
8892
+ }
8893
+ // ─── Unified Operations ──────────────────────────────────────────────────
6247
8894
  async createInvoice(providerName, params, config) {
6248
8895
  const provider = this.getProvider(providerName);
6249
8896
  return provider.createInvoice(params, config);
@@ -6303,6 +8950,22 @@ function resolveConfigFromEnv(customConfig) {
6303
8950
  sandbox = env.OY_SANDBOX === "true" || env.OY_SANDBOX === "1";
6304
8951
  } else if (env.STRIPE_SANDBOX !== void 0) {
6305
8952
  sandbox = env.STRIPE_SANDBOX === "true" || env.STRIPE_SANDBOX === "1";
8953
+ } else if (env.PAYPAL_SANDBOX !== void 0) {
8954
+ sandbox = env.PAYPAL_SANDBOX === "true" || env.PAYPAL_SANDBOX === "1";
8955
+ } else if (env.ADYEN_SANDBOX !== void 0) {
8956
+ sandbox = env.ADYEN_SANDBOX === "true" || env.ADYEN_SANDBOX === "1";
8957
+ } else if (env.CHECKOUTCOM_SANDBOX !== void 0) {
8958
+ sandbox = env.CHECKOUTCOM_SANDBOX === "true" || env.CHECKOUTCOM_SANDBOX === "1";
8959
+ } else if (env.RAZORPAY_SANDBOX !== void 0) {
8960
+ sandbox = env.RAZORPAY_SANDBOX === "true" || env.RAZORPAY_SANDBOX === "1";
8961
+ } else if (env.SQUARE_SANDBOX !== void 0) {
8962
+ sandbox = env.SQUARE_SANDBOX === "true" || env.SQUARE_SANDBOX === "1";
8963
+ } else if (env.PAYU_SANDBOX !== void 0) {
8964
+ sandbox = env.PAYU_SANDBOX === "true" || env.PAYU_SANDBOX === "1";
8965
+ } else if (env.BRAINTREE_SANDBOX !== void 0) {
8966
+ sandbox = env.BRAINTREE_SANDBOX === "true" || env.BRAINTREE_SANDBOX === "1";
8967
+ } else if (env.TWOCHECKOUT_SANDBOX !== void 0) {
8968
+ sandbox = env.TWOCHECKOUT_SANDBOX === "true" || env.TWOCHECKOUT_SANDBOX === "1";
6306
8969
  } else {
6307
8970
  sandbox = env.NODE_ENV !== "production";
6308
8971
  }
@@ -6330,6 +8993,22 @@ function resolveConfigFromEnv(customConfig) {
6330
8993
  apiKey = env.OY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
6331
8994
  } else if (provider === "stripe") {
6332
8995
  apiKey = env.STRIPE_SECRET_KEY || env.STRIPE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8996
+ } else if (provider === "paypal") {
8997
+ apiKey = env.PAYPAL_CLIENT_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8998
+ } else if (provider === "adyen") {
8999
+ apiKey = env.ADYEN_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9000
+ } else if (provider === "checkoutcom") {
9001
+ apiKey = env.CHECKOUTCOM_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9002
+ } else if (provider === "razorpay") {
9003
+ apiKey = env.RAZORPAY_KEY_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9004
+ } else if (provider === "square") {
9005
+ apiKey = env.SQUARE_ACCESS_TOKEN || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9006
+ } else if (provider === "payu") {
9007
+ apiKey = env.PAYU_MD5_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9008
+ } else if (provider === "braintree") {
9009
+ apiKey = env.BRAINTREE_PRIVATE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
9010
+ } else if (provider === "twocheckout" || provider === "2checkout") {
9011
+ apiKey = env.TWOCHECKOUT_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
6333
9012
  } else {
6334
9013
  apiKey = env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.PG_SECRET_KEY || env.BUAYAR_SECRET_KEY;
6335
9014
  }
@@ -6347,7 +9026,7 @@ function resolveConfigFromEnv(customConfig) {
6347
9026
  merchantCode = merchantCode || env.IPAYMU_VA || env.IPAYMU_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6348
9027
  } else if (provider === "doku") {
6349
9028
  merchantCode = merchantCode || env.DOKU_CLIENT_ID || env.DOKU_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6350
- clientKey = clientKey || env.DOKU_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9029
+ clientKey = clientKey || customConfig?.merchantCode || env.DOKU_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
6351
9030
  } else if (provider === "prismalink") {
6352
9031
  merchantCode = merchantCode || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6353
9032
  merchantId = merchantId || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
@@ -6363,30 +9042,67 @@ function resolveConfigFromEnv(customConfig) {
6363
9042
  merchantId = merchantId || env.NICEPAY_IMID || env.BUAYAR_MERCHANT_ID;
6364
9043
  } else if (provider === "oy" || provider === "oyindonesia") {
6365
9044
  merchantCode = merchantCode || env.OY_USERNAME || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6366
- clientKey = clientKey || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
9045
+ clientKey = clientKey || customConfig?.merchantCode || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
6367
9046
  } else if (provider === "stripe") {
6368
9047
  clientKey = clientKey || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.BUAYAR_CLIENT_KEY || env.BUAYAR_PUBLIC_KEY;
6369
9048
  merchantCode = merchantCode || clientKey || "stripe";
9049
+ } else if (provider === "paypal") {
9050
+ clientKey = clientKey || env.PAYPAL_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9051
+ merchantCode = merchantCode || env.PAYPAL_CLIENT_ID || env.BUAYAR_MERCHANT_CODE;
9052
+ } else if (provider === "adyen") {
9053
+ clientKey = clientKey || env.ADYEN_CLIENT_KEY || env.BUAYAR_CLIENT_KEY;
9054
+ merchantCode = merchantCode || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_CODE;
9055
+ merchantId = merchantId || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_ID;
9056
+ } else if (provider === "checkoutcom") {
9057
+ clientKey = clientKey || env.CHECKOUTCOM_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9058
+ merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE;
9059
+ } else if (provider === "razorpay") {
9060
+ clientKey = clientKey || env.RAZORPAY_KEY_ID || env.BUAYAR_CLIENT_KEY;
9061
+ merchantCode = merchantCode || env.RAZORPAY_KEY_ID || env.BUAYAR_MERCHANT_CODE;
9062
+ } else if (provider === "square") {
9063
+ clientKey = clientKey || env.SQUARE_APPLICATION_ID || env.BUAYAR_CLIENT_KEY;
9064
+ merchantCode = merchantCode || env.SQUARE_APPLICATION_ID || env.BUAYAR_MERCHANT_CODE;
9065
+ } else if (provider === "payu") {
9066
+ merchantCode = merchantCode || env.PAYU_POS_ID || env.BUAYAR_MERCHANT_CODE;
9067
+ merchantId = merchantId || env.PAYU_POS_ID;
9068
+ } else if (provider === "braintree") {
9069
+ clientKey = clientKey || env.BRAINTREE_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9070
+ merchantCode = merchantCode || env.BRAINTREE_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE;
9071
+ merchantId = merchantId || env.BRAINTREE_MERCHANT_ID;
9072
+ } else if (provider === "twocheckout" || provider === "2checkout") {
9073
+ merchantCode = merchantCode || env.TWOCHECKOUT_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE;
9074
+ merchantId = merchantId || env.TWOCHECKOUT_MERCHANT_CODE;
6370
9075
  } else {
6371
9076
  merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6372
9077
  }
6373
- const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID;
6374
- const publicKey = customConfig?.publicKey || env.BUAYAR_PUBLIC_KEY || env.PG_PUBLIC_KEY || env.PUBLIC_KEY || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY;
6375
- const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY;
6376
- const secretKey = customConfig?.secretKey || 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;
9078
+ const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID || env.SQUARE_LOCATION_ID;
9079
+ 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;
9080
+ const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY || env.BRAINTREE_PRIVATE_KEY;
9081
+ 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;
6377
9082
  const callbackUrl = customConfig?.callbackUrl || env.BUAYAR_CALLBACK_URL || env.PG_CALLBACK_URL || env.PAYMENT_CALLBACK_URL;
6378
9083
  const returnUrl = customConfig?.returnUrl || env.BUAYAR_RETURN_URL || env.PG_RETURN_URL || env.PAYMENT_RETURN_URL;
6379
9084
  const extra = {
6380
9085
  webhookToken: env.XENDIT_WEBHOOK_TOKEN || env.BUAYAR_WEBHOOK_TOKEN,
6381
- webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
9086
+ webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.CHECKOUTCOM_WEBHOOK_SECRET || env.RAZORPAY_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
6382
9087
  merchantName: env.FASPAY_MERCHANT_NAME || env.BUAYAR_MERCHANT_NAME,
6383
9088
  userId: env.FASPAY_USER_ID,
6384
9089
  iMid: env.NICEPAY_IMID,
6385
9090
  username: env.OY_USERNAME,
9091
+ hmacKey: env.ADYEN_HMAC_KEY,
9092
+ liveUrlPrefix: env.ADYEN_LIVE_URL_PREFIX,
9093
+ webhookId: env.PAYPAL_WEBHOOK_ID,
9094
+ merchantAccount: env.ADYEN_MERCHANT_ACCOUNT,
9095
+ md5Key: env.PAYU_MD5_KEY,
9096
+ oauthClientId: env.PAYU_OAUTH_CLIENT_ID,
9097
+ oauthClientSecret: env.PAYU_OAUTH_CLIENT_SECRET,
9098
+ locationId: env.SQUARE_LOCATION_ID,
9099
+ webhookSignatureKey: env.SQUARE_WEBHOOK_SIGNATURE_KEY,
9100
+ publicKey: env.BRAINTREE_PUBLIC_KEY || env.ADYEN_CLIENT_KEY,
9101
+ secretWord: env.TWOCHECKOUT_SECRET_WORD,
6386
9102
  ...customConfig?.extra
6387
9103
  };
6388
9104
  return {
6389
- provider: provider === "oyindonesia" ? "oy" : provider,
9105
+ provider: provider === "oyindonesia" ? "oy" : provider === "2checkout" ? "twocheckout" : provider,
6390
9106
  apiKey: apiKey || "",
6391
9107
  serverKey: apiKey || "",
6392
9108
  secretKey: secretKey || apiKey || "",
@@ -6424,7 +9140,7 @@ var Buayar = class {
6424
9140
  this.config = resolveConfigFromEnv({ ...this.config, ...config });
6425
9141
  }
6426
9142
  /**
6427
- * Dapatkan nama provider aktif ('midtrans' | 'duitku' | 'ipaymu' | 'xendit' | 'doku' | 'prismalink' | 'faspay' | 'finpay' | 'nicepay' | 'oy' | 'stripe' | ...)
9143
+ * Dapatkan nama provider aktif
6428
9144
  */
6429
9145
  get provider() {
6430
9146
  return this.config.provider || "midtrans";
@@ -6473,10 +9189,45 @@ var Buayar = class {
6473
9189
  async verifyWebhook(payload, headers, configOverride) {
6474
9190
  const mergedConfig = { ...this.config, ...configOverride };
6475
9191
  if (headers) {
6476
- const sigHeader = headers["stripe-signature"] || headers["Stripe-Signature"];
6477
- if (sigHeader) {
6478
- if (!mergedConfig.extra) mergedConfig.extra = {};
6479
- mergedConfig.extra.signatureHeader = Array.isArray(sigHeader) ? sigHeader[0] : sigHeader;
9192
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9193
+ mergedConfig.extra.headers = headers;
9194
+ const stripeSig = headers["stripe-signature"] || headers["Stripe-Signature"];
9195
+ if (stripeSig) {
9196
+ mergedConfig.extra.signatureHeader = Array.isArray(stripeSig) ? stripeSig[0] : stripeSig;
9197
+ }
9198
+ const ckoSig = headers["cko-signature"] || headers["Cko-Signature"];
9199
+ if (ckoSig) {
9200
+ mergedConfig.extra.signatureHeader = Array.isArray(ckoSig) ? ckoSig[0] : ckoSig;
9201
+ }
9202
+ const rzpSig = headers["x-razorpay-signature"] || headers["X-Razorpay-Signature"];
9203
+ if (rzpSig) {
9204
+ mergedConfig.extra.signatureHeader = Array.isArray(rzpSig) ? rzpSig[0] : rzpSig;
9205
+ }
9206
+ const squareSig = headers["x-square-hmacsha256-signature"] || headers["x-square-signature"];
9207
+ if (squareSig) {
9208
+ mergedConfig.extra.signatureHeader = Array.isArray(squareSig) ? squareSig[0] : squareSig;
9209
+ }
9210
+ const payuSig = headers["openpayu-signature"] || headers["OpenPayU-Signature"];
9211
+ if (payuSig) {
9212
+ mergedConfig.extra.signatureHeader = Array.isArray(payuSig) ? payuSig[0] : payuSig;
9213
+ }
9214
+ const btSig = headers["bt_signature"];
9215
+ const btPayload = headers["bt_payload"];
9216
+ if (btSig && btPayload) {
9217
+ mergedConfig.extra.btSignature = Array.isArray(btSig) ? btSig[0] : btSig;
9218
+ mergedConfig.extra.btPayload = Array.isArray(btPayload) ? btPayload[0] : btPayload;
9219
+ }
9220
+ const xenditToken = headers["x-callback-token"] || headers["X-Callback-Token"];
9221
+ if (xenditToken) {
9222
+ mergedConfig.extra.callbackToken = Array.isArray(xenditToken) ? xenditToken[0] : xenditToken;
9223
+ }
9224
+ const dokuSig = headers["signature"] || headers["Signature"];
9225
+ if (dokuSig) {
9226
+ mergedConfig.extra.dokuSignature = Array.isArray(dokuSig) ? dokuSig[0] : dokuSig;
9227
+ }
9228
+ const oyUser = headers["x-oy-username"] || headers["X-Oy-Username"];
9229
+ if (oyUser) {
9230
+ mergedConfig.extra.oyUsername = Array.isArray(oyUser) ? oyUser[0] : oyUser;
6480
9231
  }
6481
9232
  }
6482
9233
  let providerName = configOverride?.provider || this.provider;
@@ -6501,8 +9252,24 @@ var Buayar = class {
6501
9252
  providerName = "prismalink";
6502
9253
  } else if (payload.object === "event" || payload.type && payload.data?.object && payload.api_version) {
6503
9254
  providerName = "stripe";
9255
+ } else if (payload.event && payload.payload?.payment?.entity) {
9256
+ providerName = "razorpay";
6504
9257
  } else if (payload.external_id || payload.event?.startsWith("payment.") || payload.event?.startsWith("qr.") || payload.data?.reference_id) {
6505
9258
  providerName = "xendit";
9259
+ } else if (payload.event_type && payload.resource && (payload.event_type.startsWith("PAYMENT.") || payload.event_type.startsWith("CHECKOUT.ORDER."))) {
9260
+ providerName = "paypal";
9261
+ } else if (payload.notificationItems || payload.merchantAccountCode && payload.pspReference && payload.eventCode) {
9262
+ providerName = "adyen";
9263
+ } else if (payload.type && payload.data?._links && (payload.type.startsWith("payment_") || payload.type.startsWith("refund_"))) {
9264
+ providerName = "checkoutcom";
9265
+ } else if (payload.type && payload.data?.object?.status && payload.merchant_id) {
9266
+ providerName = "square";
9267
+ } else if (payload.order && payload.order?.status && payload.order?.extOrderId) {
9268
+ providerName = "payu";
9269
+ } else if (payload.kind && payload.subject?.transaction) {
9270
+ providerName = "braintree";
9271
+ } else if (payload.HASH && payload.REFNOEXT && payload.IPN_PID) {
9272
+ providerName = "twocheckout";
6506
9273
  }
6507
9274
  }
6508
9275
  return this.manager.verifyCallback(providerName, payload, mergedConfig);
@@ -6510,77 +9277,74 @@ var Buayar = class {
6510
9277
  async handleWebhook(payload, headers, configOverride) {
6511
9278
  return this.verifyWebhook(payload, headers, configOverride);
6512
9279
  }
9280
+ // ─── Indonesian Provider Client Getters ───────────────────────────────────
6513
9281
  getMidtransClient(configOverride) {
6514
- return new MidtransClient({
6515
- ...this.config,
6516
- ...configOverride
6517
- });
9282
+ return new MidtransClient({ ...this.config, ...configOverride });
6518
9283
  }
6519
9284
  getDuitkuClient(configOverride) {
6520
- return new DuitkuClient({
6521
- ...this.config,
6522
- ...configOverride
6523
- });
9285
+ return new DuitkuClient({ ...this.config, ...configOverride });
6524
9286
  }
6525
9287
  getIpaymuClient(configOverride) {
6526
- return new IpaymuClient({
6527
- ...this.config,
6528
- ...configOverride
6529
- });
9288
+ return new IpaymuClient({ ...this.config, ...configOverride });
6530
9289
  }
6531
9290
  getXenditClient(configOverride) {
6532
- return new XenditClient({
6533
- ...this.config,
6534
- ...configOverride
6535
- });
9291
+ return new XenditClient({ ...this.config, ...configOverride });
6536
9292
  }
6537
9293
  getDokuClient(configOverride) {
6538
- return new DokuClient({
6539
- ...this.config,
6540
- ...configOverride
6541
- });
9294
+ return new DokuClient({ ...this.config, ...configOverride });
6542
9295
  }
6543
9296
  getPrismalinkClient(configOverride) {
6544
- return new PrismalinkClient({
6545
- ...this.config,
6546
- ...configOverride
6547
- });
9297
+ return new PrismalinkClient({ ...this.config, ...configOverride });
6548
9298
  }
6549
9299
  getFaspayClient(configOverride) {
6550
- return new FaspayClient({
6551
- ...this.config,
6552
- ...configOverride
6553
- });
9300
+ return new FaspayClient({ ...this.config, ...configOverride });
6554
9301
  }
6555
9302
  getFinpayClient(configOverride) {
6556
- return new FinpayClient({
6557
- ...this.config,
6558
- ...configOverride
6559
- });
9303
+ return new FinpayClient({ ...this.config, ...configOverride });
6560
9304
  }
6561
9305
  getNicepayClient(configOverride) {
6562
- return new NicepayClient({
6563
- ...this.config,
6564
- ...configOverride
6565
- });
9306
+ return new NicepayClient({ ...this.config, ...configOverride });
6566
9307
  }
6567
9308
  getOyClient(configOverride) {
6568
- return new OyClient({
6569
- ...this.config,
6570
- ...configOverride
6571
- });
9309
+ return new OyClient({ ...this.config, ...configOverride });
6572
9310
  }
9311
+ // ─── International Provider Client Getters ────────────────────────────────
6573
9312
  getStripeClient(configOverride) {
6574
- return new StripeClient({
6575
- ...this.config,
6576
- ...configOverride
6577
- });
9313
+ return new StripeClient({ ...this.config, ...configOverride });
9314
+ }
9315
+ getPaypalClient(configOverride) {
9316
+ return new PaypalClient({ ...this.config, ...configOverride });
9317
+ }
9318
+ getAdyenClient(configOverride) {
9319
+ return new AdyenClient({ ...this.config, ...configOverride });
9320
+ }
9321
+ getCheckoutComClient(configOverride) {
9322
+ return new CheckoutComClient({ ...this.config, ...configOverride });
9323
+ }
9324
+ getRazorpayClient(configOverride) {
9325
+ return new RazorpayClient({ ...this.config, ...configOverride });
9326
+ }
9327
+ getSquareClient(configOverride) {
9328
+ return new SquareClient({ ...this.config, ...configOverride });
9329
+ }
9330
+ getPayuClient(configOverride) {
9331
+ return new PayuClient({ ...this.config, ...configOverride });
9332
+ }
9333
+ getBraintreeClient(configOverride) {
9334
+ return new BraintreeClient({ ...this.config, ...configOverride });
9335
+ }
9336
+ getTwoCheckoutClient(configOverride) {
9337
+ return new TwoCheckoutClient({ ...this.config, ...configOverride });
6578
9338
  }
6579
9339
  };
6580
9340
  var buayar = new Buayar();
6581
9341
  // Annotate the CommonJS export names for ESM import in node:
6582
9342
  0 && (module.exports = {
9343
+ AdyenClient,
9344
+ AdyenProvider,
6583
9345
  BasePaymentProvider,
9346
+ BraintreeClient,
9347
+ BraintreeProvider,
6584
9348
  Buayar,
6585
9349
  CANONICAL_TO_DOKU,
6586
9350
  CANONICAL_TO_DUITKU,
@@ -6594,6 +9358,8 @@ var buayar = new Buayar();
6594
9358
  CANONICAL_TO_STRIPE,
6595
9359
  CANONICAL_TO_XENDIT,
6596
9360
  CORE_API_METHODS,
9361
+ CheckoutComClient,
9362
+ CheckoutComProvider,
6597
9363
  DUITKU_TO_CANONICAL,
6598
9364
  DokuClient,
6599
9365
  DokuProvider,
@@ -6614,14 +9380,29 @@ var buayar = new Buayar();
6614
9380
  OyClient,
6615
9381
  OyProvider,
6616
9382
  PaymentManager,
9383
+ PaypalClient,
9384
+ PaypalProvider,
9385
+ PayuClient,
9386
+ PayuProvider,
6617
9387
  PrismalinkClient,
6618
9388
  PrismalinkProvider,
9389
+ RazorpayClient,
9390
+ RazorpayProvider,
9391
+ SquareClient,
9392
+ SquareProvider,
6619
9393
  StripeClient,
6620
9394
  StripeProvider,
9395
+ TwoCheckoutClient,
9396
+ TwoCheckoutProvider,
6621
9397
  XenditClient,
6622
9398
  XenditProvider,
6623
9399
  buayar,
9400
+ buildBraintreeBasicAuth,
6624
9401
  buildCoreChargePayload,
9402
+ buildPaypalBasicAuth,
9403
+ buildPayuBasicAuth,
9404
+ buildRazorpayBasicAuth,
9405
+ buildTwoCheckoutAuth,
6625
9406
  formatNicepayTimestamp,
6626
9407
  generateDokuHeaders,
6627
9408
  generateFaspaySignature,
@@ -6641,6 +9422,7 @@ var buayar = new Buayar();
6641
9422
  paymentManager,
6642
9423
  resolveConfigFromEnv,
6643
9424
  safeCompare,
9425
+ serializePaypalParams,
6644
9426
  serializeStripeParams,
6645
9427
  sha256,
6646
9428
  sha512,
@@ -6655,6 +9437,9 @@ var buayar = new Buayar();
6655
9437
  toPrismalinkPaymentMethod,
6656
9438
  toStripePaymentMethod,
6657
9439
  toXenditPaymentMethod,
9440
+ verifyAdyenWebhook,
9441
+ verifyBraintreeWebhook,
9442
+ verifyCheckoutComWebhook,
6658
9443
  verifyDokuWebhookSignature,
6659
9444
  verifyDuitkuCallbackSignature,
6660
9445
  verifyFaspaySignature,
@@ -6662,7 +9447,12 @@ var buayar = new Buayar();
6662
9447
  verifyIpaymuCallback,
6663
9448
  verifyNicepayWebhook,
6664
9449
  verifyOyWebhook,
9450
+ verifyPaypalWebhookSimple,
9451
+ verifyPayuWebhook,
6665
9452
  verifyPrismalinkSignature,
9453
+ verifyRazorpayWebhook,
9454
+ verifySquareWebhook,
6666
9455
  verifyStripeWebhook,
9456
+ verifyTwoCheckoutWebhook,
6667
9457
  verifyXenditWebhookToken
6668
9458
  });