@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.mjs CHANGED
@@ -416,7 +416,19 @@ function hmacSha256(data, secret) {
416
416
  }
417
417
  function safeCompare(a, b) {
418
418
  if (typeof a !== "string" || typeof b !== "string") return false;
419
- return a.toLowerCase() === b.toLowerCase();
419
+ if (!a && !b) return true;
420
+ if (!a || !b) return false;
421
+ const isHexA = /^[0-9a-fA-F]+$/.test(a);
422
+ const isHexB = /^[0-9a-fA-F]+$/.test(b);
423
+ let strA = a;
424
+ let strB = b;
425
+ if (isHexA && isHexB && a.length === b.length) {
426
+ strA = a.toLowerCase();
427
+ strB = b.toLowerCase();
428
+ }
429
+ const hashA = crypto.createHash("sha256").update(strA).digest();
430
+ const hashB = crypto.createHash("sha256").update(strB).digest();
431
+ return crypto.timingSafeEqual(hashA, hashB);
420
432
  }
421
433
 
422
434
  // src/providers/duitku/signature.ts
@@ -1911,7 +1923,7 @@ function getXenditAuthHeader(secretKey) {
1911
1923
  return `Basic ${token}`;
1912
1924
  }
1913
1925
  function verifyXenditWebhookToken(headerToken, expectedToken) {
1914
- if (!headerToken || !expectedToken) return true;
1926
+ if (!headerToken || !expectedToken) return false;
1915
1927
  return safeCompare(headerToken, expectedToken);
1916
1928
  }
1917
1929
 
@@ -2099,8 +2111,14 @@ var XenditProvider = class extends BasePaymentProvider {
2099
2111
  const orderId = body.external_id || body.reference_id || body.data?.reference_id || body.id || "";
2100
2112
  const amount = body.paid_amount || body.amount || body.data?.amount || 0;
2101
2113
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
2114
+ const webhookToken = config.extra?.webhookToken;
2115
+ const headerToken = config.extra?.callbackToken || config.extra?.headers?.["x-callback-token"] || config.extra?.headers?.["X-Callback-Token"];
2116
+ let isValid = true;
2117
+ if (webhookToken || headerToken) {
2118
+ isValid = verifyXenditWebhookToken(headerToken, webhookToken);
2119
+ }
2102
2120
  return {
2103
- isValid: true,
2121
+ isValid,
2104
2122
  provider: "xendit",
2105
2123
  orderId: String(orderId),
2106
2124
  amount: Number(amount) || 0,
@@ -2378,11 +2396,12 @@ function verifyDokuWebhookSignature(headers, body, clientId, secretKey, requestT
2378
2396
  const reqId = headers["request-id"] || headers["Request-Id"] || "";
2379
2397
  const reqTimestamp = headers["request-timestamp"] || headers["Request-Timestamp"] || "";
2380
2398
  const incomingSignature = headers["signature"] || headers["Signature"] || "";
2381
- if (!incomingSignature || !secretKey) return true;
2399
+ if (!incomingSignature || !secretKey) return false;
2400
+ const target = headers["request-target"] || headers["Request-Target"] || requestTarget;
2382
2401
  let component = `Client-Id:${reqClientId || clientId}
2383
2402
  Request-Id:${reqId}
2384
2403
  Request-Timestamp:${reqTimestamp}
2385
- Request-Target:${requestTarget}`;
2404
+ Request-Target:${target}`;
2386
2405
  if (body) {
2387
2406
  const rawBody = typeof body === "string" ? body : JSON.stringify(body);
2388
2407
  const digest = crypto2.createHash("sha256").update(rawBody).digest("base64");
@@ -2606,8 +2625,16 @@ var DokuProvider = class extends BasePaymentProvider {
2606
2625
  const orderId = body.order?.invoice_number || body.invoice_number || body.order_id || "";
2607
2626
  const amount = body.order?.amount || body.amount || 0;
2608
2627
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
2628
+ const secretKey = config.secretKey || config.apiKey || "";
2629
+ const headers = config.extra?.headers || {};
2630
+ const signature = headers["signature"] || headers["Signature"] || config.extra?.dokuSignature || config.extra?.signatureHeader;
2631
+ const clientId = config.merchantCode || config.clientKey || "";
2632
+ let isValid = true;
2633
+ if (signature || headers && (headers["request-id"] || headers["Request-Id"])) {
2634
+ isValid = verifyDokuWebhookSignature(headers, body, clientId, secretKey);
2635
+ }
2609
2636
  return {
2610
- isValid: true,
2637
+ isValid,
2611
2638
  provider: "doku",
2612
2639
  orderId: String(orderId),
2613
2640
  amount: Number(amount) || 0,
@@ -2864,7 +2891,7 @@ function generatePrismalinkSignature(merchantId, orderId, amount, secretKey) {
2864
2891
  return sha256(raw);
2865
2892
  }
2866
2893
  function verifyPrismalinkSignature(merchantId, orderId, amount, secretKey, incomingSignature) {
2867
- if (!incomingSignature || !secretKey) return true;
2894
+ if (!incomingSignature || !secretKey) return false;
2868
2895
  const computed = generatePrismalinkSignature(merchantId, orderId, amount, secretKey);
2869
2896
  return safeCompare(incomingSignature, computed);
2870
2897
  }
@@ -3255,7 +3282,7 @@ function generateFaspaySignature(userId, password, billNo) {
3255
3282
  return crypto3.createHash("sha1").update(md5Hash).digest("hex");
3256
3283
  }
3257
3284
  function verifyFaspaySignature(userId, password, billNo, paymentStatusCode, incomingSignature) {
3258
- if (!incomingSignature || !password) return true;
3285
+ if (!incomingSignature || !password) return false;
3259
3286
  const md5Hash = crypto3.createHash("md5").update(`${userId}${password}${billNo}${paymentStatusCode}`).digest("hex");
3260
3287
  const computed = crypto3.createHash("sha1").update(md5Hash).digest("hex");
3261
3288
  const simpleComputed = generateFaspaySignature(userId, password, billNo);
@@ -3676,9 +3703,9 @@ function generateFinpaySignature(merchantId, orderId, amount, merchantKey) {
3676
3703
  return crypto4.createHmac("sha512", merchantKey).update(data).digest("hex");
3677
3704
  }
3678
3705
  function verifyFinpaySignature(merchantId, orderId, amount, merchantKey, incomingSignature) {
3679
- if (!incomingSignature || !merchantKey) return true;
3706
+ if (!incomingSignature || !merchantKey) return false;
3680
3707
  const computed = generateFinpaySignature(merchantId, orderId, amount, merchantKey);
3681
- return safeCompare(incomingSignature.toLowerCase(), computed.toLowerCase());
3708
+ return safeCompare(incomingSignature, computed);
3682
3709
  }
3683
3710
 
3684
3711
  // src/providers/finpay/provider.ts
@@ -4063,9 +4090,9 @@ function generateNicepayToken(timeStamp, iMid, referenceNo, amt, merchantKey) {
4063
4090
  return sha256(raw);
4064
4091
  }
4065
4092
  function verifyNicepayWebhook(timeStamp, iMid, referenceNo, amt, merchantKey, incomingToken) {
4066
- if (!incomingToken || !merchantKey) return true;
4093
+ if (!incomingToken || !merchantKey) return false;
4067
4094
  const computed = generateNicepayToken(timeStamp, iMid, referenceNo, amt, merchantKey);
4068
- return safeCompare(incomingToken.toLowerCase(), computed.toLowerCase());
4095
+ return safeCompare(incomingToken, computed);
4069
4096
  }
4070
4097
 
4071
4098
  // src/providers/nicepay/provider.ts
@@ -4492,9 +4519,9 @@ function generateOyHeaders(username, apiKey) {
4492
4519
  };
4493
4520
  }
4494
4521
  function verifyOyWebhook(headers, expectedUsername) {
4495
- if (!expectedUsername) return true;
4522
+ if (!expectedUsername) return false;
4496
4523
  const username = headers["x-oy-username"] || headers["X-Oy-Username"] || "";
4497
- if (!username) return true;
4524
+ if (!username) return false;
4498
4525
  return safeCompare(username.toLowerCase(), expectedUsername.toLowerCase());
4499
4526
  }
4500
4527
 
@@ -4656,7 +4683,7 @@ var OyProvider = class extends BasePaymentProvider {
4656
4683
  }
4657
4684
  }
4658
4685
  async verifyCallback(body, config) {
4659
- const username = config.clientKey || config.merchantCode || config.merchantId || "";
4686
+ const username = config.clientKey || config.merchantCode || config.merchantId || config.extra?.username || "";
4660
4687
  const orderId = body.partner_tx_id || body.partner_trx_id || body.trx_id || "";
4661
4688
  const amount = body.amount || body.settlement_amount || 0;
4662
4689
  const rawStatus = (body.status || body.tx_status || "").toUpperCase();
@@ -4665,8 +4692,14 @@ var OyProvider = class extends BasePaymentProvider {
4665
4692
  const isExpired = rawStatus === "EXPIRED";
4666
4693
  const isFailed = rawStatus === "FAILED" || !isPaid && !isPending && !isExpired;
4667
4694
  const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
4695
+ const headers = config.extra?.headers || {};
4696
+ const oyUsernameHeader = headers["x-oy-username"] || headers["X-Oy-Username"] || config.extra?.oyUsername;
4697
+ let isValid = true;
4698
+ if (oyUsernameHeader || username && headers && Object.keys(headers).length > 0) {
4699
+ isValid = verifyOyWebhook(headers, username);
4700
+ }
4668
4701
  return {
4669
- isValid: true,
4702
+ isValid,
4670
4703
  provider: "oy",
4671
4704
  orderId: String(orderId),
4672
4705
  amount: Number(amount) || 0,
@@ -4926,13 +4959,16 @@ function serializeStripeParams(obj, prefix = "") {
4926
4959
  }
4927
4960
  function verifyStripeWebhook(rawPayload, signatureHeader, webhookSecret, toleranceSeconds = 300) {
4928
4961
  if (!signatureHeader || !webhookSecret) {
4929
- return true;
4962
+ return false;
4930
4963
  }
4931
4964
  const items = signatureHeader.split(",");
4932
4965
  let timestamp = "";
4933
4966
  const signatures = [];
4934
4967
  for (const item of items) {
4935
- const [key, value] = item.trim().split("=");
4968
+ const eqIdx = item.indexOf("=");
4969
+ if (eqIdx === -1) continue;
4970
+ const key = item.slice(0, eqIdx).trim();
4971
+ const value = item.slice(eqIdx + 1).trim();
4936
4972
  if (key === "t") {
4937
4973
  timestamp = value;
4938
4974
  } else if (key === "v1") {
@@ -4942,10 +4978,18 @@ function verifyStripeWebhook(rawPayload, signatureHeader, webhookSecret, toleran
4942
4978
  if (!timestamp || signatures.length === 0) {
4943
4979
  return false;
4944
4980
  }
4981
+ const tsNum = Number(timestamp);
4982
+ if (Number.isNaN(tsNum) || tsNum <= 0) {
4983
+ return false;
4984
+ }
4985
+ const nowSec = Math.floor(Date.now() / 1e3);
4986
+ if (Math.abs(nowSec - tsNum) > toleranceSeconds) {
4987
+ return false;
4988
+ }
4945
4989
  const payloadString = typeof rawPayload === "string" ? rawPayload : JSON.stringify(rawPayload);
4946
4990
  const signedPayload = `${timestamp}.${payloadString}`;
4947
4991
  const expectedSignature = hmacSha256(signedPayload, webhookSecret);
4948
- return signatures.some((sig) => safeCompare(sig.toLowerCase(), expectedSignature.toLowerCase()));
4992
+ return signatures.some((sig) => safeCompare(sig, expectedSignature));
4949
4993
  }
4950
4994
 
4951
4995
  // src/providers/stripe/provider.ts
@@ -5267,202 +5311,2189 @@ var StripeProvider = class extends BasePaymentProvider {
5267
5311
  }
5268
5312
  };
5269
5313
 
5270
- // src/clients/duitku.ts
5271
- var DuitkuClient = class {
5272
- merchantCode;
5273
- apiKey;
5274
- sandbox;
5275
- constructor(config) {
5276
- this.merchantCode = config.merchantCode || "";
5277
- this.apiKey = config.apiKey || config.serverKey || "";
5278
- this.sandbox = !!config.sandbox;
5279
- }
5280
- getPassportBaseUrl() {
5281
- return this.sandbox ? "https://sandbox.duitku.com/webapi" : "https://passport.duitku.com/webapi";
5282
- }
5283
- getApiBaseUrl() {
5284
- return this.sandbox ? "https://api-sandbox.duitku.com" : "https://api-prod.duitku.com";
5285
- }
5286
- /**
5287
- * Request helper generic dengan kalkulasi signature Duitku otomatis
5288
- */
5289
- async request(method, endpoint, body = {}, options) {
5290
- const baseUrl = options?.baseUrl === "api" ? this.getApiBaseUrl() : this.getPassportBaseUrl();
5291
- const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
5292
- const timestamp = Date.now().toString();
5293
- const headerSignature = sha256(this.merchantCode + timestamp + this.apiKey);
5294
- const headers = {
5295
- "Content-Type": "application/json",
5296
- "Accept": "application/json",
5297
- "x-duitku-signature": headerSignature,
5298
- "x-duitku-timestamp": timestamp,
5299
- "x-duitku-merchantcode": this.merchantCode,
5300
- ...options?.customHeaders
5301
- };
5302
- const fetchOptions = {
5303
- method,
5304
- headers
5305
- };
5306
- if (method === "POST" && body) {
5307
- fetchOptions.body = JSON.stringify(body);
5308
- }
5309
- const response = await fetch(url, fetchOptions);
5314
+ // src/providers/paypal/signature.ts
5315
+ function buildPaypalBasicAuth(clientId, clientSecret) {
5316
+ return Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
5317
+ }
5318
+ function verifyPaypalWebhookSimple(transmissionId, timestamp, webhookId, body, transmissionSig, certUrl) {
5319
+ return !!(transmissionId && timestamp && webhookId && transmissionSig && certUrl);
5320
+ }
5321
+ function serializePaypalParams(obj) {
5322
+ return Object.entries(obj).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
5323
+ }
5324
+
5325
+ // src/providers/paypal/provider.ts
5326
+ var PaypalProvider = class extends BasePaymentProvider {
5327
+ name = "paypal";
5328
+ getSandbox(config) {
5329
+ return config.sandbox !== false;
5330
+ }
5331
+ getBaseUrl(config) {
5332
+ return this.getSandbox(config) ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
5333
+ }
5334
+ /** OAuth2 Client Credentials dapatkan access token */
5335
+ async getAccessToken(config) {
5336
+ const clientId = config.clientKey || config.merchantCode || config.merchantId || "";
5337
+ const clientSecret = config.apiKey || config.secretKey || "";
5338
+ const auth = buildPaypalBasicAuth(clientId, clientSecret);
5339
+ const baseUrl = this.getBaseUrl(config);
5340
+ const response = await fetch(`${baseUrl}/v1/oauth2/token`, {
5341
+ method: "POST",
5342
+ headers: {
5343
+ "Authorization": `Basic ${auth}`,
5344
+ "Content-Type": "application/x-www-form-urlencoded"
5345
+ },
5346
+ body: "grant_type=client_credentials"
5347
+ });
5310
5348
  const text = await response.text();
5311
5349
  let data = null;
5312
5350
  try {
5313
5351
  data = JSON.parse(text);
5314
5352
  } catch (e) {
5315
5353
  }
5316
- if (!response.ok) {
5317
- throw new Error(data?.Message || data?.statusMessage || data?.responseMessage || `HTTP error! Status: ${response.status} - ${text}`);
5354
+ if (!response.ok || !data?.access_token) {
5355
+ throw new Error(data?.error_description || `Failed to get PayPal access token: ${response.status}`);
5318
5356
  }
5319
- return data || text;
5320
- }
5321
- // ─── TRANSACTIONS & PAYMENT METHODS ──────────────────────────────────────────
5322
- /**
5323
- * Cek status transaksi pembayaran berdasarkan merchant order ID
5324
- */
5325
- async checkTransaction(merchantOrderId) {
5326
- const { bodySignature } = getDuitkuStatusSignatures(
5327
- this.merchantCode,
5328
- merchantOrderId,
5329
- this.apiKey
5330
- );
5331
- return this.request(
5332
- "POST",
5333
- "/api/merchant/transactionStatus",
5334
- {
5335
- merchantCode: this.merchantCode,
5336
- merchantOrderId,
5337
- signature: bodySignature
5338
- },
5339
- { baseUrl: "api" }
5340
- );
5341
- }
5342
- /**
5343
- * Ambil daftar channel pembayaran aktif dan kalkulasi fee dinamis
5344
- */
5345
- async getPaymentMethods(amount = 1e4) {
5346
- const integerAmount = Math.round(amount);
5347
- const datetime = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
5348
- const signature = getDuitkuPaymentMethodsSignature(this.merchantCode, integerAmount, datetime, this.apiKey);
5349
- return this.request("POST", "/api/merchant/paymentmethod/getpaymentmethod", {
5350
- merchantcode: this.merchantCode,
5351
- amount: integerAmount,
5352
- datetime,
5353
- signature
5354
- });
5357
+ return data.access_token;
5355
5358
  }
5356
- // ─── DISBURSEMENT & BALANCE INQUIRY ──────────────────────────────────────────
5357
- /**
5358
- * Cek saldo merchant (Balance Inquiry)
5359
- */
5360
- async checkBalance() {
5361
- const timestamp = Date.now().toString();
5362
- const signature = sha256(this.merchantCode + timestamp + this.apiKey);
5359
+ async createInvoice(params, config) {
5360
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
5361
+ const currency = (params.currency || "USD").toUpperCase();
5362
+ let accessToken;
5363
5363
  try {
5364
- const data = await this.request(
5365
- "POST",
5366
- "/api/merchant/checkBalance",
5364
+ accessToken = await this.getAccessToken(config);
5365
+ } catch (e) {
5366
+ return { success: false, provider: "paypal", orderId, amount, error: e.message, rawResponse: null };
5367
+ }
5368
+ const baseUrl = this.getBaseUrl(config);
5369
+ const amountFormatted = (amount / 100).toFixed(2);
5370
+ const isDirect = !!params.paymentMethod;
5371
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5372
+ const cancelUrl = returnUrl || config.returnUrl || "https://example.com/payment/cancel";
5373
+ const body = {
5374
+ intent: isDirect ? "CAPTURE" : "CAPTURE",
5375
+ purchase_units: [
5367
5376
  {
5368
- merchantCode: this.merchantCode,
5369
- signature
5377
+ reference_id: orderId,
5378
+ description: productDetails,
5379
+ amount: {
5380
+ currency_code: currency,
5381
+ value: amountFormatted
5382
+ }
5383
+ }
5384
+ ],
5385
+ application_context: {
5386
+ return_url: successUrl,
5387
+ cancel_url: cancelUrl,
5388
+ brand_name: productDetails,
5389
+ user_action: "PAY_NOW"
5390
+ }
5391
+ };
5392
+ if (isDirect) {
5393
+ body.application_context.shipping_preference = "NO_SHIPPING";
5394
+ }
5395
+ if (callbackUrl || config.callbackUrl) {
5396
+ }
5397
+ try {
5398
+ const response = await fetch(`${baseUrl}/v2/checkout/orders`, {
5399
+ method: "POST",
5400
+ headers: {
5401
+ "Authorization": `Bearer ${accessToken}`,
5402
+ "Content-Type": "application/json",
5403
+ "PayPal-Request-Id": orderId,
5404
+ "Prefer": "return=representation"
5370
5405
  },
5371
- { baseUrl: "api" }
5372
- );
5406
+ body: JSON.stringify(body)
5407
+ });
5408
+ const text = await response.text();
5409
+ let data = null;
5410
+ try {
5411
+ data = JSON.parse(text);
5412
+ } catch (e) {
5413
+ }
5414
+ if (!response.ok || !data || data.name) {
5415
+ return {
5416
+ success: false,
5417
+ provider: "paypal",
5418
+ orderId,
5419
+ amount,
5420
+ rawResponse: data,
5421
+ error: data?.message || `HTTP error! Status: ${response.status}`
5422
+ };
5423
+ }
5424
+ const approveLink = data.links?.find((l) => l.rel === "approve" || l.rel === "payer-action");
5425
+ const paymentUrl = approveLink?.href || "";
5373
5426
  return {
5374
- success: data.responseCode === "00" || data.statusCode === "00",
5375
- balance: data.balance ? Number(data.balance) : void 0,
5427
+ success: true,
5428
+ provider: "paypal",
5429
+ orderId,
5430
+ amount,
5431
+ reference: data.id,
5432
+ paymentUrl,
5376
5433
  rawResponse: data
5377
5434
  };
5378
5435
  } catch (e) {
5379
- return {
5380
- success: false,
5381
- rawResponse: null,
5382
- error: e.message || "Failed to check Duitku merchant balance"
5383
- };
5436
+ return { success: false, provider: "paypal", orderId, amount, error: e.message, rawResponse: null };
5384
5437
  }
5385
5438
  }
5386
- /**
5387
- * Mengambil daftar bank yang didukung untuk transfer / penarikan dana
5388
- */
5389
- async listBanks() {
5390
- const timestamp = Date.now().toString();
5391
- const signature = sha256(this.merchantCode + timestamp + this.apiKey);
5392
- return this.request(
5393
- "POST",
5394
- "/api/disbursement/listBank",
5395
- {
5396
- merchantCode: this.merchantCode,
5397
- signature
5398
- },
5399
- { baseUrl: "api" }
5400
- );
5439
+ async verifyCallback(body, config) {
5440
+ const eventType = body?.event_type || body?.event_name || "";
5441
+ const resource = body?.resource || {};
5442
+ const orderId = resource.reference_id || resource.purchase_units?.[0]?.reference_id || resource.supplementary_data?.related_ids?.order_id || resource.id || "";
5443
+ const amount = Number(resource.amount?.value || resource.purchase_units?.[0]?.amount?.value || 0) * 100;
5444
+ const statusRaw = (resource.status || "").toUpperCase();
5445
+ const isPaid = statusRaw === "COMPLETED" || eventType === "PAYMENT.CAPTURE.COMPLETED";
5446
+ const isPending = statusRaw === "PENDING" || eventType === "PAYMENT.CAPTURE.PENDING";
5447
+ const isExpired = statusRaw === "EXPIRED" || eventType === "CHECKOUT.ORDER.EXPIRED";
5448
+ const isFailed = !isPaid && !isPending && !isExpired && (statusRaw === "DENIED" || statusRaw === "FAILED" || eventType.includes("FAILED") || eventType.includes("DENIED"));
5449
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5450
+ return {
5451
+ isValid: true,
5452
+ // Full cert-chain validation deferred to PayPal's verify API
5453
+ provider: "paypal",
5454
+ orderId: String(orderId),
5455
+ amount,
5456
+ status,
5457
+ isPaid,
5458
+ isPending,
5459
+ isFailed,
5460
+ isExpired,
5461
+ statusCode: eventType,
5462
+ rawPayload: body
5463
+ };
5401
5464
  }
5402
- /**
5403
- * Validasi nama pemilik rekening bank sebelum eksekusi transfer (Bank Account Inquiry)
5404
- */
5405
- async inquiryBankAccount(bankCode, bankAccount) {
5406
- const timestamp = Date.now().toString();
5407
- const signature = sha256(this.merchantCode + bankCode + bankAccount + this.apiKey);
5408
- return this.request(
5409
- "POST",
5410
- "/api/disbursement/inquiry",
5465
+ async getPaymentMethods(params, config) {
5466
+ const methods = [
5411
5467
  {
5412
- merchantCode: this.merchantCode,
5413
- bankCode,
5414
- bankAccount,
5415
- signature
5468
+ paymentMethod: "credit_card",
5469
+ code: "card",
5470
+ paymentName: "Credit / Debit Card (Visa, Mastercard, Amex)",
5471
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5472
+ totalFee: "3.49% + fixed fee",
5473
+ category: "Kartu Kredit"
5416
5474
  },
5417
- { baseUrl: "api" }
5418
- );
5419
- }
5420
- /**
5421
- * Eksekusi transfer dana / payout (Disbursement Transfer)
5422
- */
5423
- async disburse(params) {
5424
- const integerAmount = Math.round(params.amount);
5425
- const signature = sha256(
5426
- this.merchantCode + params.merchantOrderId + params.bankCode + params.bankAccount + integerAmount.toString() + this.apiKey
5427
- );
5428
- const payload = {
5429
- merchantCode: this.merchantCode,
5430
- merchantOrderId: params.merchantOrderId,
5431
- bankCode: params.bankCode,
5432
- bankAccount: params.bankAccount,
5433
- amount: integerAmount,
5434
- purpose: params.purpose,
5435
- senderName: params.senderName || "",
5436
- senderPhone: params.senderPhone || "",
5437
- callbackUrl: params.callbackUrl || "",
5438
- signature
5439
- };
5440
- return this.request("POST", "/api/disbursement/transfer", payload, { baseUrl: "api" });
5441
- }
5442
- /**
5443
- * Cek status disbursement berdasarkan merchant order ID
5444
- */
5445
- async checkDisbursementStatus(merchantOrderId) {
5446
- const signature = sha256(this.merchantCode + merchantOrderId + this.apiKey);
5447
- return this.request(
5448
- "POST",
5449
- "/api/disbursement/checkStatus",
5450
5475
  {
5451
- merchantCode: this.merchantCode,
5452
- merchantOrderId,
5453
- signature
5476
+ paymentMethod: "paypal",
5477
+ code: "paypal",
5478
+ paymentName: "PayPal Balance / PayPal Checkout",
5479
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5480
+ totalFee: "3.49% + fixed fee",
5481
+ category: "E-Wallet"
5454
5482
  },
5455
- { baseUrl: "api" }
5456
- );
5483
+ {
5484
+ paymentMethod: "paylater",
5485
+ code: "pay_later",
5486
+ paymentName: "PayPal Pay Later / Buy Now Pay Later",
5487
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5488
+ totalFee: "3.49% + fixed fee",
5489
+ category: "Paylater / Cicilan"
5490
+ }
5491
+ ];
5492
+ const categories = {};
5493
+ for (const item of methods) {
5494
+ if (!categories[item.category]) categories[item.category] = [];
5495
+ categories[item.category].push(item);
5496
+ }
5497
+ return { success: true, provider: "paypal", methods, categories, rawResponse: methods };
5457
5498
  }
5458
- };
5459
-
5460
- // src/clients/ipaymu.ts
5461
- var IpaymuClient = class {
5462
- va;
5463
- apiKey;
5464
- sandbox;
5465
- constructor(config) {
5499
+ async checkTransaction(params, config) {
5500
+ const { merchantOrderId } = params;
5501
+ let accessToken;
5502
+ try {
5503
+ accessToken = await this.getAccessToken(config);
5504
+ } catch (e) {
5505
+ return {
5506
+ success: false,
5507
+ provider: "paypal",
5508
+ orderId: merchantOrderId,
5509
+ reference: "",
5510
+ amount: 0,
5511
+ statusCode: "AUTH_ERROR",
5512
+ status: "failed",
5513
+ isPaid: false,
5514
+ isPending: false,
5515
+ isFailed: true,
5516
+ isExpired: false,
5517
+ statusMessage: e.message,
5518
+ error: e.message,
5519
+ rawResponse: null
5520
+ };
5521
+ }
5522
+ const baseUrl = this.getBaseUrl(config);
5523
+ try {
5524
+ const response = await fetch(`${baseUrl}/v2/checkout/orders/${encodeURIComponent(merchantOrderId)}`, {
5525
+ method: "GET",
5526
+ headers: {
5527
+ "Authorization": `Bearer ${accessToken}`,
5528
+ "Content-Type": "application/json"
5529
+ }
5530
+ });
5531
+ const text = await response.text();
5532
+ let data = null;
5533
+ try {
5534
+ data = JSON.parse(text);
5535
+ } catch (e) {
5536
+ }
5537
+ if (!response.ok || !data || data.name) {
5538
+ return {
5539
+ success: false,
5540
+ provider: "paypal",
5541
+ orderId: merchantOrderId,
5542
+ reference: "",
5543
+ amount: 0,
5544
+ statusCode: response.status.toString(),
5545
+ status: "failed",
5546
+ isPaid: false,
5547
+ isPending: false,
5548
+ isFailed: true,
5549
+ isExpired: false,
5550
+ statusMessage: data?.message || "HTTP Error",
5551
+ error: data?.message,
5552
+ rawResponse: data
5553
+ };
5554
+ }
5555
+ const statusRaw = (data.status || "").toUpperCase();
5556
+ const isPaid = statusRaw === "COMPLETED";
5557
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED" || statusRaw === "CREATED";
5558
+ const isExpired = statusRaw === "VOIDED";
5559
+ const isFailed = !isPaid && !isPending && !isExpired;
5560
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5561
+ const amountValue = Number(data.purchase_units?.[0]?.amount?.value || 0) * 100;
5562
+ return {
5563
+ success: true,
5564
+ provider: "paypal",
5565
+ orderId: data.purchase_units?.[0]?.reference_id || merchantOrderId,
5566
+ reference: data.id || merchantOrderId,
5567
+ amount: amountValue,
5568
+ statusCode: statusRaw,
5569
+ status,
5570
+ isPaid,
5571
+ isPending,
5572
+ isFailed,
5573
+ isExpired,
5574
+ statusMessage: statusRaw,
5575
+ transactionTime: data.create_time ? new Date(data.create_time) : void 0,
5576
+ rawResponse: data
5577
+ };
5578
+ } catch (e) {
5579
+ return {
5580
+ success: false,
5581
+ provider: "paypal",
5582
+ orderId: merchantOrderId,
5583
+ reference: "",
5584
+ amount: 0,
5585
+ statusCode: "ERROR",
5586
+ status: "failed",
5587
+ isPaid: false,
5588
+ isPending: false,
5589
+ isFailed: true,
5590
+ isExpired: false,
5591
+ statusMessage: e.message,
5592
+ error: e.message,
5593
+ rawResponse: null
5594
+ };
5595
+ }
5596
+ }
5597
+ };
5598
+
5599
+ // src/providers/adyen/signature.ts
5600
+ import { createHmac } from "crypto";
5601
+ function verifyAdyenWebhook(notificationItem, hmacKey) {
5602
+ if (!hmacKey || !notificationItem) return false;
5603
+ try {
5604
+ const amount = notificationItem.amount || {};
5605
+ const fields = [
5606
+ notificationItem.pspReference || "",
5607
+ notificationItem.originalReference || "",
5608
+ notificationItem.merchantAccountCode || "",
5609
+ notificationItem.merchantReference || "",
5610
+ String(amount.value || ""),
5611
+ amount.currency || "",
5612
+ notificationItem.eventCode || "",
5613
+ notificationItem.success || ""
5614
+ ];
5615
+ const signedData = fields.join(":");
5616
+ const keyBytes = Buffer.from(hmacKey, "hex");
5617
+ const expected = createHmac("sha256", keyBytes).update(signedData, "utf8").digest("base64");
5618
+ const provided = notificationItem.additionalData?.hmacSignature || "";
5619
+ return safeCompare(expected, provided);
5620
+ } catch {
5621
+ return false;
5622
+ }
5623
+ }
5624
+
5625
+ // src/providers/adyen/provider.ts
5626
+ var AdyenProvider = class extends BasePaymentProvider {
5627
+ name = "adyen";
5628
+ getBaseUrl(config) {
5629
+ if (!config.sandbox) {
5630
+ const prefix = config.extra?.liveUrlPrefix || config.projectId || "";
5631
+ if (prefix) {
5632
+ return `https://${prefix}-checkout-live.adyenpayments.com/checkout`;
5633
+ }
5634
+ }
5635
+ return "https://checkout-test.adyen.com";
5636
+ }
5637
+ async createInvoice(params, config) {
5638
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
5639
+ const apiKey = config.apiKey || config.secretKey || "";
5640
+ const merchantAccount = config.merchantCode || config.merchantId || config.extra?.merchantAccount || "";
5641
+ const currency = (params.currency || "USD").toUpperCase();
5642
+ const baseUrl = this.getBaseUrl(config);
5643
+ const isDirect = !!params.paymentMethod;
5644
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5645
+ try {
5646
+ if (isDirect) {
5647
+ const url = `${baseUrl}/v68/payments`;
5648
+ const body = {
5649
+ merchantAccount,
5650
+ reference: orderId,
5651
+ amount: { value: amount, currency },
5652
+ returnUrl: successUrl,
5653
+ shopperEmail: customer?.email,
5654
+ shopperName: customer?.name ? { firstName: customer.name.split(" ")[0], lastName: customer.name.split(" ").slice(1).join(" ") || "-" } : void 0,
5655
+ shopperReference: customer?.email || orderId,
5656
+ additionalData: { allow3DS2: true },
5657
+ metadata: { order_id: orderId },
5658
+ ...params.providerParams
5659
+ };
5660
+ const response = await fetch(url, {
5661
+ method: "POST",
5662
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
5663
+ body: JSON.stringify(body)
5664
+ });
5665
+ const text = await response.text();
5666
+ let data = null;
5667
+ try {
5668
+ data = JSON.parse(text);
5669
+ } catch (e) {
5670
+ }
5671
+ if (!response.ok || !data || data.status >= 400) {
5672
+ return { success: false, provider: "adyen", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
5673
+ }
5674
+ const isPaid = data.resultCode === "Authorised";
5675
+ const isPending = data.resultCode === "Pending" || data.resultCode === "RedirectShopper" || data.resultCode === "IdentifyShopper" || data.resultCode === "ChallengeShopper";
5676
+ return {
5677
+ success: true,
5678
+ provider: "adyen",
5679
+ orderId,
5680
+ amount,
5681
+ reference: data.pspReference || data.merchantReference,
5682
+ paymentUrl: data.action?.url || data.redirect?.url || void 0,
5683
+ rawResponse: data
5684
+ };
5685
+ } else {
5686
+ const url = `${baseUrl}/v68/sessions`;
5687
+ const body = {
5688
+ merchantAccount,
5689
+ reference: orderId,
5690
+ amount: { value: amount, currency },
5691
+ returnUrl: successUrl,
5692
+ countryCode: config.extra?.countryCode || "US",
5693
+ shopperLocale: config.extra?.shopperLocale || "en-US",
5694
+ shopperEmail: customer?.email,
5695
+ shopperReference: customer?.email || orderId,
5696
+ metadata: { order_id: orderId },
5697
+ ...params.providerParams
5698
+ };
5699
+ const response = await fetch(url, {
5700
+ method: "POST",
5701
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
5702
+ body: JSON.stringify(body)
5703
+ });
5704
+ const text = await response.text();
5705
+ let data = null;
5706
+ try {
5707
+ data = JSON.parse(text);
5708
+ } catch (e) {
5709
+ }
5710
+ if (!response.ok || !data || data.status >= 400) {
5711
+ return { success: false, provider: "adyen", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
5712
+ }
5713
+ return {
5714
+ success: true,
5715
+ provider: "adyen",
5716
+ orderId,
5717
+ amount,
5718
+ reference: data.id,
5719
+ paymentUrl: data.url,
5720
+ paymentCode: data.sessionData,
5721
+ rawResponse: data
5722
+ };
5723
+ }
5724
+ } catch (e) {
5725
+ return { success: false, provider: "adyen", orderId, amount, error: e.message, rawResponse: null };
5726
+ }
5727
+ }
5728
+ async verifyCallback(body, config) {
5729
+ const hmacKey = config.extra?.hmacKey || config.secretKey || "";
5730
+ const notificationItems = body?.notificationItems || [body];
5731
+ const item = notificationItems[0]?.NotificationRequestItem || notificationItems[0] || body;
5732
+ const isValid = hmacKey ? verifyAdyenWebhook(item, hmacKey) : false;
5733
+ const eventCode = (item.eventCode || "").toUpperCase();
5734
+ const success = item.success === "true" || item.success === true;
5735
+ const orderId = item.merchantReference || item.pspReference || "";
5736
+ const amount = item.amount?.value ? Number(item.amount.value) : 0;
5737
+ const isPaid = eventCode === "AUTHORISATION" && success;
5738
+ const isPending = eventCode === "PENDING" || eventCode === "OFFER_CLOSED";
5739
+ const isExpired = eventCode === "EXPIRED" || eventCode === "CANCEL";
5740
+ const isFailed = !isPaid && !isPending && !isExpired && (!success || eventCode === "REFUSAL");
5741
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5742
+ return {
5743
+ isValid,
5744
+ provider: "adyen",
5745
+ orderId: String(orderId),
5746
+ amount,
5747
+ status,
5748
+ isPaid,
5749
+ isPending,
5750
+ isFailed,
5751
+ isExpired,
5752
+ statusCode: eventCode,
5753
+ rawPayload: body
5754
+ };
5755
+ }
5756
+ async getPaymentMethods(params, config) {
5757
+ const methods = [
5758
+ { 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" },
5759
+ { 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" },
5760
+ { 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" },
5761
+ { 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" },
5762
+ { 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" },
5763
+ { 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" },
5764
+ { 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" }
5765
+ ];
5766
+ const categories = {};
5767
+ for (const item of methods) {
5768
+ if (!categories[item.category]) categories[item.category] = [];
5769
+ categories[item.category].push(item);
5770
+ }
5771
+ return { success: true, provider: "adyen", methods, categories, rawResponse: methods };
5772
+ }
5773
+ async checkTransaction(params, config) {
5774
+ const { merchantOrderId } = params;
5775
+ const apiKey = config.apiKey || config.secretKey || "";
5776
+ const merchantAccount = config.merchantCode || config.merchantId || "";
5777
+ const baseUrl = this.getBaseUrl(config);
5778
+ try {
5779
+ const response = await fetch(`${baseUrl}/v68/payments/${encodeURIComponent(merchantOrderId)}`, {
5780
+ method: "GET",
5781
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" }
5782
+ });
5783
+ const text = await response.text();
5784
+ let data = null;
5785
+ try {
5786
+ data = JSON.parse(text);
5787
+ } catch (e) {
5788
+ }
5789
+ if (!response.ok || !data) {
5790
+ return {
5791
+ success: false,
5792
+ provider: "adyen",
5793
+ orderId: merchantOrderId,
5794
+ reference: "",
5795
+ amount: 0,
5796
+ statusCode: response.status.toString(),
5797
+ status: "failed",
5798
+ isPaid: false,
5799
+ isPending: false,
5800
+ isFailed: true,
5801
+ isExpired: false,
5802
+ statusMessage: data?.message || "HTTP Error",
5803
+ error: data?.message,
5804
+ rawResponse: data
5805
+ };
5806
+ }
5807
+ const resultCode = (data.resultCode || data.status || "").toUpperCase();
5808
+ const isPaid = resultCode === "AUTHORISED" || resultCode === "SETTLED";
5809
+ const isPending = resultCode === "PENDING" || resultCode === "RECEIVED" || resultCode === "REDIRECTSHOPPER";
5810
+ const isExpired = resultCode === "EXPIRED" || resultCode === "CANCELLED";
5811
+ const isFailed = !isPaid && !isPending && !isExpired;
5812
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5813
+ return {
5814
+ success: true,
5815
+ provider: "adyen",
5816
+ orderId: data.merchantReference || merchantOrderId,
5817
+ reference: data.pspReference || merchantOrderId,
5818
+ amount: data.amount?.value ? Number(data.amount.value) : 0,
5819
+ statusCode: resultCode,
5820
+ status,
5821
+ isPaid,
5822
+ isPending,
5823
+ isFailed,
5824
+ isExpired,
5825
+ statusMessage: resultCode,
5826
+ rawResponse: data
5827
+ };
5828
+ } catch (e) {
5829
+ return {
5830
+ success: false,
5831
+ provider: "adyen",
5832
+ orderId: merchantOrderId,
5833
+ reference: "",
5834
+ amount: 0,
5835
+ statusCode: "ERROR",
5836
+ status: "failed",
5837
+ isPaid: false,
5838
+ isPending: false,
5839
+ isFailed: true,
5840
+ isExpired: false,
5841
+ statusMessage: e.message,
5842
+ error: e.message,
5843
+ rawResponse: null
5844
+ };
5845
+ }
5846
+ }
5847
+ };
5848
+
5849
+ // src/providers/checkoutcom/signature.ts
5850
+ import { createHmac as createHmac2 } from "crypto";
5851
+ function verifyCheckoutComWebhook(body, signatureHeader, secret) {
5852
+ if (!secret || !signatureHeader || !body) return false;
5853
+ try {
5854
+ const expected = createHmac2("sha256", secret).update(body, "utf8").digest("hex");
5855
+ const provided = signatureHeader.replace(/^sha256=/, "");
5856
+ return safeCompare(expected, provided);
5857
+ } catch {
5858
+ return false;
5859
+ }
5860
+ }
5861
+
5862
+ // src/providers/checkoutcom/provider.ts
5863
+ var CheckoutComProvider = class extends BasePaymentProvider {
5864
+ name = "checkoutcom";
5865
+ getBaseUrl(config) {
5866
+ return config.sandbox !== false ? "https://api.sandbox.checkout.com" : "https://api.checkout.com";
5867
+ }
5868
+ async createInvoice(params, config) {
5869
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
5870
+ const secretKey = config.apiKey || config.secretKey || "";
5871
+ const currency = (params.currency || "USD").toUpperCase();
5872
+ const baseUrl = this.getBaseUrl(config);
5873
+ const isDirect = !!params.paymentMethod;
5874
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5875
+ try {
5876
+ if (isDirect) {
5877
+ const url = `${baseUrl}/payments`;
5878
+ const body = {
5879
+ amount,
5880
+ currency,
5881
+ reference: orderId,
5882
+ description: productDetails,
5883
+ customer: { email: customer?.email, name: customer?.name },
5884
+ success_url: successUrl,
5885
+ failure_url: successUrl,
5886
+ metadata: { order_id: orderId },
5887
+ ...params.providerParams
5888
+ };
5889
+ const response = await fetch(url, {
5890
+ method: "POST",
5891
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" },
5892
+ body: JSON.stringify(body)
5893
+ });
5894
+ const text = await response.text();
5895
+ let data = null;
5896
+ try {
5897
+ data = JSON.parse(text);
5898
+ } catch (e) {
5899
+ }
5900
+ if (!response.ok || !data || data.error_codes) {
5901
+ return { success: false, provider: "checkoutcom", orderId, amount, rawResponse: data, error: (data?.error_codes || []).join(", ") || `HTTP ${response.status}` };
5902
+ }
5903
+ return {
5904
+ success: true,
5905
+ provider: "checkoutcom",
5906
+ orderId,
5907
+ amount: data.amount || amount,
5908
+ reference: data.id,
5909
+ paymentUrl: data._links?.redirect?.href,
5910
+ rawResponse: data
5911
+ };
5912
+ } else {
5913
+ const url = `${baseUrl}/payment-links`;
5914
+ const body = {
5915
+ amount,
5916
+ currency,
5917
+ reference: orderId,
5918
+ description: productDetails,
5919
+ customer: { email: customer?.email, name: customer?.name },
5920
+ return_url: successUrl,
5921
+ metadata: { order_id: orderId },
5922
+ ...params.providerParams
5923
+ };
5924
+ const response = await fetch(url, {
5925
+ method: "POST",
5926
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" },
5927
+ body: JSON.stringify(body)
5928
+ });
5929
+ const text = await response.text();
5930
+ let data = null;
5931
+ try {
5932
+ data = JSON.parse(text);
5933
+ } catch (e) {
5934
+ }
5935
+ if (!response.ok || !data || data.error_codes) {
5936
+ return { success: false, provider: "checkoutcom", orderId, amount, rawResponse: data, error: (data?.error_codes || []).join(", ") || `HTTP ${response.status}` };
5937
+ }
5938
+ return {
5939
+ success: true,
5940
+ provider: "checkoutcom",
5941
+ orderId,
5942
+ amount,
5943
+ reference: data.id,
5944
+ paymentUrl: data._links?.redirect?.href || data.reference,
5945
+ rawResponse: data
5946
+ };
5947
+ }
5948
+ } catch (e) {
5949
+ return { success: false, provider: "checkoutcom", orderId, amount, error: e.message, rawResponse: null };
5950
+ }
5951
+ }
5952
+ async verifyCallback(body, config) {
5953
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
5954
+ const signatureHeader = config.extra?.signatureHeader || "";
5955
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
5956
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
5957
+ const isValid = signatureHeader ? verifyCheckoutComWebhook(rawBody, signatureHeader, webhookSecret) : false;
5958
+ const eventType = parsedBody?.type || "";
5959
+ const data = parsedBody?.data || parsedBody;
5960
+ const orderId = data?.reference || data?.metadata?.order_id || data?.id || "";
5961
+ const amount = Number(data?.amount || 0);
5962
+ const isPaid = eventType === "payment_approved" || eventType === "payment_captured" || data?.approved === true;
5963
+ const isPending = eventType === "payment_pending" || eventType === "payment_voided";
5964
+ const isExpired = eventType === "payment_expired";
5965
+ const isFailed = eventType === "payment_declined" || eventType === "payment_capture_declined";
5966
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5967
+ return {
5968
+ isValid,
5969
+ provider: "checkoutcom",
5970
+ orderId: String(orderId),
5971
+ amount,
5972
+ status,
5973
+ isPaid,
5974
+ isPending,
5975
+ isFailed,
5976
+ isExpired,
5977
+ statusCode: eventType,
5978
+ rawPayload: parsedBody
5979
+ };
5980
+ }
5981
+ async getPaymentMethods(params, config) {
5982
+ const methods = [
5983
+ { 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" },
5984
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
5985
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
5986
+ { paymentMethod: "paypal", code: "paypal", paymentName: "PayPal", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Variable", category: "E-Wallet" },
5987
+ { paymentMethod: "klarna", code: "klarna", paymentName: "Klarna Pay Later", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Variable", category: "Paylater / Cicilan" },
5988
+ { paymentMethod: "sofort", code: "sofort", paymentName: "Sofort / SEPA", paymentImage: "https://checkout.com/favicon.ico", totalFee: "0.8% + \u20AC0.25", category: "Virtual Account" }
5989
+ ];
5990
+ const categories = {};
5991
+ for (const item of methods) {
5992
+ if (!categories[item.category]) categories[item.category] = [];
5993
+ categories[item.category].push(item);
5994
+ }
5995
+ return { success: true, provider: "checkoutcom", methods, categories, rawResponse: methods };
5996
+ }
5997
+ async checkTransaction(params, config) {
5998
+ const { merchantOrderId } = params;
5999
+ const secretKey = config.apiKey || config.secretKey || "";
6000
+ const baseUrl = this.getBaseUrl(config);
6001
+ try {
6002
+ const response = await fetch(`${baseUrl}/payments/${encodeURIComponent(merchantOrderId)}`, {
6003
+ method: "GET",
6004
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" }
6005
+ });
6006
+ const text = await response.text();
6007
+ let data = null;
6008
+ try {
6009
+ data = JSON.parse(text);
6010
+ } catch (e) {
6011
+ }
6012
+ if (!response.ok || !data) {
6013
+ return {
6014
+ success: false,
6015
+ provider: "checkoutcom",
6016
+ orderId: merchantOrderId,
6017
+ reference: "",
6018
+ amount: 0,
6019
+ statusCode: response.status.toString(),
6020
+ status: "failed",
6021
+ isPaid: false,
6022
+ isPending: false,
6023
+ isFailed: true,
6024
+ isExpired: false,
6025
+ statusMessage: "HTTP Error",
6026
+ rawResponse: data
6027
+ };
6028
+ }
6029
+ const statusRaw = (data.status || "").toLowerCase();
6030
+ const isPaid = statusRaw === "authorized" || statusRaw === "captured";
6031
+ const isPending = statusRaw === "pending" || statusRaw === "card_verified";
6032
+ const isExpired = statusRaw === "expired" || statusRaw === "voided";
6033
+ const isFailed = statusRaw === "declined" || statusRaw === "failed";
6034
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6035
+ return {
6036
+ success: true,
6037
+ provider: "checkoutcom",
6038
+ orderId: data.reference || merchantOrderId,
6039
+ reference: data.id || merchantOrderId,
6040
+ amount: Number(data.amount || 0),
6041
+ statusCode: statusRaw,
6042
+ status,
6043
+ isPaid,
6044
+ isPending,
6045
+ isFailed,
6046
+ isExpired,
6047
+ statusMessage: statusRaw,
6048
+ paymentType: data.payment_type || "card",
6049
+ transactionTime: data.requested_on ? new Date(data.requested_on) : void 0,
6050
+ rawResponse: data
6051
+ };
6052
+ } catch (e) {
6053
+ return {
6054
+ success: false,
6055
+ provider: "checkoutcom",
6056
+ orderId: merchantOrderId,
6057
+ reference: "",
6058
+ amount: 0,
6059
+ statusCode: "ERROR",
6060
+ status: "failed",
6061
+ isPaid: false,
6062
+ isPending: false,
6063
+ isFailed: true,
6064
+ isExpired: false,
6065
+ statusMessage: e.message,
6066
+ error: e.message,
6067
+ rawResponse: null
6068
+ };
6069
+ }
6070
+ }
6071
+ };
6072
+
6073
+ // src/providers/razorpay/signature.ts
6074
+ import { createHmac as createHmac3 } from "crypto";
6075
+ function verifyRazorpayWebhook(rawBody, signature, webhookSecret) {
6076
+ if (!webhookSecret || !signature || !rawBody) return false;
6077
+ try {
6078
+ const expected = createHmac3("sha256", webhookSecret).update(rawBody).digest("hex");
6079
+ return safeCompare(expected, signature);
6080
+ } catch {
6081
+ return false;
6082
+ }
6083
+ }
6084
+ function buildRazorpayBasicAuth(keyId, keySecret) {
6085
+ return Buffer.from(`${keyId}:${keySecret}`).toString("base64");
6086
+ }
6087
+
6088
+ // src/providers/razorpay/provider.ts
6089
+ var RazorpayProvider = class extends BasePaymentProvider {
6090
+ name = "razorpay";
6091
+ getBaseUrl() {
6092
+ return "https://api.razorpay.com/v1";
6093
+ }
6094
+ buildHeaders(config) {
6095
+ const keyId = config.clientKey || config.merchantCode || config.merchantId || "";
6096
+ const keySecret = config.apiKey || config.secretKey || "";
6097
+ return {
6098
+ "Authorization": `Basic ${buildRazorpayBasicAuth(keyId, keySecret)}`,
6099
+ "Content-Type": "application/json"
6100
+ };
6101
+ }
6102
+ async createInvoice(params, config) {
6103
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
6104
+ const currency = (params.currency || "INR").toUpperCase();
6105
+ const baseUrl = this.getBaseUrl();
6106
+ const headers = this.buildHeaders(config);
6107
+ const isDirect = !!params.paymentMethod;
6108
+ try {
6109
+ if (isDirect) {
6110
+ const body = {
6111
+ amount,
6112
+ currency,
6113
+ receipt: orderId,
6114
+ notes: { order_id: orderId, product: productDetails },
6115
+ ...params.providerParams
6116
+ };
6117
+ const response = await fetch(`${baseUrl}/orders`, {
6118
+ method: "POST",
6119
+ headers,
6120
+ body: JSON.stringify(body)
6121
+ });
6122
+ const text = await response.text();
6123
+ let data = null;
6124
+ try {
6125
+ data = JSON.parse(text);
6126
+ } catch (e) {
6127
+ }
6128
+ if (!response.ok || !data || data.error) {
6129
+ return { success: false, provider: "razorpay", orderId, amount, rawResponse: data, error: data?.error?.description || `HTTP ${response.status}` };
6130
+ }
6131
+ return {
6132
+ success: true,
6133
+ provider: "razorpay",
6134
+ orderId,
6135
+ amount: data.amount || amount,
6136
+ reference: data.id,
6137
+ paymentCode: data.id,
6138
+ rawResponse: data
6139
+ };
6140
+ } else {
6141
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6142
+ const body = {
6143
+ amount,
6144
+ currency,
6145
+ description: productDetails,
6146
+ reference_id: orderId,
6147
+ customer: { name: customer?.name, email: customer?.email, contact: customer?.phone || "" },
6148
+ notify: { sms: false, email: !!customer?.email },
6149
+ reminder_enable: false,
6150
+ callback_url: callbackUrl || config.callbackUrl || successUrl,
6151
+ callback_method: "get",
6152
+ notes: { order_id: orderId },
6153
+ ...params.providerParams
6154
+ };
6155
+ const response = await fetch(`${baseUrl}/payment_links`, {
6156
+ method: "POST",
6157
+ headers,
6158
+ body: JSON.stringify(body)
6159
+ });
6160
+ const text = await response.text();
6161
+ let data = null;
6162
+ try {
6163
+ data = JSON.parse(text);
6164
+ } catch (e) {
6165
+ }
6166
+ if (!response.ok || !data || data.error) {
6167
+ return { success: false, provider: "razorpay", orderId, amount, rawResponse: data, error: data?.error?.description || `HTTP ${response.status}` };
6168
+ }
6169
+ return {
6170
+ success: true,
6171
+ provider: "razorpay",
6172
+ orderId,
6173
+ amount: data.amount || amount,
6174
+ reference: data.id,
6175
+ paymentUrl: data.short_url,
6176
+ rawResponse: data
6177
+ };
6178
+ }
6179
+ } catch (e) {
6180
+ return { success: false, provider: "razorpay", orderId, amount, error: e.message, rawResponse: null };
6181
+ }
6182
+ }
6183
+ async verifyCallback(body, config) {
6184
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
6185
+ const signatureHeader = config.extra?.signatureHeader || "";
6186
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6187
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6188
+ const isValid = signatureHeader ? verifyRazorpayWebhook(rawBody, signatureHeader, webhookSecret) : false;
6189
+ const eventType = parsedBody?.event || "";
6190
+ const payload = parsedBody?.payload;
6191
+ const paymentEntity = payload?.payment?.entity || payload?.payment_link?.entity || parsedBody;
6192
+ const orderId = paymentEntity?.notes?.order_id || paymentEntity?.order_id || paymentEntity?.reference_id || paymentEntity?.id || "";
6193
+ const amount = Number(paymentEntity?.amount || 0);
6194
+ const statusRaw = (paymentEntity?.status || "").toLowerCase();
6195
+ const isPaid = eventType === "payment.captured" || eventType === "payment_link.paid" || statusRaw === "captured";
6196
+ const isPending = eventType === "payment.authorized" || statusRaw === "authorized" || statusRaw === "created";
6197
+ const isExpired = eventType === "payment_link.expired" || statusRaw === "expired";
6198
+ const isFailed = eventType === "payment.failed" || statusRaw === "failed";
6199
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6200
+ return {
6201
+ isValid,
6202
+ provider: "razorpay",
6203
+ orderId: String(orderId),
6204
+ amount,
6205
+ status,
6206
+ isPaid,
6207
+ isPending,
6208
+ isFailed,
6209
+ isExpired,
6210
+ statusCode: eventType || statusRaw,
6211
+ rawPayload: parsedBody
6212
+ };
6213
+ }
6214
+ async getPaymentMethods(params, config) {
6215
+ const methods = [
6216
+ { paymentMethod: "credit_card", code: "card", paymentName: "Credit / Debit Card", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "2% + GST", category: "Kartu Kredit" },
6217
+ { paymentMethod: "upi", code: "upi", paymentName: "UPI (GPay, PhonePe, Paytm)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Free", category: "QRIS" },
6218
+ { paymentMethod: "netbanking", code: "netbanking", paymentName: "Net Banking (50+ banks)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "\u20B910", category: "Virtual Account" },
6219
+ { paymentMethod: "wallet", code: "wallet", paymentName: "Wallets (Paytm, PhonePe, etc.)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Variable", category: "E-Wallet" },
6220
+ { paymentMethod: "emi", code: "emi", paymentName: "EMI (Card / Cardless)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Bank charge", category: "Paylater / Cicilan" }
6221
+ ];
6222
+ const categories = {};
6223
+ for (const item of methods) {
6224
+ if (!categories[item.category]) categories[item.category] = [];
6225
+ categories[item.category].push(item);
6226
+ }
6227
+ return { success: true, provider: "razorpay", methods, categories, rawResponse: methods };
6228
+ }
6229
+ async checkTransaction(params, config) {
6230
+ const { merchantOrderId } = params;
6231
+ const baseUrl = this.getBaseUrl();
6232
+ const headers = this.buildHeaders(config);
6233
+ try {
6234
+ const endpoint = merchantOrderId.startsWith("plink_") ? `/payment_links/${encodeURIComponent(merchantOrderId)}` : `/payments/${encodeURIComponent(merchantOrderId)}`;
6235
+ const response = await fetch(`${baseUrl}${endpoint}`, { method: "GET", headers });
6236
+ const text = await response.text();
6237
+ let data = null;
6238
+ try {
6239
+ data = JSON.parse(text);
6240
+ } catch (e) {
6241
+ }
6242
+ if (!response.ok || !data || data.error) {
6243
+ return {
6244
+ success: false,
6245
+ provider: "razorpay",
6246
+ orderId: merchantOrderId,
6247
+ reference: "",
6248
+ amount: 0,
6249
+ statusCode: response.status.toString(),
6250
+ status: "failed",
6251
+ isPaid: false,
6252
+ isPending: false,
6253
+ isFailed: true,
6254
+ isExpired: false,
6255
+ statusMessage: data?.error?.description || "HTTP Error",
6256
+ rawResponse: data
6257
+ };
6258
+ }
6259
+ const statusRaw = (data.status || "").toLowerCase();
6260
+ const isPaid = statusRaw === "captured" || statusRaw === "paid";
6261
+ const isPending = statusRaw === "authorized" || statusRaw === "created";
6262
+ const isExpired = statusRaw === "expired";
6263
+ const isFailed = statusRaw === "failed";
6264
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6265
+ return {
6266
+ success: true,
6267
+ provider: "razorpay",
6268
+ orderId: data.notes?.order_id || data.reference_id || merchantOrderId,
6269
+ reference: data.id || merchantOrderId,
6270
+ amount: Number(data.amount || 0),
6271
+ statusCode: statusRaw,
6272
+ status,
6273
+ isPaid,
6274
+ isPending,
6275
+ isFailed,
6276
+ isExpired,
6277
+ statusMessage: statusRaw,
6278
+ paymentType: data.method || "card",
6279
+ transactionTime: data.created_at ? new Date(data.created_at * 1e3) : void 0,
6280
+ rawResponse: data
6281
+ };
6282
+ } catch (e) {
6283
+ return {
6284
+ success: false,
6285
+ provider: "razorpay",
6286
+ orderId: merchantOrderId,
6287
+ reference: "",
6288
+ amount: 0,
6289
+ statusCode: "ERROR",
6290
+ status: "failed",
6291
+ isPaid: false,
6292
+ isPending: false,
6293
+ isFailed: true,
6294
+ isExpired: false,
6295
+ statusMessage: e.message,
6296
+ error: e.message,
6297
+ rawResponse: null
6298
+ };
6299
+ }
6300
+ }
6301
+ };
6302
+
6303
+ // src/providers/square/signature.ts
6304
+ import { createHmac as createHmac4 } from "crypto";
6305
+ function verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) {
6306
+ if (!signatureKey || !signatureHeader || !rawBody) return false;
6307
+ try {
6308
+ const payload = notificationUrl + rawBody;
6309
+ const expected = createHmac4("sha256", signatureKey).update(payload).digest("base64");
6310
+ return safeCompare(expected, signatureHeader);
6311
+ } catch {
6312
+ return false;
6313
+ }
6314
+ }
6315
+
6316
+ // src/providers/square/provider.ts
6317
+ var SquareProvider = class extends BasePaymentProvider {
6318
+ name = "square";
6319
+ getBaseUrl(config) {
6320
+ return config.sandbox !== false ? "https://connect.squareupsandbox.com" : "https://connect.squareup.com";
6321
+ }
6322
+ buildHeaders(config) {
6323
+ return {
6324
+ "Authorization": `Bearer ${config.apiKey || config.secretKey || ""}`,
6325
+ "Content-Type": "application/json",
6326
+ "Square-Version": "2024-01-17"
6327
+ };
6328
+ }
6329
+ async createInvoice(params, config) {
6330
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
6331
+ const currency = (params.currency || "USD").toUpperCase();
6332
+ const locationId = config.extra?.locationId || config.projectId || "";
6333
+ const baseUrl = this.getBaseUrl(config);
6334
+ const headers = this.buildHeaders(config);
6335
+ const isDirect = !!params.paymentMethod;
6336
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6337
+ try {
6338
+ if (isDirect) {
6339
+ const sourceId = params.providerParams?.sourceId || params.providerParams?.nonce || "cnon:card-nonce-ok";
6340
+ const body = {
6341
+ idempotency_key: orderId,
6342
+ source_id: sourceId,
6343
+ amount_money: { amount, currency },
6344
+ reference_id: orderId,
6345
+ note: productDetails,
6346
+ buyer_email_address: customer?.email,
6347
+ ...params.providerParams
6348
+ };
6349
+ const response = await fetch(`${baseUrl}/v2/payments`, {
6350
+ method: "POST",
6351
+ headers,
6352
+ body: JSON.stringify(body)
6353
+ });
6354
+ const text = await response.text();
6355
+ let data = null;
6356
+ try {
6357
+ data = JSON.parse(text);
6358
+ } catch (e) {
6359
+ }
6360
+ if (!response.ok || !data || data.errors?.length) {
6361
+ return { success: false, provider: "square", orderId, amount, rawResponse: data, error: data?.errors?.[0]?.detail || `HTTP ${response.status}` };
6362
+ }
6363
+ const payment = data.payment || data;
6364
+ return {
6365
+ success: true,
6366
+ provider: "square",
6367
+ orderId,
6368
+ amount: payment.amount_money?.amount || amount,
6369
+ reference: payment.id,
6370
+ rawResponse: data
6371
+ };
6372
+ } else {
6373
+ const body = {
6374
+ idempotency_key: orderId,
6375
+ order: {
6376
+ location_id: locationId,
6377
+ reference_id: orderId,
6378
+ line_items: [
6379
+ {
6380
+ name: productDetails,
6381
+ quantity: "1",
6382
+ base_price_money: { amount, currency }
6383
+ }
6384
+ ]
6385
+ },
6386
+ checkout_options: {
6387
+ redirect_url: successUrl,
6388
+ ask_for_shipping_address: false
6389
+ },
6390
+ pre_populated_data: {
6391
+ buyer_email: customer?.email
6392
+ },
6393
+ ...params.providerParams
6394
+ };
6395
+ const response = await fetch(`${baseUrl}/v2/online-checkout/payment-links`, {
6396
+ method: "POST",
6397
+ headers,
6398
+ body: JSON.stringify(body)
6399
+ });
6400
+ const text = await response.text();
6401
+ let data = null;
6402
+ try {
6403
+ data = JSON.parse(text);
6404
+ } catch (e) {
6405
+ }
6406
+ if (!response.ok || !data || data.errors?.length) {
6407
+ return { success: false, provider: "square", orderId, amount, rawResponse: data, error: data?.errors?.[0]?.detail || `HTTP ${response.status}` };
6408
+ }
6409
+ const link = data.payment_link || data;
6410
+ return {
6411
+ success: true,
6412
+ provider: "square",
6413
+ orderId,
6414
+ amount,
6415
+ reference: link.id,
6416
+ paymentUrl: link.url,
6417
+ rawResponse: data
6418
+ };
6419
+ }
6420
+ } catch (e) {
6421
+ return { success: false, provider: "square", orderId, amount, error: e.message, rawResponse: null };
6422
+ }
6423
+ }
6424
+ async verifyCallback(body, config) {
6425
+ const signatureKey = config.extra?.webhookSignatureKey || config.secretKey || "";
6426
+ const signatureHeader = config.extra?.signatureHeader || "";
6427
+ const notificationUrl = config.callbackUrl || config.extra?.notificationUrl || "";
6428
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6429
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6430
+ const isValid = signatureHeader ? verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) : false;
6431
+ const eventType = parsedBody?.type || "";
6432
+ const data = parsedBody?.data?.object || parsedBody?.data || parsedBody;
6433
+ const payment = data?.payment || data;
6434
+ const orderId = payment?.reference_id || payment?.order_id || payment?.id || "";
6435
+ const amount = Number(payment?.amount_money?.amount || 0);
6436
+ const statusRaw = (payment?.status || "").toUpperCase();
6437
+ const isPaid = statusRaw === "COMPLETED" || eventType === "payment.completed";
6438
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED";
6439
+ const isFailed = statusRaw === "FAILED" || statusRaw === "CANCELED";
6440
+ const isExpired = eventType === "payment.expired";
6441
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6442
+ return {
6443
+ isValid,
6444
+ provider: "square",
6445
+ orderId: String(orderId),
6446
+ amount,
6447
+ status,
6448
+ isPaid,
6449
+ isPending,
6450
+ isFailed,
6451
+ isExpired,
6452
+ statusCode: eventType || statusRaw,
6453
+ rawPayload: parsedBody
6454
+ };
6455
+ }
6456
+ async getPaymentMethods(params, config) {
6457
+ const methods = [
6458
+ { 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" },
6459
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6460
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6461
+ { paymentMethod: "cash_app", code: "cashapp", paymentName: "Cash App Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6462
+ { paymentMethod: "afterpay", code: "afterpay", paymentName: "Afterpay / Clearpay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "6% + $0.30", category: "Paylater / Cicilan" }
6463
+ ];
6464
+ const categories = {};
6465
+ for (const item of methods) {
6466
+ if (!categories[item.category]) categories[item.category] = [];
6467
+ categories[item.category].push(item);
6468
+ }
6469
+ return { success: true, provider: "square", methods, categories, rawResponse: methods };
6470
+ }
6471
+ async checkTransaction(params, config) {
6472
+ const { merchantOrderId } = params;
6473
+ const baseUrl = this.getBaseUrl(config);
6474
+ const headers = this.buildHeaders(config);
6475
+ try {
6476
+ const response = await fetch(`${baseUrl}/v2/payments/${encodeURIComponent(merchantOrderId)}`, {
6477
+ method: "GET",
6478
+ headers
6479
+ });
6480
+ const text = await response.text();
6481
+ let data = null;
6482
+ try {
6483
+ data = JSON.parse(text);
6484
+ } catch (e) {
6485
+ }
6486
+ if (!response.ok || !data || data.errors?.length) {
6487
+ return {
6488
+ success: false,
6489
+ provider: "square",
6490
+ orderId: merchantOrderId,
6491
+ reference: "",
6492
+ amount: 0,
6493
+ statusCode: response.status.toString(),
6494
+ status: "failed",
6495
+ isPaid: false,
6496
+ isPending: false,
6497
+ isFailed: true,
6498
+ isExpired: false,
6499
+ statusMessage: data?.errors?.[0]?.detail || "HTTP Error",
6500
+ rawResponse: data
6501
+ };
6502
+ }
6503
+ const payment = data.payment || data;
6504
+ const statusRaw = (payment.status || "").toUpperCase();
6505
+ const isPaid = statusRaw === "COMPLETED";
6506
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED";
6507
+ const isExpired = statusRaw === "CANCELED";
6508
+ const isFailed = statusRaw === "FAILED";
6509
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6510
+ return {
6511
+ success: true,
6512
+ provider: "square",
6513
+ orderId: payment.reference_id || merchantOrderId,
6514
+ reference: payment.id || merchantOrderId,
6515
+ amount: Number(payment.amount_money?.amount || 0),
6516
+ statusCode: statusRaw,
6517
+ status,
6518
+ isPaid,
6519
+ isPending,
6520
+ isFailed,
6521
+ isExpired,
6522
+ statusMessage: statusRaw,
6523
+ paymentType: payment.source_type || "card",
6524
+ transactionTime: payment.created_at ? new Date(payment.created_at) : void 0,
6525
+ rawResponse: data
6526
+ };
6527
+ } catch (e) {
6528
+ return {
6529
+ success: false,
6530
+ provider: "square",
6531
+ orderId: merchantOrderId,
6532
+ reference: "",
6533
+ amount: 0,
6534
+ statusCode: "ERROR",
6535
+ status: "failed",
6536
+ isPaid: false,
6537
+ isPending: false,
6538
+ isFailed: true,
6539
+ isExpired: false,
6540
+ statusMessage: e.message,
6541
+ error: e.message,
6542
+ rawResponse: null
6543
+ };
6544
+ }
6545
+ }
6546
+ };
6547
+
6548
+ // src/providers/payu/signature.ts
6549
+ import { createHash } from "crypto";
6550
+ function verifyPayuWebhook(rawBody, signatureHeader, md5Key) {
6551
+ if (!md5Key || !signatureHeader || !rawBody) return false;
6552
+ try {
6553
+ const parts = {};
6554
+ for (const part of signatureHeader.split(";")) {
6555
+ const [k, v] = part.split("=");
6556
+ if (k && v) parts[k.trim()] = v.trim();
6557
+ }
6558
+ const providedSig = parts["signature"];
6559
+ const algorithm = (parts["algorithm"] || "MD5").toUpperCase();
6560
+ if (!providedSig) return false;
6561
+ if (algorithm === "MD5") {
6562
+ const expected = createHash("md5").update(rawBody + md5Key).digest("hex");
6563
+ return safeCompare(expected, providedSig);
6564
+ } else if (algorithm === "SHA-256") {
6565
+ const expected = createHash("sha256").update(rawBody + md5Key).digest("hex");
6566
+ return safeCompare(expected, providedSig);
6567
+ }
6568
+ return false;
6569
+ } catch {
6570
+ return false;
6571
+ }
6572
+ }
6573
+ function buildPayuBasicAuth(clientId, clientSecret) {
6574
+ return Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
6575
+ }
6576
+
6577
+ // src/providers/payu/provider.ts
6578
+ var PayuProvider = class extends BasePaymentProvider {
6579
+ name = "payu";
6580
+ getBaseUrl(config) {
6581
+ return config.sandbox !== false ? "https://secure.snd.payu.com" : "https://secure.payu.com";
6582
+ }
6583
+ /** OAuth2 Bearer Token untuk PayU */
6584
+ async getAccessToken(config) {
6585
+ const clientId = config.extra?.oauthClientId || config.clientKey || "";
6586
+ const clientSecret = config.extra?.oauthClientSecret || config.apiKey || config.secretKey || "";
6587
+ if (!clientId || !clientSecret) {
6588
+ return "";
6589
+ }
6590
+ const baseUrl = this.getBaseUrl(config);
6591
+ const response = await fetch(`${baseUrl}/pl/standard/user/oauth/authorize`, {
6592
+ method: "POST",
6593
+ headers: {
6594
+ "Authorization": `Basic ${buildPayuBasicAuth(clientId, clientSecret)}`,
6595
+ "Content-Type": "application/x-www-form-urlencoded"
6596
+ },
6597
+ body: "grant_type=client_credentials"
6598
+ });
6599
+ const text = await response.text();
6600
+ let data = null;
6601
+ try {
6602
+ data = JSON.parse(text);
6603
+ } catch (e) {
6604
+ }
6605
+ if (!response.ok || !data?.access_token) {
6606
+ throw new Error(data?.error_description || `Failed to get PayU access token: ${response.status}`);
6607
+ }
6608
+ return data.access_token;
6609
+ }
6610
+ async createInvoice(params, config) {
6611
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
6612
+ const currency = (params.currency || "PLN").toUpperCase();
6613
+ const posId = config.merchantCode || config.merchantId || config.extra?.posId || "";
6614
+ const baseUrl = this.getBaseUrl(config);
6615
+ let accessToken;
6616
+ try {
6617
+ accessToken = await this.getAccessToken(config);
6618
+ } catch (e) {
6619
+ return { success: false, provider: "payu", orderId, amount, error: e.message, rawResponse: null };
6620
+ }
6621
+ const isDirect = !!params.paymentMethod;
6622
+ const continueUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6623
+ const notifyUrl = callbackUrl || config.callbackUrl || "";
6624
+ const body = {
6625
+ notifyUrl,
6626
+ customerIp: params.providerParams?.customerIp || "127.0.0.1",
6627
+ merchantPosId: posId,
6628
+ description: productDetails,
6629
+ currencyCode: currency,
6630
+ totalAmount: amount.toString(),
6631
+ extOrderId: orderId,
6632
+ continueUrl,
6633
+ buyer: {
6634
+ email: customer?.email,
6635
+ firstName: customer?.name?.split(" ")[0],
6636
+ lastName: customer?.name?.split(" ").slice(1).join(" ") || "-",
6637
+ phone: customer?.phone,
6638
+ language: "en"
6639
+ },
6640
+ products: [
6641
+ { name: productDetails, unitPrice: amount.toString(), quantity: "1" }
6642
+ ],
6643
+ ...params.providerParams
6644
+ };
6645
+ if (isDirect && params.paymentMethod) {
6646
+ body.payMethods = {
6647
+ payMethod: {
6648
+ type: "PBL",
6649
+ value: params.paymentMethod
6650
+ // e.g. "blik", "c" (card), "ap" (Apple Pay)
6651
+ }
6652
+ };
6653
+ }
6654
+ try {
6655
+ const response = await fetch(`${baseUrl}/api/v2_1/orders`, {
6656
+ method: "POST",
6657
+ headers: {
6658
+ "Authorization": `Bearer ${accessToken}`,
6659
+ "Content-Type": "application/json"
6660
+ },
6661
+ body: JSON.stringify(body),
6662
+ redirect: "manual"
6663
+ // PayU responds with 302
6664
+ });
6665
+ const text = await response.text();
6666
+ let data = null;
6667
+ try {
6668
+ data = JSON.parse(text);
6669
+ } catch (e) {
6670
+ }
6671
+ if (response.status === 302 || response.headers.get("location")) {
6672
+ const location = response.headers.get("location") || "";
6673
+ return {
6674
+ success: true,
6675
+ provider: "payu",
6676
+ orderId,
6677
+ amount,
6678
+ reference: data?.orderId || orderId,
6679
+ paymentUrl: location,
6680
+ rawResponse: data
6681
+ };
6682
+ }
6683
+ if (!response.ok || !data || data.status?.statusCode === "ERROR") {
6684
+ return { success: false, provider: "payu", orderId, amount, rawResponse: data, error: data?.status?.statusDesc || `HTTP ${response.status}` };
6685
+ }
6686
+ return {
6687
+ success: true,
6688
+ provider: "payu",
6689
+ orderId,
6690
+ amount,
6691
+ reference: data.orderId || orderId,
6692
+ paymentUrl: data.redirectUri,
6693
+ rawResponse: data
6694
+ };
6695
+ } catch (e) {
6696
+ return { success: false, provider: "payu", orderId, amount, error: e.message, rawResponse: null };
6697
+ }
6698
+ }
6699
+ async verifyCallback(body, config) {
6700
+ const md5Key = config.extra?.md5Key || config.apiKey || config.secretKey || "";
6701
+ const signatureHeader = config.extra?.signatureHeader || "";
6702
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6703
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6704
+ const isValid = signatureHeader ? verifyPayuWebhook(rawBody, signatureHeader, md5Key) : false;
6705
+ const order = parsedBody?.order || parsedBody;
6706
+ const orderId = order.extOrderId || order.orderId || "";
6707
+ const amount = Number(order.totalAmount || 0);
6708
+ const statusRaw = (order.status || "").toUpperCase();
6709
+ const isPaid = statusRaw === "COMPLETED";
6710
+ const isPending = statusRaw === "PENDING" || statusRaw === "WAITING_FOR_CONFIRMATION";
6711
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REJECTED";
6712
+ const isExpired = false;
6713
+ const status = isPaid ? "paid" : isPending ? "pending" : "failed";
6714
+ return {
6715
+ isValid,
6716
+ provider: "payu",
6717
+ orderId: String(orderId),
6718
+ amount,
6719
+ status,
6720
+ isPaid,
6721
+ isPending,
6722
+ isFailed,
6723
+ isExpired,
6724
+ statusCode: statusRaw,
6725
+ rawPayload: parsedBody
6726
+ };
6727
+ }
6728
+ async getPaymentMethods(params, config) {
6729
+ const methods = [
6730
+ { paymentMethod: "credit_card", code: "c", paymentName: "Credit / Debit Card", paymentImage: "https://payu.com/favicon.ico", totalFee: "1.5%+", category: "Kartu Kredit" },
6731
+ { paymentMethod: "blik", code: "blik", paymentName: "BLIK (Poland)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Fixed fee", category: "E-Wallet" },
6732
+ { paymentMethod: "apple_pay", code: "ap", paymentName: "Apple Pay", paymentImage: "https://payu.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6733
+ { paymentMethod: "google_pay", code: "gp", paymentName: "Google Pay", paymentImage: "https://payu.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6734
+ { paymentMethod: "bank_transfer", code: "t", paymentName: "Online Bank Transfer (50+ banks)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Fixed fee", category: "Virtual Account" },
6735
+ { paymentMethod: "installment", code: "ai", paymentName: "Installments (PayU)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Bank rate", category: "Paylater / Cicilan" }
6736
+ ];
6737
+ const categories = {};
6738
+ for (const item of methods) {
6739
+ if (!categories[item.category]) categories[item.category] = [];
6740
+ categories[item.category].push(item);
6741
+ }
6742
+ return { success: true, provider: "payu", methods, categories, rawResponse: methods };
6743
+ }
6744
+ async checkTransaction(params, config) {
6745
+ const { merchantOrderId } = params;
6746
+ const baseUrl = this.getBaseUrl(config);
6747
+ let accessToken;
6748
+ try {
6749
+ accessToken = await this.getAccessToken(config);
6750
+ } catch (e) {
6751
+ return {
6752
+ success: false,
6753
+ provider: "payu",
6754
+ orderId: merchantOrderId,
6755
+ reference: "",
6756
+ amount: 0,
6757
+ statusCode: "AUTH_ERROR",
6758
+ status: "failed",
6759
+ isPaid: false,
6760
+ isPending: false,
6761
+ isFailed: true,
6762
+ isExpired: false,
6763
+ statusMessage: e.message,
6764
+ error: e.message,
6765
+ rawResponse: null
6766
+ };
6767
+ }
6768
+ try {
6769
+ const response = await fetch(`${baseUrl}/api/v2_1/orders/${encodeURIComponent(merchantOrderId)}`, {
6770
+ method: "GET",
6771
+ headers: { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json" }
6772
+ });
6773
+ const text = await response.text();
6774
+ let data = null;
6775
+ try {
6776
+ data = JSON.parse(text);
6777
+ } catch (e) {
6778
+ }
6779
+ if (!response.ok || !data) {
6780
+ return {
6781
+ success: false,
6782
+ provider: "payu",
6783
+ orderId: merchantOrderId,
6784
+ reference: "",
6785
+ amount: 0,
6786
+ statusCode: response.status.toString(),
6787
+ status: "failed",
6788
+ isPaid: false,
6789
+ isPending: false,
6790
+ isFailed: true,
6791
+ isExpired: false,
6792
+ statusMessage: "HTTP Error",
6793
+ rawResponse: data
6794
+ };
6795
+ }
6796
+ const order = data.orders?.[0] || data;
6797
+ const statusRaw = (order.status || "").toUpperCase();
6798
+ const isPaid = statusRaw === "COMPLETED";
6799
+ const isPending = statusRaw === "PENDING" || statusRaw === "WAITING_FOR_CONFIRMATION";
6800
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REJECTED";
6801
+ const isExpired = false;
6802
+ const status = isPaid ? "paid" : isPending ? "pending" : "failed";
6803
+ return {
6804
+ success: true,
6805
+ provider: "payu",
6806
+ orderId: order.extOrderId || merchantOrderId,
6807
+ reference: order.orderId || merchantOrderId,
6808
+ amount: Number(order.totalAmount || 0),
6809
+ statusCode: statusRaw,
6810
+ status,
6811
+ isPaid,
6812
+ isPending,
6813
+ isFailed,
6814
+ isExpired,
6815
+ statusMessage: statusRaw,
6816
+ transactionTime: order.orderCreateDate ? new Date(order.orderCreateDate) : void 0,
6817
+ rawResponse: data
6818
+ };
6819
+ } catch (e) {
6820
+ return {
6821
+ success: false,
6822
+ provider: "payu",
6823
+ orderId: merchantOrderId,
6824
+ reference: "",
6825
+ amount: 0,
6826
+ statusCode: "ERROR",
6827
+ status: "failed",
6828
+ isPaid: false,
6829
+ isPending: false,
6830
+ isFailed: true,
6831
+ isExpired: false,
6832
+ statusMessage: e.message,
6833
+ error: e.message,
6834
+ rawResponse: null
6835
+ };
6836
+ }
6837
+ }
6838
+ };
6839
+
6840
+ // src/providers/braintree/signature.ts
6841
+ import { createHash as createHash2, createHmac as createHmac6 } from "crypto";
6842
+ function verifyBraintreeWebhook(btSignature, btPayload, privateKey) {
6843
+ if (!privateKey || !btSignature || !btPayload) return false;
6844
+ try {
6845
+ const parts = btSignature.split("|");
6846
+ if (parts.length < 2) return false;
6847
+ const providedHmac = parts[1];
6848
+ const payload = Buffer.from(btPayload, "base64").toString("utf8");
6849
+ const secretHash = createHash2("sha1").update(privateKey).digest("hex");
6850
+ const expected = createHmac6("sha1", secretHash).update(payload).digest("hex");
6851
+ return safeCompare(expected, providedHmac);
6852
+ } catch {
6853
+ return false;
6854
+ }
6855
+ }
6856
+ function buildBraintreeBasicAuth(publicKey, privateKey) {
6857
+ return Buffer.from(`${publicKey}:${privateKey}`).toString("base64");
6858
+ }
6859
+
6860
+ // src/providers/braintree/provider.ts
6861
+ var BraintreeProvider = class extends BasePaymentProvider {
6862
+ name = "braintree";
6863
+ getBaseUrl(config) {
6864
+ const merchantId = config.merchantCode || config.merchantId || "";
6865
+ const base = config.sandbox !== false ? "https://api.sandbox.braintreegateway.com" : "https://api.braintreegateway.com";
6866
+ return `${base}/merchants/${merchantId}`;
6867
+ }
6868
+ buildHeaders(config) {
6869
+ const publicKey = config.clientKey || config.extra?.publicKey || "";
6870
+ const privateKey = config.apiKey || config.secretKey || "";
6871
+ return {
6872
+ "Authorization": `Basic ${buildBraintreeBasicAuth(publicKey, privateKey)}`,
6873
+ "Content-Type": "application/json",
6874
+ "Braintree-Version": "2019-01-01"
6875
+ };
6876
+ }
6877
+ async createInvoice(params, config) {
6878
+ const { orderId, amount, productDetails, customer } = params;
6879
+ const currency = (params.currency || "USD").toUpperCase();
6880
+ const baseUrl = this.getBaseUrl(config);
6881
+ const headers = this.buildHeaders(config);
6882
+ const isDirect = !!params.paymentMethod;
6883
+ try {
6884
+ if (isDirect) {
6885
+ const paymentMethodNonce = params.providerParams?.nonce || params.providerParams?.paymentMethodNonce || "fake-valid-nonce";
6886
+ const body = {
6887
+ transaction: {
6888
+ amount: (amount / 100).toFixed(2),
6889
+ payment_method_nonce: paymentMethodNonce,
6890
+ order_id: orderId,
6891
+ currency_iso_code: currency,
6892
+ options: { submit_for_settlement: true },
6893
+ customer: { first_name: customer?.name, email: customer?.email },
6894
+ custom_fields: { order_id: orderId },
6895
+ ...params.providerParams
6896
+ }
6897
+ };
6898
+ const response = await fetch(`${baseUrl}/transactions`, {
6899
+ method: "POST",
6900
+ headers,
6901
+ body: JSON.stringify(body)
6902
+ });
6903
+ const text = await response.text();
6904
+ let data = null;
6905
+ try {
6906
+ data = JSON.parse(text);
6907
+ } catch (e) {
6908
+ }
6909
+ if (!response.ok || data?.apiErrorResponse) {
6910
+ return { success: false, provider: "braintree", orderId, amount, rawResponse: data, error: data?.apiErrorResponse?.message || `HTTP ${response.status}` };
6911
+ }
6912
+ const tx = data?.transaction || data;
6913
+ const statusRaw = (tx.status || "").toLowerCase();
6914
+ return {
6915
+ success: statusRaw === "submitted_for_settlement" || statusRaw === "settling" || statusRaw === "settled",
6916
+ provider: "braintree",
6917
+ orderId,
6918
+ amount: Math.round(Number(tx.amount || amount / 100) * 100),
6919
+ reference: tx.id,
6920
+ rawResponse: data
6921
+ };
6922
+ } else {
6923
+ const body = { client_token: { customer_id: customer?.email || orderId } };
6924
+ const response = await fetch(`${baseUrl}/client_token`, {
6925
+ method: "POST",
6926
+ headers,
6927
+ body: JSON.stringify(body)
6928
+ });
6929
+ const text = await response.text();
6930
+ let data = null;
6931
+ try {
6932
+ data = JSON.parse(text);
6933
+ } catch (e) {
6934
+ }
6935
+ if (!response.ok || !data?.clientToken) {
6936
+ return { success: false, provider: "braintree", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
6937
+ }
6938
+ return {
6939
+ success: true,
6940
+ provider: "braintree",
6941
+ orderId,
6942
+ amount,
6943
+ reference: orderId,
6944
+ paymentCode: data.clientToken,
6945
+ // Frontend uses this token for Drop-in UI
6946
+ rawResponse: data
6947
+ };
6948
+ }
6949
+ } catch (e) {
6950
+ return { success: false, provider: "braintree", orderId, amount, error: e.message, rawResponse: null };
6951
+ }
6952
+ }
6953
+ async verifyCallback(body, config) {
6954
+ const privateKey = config.apiKey || config.secretKey || "";
6955
+ const btSignature = config.extra?.btSignature || "";
6956
+ const btPayload = config.extra?.btPayload || "";
6957
+ const isValid = btSignature && btPayload ? verifyBraintreeWebhook(btSignature, btPayload, privateKey) : false;
6958
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6959
+ const subject = parsedBody?.subject || parsedBody;
6960
+ const transaction = subject?.transaction || subject?.disbursement || parsedBody;
6961
+ const kind = parsedBody?.kind || parsedBody?.event || "";
6962
+ const orderId = transaction?.orderId || transaction?.order_id || transaction?.id || "";
6963
+ const amount = Math.round(Number(transaction?.amount || 0) * 100);
6964
+ const statusRaw = (transaction?.status || "").toLowerCase();
6965
+ const isPaid = kind === "transaction_settled" || kind === "transaction_disbursed" || statusRaw === "settled";
6966
+ const isPending = kind === "transaction_settlement_declined" || statusRaw === "submitted_for_settlement" || statusRaw === "settling";
6967
+ const isFailed = kind === "transaction_failed" || statusRaw === "failed" || statusRaw === "voided";
6968
+ const isExpired = statusRaw === "expired";
6969
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6970
+ return {
6971
+ isValid,
6972
+ provider: "braintree",
6973
+ orderId: String(orderId),
6974
+ amount,
6975
+ status,
6976
+ isPaid,
6977
+ isPending,
6978
+ isFailed,
6979
+ isExpired,
6980
+ statusCode: kind || statusRaw,
6981
+ rawPayload: parsedBody
6982
+ };
6983
+ }
6984
+ async getPaymentMethods(params, config) {
6985
+ const methods = [
6986
+ { 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" },
6987
+ { paymentMethod: "paypal", code: "PayPalAccount", paymentName: "PayPal (via Drop-in UI)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "3.49% + fixed", category: "E-Wallet" },
6988
+ { paymentMethod: "apple_pay", code: "ApplePayCard", paymentName: "Apple Pay", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "Card network fee", category: "E-Wallet" },
6989
+ { paymentMethod: "google_pay", code: "AndroidPayCard", paymentName: "Google Pay", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "Card network fee", category: "E-Wallet" },
6990
+ { paymentMethod: "venmo", code: "VenmoAccount", paymentName: "Venmo (US only)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "1.9% + $0.10", category: "E-Wallet" }
6991
+ ];
6992
+ const categories = {};
6993
+ for (const item of methods) {
6994
+ if (!categories[item.category]) categories[item.category] = [];
6995
+ categories[item.category].push(item);
6996
+ }
6997
+ return { success: true, provider: "braintree", methods, categories, rawResponse: methods };
6998
+ }
6999
+ async checkTransaction(params, config) {
7000
+ const { merchantOrderId } = params;
7001
+ const baseUrl = this.getBaseUrl(config);
7002
+ const headers = this.buildHeaders(config);
7003
+ try {
7004
+ const response = await fetch(`${baseUrl}/transactions/${encodeURIComponent(merchantOrderId)}`, {
7005
+ method: "GET",
7006
+ headers
7007
+ });
7008
+ const text = await response.text();
7009
+ let data = null;
7010
+ try {
7011
+ data = JSON.parse(text);
7012
+ } catch (e) {
7013
+ }
7014
+ if (!response.ok || !data) {
7015
+ return {
7016
+ success: false,
7017
+ provider: "braintree",
7018
+ orderId: merchantOrderId,
7019
+ reference: "",
7020
+ amount: 0,
7021
+ statusCode: response.status.toString(),
7022
+ status: "failed",
7023
+ isPaid: false,
7024
+ isPending: false,
7025
+ isFailed: true,
7026
+ isExpired: false,
7027
+ statusMessage: "HTTP Error",
7028
+ rawResponse: data
7029
+ };
7030
+ }
7031
+ const tx = data.transaction || data;
7032
+ const statusRaw = (tx.status || "").toLowerCase();
7033
+ const isPaid = statusRaw === "settled" || statusRaw === "settling";
7034
+ const isPending = statusRaw === "submitted_for_settlement" || statusRaw === "authorized";
7035
+ const isExpired = statusRaw === "expired";
7036
+ const isFailed = statusRaw === "failed" || statusRaw === "voided";
7037
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7038
+ return {
7039
+ success: true,
7040
+ provider: "braintree",
7041
+ orderId: tx.orderId || merchantOrderId,
7042
+ reference: tx.id || merchantOrderId,
7043
+ amount: Math.round(Number(tx.amount || 0) * 100),
7044
+ statusCode: statusRaw,
7045
+ status,
7046
+ isPaid,
7047
+ isPending,
7048
+ isFailed,
7049
+ isExpired,
7050
+ statusMessage: statusRaw,
7051
+ paymentType: tx.paymentInstrumentType || "card",
7052
+ transactionTime: tx.createdAt ? new Date(tx.createdAt) : void 0,
7053
+ rawResponse: data
7054
+ };
7055
+ } catch (e) {
7056
+ return {
7057
+ success: false,
7058
+ provider: "braintree",
7059
+ orderId: merchantOrderId,
7060
+ reference: "",
7061
+ amount: 0,
7062
+ statusCode: "ERROR",
7063
+ status: "failed",
7064
+ isPaid: false,
7065
+ isPending: false,
7066
+ isFailed: true,
7067
+ isExpired: false,
7068
+ statusMessage: e.message,
7069
+ error: e.message,
7070
+ rawResponse: null
7071
+ };
7072
+ }
7073
+ }
7074
+ };
7075
+
7076
+ // src/providers/twocheckout/signature.ts
7077
+ import { createHash as createHash3, createHmac as createHmac7 } from "crypto";
7078
+ function buildTwoCheckoutAuth(merchantCode, secretKey) {
7079
+ const date = Math.floor(Date.now() / 1e3).toString();
7080
+ const raw = merchantCode + date;
7081
+ const hmac = createHmac7("sha256", secretKey).update(raw).digest("hex");
7082
+ const header = `code="${merchantCode}" date="${date}" hash="${hmac}"`;
7083
+ return { header, date };
7084
+ }
7085
+ function verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, providedHash) {
7086
+ if (!secretWord || !providedHash) return false;
7087
+ try {
7088
+ const raw = secretWord + saleId + productId + invoiceId;
7089
+ const expected = createHash3("md5").update(raw).digest("hex");
7090
+ return safeCompare(expected, providedHash);
7091
+ } catch {
7092
+ return false;
7093
+ }
7094
+ }
7095
+
7096
+ // src/providers/twocheckout/provider.ts
7097
+ var TwoCheckoutProvider = class extends BasePaymentProvider {
7098
+ name = "twocheckout";
7099
+ getBaseUrl(config) {
7100
+ return config.sandbox !== false ? "https://api.sandbox.2checkout.com/rest" : "https://api.2checkout.com/rest";
7101
+ }
7102
+ buildHeaders(config) {
7103
+ const merchantCode = config.merchantCode || config.merchantId || "";
7104
+ const secretKey = config.apiKey || config.secretKey || "";
7105
+ const { header } = buildTwoCheckoutAuth(merchantCode, secretKey);
7106
+ return {
7107
+ "X-Avangate-Authentication": header,
7108
+ "Content-Type": "application/json",
7109
+ "Accept": "application/json"
7110
+ };
7111
+ }
7112
+ async createInvoice(params, config) {
7113
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
7114
+ const currency = (params.currency || "USD").toUpperCase();
7115
+ const baseUrl = this.getBaseUrl(config);
7116
+ const headers = this.buildHeaders(config);
7117
+ const isDirect = !!params.paymentMethod;
7118
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
7119
+ const body = {
7120
+ Currency: currency,
7121
+ Language: "en",
7122
+ Country: config.extra?.country || "US",
7123
+ CustomerIP: params.providerParams?.customerIp || "127.0.0.1",
7124
+ Source: "API",
7125
+ MerchantReference: orderId,
7126
+ Items: [
7127
+ {
7128
+ Name: productDetails,
7129
+ Quantity: 1,
7130
+ Price: { Amount: (amount / 100).toFixed(2), Type: "CUSTOM" },
7131
+ Type: "PRODUCT",
7132
+ IsDynamic: true,
7133
+ Tangible: false
7134
+ }
7135
+ ],
7136
+ BillingDetails: {
7137
+ FirstName: customer?.name?.split(" ")[0] || "Customer",
7138
+ LastName: customer?.name?.split(" ").slice(1).join(" ") || "Name",
7139
+ Email: customer?.email,
7140
+ Country: config.extra?.country || "US",
7141
+ Address1: config.extra?.address || "N/A",
7142
+ City: config.extra?.city || "N/A",
7143
+ State: config.extra?.state || "",
7144
+ Zip: config.extra?.zip || "00000"
7145
+ },
7146
+ ...params.providerParams
7147
+ };
7148
+ if (!isDirect) {
7149
+ body.PaymentDetails = { Type: "EES_TOKEN_PAYMENT", Currency: currency };
7150
+ } else {
7151
+ body.PaymentDetails = { Type: params.paymentMethod === "paypal" ? "PAYPAL" : "EES_TOKEN_PAYMENT", Currency: currency };
7152
+ }
7153
+ try {
7154
+ const response = await fetch(`${baseUrl}/6.0/orders`, {
7155
+ method: "POST",
7156
+ headers,
7157
+ body: JSON.stringify(body)
7158
+ });
7159
+ const text = await response.text();
7160
+ let data = null;
7161
+ try {
7162
+ data = JSON.parse(text);
7163
+ } catch (e) {
7164
+ }
7165
+ if (!response.ok || !data || data.error_code) {
7166
+ return { success: false, provider: "twocheckout", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
7167
+ }
7168
+ const paymentUrl = data.PaymentDetails?.PaymentMethod?.RedirectURL || data.PaymentDetails?.PaymentMethod?.Href || `${successUrl}?ref=${data.RefNo}`;
7169
+ return {
7170
+ success: true,
7171
+ provider: "twocheckout",
7172
+ orderId,
7173
+ amount,
7174
+ reference: data.RefNo || data.OrderNo?.toString(),
7175
+ paymentUrl,
7176
+ rawResponse: data
7177
+ };
7178
+ } catch (e) {
7179
+ return { success: false, provider: "twocheckout", orderId, amount, error: e.message, rawResponse: null };
7180
+ }
7181
+ }
7182
+ async verifyCallback(body, config) {
7183
+ const secretWord = config.extra?.secretWord || config.apiKey || "";
7184
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
7185
+ const saleId = parsedBody?.SALE_ID || parsedBody?.sale_id || "";
7186
+ const productId = parsedBody?.IPN_PID?.[0] || parsedBody?.product_id || "";
7187
+ const invoiceId = parsedBody?.IPN_PNAME?.[0] || parsedBody?.invoice_id || "";
7188
+ const providedHash = parsedBody?.HASH || parsedBody?.hash || "";
7189
+ const isValid = secretWord ? verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, providedHash) : false;
7190
+ const orderId = parsedBody?.REFNOEXT || parsedBody?.ext_ref_no || parsedBody?.SALE_ID || "";
7191
+ const amount = Math.round(Number(parsedBody?.IPN_TOTAL_GENERAL || parsedBody?.total || 0) * 100);
7192
+ const statusRaw = (parsedBody?.ORDERSTATUS || parsedBody?.order_status || "").toUpperCase();
7193
+ const isPaid = statusRaw === "COMPLETE" || statusRaw === "COMPLETE_MANUAL";
7194
+ const isPending = statusRaw === "PENDING" || statusRaw === "PURCHASE_PENDING";
7195
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REFUND" || statusRaw === "FRAUD";
7196
+ const isExpired = statusRaw === "EXPIRED";
7197
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7198
+ return {
7199
+ isValid,
7200
+ provider: "twocheckout",
7201
+ orderId: String(orderId),
7202
+ amount,
7203
+ status,
7204
+ isPaid,
7205
+ isPending,
7206
+ isFailed,
7207
+ isExpired,
7208
+ statusCode: statusRaw,
7209
+ rawPayload: parsedBody
7210
+ };
7211
+ }
7212
+ async getPaymentMethods(params, config) {
7213
+ const methods = [
7214
+ { 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" },
7215
+ { paymentMethod: "paypal", code: "PAYPAL", paymentName: "PayPal", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "3.5% + $0.35", category: "E-Wallet" },
7216
+ { paymentMethod: "wire_transfer", code: "WIRE", paymentName: "Wire Transfer / Bank Transfer", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "Fixed fee", category: "Virtual Account" },
7217
+ { paymentMethod: "paylater", code: "PAY_LATER", paymentName: "Buy Now Pay Later (Klarna)", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "Variable", category: "Paylater / Cicilan" }
7218
+ ];
7219
+ const categories = {};
7220
+ for (const item of methods) {
7221
+ if (!categories[item.category]) categories[item.category] = [];
7222
+ categories[item.category].push(item);
7223
+ }
7224
+ return { success: true, provider: "twocheckout", methods, categories, rawResponse: methods };
7225
+ }
7226
+ async checkTransaction(params, config) {
7227
+ const { merchantOrderId } = params;
7228
+ const baseUrl = this.getBaseUrl(config);
7229
+ const headers = this.buildHeaders(config);
7230
+ try {
7231
+ const response = await fetch(`${baseUrl}/6.0/orders/${encodeURIComponent(merchantOrderId)}`, {
7232
+ method: "GET",
7233
+ headers
7234
+ });
7235
+ const text = await response.text();
7236
+ let data = null;
7237
+ try {
7238
+ data = JSON.parse(text);
7239
+ } catch (e) {
7240
+ }
7241
+ if (!response.ok || !data || data.error_code) {
7242
+ return {
7243
+ success: false,
7244
+ provider: "twocheckout",
7245
+ orderId: merchantOrderId,
7246
+ reference: "",
7247
+ amount: 0,
7248
+ statusCode: response.status.toString(),
7249
+ status: "failed",
7250
+ isPaid: false,
7251
+ isPending: false,
7252
+ isFailed: true,
7253
+ isExpired: false,
7254
+ statusMessage: data?.message || "HTTP Error",
7255
+ rawResponse: data
7256
+ };
7257
+ }
7258
+ const statusRaw = (data.Status || "").toUpperCase();
7259
+ const isPaid = statusRaw === "COMPLETE";
7260
+ const isPending = statusRaw === "PENDING" || statusRaw === "PURCHASE_PENDING";
7261
+ const isExpired = statusRaw === "EXPIRED";
7262
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REFUND";
7263
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7264
+ return {
7265
+ success: true,
7266
+ provider: "twocheckout",
7267
+ orderId: data.ExternalReference || merchantOrderId,
7268
+ reference: data.RefNo?.toString() || merchantOrderId,
7269
+ amount: Math.round(Number(data.GrossAmount || 0) * 100),
7270
+ statusCode: statusRaw,
7271
+ status,
7272
+ isPaid,
7273
+ isPending,
7274
+ isFailed,
7275
+ isExpired,
7276
+ statusMessage: statusRaw,
7277
+ transactionTime: data.OrderDate ? new Date(data.OrderDate) : void 0,
7278
+ rawResponse: data
7279
+ };
7280
+ } catch (e) {
7281
+ return {
7282
+ success: false,
7283
+ provider: "twocheckout",
7284
+ orderId: merchantOrderId,
7285
+ reference: "",
7286
+ amount: 0,
7287
+ statusCode: "ERROR",
7288
+ status: "failed",
7289
+ isPaid: false,
7290
+ isPending: false,
7291
+ isFailed: true,
7292
+ isExpired: false,
7293
+ statusMessage: e.message,
7294
+ error: e.message,
7295
+ rawResponse: null
7296
+ };
7297
+ }
7298
+ }
7299
+ };
7300
+
7301
+ // src/clients/duitku.ts
7302
+ var DuitkuClient = class {
7303
+ merchantCode;
7304
+ apiKey;
7305
+ sandbox;
7306
+ constructor(config) {
7307
+ this.merchantCode = config.merchantCode || "";
7308
+ this.apiKey = config.apiKey || config.serverKey || "";
7309
+ this.sandbox = !!config.sandbox;
7310
+ }
7311
+ getPassportBaseUrl() {
7312
+ return this.sandbox ? "https://sandbox.duitku.com/webapi" : "https://passport.duitku.com/webapi";
7313
+ }
7314
+ getApiBaseUrl() {
7315
+ return this.sandbox ? "https://api-sandbox.duitku.com" : "https://api-prod.duitku.com";
7316
+ }
7317
+ /**
7318
+ * Request helper generic dengan kalkulasi signature Duitku otomatis
7319
+ */
7320
+ async request(method, endpoint, body = {}, options) {
7321
+ const baseUrl = options?.baseUrl === "api" ? this.getApiBaseUrl() : this.getPassportBaseUrl();
7322
+ const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
7323
+ const timestamp = Date.now().toString();
7324
+ const headerSignature = sha256(this.merchantCode + timestamp + this.apiKey);
7325
+ const headers = {
7326
+ "Content-Type": "application/json",
7327
+ "Accept": "application/json",
7328
+ "x-duitku-signature": headerSignature,
7329
+ "x-duitku-timestamp": timestamp,
7330
+ "x-duitku-merchantcode": this.merchantCode,
7331
+ ...options?.customHeaders
7332
+ };
7333
+ const fetchOptions = {
7334
+ method,
7335
+ headers
7336
+ };
7337
+ if (method === "POST" && body) {
7338
+ fetchOptions.body = JSON.stringify(body);
7339
+ }
7340
+ const response = await fetch(url, fetchOptions);
7341
+ const text = await response.text();
7342
+ let data = null;
7343
+ try {
7344
+ data = JSON.parse(text);
7345
+ } catch (e) {
7346
+ }
7347
+ if (!response.ok) {
7348
+ throw new Error(data?.Message || data?.statusMessage || data?.responseMessage || `HTTP error! Status: ${response.status} - ${text}`);
7349
+ }
7350
+ return data || text;
7351
+ }
7352
+ // ─── TRANSACTIONS & PAYMENT METHODS ──────────────────────────────────────────
7353
+ /**
7354
+ * Cek status transaksi pembayaran berdasarkan merchant order ID
7355
+ */
7356
+ async checkTransaction(merchantOrderId) {
7357
+ const { bodySignature } = getDuitkuStatusSignatures(
7358
+ this.merchantCode,
7359
+ merchantOrderId,
7360
+ this.apiKey
7361
+ );
7362
+ return this.request(
7363
+ "POST",
7364
+ "/api/merchant/transactionStatus",
7365
+ {
7366
+ merchantCode: this.merchantCode,
7367
+ merchantOrderId,
7368
+ signature: bodySignature
7369
+ },
7370
+ { baseUrl: "api" }
7371
+ );
7372
+ }
7373
+ /**
7374
+ * Ambil daftar channel pembayaran aktif dan kalkulasi fee dinamis
7375
+ */
7376
+ async getPaymentMethods(amount = 1e4) {
7377
+ const integerAmount = Math.round(amount);
7378
+ const datetime = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
7379
+ const signature = getDuitkuPaymentMethodsSignature(this.merchantCode, integerAmount, datetime, this.apiKey);
7380
+ return this.request("POST", "/api/merchant/paymentmethod/getpaymentmethod", {
7381
+ merchantcode: this.merchantCode,
7382
+ amount: integerAmount,
7383
+ datetime,
7384
+ signature
7385
+ });
7386
+ }
7387
+ // ─── DISBURSEMENT & BALANCE INQUIRY ──────────────────────────────────────────
7388
+ /**
7389
+ * Cek saldo merchant (Balance Inquiry)
7390
+ */
7391
+ async checkBalance() {
7392
+ const timestamp = Date.now().toString();
7393
+ const signature = sha256(this.merchantCode + timestamp + this.apiKey);
7394
+ try {
7395
+ const data = await this.request(
7396
+ "POST",
7397
+ "/api/merchant/checkBalance",
7398
+ {
7399
+ merchantCode: this.merchantCode,
7400
+ signature
7401
+ },
7402
+ { baseUrl: "api" }
7403
+ );
7404
+ return {
7405
+ success: data.responseCode === "00" || data.statusCode === "00",
7406
+ balance: data.balance ? Number(data.balance) : void 0,
7407
+ rawResponse: data
7408
+ };
7409
+ } catch (e) {
7410
+ return {
7411
+ success: false,
7412
+ rawResponse: null,
7413
+ error: e.message || "Failed to check Duitku merchant balance"
7414
+ };
7415
+ }
7416
+ }
7417
+ /**
7418
+ * Mengambil daftar bank yang didukung untuk transfer / penarikan dana
7419
+ */
7420
+ async listBanks() {
7421
+ const timestamp = Date.now().toString();
7422
+ const signature = sha256(this.merchantCode + timestamp + this.apiKey);
7423
+ return this.request(
7424
+ "POST",
7425
+ "/api/disbursement/listBank",
7426
+ {
7427
+ merchantCode: this.merchantCode,
7428
+ signature
7429
+ },
7430
+ { baseUrl: "api" }
7431
+ );
7432
+ }
7433
+ /**
7434
+ * Validasi nama pemilik rekening bank sebelum eksekusi transfer (Bank Account Inquiry)
7435
+ */
7436
+ async inquiryBankAccount(bankCode, bankAccount) {
7437
+ const timestamp = Date.now().toString();
7438
+ const signature = sha256(this.merchantCode + bankCode + bankAccount + this.apiKey);
7439
+ return this.request(
7440
+ "POST",
7441
+ "/api/disbursement/inquiry",
7442
+ {
7443
+ merchantCode: this.merchantCode,
7444
+ bankCode,
7445
+ bankAccount,
7446
+ signature
7447
+ },
7448
+ { baseUrl: "api" }
7449
+ );
7450
+ }
7451
+ /**
7452
+ * Eksekusi transfer dana / payout (Disbursement Transfer)
7453
+ */
7454
+ async disburse(params) {
7455
+ const integerAmount = Math.round(params.amount);
7456
+ const signature = sha256(
7457
+ this.merchantCode + params.merchantOrderId + params.bankCode + params.bankAccount + integerAmount.toString() + this.apiKey
7458
+ );
7459
+ const payload = {
7460
+ merchantCode: this.merchantCode,
7461
+ merchantOrderId: params.merchantOrderId,
7462
+ bankCode: params.bankCode,
7463
+ bankAccount: params.bankAccount,
7464
+ amount: integerAmount,
7465
+ purpose: params.purpose,
7466
+ senderName: params.senderName || "",
7467
+ senderPhone: params.senderPhone || "",
7468
+ callbackUrl: params.callbackUrl || "",
7469
+ signature
7470
+ };
7471
+ return this.request("POST", "/api/disbursement/transfer", payload, { baseUrl: "api" });
7472
+ }
7473
+ /**
7474
+ * Cek status disbursement berdasarkan merchant order ID
7475
+ */
7476
+ async checkDisbursementStatus(merchantOrderId) {
7477
+ const signature = sha256(this.merchantCode + merchantOrderId + this.apiKey);
7478
+ return this.request(
7479
+ "POST",
7480
+ "/api/disbursement/checkStatus",
7481
+ {
7482
+ merchantCode: this.merchantCode,
7483
+ merchantOrderId,
7484
+ signature
7485
+ },
7486
+ { baseUrl: "api" }
7487
+ );
7488
+ }
7489
+ };
7490
+
7491
+ // src/clients/ipaymu.ts
7492
+ var IpaymuClient = class {
7493
+ va;
7494
+ apiKey;
7495
+ sandbox;
7496
+ constructor(config) {
5466
7497
  this.va = config.merchantCode || config.merchantId || "";
5467
7498
  this.apiKey = config.apiKey || config.serverKey || "";
5468
7499
  this.sandbox = !!config.sandbox;
@@ -6032,6 +8063,533 @@ var StripeClient = class {
6032
8063
  }
6033
8064
  };
6034
8065
 
8066
+ // src/clients/paypal.ts
8067
+ var PaypalClient = class {
8068
+ config;
8069
+ constructor(config) {
8070
+ this.config = config;
8071
+ }
8072
+ getBaseUrl() {
8073
+ return this.config.sandbox !== false ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
8074
+ }
8075
+ async getAccessToken() {
8076
+ const clientId = this.config.clientKey || this.config.merchantCode || this.config.merchantId || "";
8077
+ const clientSecret = this.config.apiKey || this.config.secretKey || "";
8078
+ const auth = buildPaypalBasicAuth(clientId, clientSecret);
8079
+ const response = await fetch(`${this.getBaseUrl()}/v1/oauth2/token`, {
8080
+ method: "POST",
8081
+ headers: { "Authorization": `Basic ${auth}`, "Content-Type": "application/x-www-form-urlencoded" },
8082
+ body: "grant_type=client_credentials"
8083
+ });
8084
+ const data = await response.json();
8085
+ if (!data?.access_token) throw new Error(data?.error_description || "Failed to get PayPal access token");
8086
+ return data.access_token;
8087
+ }
8088
+ /** Ambil detail order PayPal berdasarkan Order ID */
8089
+ async getOrder(orderId) {
8090
+ const token = await this.getAccessToken();
8091
+ const response = await fetch(`${this.getBaseUrl()}/v2/checkout/orders/${orderId}`, {
8092
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8093
+ });
8094
+ return response.json();
8095
+ }
8096
+ /** Capture order PayPal (mengeksekusi pembayaran yang sudah diapprove buyer) */
8097
+ async captureOrder(orderId) {
8098
+ const token = await this.getAccessToken();
8099
+ const response = await fetch(`${this.getBaseUrl()}/v2/checkout/orders/${orderId}/capture`, {
8100
+ method: "POST",
8101
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8102
+ body: "{}"
8103
+ });
8104
+ return response.json();
8105
+ }
8106
+ /** Refund capture PayPal */
8107
+ async refundCapture(captureId, amount, currency) {
8108
+ const token = await this.getAccessToken();
8109
+ const body = {};
8110
+ if (amount && currency) {
8111
+ body.amount = { value: (amount / 100).toFixed(2), currency_code: currency };
8112
+ body.note_to_payer = "Refund";
8113
+ }
8114
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/captures/${captureId}/refund`, {
8115
+ method: "POST",
8116
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8117
+ body: JSON.stringify(body)
8118
+ });
8119
+ return response.json();
8120
+ }
8121
+ /** Cek saldo akun PayPal merchant (hanya tersedia di account via Seller REST API) */
8122
+ async checkBalance() {
8123
+ const token = await this.getAccessToken();
8124
+ const response = await fetch(`${this.getBaseUrl()}/v1/reporting/balances`, {
8125
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8126
+ });
8127
+ return response.json();
8128
+ }
8129
+ /** Verifikasi webhook via PayPal Webhook Verification API */
8130
+ async verifyWebhookSignature(webhookId, body, headers) {
8131
+ const token = await this.getAccessToken();
8132
+ const verifyBody = {
8133
+ auth_algo: headers["paypal-auth-algo"],
8134
+ cert_url: headers["paypal-cert-url"],
8135
+ transmission_id: headers["paypal-transmission-id"],
8136
+ transmission_sig: headers["paypal-transmission-sig"],
8137
+ transmission_time: headers["paypal-transmission-time"],
8138
+ webhook_id: webhookId,
8139
+ webhook_event: typeof body === "string" ? JSON.parse(body) : body
8140
+ };
8141
+ const response = await fetch(`${this.getBaseUrl()}/v1/notifications/verify-webhook-signature`, {
8142
+ method: "POST",
8143
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8144
+ body: JSON.stringify(verifyBody)
8145
+ });
8146
+ const data = await response.json();
8147
+ return data?.verification_status === "SUCCESS";
8148
+ }
8149
+ };
8150
+
8151
+ // src/clients/adyen.ts
8152
+ var AdyenClient = class {
8153
+ config;
8154
+ constructor(config) {
8155
+ this.config = config;
8156
+ }
8157
+ getBaseUrl() {
8158
+ if (this.config.sandbox === false) {
8159
+ const prefix = this.config.extra?.liveUrlPrefix || this.config.projectId || "";
8160
+ if (prefix) return `https://${prefix}-checkout-live.adyenpayments.com/checkout`;
8161
+ }
8162
+ return "https://checkout-test.adyen.com";
8163
+ }
8164
+ buildHeaders() {
8165
+ return {
8166
+ "X-API-Key": this.config.apiKey || this.config.secretKey || "",
8167
+ "Content-Type": "application/json"
8168
+ };
8169
+ }
8170
+ /** Ambil detail payment berdasarkan PSP Reference */
8171
+ async getPaymentDetails(pspReference) {
8172
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}`, {
8173
+ method: "GET",
8174
+ headers: this.buildHeaders()
8175
+ });
8176
+ return response.json();
8177
+ }
8178
+ /** Batalkan payment (sebelum capture) */
8179
+ async cancelPayment(pspReference, merchantAccount) {
8180
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8181
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/cancels`, {
8182
+ method: "POST",
8183
+ headers: this.buildHeaders(),
8184
+ body: JSON.stringify({ merchantAccount: account })
8185
+ });
8186
+ return response.json();
8187
+ }
8188
+ /** Refund payment yang sudah di-capture */
8189
+ async refundPayment(pspReference, amount, currency, merchantAccount) {
8190
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8191
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/refunds`, {
8192
+ method: "POST",
8193
+ headers: this.buildHeaders(),
8194
+ body: JSON.stringify({
8195
+ merchantAccount: account,
8196
+ amount: { value: amount, currency }
8197
+ })
8198
+ });
8199
+ return response.json();
8200
+ }
8201
+ /** Capture authorized payment */
8202
+ async capturePayment(pspReference, amount, currency, merchantAccount) {
8203
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8204
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/captures`, {
8205
+ method: "POST",
8206
+ headers: this.buildHeaders(),
8207
+ body: JSON.stringify({
8208
+ merchantAccount: account,
8209
+ amount: { value: amount, currency }
8210
+ })
8211
+ });
8212
+ return response.json();
8213
+ }
8214
+ /** Ambil daftar payment methods yang tersedia */
8215
+ async getAvailablePaymentMethods(merchantAccount, countryCode, currency, amount) {
8216
+ const response = await fetch(`${this.getBaseUrl()}/v68/paymentMethods`, {
8217
+ method: "POST",
8218
+ headers: this.buildHeaders(),
8219
+ body: JSON.stringify({ merchantAccount, countryCode, channel: "Web", amount: { value: amount, currency } })
8220
+ });
8221
+ return response.json();
8222
+ }
8223
+ };
8224
+
8225
+ // src/clients/checkoutcom.ts
8226
+ var CheckoutComClient = class {
8227
+ config;
8228
+ constructor(config) {
8229
+ this.config = config;
8230
+ }
8231
+ getBaseUrl() {
8232
+ return this.config.sandbox !== false ? "https://api.sandbox.checkout.com" : "https://api.checkout.com";
8233
+ }
8234
+ buildHeaders() {
8235
+ return {
8236
+ "Authorization": `Bearer ${this.config.apiKey || this.config.secretKey || ""}`,
8237
+ "Content-Type": "application/json"
8238
+ };
8239
+ }
8240
+ /** Ambil detail payment berdasarkan Payment ID */
8241
+ async getPaymentDetails(paymentId) {
8242
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}`, {
8243
+ method: "GET",
8244
+ headers: this.buildHeaders()
8245
+ });
8246
+ return response.json();
8247
+ }
8248
+ /** Void (batalkan) payment yang belum di-capture */
8249
+ async voidPayment(paymentId, reference) {
8250
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/voids`, {
8251
+ method: "POST",
8252
+ headers: this.buildHeaders(),
8253
+ body: JSON.stringify({ reference })
8254
+ });
8255
+ return response.json();
8256
+ }
8257
+ /** Refund payment yang sudah di-capture */
8258
+ async refundPayment(paymentId, amount, reference) {
8259
+ const body = { reference };
8260
+ if (amount) body.amount = amount;
8261
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/refunds`, {
8262
+ method: "POST",
8263
+ headers: this.buildHeaders(),
8264
+ body: JSON.stringify(body)
8265
+ });
8266
+ return response.json();
8267
+ }
8268
+ /** Cek saldo merchant di Checkout.com */
8269
+ async checkBalance() {
8270
+ const response = await fetch(`${this.getBaseUrl()}/balances`, {
8271
+ method: "GET",
8272
+ headers: this.buildHeaders()
8273
+ });
8274
+ return response.json();
8275
+ }
8276
+ /** Ambil daftar payment links */
8277
+ async listPaymentLinks() {
8278
+ const response = await fetch(`${this.getBaseUrl()}/payment-links`, {
8279
+ method: "GET",
8280
+ headers: this.buildHeaders()
8281
+ });
8282
+ return response.json();
8283
+ }
8284
+ };
8285
+
8286
+ // src/clients/razorpay.ts
8287
+ var RazorpayClient = class {
8288
+ config;
8289
+ constructor(config) {
8290
+ this.config = config;
8291
+ }
8292
+ getBaseUrl() {
8293
+ return "https://api.razorpay.com/v1";
8294
+ }
8295
+ buildHeaders() {
8296
+ const keyId = this.config.clientKey || this.config.merchantCode || this.config.merchantId || "";
8297
+ const keySecret = this.config.apiKey || this.config.secretKey || "";
8298
+ return {
8299
+ "Authorization": `Basic ${buildRazorpayBasicAuth(keyId, keySecret)}`,
8300
+ "Content-Type": "application/json"
8301
+ };
8302
+ }
8303
+ /** Ambil detail payment */
8304
+ async fetchPayment(paymentId) {
8305
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}`, {
8306
+ method: "GET",
8307
+ headers: this.buildHeaders()
8308
+ });
8309
+ return response.json();
8310
+ }
8311
+ /** Capture authorized payment */
8312
+ async capturePayment(paymentId, amount, currency) {
8313
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/capture`, {
8314
+ method: "POST",
8315
+ headers: this.buildHeaders(),
8316
+ body: JSON.stringify({ amount, currency: currency || "INR" })
8317
+ });
8318
+ return response.json();
8319
+ }
8320
+ /** Buat refund untuk payment */
8321
+ async createRefund(paymentId, amount, notes) {
8322
+ const body = { notes };
8323
+ if (amount) body.amount = amount;
8324
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/refund`, {
8325
+ method: "POST",
8326
+ headers: this.buildHeaders(),
8327
+ body: JSON.stringify(body)
8328
+ });
8329
+ return response.json();
8330
+ }
8331
+ /** Cek saldo akun Razorpay */
8332
+ async checkBalance() {
8333
+ const response = await fetch(`${this.getBaseUrl()}/balance`, {
8334
+ method: "GET",
8335
+ headers: this.buildHeaders()
8336
+ });
8337
+ return response.json();
8338
+ }
8339
+ /** Ambil daftar semua payment */
8340
+ async listPayments(from, to, count) {
8341
+ const params = new URLSearchParams();
8342
+ if (from) params.set("from", from.toString());
8343
+ if (to) params.set("to", to.toString());
8344
+ if (count) params.set("count", count.toString());
8345
+ const response = await fetch(`${this.getBaseUrl()}/payments?${params}`, {
8346
+ method: "GET",
8347
+ headers: this.buildHeaders()
8348
+ });
8349
+ return response.json();
8350
+ }
8351
+ };
8352
+
8353
+ // src/clients/square.ts
8354
+ var SquareClient = class {
8355
+ config;
8356
+ constructor(config) {
8357
+ this.config = config;
8358
+ }
8359
+ getBaseUrl() {
8360
+ return this.config.sandbox !== false ? "https://connect.squareupsandbox.com" : "https://connect.squareup.com";
8361
+ }
8362
+ buildHeaders() {
8363
+ return {
8364
+ "Authorization": `Bearer ${this.config.apiKey || this.config.secretKey || ""}`,
8365
+ "Content-Type": "application/json",
8366
+ "Square-Version": "2024-01-17"
8367
+ };
8368
+ }
8369
+ /** Ambil detail payment Square */
8370
+ async getPayment(paymentId) {
8371
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/${paymentId}`, {
8372
+ method: "GET",
8373
+ headers: this.buildHeaders()
8374
+ });
8375
+ return response.json();
8376
+ }
8377
+ /** Batalkan payment Square */
8378
+ async cancelPayment(paymentId) {
8379
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/${paymentId}/cancel`, {
8380
+ method: "POST",
8381
+ headers: this.buildHeaders(),
8382
+ body: "{}"
8383
+ });
8384
+ return response.json();
8385
+ }
8386
+ /** Refund payment Square */
8387
+ async refundPayment(paymentId, amount, currency, idempotencyKey, reason) {
8388
+ const response = await fetch(`${this.getBaseUrl()}/v2/refunds`, {
8389
+ method: "POST",
8390
+ headers: this.buildHeaders(),
8391
+ body: JSON.stringify({
8392
+ idempotency_key: idempotencyKey,
8393
+ payment_id: paymentId,
8394
+ amount_money: { amount, currency },
8395
+ reason
8396
+ })
8397
+ });
8398
+ return response.json();
8399
+ }
8400
+ /** Ambil saldo location Square */
8401
+ async retrieveBalance(locationId) {
8402
+ const id = locationId || this.config.extra?.locationId || this.config.projectId || "";
8403
+ const response = await fetch(`${this.getBaseUrl()}/v2/locations/${id}`, {
8404
+ method: "GET",
8405
+ headers: this.buildHeaders()
8406
+ });
8407
+ return response.json();
8408
+ }
8409
+ /** List semua locations merchant */
8410
+ async listLocations() {
8411
+ const response = await fetch(`${this.getBaseUrl()}/v2/locations`, {
8412
+ method: "GET",
8413
+ headers: this.buildHeaders()
8414
+ });
8415
+ return response.json();
8416
+ }
8417
+ };
8418
+
8419
+ // src/clients/payu.ts
8420
+ var PayuClient = class {
8421
+ config;
8422
+ accessToken = null;
8423
+ constructor(config) {
8424
+ this.config = config;
8425
+ }
8426
+ getBaseUrl() {
8427
+ return this.config.sandbox !== false ? "https://secure.snd.payu.com" : "https://secure.payu.com";
8428
+ }
8429
+ async getToken() {
8430
+ if (this.accessToken) return this.accessToken;
8431
+ const clientId = this.config.extra?.oauthClientId || this.config.clientKey || "";
8432
+ const clientSecret = this.config.extra?.oauthClientSecret || this.config.apiKey || this.config.secretKey || "";
8433
+ const response = await fetch(`${this.getBaseUrl()}/pl/standard/user/oauth/authorize`, {
8434
+ method: "POST",
8435
+ headers: { "Authorization": `Basic ${buildPayuBasicAuth(clientId, clientSecret)}`, "Content-Type": "application/x-www-form-urlencoded" },
8436
+ body: "grant_type=client_credentials"
8437
+ });
8438
+ const data = await response.json();
8439
+ if (!data?.access_token) throw new Error("Failed to get PayU access token");
8440
+ this.accessToken = data.access_token;
8441
+ return this.accessToken;
8442
+ }
8443
+ /** Ambil detail order PayU */
8444
+ async getOrder(orderId) {
8445
+ const token = await this.getToken();
8446
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}`, {
8447
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8448
+ });
8449
+ return response.json();
8450
+ }
8451
+ /** Batalkan order PayU */
8452
+ async cancelOrder(orderId) {
8453
+ const token = await this.getToken();
8454
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}`, {
8455
+ method: "DELETE",
8456
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8457
+ });
8458
+ return response.json();
8459
+ }
8460
+ /** Refund order PayU */
8461
+ async refundOrder(orderId, amount, description) {
8462
+ const token = await this.getToken();
8463
+ const body = { refund: { description: description || "Refund" } };
8464
+ if (amount) body.refund.amount = amount;
8465
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}/refunds`, {
8466
+ method: "POST",
8467
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8468
+ body: JSON.stringify(body)
8469
+ });
8470
+ return response.json();
8471
+ }
8472
+ };
8473
+
8474
+ // src/clients/braintree.ts
8475
+ var BraintreeClient = class {
8476
+ config;
8477
+ constructor(config) {
8478
+ this.config = config;
8479
+ }
8480
+ getBaseUrl() {
8481
+ const merchantId = this.config.merchantCode || this.config.merchantId || "";
8482
+ const base = this.config.sandbox !== false ? "https://api.sandbox.braintreegateway.com" : "https://api.braintreegateway.com";
8483
+ return `${base}/merchants/${merchantId}`;
8484
+ }
8485
+ buildHeaders() {
8486
+ const publicKey = this.config.clientKey || this.config.extra?.publicKey || "";
8487
+ const privateKey = this.config.apiKey || this.config.secretKey || "";
8488
+ return {
8489
+ "Authorization": `Basic ${buildBraintreeBasicAuth(publicKey, privateKey)}`,
8490
+ "Content-Type": "application/json",
8491
+ "Braintree-Version": "2019-01-01"
8492
+ };
8493
+ }
8494
+ /** Generate Client Token untuk frontend Drop-in UI */
8495
+ async getClientToken(customerId) {
8496
+ const body = {};
8497
+ if (customerId) body.client_token = { customer_id: customerId };
8498
+ const response = await fetch(`${this.getBaseUrl()}/client_token`, {
8499
+ method: "POST",
8500
+ headers: this.buildHeaders(),
8501
+ body: JSON.stringify(body)
8502
+ });
8503
+ const data = await response.json();
8504
+ return data.clientToken || "";
8505
+ }
8506
+ /** Ambil detail transaction */
8507
+ async findTransaction(transactionId) {
8508
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}`, {
8509
+ method: "GET",
8510
+ headers: this.buildHeaders()
8511
+ });
8512
+ return response.json();
8513
+ }
8514
+ /** Refund transaction Braintree */
8515
+ async refundTransaction(transactionId, amount) {
8516
+ const body = {};
8517
+ if (amount) body.transaction = { amount: (amount / 100).toFixed(2) };
8518
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}/refund`, {
8519
+ method: "POST",
8520
+ headers: this.buildHeaders(),
8521
+ body: JSON.stringify(body)
8522
+ });
8523
+ return response.json();
8524
+ }
8525
+ /** Void (batalkan) transaction sebelum settlement */
8526
+ async voidTransaction(transactionId) {
8527
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}/void`, {
8528
+ method: "PUT",
8529
+ headers: this.buildHeaders(),
8530
+ body: "{}"
8531
+ });
8532
+ return response.json();
8533
+ }
8534
+ };
8535
+
8536
+ // src/clients/twocheckout.ts
8537
+ var TwoCheckoutClient = class {
8538
+ config;
8539
+ constructor(config) {
8540
+ this.config = config;
8541
+ }
8542
+ getBaseUrl() {
8543
+ return this.config.sandbox !== false ? "https://api.sandbox.2checkout.com/rest" : "https://api.2checkout.com/rest";
8544
+ }
8545
+ buildHeaders() {
8546
+ const merchantCode = this.config.merchantCode || this.config.merchantId || "";
8547
+ const secretKey = this.config.apiKey || this.config.secretKey || "";
8548
+ const { header } = buildTwoCheckoutAuth(merchantCode, secretKey);
8549
+ return {
8550
+ "X-Avangate-Authentication": header,
8551
+ "Content-Type": "application/json",
8552
+ "Accept": "application/json"
8553
+ };
8554
+ }
8555
+ /** Ambil detail order 2Checkout berdasarkan Reference Number */
8556
+ async getOrder(refNo) {
8557
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders/${refNo}`, {
8558
+ method: "GET",
8559
+ headers: this.buildHeaders()
8560
+ });
8561
+ return response.json();
8562
+ }
8563
+ /** Refund order 2Checkout */
8564
+ async refundOrder(refNo, amount, comment) {
8565
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders/${refNo}/refund`, {
8566
+ method: "POST",
8567
+ headers: this.buildHeaders(),
8568
+ body: JSON.stringify({ amount, comment: comment || "Refund", reason: "NOT_SATISFIED" })
8569
+ });
8570
+ return response.json();
8571
+ }
8572
+ /** Ambil detail subscription */
8573
+ async getSubscription(subscriptionRef) {
8574
+ const response = await fetch(`${this.getBaseUrl()}/6.0/subscriptions/${subscriptionRef}`, {
8575
+ method: "GET",
8576
+ headers: this.buildHeaders()
8577
+ });
8578
+ return response.json();
8579
+ }
8580
+ /** List semua orders merchant */
8581
+ async listOrders(page, limit) {
8582
+ const params = new URLSearchParams({
8583
+ Pagination: JSON.stringify({ Page: page || 1, Limit: limit || 10 })
8584
+ });
8585
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders?${params}`, {
8586
+ method: "GET",
8587
+ headers: this.buildHeaders()
8588
+ });
8589
+ return response.json();
8590
+ }
8591
+ };
8592
+
6035
8593
  // src/core/manager.ts
6036
8594
  var PaymentManager = class {
6037
8595
  providers = /* @__PURE__ */ new Map();
@@ -6047,6 +8605,14 @@ var PaymentManager = class {
6047
8605
  this.registerProvider(new NicepayProvider());
6048
8606
  this.registerProvider(new OyProvider());
6049
8607
  this.registerProvider(new StripeProvider());
8608
+ this.registerProvider(new PaypalProvider());
8609
+ this.registerProvider(new AdyenProvider());
8610
+ this.registerProvider(new CheckoutComProvider());
8611
+ this.registerProvider(new RazorpayProvider());
8612
+ this.registerProvider(new SquareProvider());
8613
+ this.registerProvider(new PayuProvider());
8614
+ this.registerProvider(new BraintreeProvider());
8615
+ this.registerProvider(new TwoCheckoutProvider());
6050
8616
  }
6051
8617
  registerProvider(provider) {
6052
8618
  this.providers.set(provider.name.toLowerCase(), provider);
@@ -6058,6 +8624,7 @@ var PaymentManager = class {
6058
8624
  }
6059
8625
  return provider;
6060
8626
  }
8627
+ // ─── Indonesian Provider Getters ──────────────────────────────────────────
6061
8628
  getMidtransProvider() {
6062
8629
  return this.getProvider("midtrans");
6063
8630
  }
@@ -6118,12 +8685,62 @@ var PaymentManager = class {
6118
8685
  getOyClient(config) {
6119
8686
  return new OyClient(config);
6120
8687
  }
8688
+ // ─── International Provider Getters ─────────────────────────────────────
6121
8689
  getStripeProvider() {
6122
8690
  return this.getProvider("stripe");
6123
8691
  }
6124
8692
  getStripeClient(config) {
6125
8693
  return new StripeClient(config);
6126
8694
  }
8695
+ getPaypalProvider() {
8696
+ return this.getProvider("paypal");
8697
+ }
8698
+ getPaypalClient(config) {
8699
+ return new PaypalClient(config);
8700
+ }
8701
+ getAdyenProvider() {
8702
+ return this.getProvider("adyen");
8703
+ }
8704
+ getAdyenClient(config) {
8705
+ return new AdyenClient(config);
8706
+ }
8707
+ getCheckoutComProvider() {
8708
+ return this.getProvider("checkoutcom");
8709
+ }
8710
+ getCheckoutComClient(config) {
8711
+ return new CheckoutComClient(config);
8712
+ }
8713
+ getRazorpayProvider() {
8714
+ return this.getProvider("razorpay");
8715
+ }
8716
+ getRazorpayClient(config) {
8717
+ return new RazorpayClient(config);
8718
+ }
8719
+ getSquareProvider() {
8720
+ return this.getProvider("square");
8721
+ }
8722
+ getSquareClient(config) {
8723
+ return new SquareClient(config);
8724
+ }
8725
+ getPayuProvider() {
8726
+ return this.getProvider("payu");
8727
+ }
8728
+ getPayuClient(config) {
8729
+ return new PayuClient(config);
8730
+ }
8731
+ getBraintreeProvider() {
8732
+ return this.getProvider("braintree");
8733
+ }
8734
+ getBraintreeClient(config) {
8735
+ return new BraintreeClient(config);
8736
+ }
8737
+ getTwoCheckoutProvider() {
8738
+ return this.getProvider("twocheckout");
8739
+ }
8740
+ getTwoCheckoutClient(config) {
8741
+ return new TwoCheckoutClient(config);
8742
+ }
8743
+ // ─── Unified Operations ──────────────────────────────────────────────────
6127
8744
  async createInvoice(providerName, params, config) {
6128
8745
  const provider = this.getProvider(providerName);
6129
8746
  return provider.createInvoice(params, config);
@@ -6183,6 +8800,22 @@ function resolveConfigFromEnv(customConfig) {
6183
8800
  sandbox = env.OY_SANDBOX === "true" || env.OY_SANDBOX === "1";
6184
8801
  } else if (env.STRIPE_SANDBOX !== void 0) {
6185
8802
  sandbox = env.STRIPE_SANDBOX === "true" || env.STRIPE_SANDBOX === "1";
8803
+ } else if (env.PAYPAL_SANDBOX !== void 0) {
8804
+ sandbox = env.PAYPAL_SANDBOX === "true" || env.PAYPAL_SANDBOX === "1";
8805
+ } else if (env.ADYEN_SANDBOX !== void 0) {
8806
+ sandbox = env.ADYEN_SANDBOX === "true" || env.ADYEN_SANDBOX === "1";
8807
+ } else if (env.CHECKOUTCOM_SANDBOX !== void 0) {
8808
+ sandbox = env.CHECKOUTCOM_SANDBOX === "true" || env.CHECKOUTCOM_SANDBOX === "1";
8809
+ } else if (env.RAZORPAY_SANDBOX !== void 0) {
8810
+ sandbox = env.RAZORPAY_SANDBOX === "true" || env.RAZORPAY_SANDBOX === "1";
8811
+ } else if (env.SQUARE_SANDBOX !== void 0) {
8812
+ sandbox = env.SQUARE_SANDBOX === "true" || env.SQUARE_SANDBOX === "1";
8813
+ } else if (env.PAYU_SANDBOX !== void 0) {
8814
+ sandbox = env.PAYU_SANDBOX === "true" || env.PAYU_SANDBOX === "1";
8815
+ } else if (env.BRAINTREE_SANDBOX !== void 0) {
8816
+ sandbox = env.BRAINTREE_SANDBOX === "true" || env.BRAINTREE_SANDBOX === "1";
8817
+ } else if (env.TWOCHECKOUT_SANDBOX !== void 0) {
8818
+ sandbox = env.TWOCHECKOUT_SANDBOX === "true" || env.TWOCHECKOUT_SANDBOX === "1";
6186
8819
  } else {
6187
8820
  sandbox = env.NODE_ENV !== "production";
6188
8821
  }
@@ -6210,6 +8843,22 @@ function resolveConfigFromEnv(customConfig) {
6210
8843
  apiKey = env.OY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
6211
8844
  } else if (provider === "stripe") {
6212
8845
  apiKey = env.STRIPE_SECRET_KEY || env.STRIPE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8846
+ } else if (provider === "paypal") {
8847
+ apiKey = env.PAYPAL_CLIENT_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8848
+ } else if (provider === "adyen") {
8849
+ apiKey = env.ADYEN_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8850
+ } else if (provider === "checkoutcom") {
8851
+ apiKey = env.CHECKOUTCOM_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8852
+ } else if (provider === "razorpay") {
8853
+ apiKey = env.RAZORPAY_KEY_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8854
+ } else if (provider === "square") {
8855
+ apiKey = env.SQUARE_ACCESS_TOKEN || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8856
+ } else if (provider === "payu") {
8857
+ apiKey = env.PAYU_MD5_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8858
+ } else if (provider === "braintree") {
8859
+ apiKey = env.BRAINTREE_PRIVATE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8860
+ } else if (provider === "twocheckout" || provider === "2checkout") {
8861
+ apiKey = env.TWOCHECKOUT_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
6213
8862
  } else {
6214
8863
  apiKey = env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.PG_SECRET_KEY || env.BUAYAR_SECRET_KEY;
6215
8864
  }
@@ -6227,7 +8876,7 @@ function resolveConfigFromEnv(customConfig) {
6227
8876
  merchantCode = merchantCode || env.IPAYMU_VA || env.IPAYMU_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6228
8877
  } else if (provider === "doku") {
6229
8878
  merchantCode = merchantCode || env.DOKU_CLIENT_ID || env.DOKU_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6230
- clientKey = clientKey || env.DOKU_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
8879
+ clientKey = clientKey || customConfig?.merchantCode || env.DOKU_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
6231
8880
  } else if (provider === "prismalink") {
6232
8881
  merchantCode = merchantCode || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6233
8882
  merchantId = merchantId || env.PRISMALINK_MERCHANT_ID || env.BUAYAR_MERCHANT_ID;
@@ -6243,30 +8892,67 @@ function resolveConfigFromEnv(customConfig) {
6243
8892
  merchantId = merchantId || env.NICEPAY_IMID || env.BUAYAR_MERCHANT_ID;
6244
8893
  } else if (provider === "oy" || provider === "oyindonesia") {
6245
8894
  merchantCode = merchantCode || env.OY_USERNAME || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6246
- clientKey = clientKey || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
8895
+ clientKey = clientKey || customConfig?.merchantCode || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
6247
8896
  } else if (provider === "stripe") {
6248
8897
  clientKey = clientKey || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.BUAYAR_CLIENT_KEY || env.BUAYAR_PUBLIC_KEY;
6249
8898
  merchantCode = merchantCode || clientKey || "stripe";
8899
+ } else if (provider === "paypal") {
8900
+ clientKey = clientKey || env.PAYPAL_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
8901
+ merchantCode = merchantCode || env.PAYPAL_CLIENT_ID || env.BUAYAR_MERCHANT_CODE;
8902
+ } else if (provider === "adyen") {
8903
+ clientKey = clientKey || env.ADYEN_CLIENT_KEY || env.BUAYAR_CLIENT_KEY;
8904
+ merchantCode = merchantCode || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_CODE;
8905
+ merchantId = merchantId || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_ID;
8906
+ } else if (provider === "checkoutcom") {
8907
+ clientKey = clientKey || env.CHECKOUTCOM_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
8908
+ merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE;
8909
+ } else if (provider === "razorpay") {
8910
+ clientKey = clientKey || env.RAZORPAY_KEY_ID || env.BUAYAR_CLIENT_KEY;
8911
+ merchantCode = merchantCode || env.RAZORPAY_KEY_ID || env.BUAYAR_MERCHANT_CODE;
8912
+ } else if (provider === "square") {
8913
+ clientKey = clientKey || env.SQUARE_APPLICATION_ID || env.BUAYAR_CLIENT_KEY;
8914
+ merchantCode = merchantCode || env.SQUARE_APPLICATION_ID || env.BUAYAR_MERCHANT_CODE;
8915
+ } else if (provider === "payu") {
8916
+ merchantCode = merchantCode || env.PAYU_POS_ID || env.BUAYAR_MERCHANT_CODE;
8917
+ merchantId = merchantId || env.PAYU_POS_ID;
8918
+ } else if (provider === "braintree") {
8919
+ clientKey = clientKey || env.BRAINTREE_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
8920
+ merchantCode = merchantCode || env.BRAINTREE_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE;
8921
+ merchantId = merchantId || env.BRAINTREE_MERCHANT_ID;
8922
+ } else if (provider === "twocheckout" || provider === "2checkout") {
8923
+ merchantCode = merchantCode || env.TWOCHECKOUT_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE;
8924
+ merchantId = merchantId || env.TWOCHECKOUT_MERCHANT_CODE;
6250
8925
  } else {
6251
8926
  merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
6252
8927
  }
6253
- const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID;
6254
- const publicKey = customConfig?.publicKey || env.BUAYAR_PUBLIC_KEY || env.PG_PUBLIC_KEY || env.PUBLIC_KEY || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY;
6255
- const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY;
6256
- 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;
8928
+ const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID || env.SQUARE_LOCATION_ID;
8929
+ 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;
8930
+ const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY || env.BRAINTREE_PRIVATE_KEY;
8931
+ 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;
6257
8932
  const callbackUrl = customConfig?.callbackUrl || env.BUAYAR_CALLBACK_URL || env.PG_CALLBACK_URL || env.PAYMENT_CALLBACK_URL;
6258
8933
  const returnUrl = customConfig?.returnUrl || env.BUAYAR_RETURN_URL || env.PG_RETURN_URL || env.PAYMENT_RETURN_URL;
6259
8934
  const extra = {
6260
8935
  webhookToken: env.XENDIT_WEBHOOK_TOKEN || env.BUAYAR_WEBHOOK_TOKEN,
6261
- webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
8936
+ webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.CHECKOUTCOM_WEBHOOK_SECRET || env.RAZORPAY_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
6262
8937
  merchantName: env.FASPAY_MERCHANT_NAME || env.BUAYAR_MERCHANT_NAME,
6263
8938
  userId: env.FASPAY_USER_ID,
6264
8939
  iMid: env.NICEPAY_IMID,
6265
8940
  username: env.OY_USERNAME,
8941
+ hmacKey: env.ADYEN_HMAC_KEY,
8942
+ liveUrlPrefix: env.ADYEN_LIVE_URL_PREFIX,
8943
+ webhookId: env.PAYPAL_WEBHOOK_ID,
8944
+ merchantAccount: env.ADYEN_MERCHANT_ACCOUNT,
8945
+ md5Key: env.PAYU_MD5_KEY,
8946
+ oauthClientId: env.PAYU_OAUTH_CLIENT_ID,
8947
+ oauthClientSecret: env.PAYU_OAUTH_CLIENT_SECRET,
8948
+ locationId: env.SQUARE_LOCATION_ID,
8949
+ webhookSignatureKey: env.SQUARE_WEBHOOK_SIGNATURE_KEY,
8950
+ publicKey: env.BRAINTREE_PUBLIC_KEY || env.ADYEN_CLIENT_KEY,
8951
+ secretWord: env.TWOCHECKOUT_SECRET_WORD,
6266
8952
  ...customConfig?.extra
6267
8953
  };
6268
8954
  return {
6269
- provider: provider === "oyindonesia" ? "oy" : provider,
8955
+ provider: provider === "oyindonesia" ? "oy" : provider === "2checkout" ? "twocheckout" : provider,
6270
8956
  apiKey: apiKey || "",
6271
8957
  serverKey: apiKey || "",
6272
8958
  secretKey: secretKey || apiKey || "",
@@ -6304,7 +8990,7 @@ var Buayar = class {
6304
8990
  this.config = resolveConfigFromEnv({ ...this.config, ...config });
6305
8991
  }
6306
8992
  /**
6307
- * Dapatkan nama provider aktif ('midtrans' | 'duitku' | 'ipaymu' | 'xendit' | 'doku' | 'prismalink' | 'faspay' | 'finpay' | 'nicepay' | 'oy' | 'stripe' | ...)
8993
+ * Dapatkan nama provider aktif
6308
8994
  */
6309
8995
  get provider() {
6310
8996
  return this.config.provider || "midtrans";
@@ -6353,10 +9039,45 @@ var Buayar = class {
6353
9039
  async verifyWebhook(payload, headers, configOverride) {
6354
9040
  const mergedConfig = { ...this.config, ...configOverride };
6355
9041
  if (headers) {
6356
- const sigHeader = headers["stripe-signature"] || headers["Stripe-Signature"];
6357
- if (sigHeader) {
6358
- if (!mergedConfig.extra) mergedConfig.extra = {};
6359
- mergedConfig.extra.signatureHeader = Array.isArray(sigHeader) ? sigHeader[0] : sigHeader;
9042
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9043
+ mergedConfig.extra.headers = headers;
9044
+ const stripeSig = headers["stripe-signature"] || headers["Stripe-Signature"];
9045
+ if (stripeSig) {
9046
+ mergedConfig.extra.signatureHeader = Array.isArray(stripeSig) ? stripeSig[0] : stripeSig;
9047
+ }
9048
+ const ckoSig = headers["cko-signature"] || headers["Cko-Signature"];
9049
+ if (ckoSig) {
9050
+ mergedConfig.extra.signatureHeader = Array.isArray(ckoSig) ? ckoSig[0] : ckoSig;
9051
+ }
9052
+ const rzpSig = headers["x-razorpay-signature"] || headers["X-Razorpay-Signature"];
9053
+ if (rzpSig) {
9054
+ mergedConfig.extra.signatureHeader = Array.isArray(rzpSig) ? rzpSig[0] : rzpSig;
9055
+ }
9056
+ const squareSig = headers["x-square-hmacsha256-signature"] || headers["x-square-signature"];
9057
+ if (squareSig) {
9058
+ mergedConfig.extra.signatureHeader = Array.isArray(squareSig) ? squareSig[0] : squareSig;
9059
+ }
9060
+ const payuSig = headers["openpayu-signature"] || headers["OpenPayU-Signature"];
9061
+ if (payuSig) {
9062
+ mergedConfig.extra.signatureHeader = Array.isArray(payuSig) ? payuSig[0] : payuSig;
9063
+ }
9064
+ const btSig = headers["bt_signature"];
9065
+ const btPayload = headers["bt_payload"];
9066
+ if (btSig && btPayload) {
9067
+ mergedConfig.extra.btSignature = Array.isArray(btSig) ? btSig[0] : btSig;
9068
+ mergedConfig.extra.btPayload = Array.isArray(btPayload) ? btPayload[0] : btPayload;
9069
+ }
9070
+ const xenditToken = headers["x-callback-token"] || headers["X-Callback-Token"];
9071
+ if (xenditToken) {
9072
+ mergedConfig.extra.callbackToken = Array.isArray(xenditToken) ? xenditToken[0] : xenditToken;
9073
+ }
9074
+ const dokuSig = headers["signature"] || headers["Signature"];
9075
+ if (dokuSig) {
9076
+ mergedConfig.extra.dokuSignature = Array.isArray(dokuSig) ? dokuSig[0] : dokuSig;
9077
+ }
9078
+ const oyUser = headers["x-oy-username"] || headers["X-Oy-Username"];
9079
+ if (oyUser) {
9080
+ mergedConfig.extra.oyUsername = Array.isArray(oyUser) ? oyUser[0] : oyUser;
6360
9081
  }
6361
9082
  }
6362
9083
  let providerName = configOverride?.provider || this.provider;
@@ -6381,8 +9102,24 @@ var Buayar = class {
6381
9102
  providerName = "prismalink";
6382
9103
  } else if (payload.object === "event" || payload.type && payload.data?.object && payload.api_version) {
6383
9104
  providerName = "stripe";
9105
+ } else if (payload.event && payload.payload?.payment?.entity) {
9106
+ providerName = "razorpay";
6384
9107
  } else if (payload.external_id || payload.event?.startsWith("payment.") || payload.event?.startsWith("qr.") || payload.data?.reference_id) {
6385
9108
  providerName = "xendit";
9109
+ } else if (payload.event_type && payload.resource && (payload.event_type.startsWith("PAYMENT.") || payload.event_type.startsWith("CHECKOUT.ORDER."))) {
9110
+ providerName = "paypal";
9111
+ } else if (payload.notificationItems || payload.merchantAccountCode && payload.pspReference && payload.eventCode) {
9112
+ providerName = "adyen";
9113
+ } else if (payload.type && payload.data?._links && (payload.type.startsWith("payment_") || payload.type.startsWith("refund_"))) {
9114
+ providerName = "checkoutcom";
9115
+ } else if (payload.type && payload.data?.object?.status && payload.merchant_id) {
9116
+ providerName = "square";
9117
+ } else if (payload.order && payload.order?.status && payload.order?.extOrderId) {
9118
+ providerName = "payu";
9119
+ } else if (payload.kind && payload.subject?.transaction) {
9120
+ providerName = "braintree";
9121
+ } else if (payload.HASH && payload.REFNOEXT && payload.IPN_PID) {
9122
+ providerName = "twocheckout";
6386
9123
  }
6387
9124
  }
6388
9125
  return this.manager.verifyCallback(providerName, payload, mergedConfig);
@@ -6390,76 +9127,73 @@ var Buayar = class {
6390
9127
  async handleWebhook(payload, headers, configOverride) {
6391
9128
  return this.verifyWebhook(payload, headers, configOverride);
6392
9129
  }
9130
+ // ─── Indonesian Provider Client Getters ───────────────────────────────────
6393
9131
  getMidtransClient(configOverride) {
6394
- return new MidtransClient({
6395
- ...this.config,
6396
- ...configOverride
6397
- });
9132
+ return new MidtransClient({ ...this.config, ...configOverride });
6398
9133
  }
6399
9134
  getDuitkuClient(configOverride) {
6400
- return new DuitkuClient({
6401
- ...this.config,
6402
- ...configOverride
6403
- });
9135
+ return new DuitkuClient({ ...this.config, ...configOverride });
6404
9136
  }
6405
9137
  getIpaymuClient(configOverride) {
6406
- return new IpaymuClient({
6407
- ...this.config,
6408
- ...configOverride
6409
- });
9138
+ return new IpaymuClient({ ...this.config, ...configOverride });
6410
9139
  }
6411
9140
  getXenditClient(configOverride) {
6412
- return new XenditClient({
6413
- ...this.config,
6414
- ...configOverride
6415
- });
9141
+ return new XenditClient({ ...this.config, ...configOverride });
6416
9142
  }
6417
9143
  getDokuClient(configOverride) {
6418
- return new DokuClient({
6419
- ...this.config,
6420
- ...configOverride
6421
- });
9144
+ return new DokuClient({ ...this.config, ...configOverride });
6422
9145
  }
6423
9146
  getPrismalinkClient(configOverride) {
6424
- return new PrismalinkClient({
6425
- ...this.config,
6426
- ...configOverride
6427
- });
9147
+ return new PrismalinkClient({ ...this.config, ...configOverride });
6428
9148
  }
6429
9149
  getFaspayClient(configOverride) {
6430
- return new FaspayClient({
6431
- ...this.config,
6432
- ...configOverride
6433
- });
9150
+ return new FaspayClient({ ...this.config, ...configOverride });
6434
9151
  }
6435
9152
  getFinpayClient(configOverride) {
6436
- return new FinpayClient({
6437
- ...this.config,
6438
- ...configOverride
6439
- });
9153
+ return new FinpayClient({ ...this.config, ...configOverride });
6440
9154
  }
6441
9155
  getNicepayClient(configOverride) {
6442
- return new NicepayClient({
6443
- ...this.config,
6444
- ...configOverride
6445
- });
9156
+ return new NicepayClient({ ...this.config, ...configOverride });
6446
9157
  }
6447
9158
  getOyClient(configOverride) {
6448
- return new OyClient({
6449
- ...this.config,
6450
- ...configOverride
6451
- });
9159
+ return new OyClient({ ...this.config, ...configOverride });
6452
9160
  }
9161
+ // ─── International Provider Client Getters ────────────────────────────────
6453
9162
  getStripeClient(configOverride) {
6454
- return new StripeClient({
6455
- ...this.config,
6456
- ...configOverride
6457
- });
9163
+ return new StripeClient({ ...this.config, ...configOverride });
9164
+ }
9165
+ getPaypalClient(configOverride) {
9166
+ return new PaypalClient({ ...this.config, ...configOverride });
9167
+ }
9168
+ getAdyenClient(configOverride) {
9169
+ return new AdyenClient({ ...this.config, ...configOverride });
9170
+ }
9171
+ getCheckoutComClient(configOverride) {
9172
+ return new CheckoutComClient({ ...this.config, ...configOverride });
9173
+ }
9174
+ getRazorpayClient(configOverride) {
9175
+ return new RazorpayClient({ ...this.config, ...configOverride });
9176
+ }
9177
+ getSquareClient(configOverride) {
9178
+ return new SquareClient({ ...this.config, ...configOverride });
9179
+ }
9180
+ getPayuClient(configOverride) {
9181
+ return new PayuClient({ ...this.config, ...configOverride });
9182
+ }
9183
+ getBraintreeClient(configOverride) {
9184
+ return new BraintreeClient({ ...this.config, ...configOverride });
9185
+ }
9186
+ getTwoCheckoutClient(configOverride) {
9187
+ return new TwoCheckoutClient({ ...this.config, ...configOverride });
6458
9188
  }
6459
9189
  };
6460
9190
  var buayar = new Buayar();
6461
9191
  export {
9192
+ AdyenClient,
9193
+ AdyenProvider,
6462
9194
  BasePaymentProvider,
9195
+ BraintreeClient,
9196
+ BraintreeProvider,
6463
9197
  Buayar,
6464
9198
  CANONICAL_TO_DOKU,
6465
9199
  CANONICAL_TO_DUITKU,
@@ -6473,6 +9207,8 @@ export {
6473
9207
  CANONICAL_TO_STRIPE,
6474
9208
  CANONICAL_TO_XENDIT,
6475
9209
  CORE_API_METHODS,
9210
+ CheckoutComClient,
9211
+ CheckoutComProvider,
6476
9212
  DUITKU_TO_CANONICAL,
6477
9213
  DokuClient,
6478
9214
  DokuProvider,
@@ -6493,14 +9229,29 @@ export {
6493
9229
  OyClient,
6494
9230
  OyProvider,
6495
9231
  PaymentManager,
9232
+ PaypalClient,
9233
+ PaypalProvider,
9234
+ PayuClient,
9235
+ PayuProvider,
6496
9236
  PrismalinkClient,
6497
9237
  PrismalinkProvider,
9238
+ RazorpayClient,
9239
+ RazorpayProvider,
9240
+ SquareClient,
9241
+ SquareProvider,
6498
9242
  StripeClient,
6499
9243
  StripeProvider,
9244
+ TwoCheckoutClient,
9245
+ TwoCheckoutProvider,
6500
9246
  XenditClient,
6501
9247
  XenditProvider,
6502
9248
  buayar,
9249
+ buildBraintreeBasicAuth,
6503
9250
  buildCoreChargePayload,
9251
+ buildPaypalBasicAuth,
9252
+ buildPayuBasicAuth,
9253
+ buildRazorpayBasicAuth,
9254
+ buildTwoCheckoutAuth,
6504
9255
  formatNicepayTimestamp,
6505
9256
  generateDokuHeaders,
6506
9257
  generateFaspaySignature,
@@ -6520,6 +9271,7 @@ export {
6520
9271
  paymentManager,
6521
9272
  resolveConfigFromEnv,
6522
9273
  safeCompare,
9274
+ serializePaypalParams,
6523
9275
  serializeStripeParams,
6524
9276
  sha256,
6525
9277
  sha512,
@@ -6534,6 +9286,9 @@ export {
6534
9286
  toPrismalinkPaymentMethod,
6535
9287
  toStripePaymentMethod,
6536
9288
  toXenditPaymentMethod,
9289
+ verifyAdyenWebhook,
9290
+ verifyBraintreeWebhook,
9291
+ verifyCheckoutComWebhook,
6537
9292
  verifyDokuWebhookSignature,
6538
9293
  verifyDuitkuCallbackSignature,
6539
9294
  verifyFaspaySignature,
@@ -6541,7 +9296,12 @@ export {
6541
9296
  verifyIpaymuCallback,
6542
9297
  verifyNicepayWebhook,
6543
9298
  verifyOyWebhook,
9299
+ verifyPaypalWebhookSimple,
9300
+ verifyPayuWebhook,
6544
9301
  verifyPrismalinkSignature,
9302
+ verifyRazorpayWebhook,
9303
+ verifySquareWebhook,
6545
9304
  verifyStripeWebhook,
9305
+ verifyTwoCheckoutWebhook,
6546
9306
  verifyXenditWebhookToken
6547
9307
  };