@crediblemark/buayar 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -30,7 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AdyenClient: () => AdyenClient,
34
+ AdyenProvider: () => AdyenProvider,
33
35
  BasePaymentProvider: () => BasePaymentProvider,
36
+ BraintreeClient: () => BraintreeClient,
37
+ BraintreeProvider: () => BraintreeProvider,
34
38
  Buayar: () => Buayar,
35
39
  CANONICAL_TO_DOKU: () => CANONICAL_TO_DOKU,
36
40
  CANONICAL_TO_DUITKU: () => CANONICAL_TO_DUITKU,
@@ -41,8 +45,11 @@ __export(index_exports, {
41
45
  CANONICAL_TO_NICEPAY: () => CANONICAL_TO_NICEPAY,
42
46
  CANONICAL_TO_OY: () => CANONICAL_TO_OY,
43
47
  CANONICAL_TO_PRISMALINK: () => CANONICAL_TO_PRISMALINK,
48
+ CANONICAL_TO_STRIPE: () => CANONICAL_TO_STRIPE,
44
49
  CANONICAL_TO_XENDIT: () => CANONICAL_TO_XENDIT,
45
50
  CORE_API_METHODS: () => CORE_API_METHODS,
51
+ CheckoutComClient: () => CheckoutComClient,
52
+ CheckoutComProvider: () => CheckoutComProvider,
46
53
  DUITKU_TO_CANONICAL: () => DUITKU_TO_CANONICAL,
47
54
  DokuClient: () => DokuClient,
48
55
  DokuProvider: () => DokuProvider,
@@ -63,12 +70,29 @@ __export(index_exports, {
63
70
  OyClient: () => OyClient,
64
71
  OyProvider: () => OyProvider,
65
72
  PaymentManager: () => PaymentManager,
73
+ PaypalClient: () => PaypalClient,
74
+ PaypalProvider: () => PaypalProvider,
75
+ PayuClient: () => PayuClient,
76
+ PayuProvider: () => PayuProvider,
66
77
  PrismalinkClient: () => PrismalinkClient,
67
78
  PrismalinkProvider: () => PrismalinkProvider,
79
+ RazorpayClient: () => RazorpayClient,
80
+ RazorpayProvider: () => RazorpayProvider,
81
+ SquareClient: () => SquareClient,
82
+ SquareProvider: () => SquareProvider,
83
+ StripeClient: () => StripeClient,
84
+ StripeProvider: () => StripeProvider,
85
+ TwoCheckoutClient: () => TwoCheckoutClient,
86
+ TwoCheckoutProvider: () => TwoCheckoutProvider,
68
87
  XenditClient: () => XenditClient,
69
88
  XenditProvider: () => XenditProvider,
70
89
  buayar: () => buayar,
90
+ buildBraintreeBasicAuth: () => buildBraintreeBasicAuth,
71
91
  buildCoreChargePayload: () => buildCoreChargePayload,
92
+ buildPaypalBasicAuth: () => buildPaypalBasicAuth,
93
+ buildPayuBasicAuth: () => buildPayuBasicAuth,
94
+ buildRazorpayBasicAuth: () => buildRazorpayBasicAuth,
95
+ buildTwoCheckoutAuth: () => buildTwoCheckoutAuth,
72
96
  formatNicepayTimestamp: () => formatNicepayTimestamp,
73
97
  generateDokuHeaders: () => generateDokuHeaders,
74
98
  generateFaspaySignature: () => generateFaspaySignature,
@@ -88,6 +112,8 @@ __export(index_exports, {
88
112
  paymentManager: () => paymentManager,
89
113
  resolveConfigFromEnv: () => resolveConfigFromEnv,
90
114
  safeCompare: () => safeCompare,
115
+ serializePaypalParams: () => serializePaypalParams,
116
+ serializeStripeParams: () => serializeStripeParams,
91
117
  sha256: () => sha256,
92
118
  sha512: () => sha512,
93
119
  toCanonicalPaymentMethod: () => toCanonicalPaymentMethod,
@@ -99,7 +125,11 @@ __export(index_exports, {
99
125
  toNicepayPaymentMethod: () => toNicepayPaymentMethod,
100
126
  toOyPaymentMethod: () => toOyPaymentMethod,
101
127
  toPrismalinkPaymentMethod: () => toPrismalinkPaymentMethod,
128
+ toStripePaymentMethod: () => toStripePaymentMethod,
102
129
  toXenditPaymentMethod: () => toXenditPaymentMethod,
130
+ verifyAdyenWebhook: () => verifyAdyenWebhook,
131
+ verifyBraintreeWebhook: () => verifyBraintreeWebhook,
132
+ verifyCheckoutComWebhook: () => verifyCheckoutComWebhook,
103
133
  verifyDokuWebhookSignature: () => verifyDokuWebhookSignature,
104
134
  verifyDuitkuCallbackSignature: () => verifyDuitkuCallbackSignature,
105
135
  verifyFaspaySignature: () => verifyFaspaySignature,
@@ -107,7 +137,13 @@ __export(index_exports, {
107
137
  verifyIpaymuCallback: () => verifyIpaymuCallback,
108
138
  verifyNicepayWebhook: () => verifyNicepayWebhook,
109
139
  verifyOyWebhook: () => verifyOyWebhook,
140
+ verifyPaypalWebhookSimple: () => verifyPaypalWebhookSimple,
141
+ verifyPayuWebhook: () => verifyPayuWebhook,
110
142
  verifyPrismalinkSignature: () => verifyPrismalinkSignature,
143
+ verifyRazorpayWebhook: () => verifyRazorpayWebhook,
144
+ verifySquareWebhook: () => verifySquareWebhook,
145
+ verifyStripeWebhook: () => verifyStripeWebhook,
146
+ verifyTwoCheckoutWebhook: () => verifyTwoCheckoutWebhook,
111
147
  verifyXenditWebhookToken: () => verifyXenditWebhookToken
112
148
  });
113
149
  module.exports = __toCommonJS(index_exports);
@@ -395,6 +431,17 @@ var CANONICAL_TO_OY = {
395
431
  alfamart: { type: "cstore", channel: "alfamart" },
396
432
  indomaret: { type: "cstore", channel: "indomaret" }
397
433
  };
434
+ var CANONICAL_TO_STRIPE = {
435
+ credit_card: "card",
436
+ qris: "qris",
437
+ gopay_qris: "qris",
438
+ shopeepay_qris: "qris",
439
+ bca_va: "customer_balance",
440
+ mandiri_va: "customer_balance",
441
+ bni_va: "customer_balance",
442
+ bri_va: "customer_balance",
443
+ permata_va: "customer_balance"
444
+ };
398
445
  function toDuitkuPaymentMethod(code) {
399
446
  if (!code) return void 0;
400
447
  const lower = code.toLowerCase().trim();
@@ -482,6 +529,14 @@ function toOyPaymentMethod(code) {
482
529
  }
483
530
  return void 0;
484
531
  }
532
+ function toStripePaymentMethod(code) {
533
+ if (!code) return void 0;
534
+ const lower = code.toLowerCase().trim();
535
+ if (CANONICAL_TO_STRIPE[lower]) {
536
+ return CANONICAL_TO_STRIPE[lower];
537
+ }
538
+ return lower;
539
+ }
485
540
  function toCanonicalPaymentMethod(provider, code) {
486
541
  if (!code) return "";
487
542
  const upper = code.toUpperCase().trim();
@@ -489,7 +544,7 @@ function toCanonicalPaymentMethod(provider, code) {
489
544
  if (provider.toLowerCase() === "duitku" && DUITKU_TO_CANONICAL[upper]) {
490
545
  return DUITKU_TO_CANONICAL[upper];
491
546
  }
492
- if (CANONICAL_TO_MIDTRANS[lower] || CANONICAL_TO_DUITKU[lower] || CANONICAL_TO_IPAYMU[lower] || CANONICAL_TO_XENDIT[lower] || CANONICAL_TO_DOKU[lower] || CANONICAL_TO_PRISMALINK[lower] || CANONICAL_TO_FASPAY[lower] || CANONICAL_TO_FINPAY[lower] || CANONICAL_TO_NICEPAY[lower] || CANONICAL_TO_OY[lower]) {
547
+ if (CANONICAL_TO_MIDTRANS[lower] || CANONICAL_TO_DUITKU[lower] || CANONICAL_TO_IPAYMU[lower] || CANONICAL_TO_XENDIT[lower] || CANONICAL_TO_DOKU[lower] || CANONICAL_TO_PRISMALINK[lower] || CANONICAL_TO_FASPAY[lower] || CANONICAL_TO_FINPAY[lower] || CANONICAL_TO_NICEPAY[lower] || CANONICAL_TO_OY[lower] || CANONICAL_TO_STRIPE[lower]) {
493
548
  return lower;
494
549
  }
495
550
  return lower;
@@ -5000,225 +5055,2770 @@ var OyProvider = class extends BasePaymentProvider {
5000
5055
  }
5001
5056
  };
5002
5057
 
5003
- // src/clients/duitku.ts
5004
- var DuitkuClient = class {
5005
- merchantCode;
5006
- apiKey;
5007
- sandbox;
5008
- constructor(config) {
5009
- this.merchantCode = config.merchantCode || "";
5010
- this.apiKey = config.apiKey || config.serverKey || "";
5011
- this.sandbox = !!config.sandbox;
5012
- }
5013
- getPassportBaseUrl() {
5014
- return this.sandbox ? "https://sandbox.duitku.com/webapi" : "https://passport.duitku.com/webapi";
5015
- }
5016
- getApiBaseUrl() {
5017
- return this.sandbox ? "https://api-sandbox.duitku.com" : "https://api-prod.duitku.com";
5018
- }
5019
- /**
5020
- * Request helper generic dengan kalkulasi signature Duitku otomatis
5021
- */
5022
- async request(method, endpoint, body = {}, options) {
5023
- const baseUrl = options?.baseUrl === "api" ? this.getApiBaseUrl() : this.getPassportBaseUrl();
5024
- const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
5025
- const timestamp = Date.now().toString();
5026
- const headerSignature = sha256(this.merchantCode + timestamp + this.apiKey);
5027
- const headers = {
5028
- "Content-Type": "application/json",
5029
- "Accept": "application/json",
5030
- "x-duitku-signature": headerSignature,
5031
- "x-duitku-timestamp": timestamp,
5032
- "x-duitku-merchantcode": this.merchantCode,
5033
- ...options?.customHeaders
5034
- };
5035
- const fetchOptions = {
5036
- method,
5037
- headers
5038
- };
5039
- if (method === "POST" && body) {
5040
- fetchOptions.body = JSON.stringify(body);
5041
- }
5042
- const response = await fetch(url, fetchOptions);
5043
- const text = await response.text();
5044
- let data = null;
5045
- try {
5046
- data = JSON.parse(text);
5047
- } catch (e) {
5058
+ // src/providers/stripe/signature.ts
5059
+ function serializeStripeParams(obj, prefix = "") {
5060
+ const pairs = [];
5061
+ if (obj === null || obj === void 0) {
5062
+ return "";
5063
+ }
5064
+ for (const key of Object.keys(obj)) {
5065
+ const val = obj[key];
5066
+ if (val === void 0 || val === null) continue;
5067
+ const fullKey = prefix ? `${prefix}[${key}]` : key;
5068
+ if (typeof val === "object" && !(val instanceof Date)) {
5069
+ const nested = serializeStripeParams(val, fullKey);
5070
+ if (nested) pairs.push(nested);
5071
+ } else {
5072
+ pairs.push(`${encodeURIComponent(fullKey)}=${encodeURIComponent(String(val))}`);
5048
5073
  }
5049
- if (!response.ok) {
5050
- throw new Error(data?.Message || data?.statusMessage || data?.responseMessage || `HTTP error! Status: ${response.status} - ${text}`);
5074
+ }
5075
+ return pairs.join("&");
5076
+ }
5077
+ function verifyStripeWebhook(rawPayload, signatureHeader, webhookSecret, toleranceSeconds = 300) {
5078
+ if (!signatureHeader || !webhookSecret) {
5079
+ return true;
5080
+ }
5081
+ const items = signatureHeader.split(",");
5082
+ let timestamp = "";
5083
+ const signatures = [];
5084
+ for (const item of items) {
5085
+ const [key, value] = item.trim().split("=");
5086
+ if (key === "t") {
5087
+ timestamp = value;
5088
+ } else if (key === "v1") {
5089
+ signatures.push(value);
5051
5090
  }
5052
- return data || text;
5053
5091
  }
5054
- // ─── TRANSACTIONS & PAYMENT METHODS ──────────────────────────────────────────
5055
- /**
5056
- * Cek status transaksi pembayaran berdasarkan merchant order ID
5057
- */
5058
- async checkTransaction(merchantOrderId) {
5059
- const { bodySignature } = getDuitkuStatusSignatures(
5060
- this.merchantCode,
5061
- merchantOrderId,
5062
- this.apiKey
5063
- );
5064
- return this.request(
5065
- "POST",
5066
- "/api/merchant/transactionStatus",
5067
- {
5068
- merchantCode: this.merchantCode,
5069
- merchantOrderId,
5070
- signature: bodySignature
5071
- },
5072
- { baseUrl: "api" }
5073
- );
5092
+ if (!timestamp || signatures.length === 0) {
5093
+ return false;
5074
5094
  }
5075
- /**
5076
- * Ambil daftar channel pembayaran aktif dan kalkulasi fee dinamis
5077
- */
5078
- async getPaymentMethods(amount = 1e4) {
5079
- const integerAmount = Math.round(amount);
5080
- const datetime = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
5081
- const signature = getDuitkuPaymentMethodsSignature(this.merchantCode, integerAmount, datetime, this.apiKey);
5082
- return this.request("POST", "/api/merchant/paymentmethod/getpaymentmethod", {
5083
- merchantcode: this.merchantCode,
5084
- amount: integerAmount,
5085
- datetime,
5086
- signature
5087
- });
5095
+ const payloadString = typeof rawPayload === "string" ? rawPayload : JSON.stringify(rawPayload);
5096
+ const signedPayload = `${timestamp}.${payloadString}`;
5097
+ const expectedSignature = hmacSha256(signedPayload, webhookSecret);
5098
+ return signatures.some((sig) => safeCompare(sig.toLowerCase(), expectedSignature.toLowerCase()));
5099
+ }
5100
+
5101
+ // src/providers/stripe/provider.ts
5102
+ var StripeProvider = class extends BasePaymentProvider {
5103
+ name = "stripe";
5104
+ getBaseUrl() {
5105
+ return "https://api.stripe.com/v1";
5088
5106
  }
5089
- // ─── DISBURSEMENT & BALANCE INQUIRY ──────────────────────────────────────────
5090
- /**
5091
- * Cek saldo merchant (Balance Inquiry)
5092
- */
5093
- async checkBalance() {
5094
- const timestamp = Date.now().toString();
5095
- const signature = sha256(this.merchantCode + timestamp + this.apiKey);
5107
+ async createInvoice(params, config) {
5108
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
5109
+ const secretKey = config.apiKey || config.serverKey || config.secretKey || "";
5110
+ const integerAmount = Math.round(amount);
5111
+ const stripeMethod = toStripePaymentMethod(params.paymentMethod);
5112
+ const isDirect = !!params.paymentMethod;
5113
+ const baseUrl = this.getBaseUrl();
5114
+ const headers = {
5115
+ "Authorization": `Bearer ${secretKey}`,
5116
+ "Content-Type": "application/x-www-form-urlencoded"
5117
+ };
5096
5118
  try {
5097
- const data = await this.request(
5098
- "POST",
5099
- "/api/merchant/checkBalance",
5100
- {
5101
- merchantCode: this.merchantCode,
5102
- signature
5103
- },
5104
- { baseUrl: "api" }
5105
- );
5106
- return {
5107
- success: data.responseCode === "00" || data.statusCode === "00",
5108
- balance: data.balance ? Number(data.balance) : void 0,
5109
- rawResponse: data
5110
- };
5119
+ if (isDirect) {
5120
+ const url = `${baseUrl}/payment_intents`;
5121
+ const payload = {
5122
+ amount: integerAmount,
5123
+ currency: (params.currency || "idr").toLowerCase(),
5124
+ description: productDetails,
5125
+ receipt_email: customer?.email,
5126
+ payment_method_types: [stripeMethod || "card"],
5127
+ metadata: {
5128
+ order_id: orderId,
5129
+ customer_name: customer?.name
5130
+ },
5131
+ ...params.providerParams
5132
+ };
5133
+ const response = await fetch(url, {
5134
+ method: "POST",
5135
+ headers,
5136
+ body: serializeStripeParams(payload)
5137
+ });
5138
+ const text = await response.text();
5139
+ let data = null;
5140
+ try {
5141
+ data = JSON.parse(text);
5142
+ } catch (e) {
5143
+ }
5144
+ if (!response.ok || !data || data.error) {
5145
+ return {
5146
+ success: false,
5147
+ provider: "stripe",
5148
+ orderId,
5149
+ amount: integerAmount,
5150
+ rawResponse: data,
5151
+ error: data?.error?.message || `HTTP error! Status: ${response.status} - ${text}`
5152
+ };
5153
+ }
5154
+ return {
5155
+ success: true,
5156
+ provider: "stripe",
5157
+ orderId,
5158
+ amount: data.amount ? Number(data.amount) : integerAmount,
5159
+ reference: data.id,
5160
+ paymentCode: data.client_secret,
5161
+ rawResponse: data
5162
+ };
5163
+ } else {
5164
+ const url = `${baseUrl}/checkout/sessions`;
5165
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5166
+ const cancelUrl = returnUrl || config.returnUrl || "https://example.com/payment/cancel";
5167
+ const payload = {
5168
+ mode: "payment",
5169
+ client_reference_id: orderId,
5170
+ customer_email: customer?.email,
5171
+ line_items: [
5172
+ {
5173
+ price_data: {
5174
+ currency: (params.currency || "idr").toLowerCase(),
5175
+ product_data: {
5176
+ name: productDetails
5177
+ },
5178
+ unit_amount: integerAmount
5179
+ },
5180
+ quantity: 1
5181
+ }
5182
+ ],
5183
+ metadata: {
5184
+ order_id: orderId
5185
+ },
5186
+ success_url: successUrl,
5187
+ cancel_url: cancelUrl,
5188
+ ...params.providerParams
5189
+ };
5190
+ const response = await fetch(url, {
5191
+ method: "POST",
5192
+ headers,
5193
+ body: serializeStripeParams(payload)
5194
+ });
5195
+ const text = await response.text();
5196
+ let data = null;
5197
+ try {
5198
+ data = JSON.parse(text);
5199
+ } catch (e) {
5200
+ }
5201
+ if (!response.ok || !data || data.error) {
5202
+ return {
5203
+ success: false,
5204
+ provider: "stripe",
5205
+ orderId,
5206
+ amount: integerAmount,
5207
+ rawResponse: data,
5208
+ error: data?.error?.message || `HTTP error! Status: ${response.status} - ${text}`
5209
+ };
5210
+ }
5211
+ return {
5212
+ success: true,
5213
+ provider: "stripe",
5214
+ orderId: data.client_reference_id || orderId,
5215
+ amount: data.amount_total ? Number(data.amount_total) : integerAmount,
5216
+ reference: data.id,
5217
+ paymentUrl: data.url,
5218
+ rawResponse: data
5219
+ };
5220
+ }
5111
5221
  } catch (e) {
5112
5222
  return {
5113
5223
  success: false,
5224
+ provider: "stripe",
5225
+ orderId,
5226
+ amount: integerAmount,
5114
5227
  rawResponse: null,
5115
- error: e.message || "Failed to check Duitku merchant balance"
5228
+ error: e.message || "Failed to make request to Stripe API"
5116
5229
  };
5117
5230
  }
5118
5231
  }
5119
- /**
5120
- * Mengambil daftar bank yang didukung untuk transfer / penarikan dana
5121
- */
5122
- async listBanks() {
5123
- const timestamp = Date.now().toString();
5124
- const signature = sha256(this.merchantCode + timestamp + this.apiKey);
5125
- return this.request(
5126
- "POST",
5127
- "/api/disbursement/listBank",
5232
+ async verifyCallback(body, config) {
5233
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
5234
+ const signatureHeader = config.extra?.signatureHeader || "";
5235
+ const isValid = verifyStripeWebhook(body, signatureHeader, webhookSecret);
5236
+ const eventType = body.type || "";
5237
+ const obj = body.data?.object || body;
5238
+ const orderId = obj.metadata?.order_id || obj.client_reference_id || obj.id || "";
5239
+ const amount = obj.amount_total || obj.amount || 0;
5240
+ const paymentStatus = (obj.payment_status || obj.status || "").toLowerCase();
5241
+ const isPaid = eventType === "checkout.session.completed" && (paymentStatus === "paid" || paymentStatus === "complete") || eventType === "payment_intent.succeeded" && paymentStatus === "succeeded" || eventType === "charge.succeeded" && (paymentStatus === "succeeded" || paymentStatus === "paid") || paymentStatus === "paid" || paymentStatus === "succeeded";
5242
+ const isPending = paymentStatus === "unpaid" || paymentStatus === "processing" || paymentStatus === "requires_action";
5243
+ const isExpired = paymentStatus === "expired" || eventType === "checkout.session.expired";
5244
+ const isFailed = !isPaid && !isPending && !isExpired;
5245
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5246
+ return {
5247
+ isValid,
5248
+ provider: "stripe",
5249
+ orderId: String(orderId),
5250
+ amount: Number(amount) || 0,
5251
+ status,
5252
+ isPaid,
5253
+ isPending,
5254
+ isFailed,
5255
+ isExpired,
5256
+ statusCode: eventType || paymentStatus,
5257
+ rawPayload: body
5258
+ };
5259
+ }
5260
+ async getPaymentMethods(params, config) {
5261
+ const staticMethods = [
5128
5262
  {
5129
- merchantCode: this.merchantCode,
5130
- signature
5263
+ paymentMethod: "credit_card",
5264
+ code: "credit_card",
5265
+ paymentName: "Credit / Debit Card (Visa, Mastercard, JCB, Amex)",
5266
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5267
+ totalFee: "2.9% + IDR 2,000",
5268
+ category: "Kartu Kredit"
5131
5269
  },
5132
- { baseUrl: "api" }
5133
- );
5134
- }
5135
- /**
5136
- * Validasi nama pemilik rekening bank sebelum eksekusi transfer (Bank Account Inquiry)
5137
- */
5138
- async inquiryBankAccount(bankCode, bankAccount) {
5139
- const timestamp = Date.now().toString();
5140
- const signature = sha256(this.merchantCode + bankCode + bankAccount + this.apiKey);
5141
- return this.request(
5142
- "POST",
5143
- "/api/disbursement/inquiry",
5144
5270
  {
5145
- merchantCode: this.merchantCode,
5146
- bankCode,
5147
- bankAccount,
5148
- signature
5271
+ paymentMethod: "qris",
5272
+ code: "qris",
5273
+ paymentName: "QRIS (Indonesia)",
5274
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5275
+ totalFee: "0.7%",
5276
+ category: "QRIS"
5149
5277
  },
5150
- { baseUrl: "api" }
5151
- );
5152
- }
5153
- /**
5154
- * Eksekusi transfer dana / payout (Disbursement Transfer)
5155
- */
5156
- async disburse(params) {
5157
- const integerAmount = Math.round(params.amount);
5158
- const signature = sha256(
5159
- this.merchantCode + params.merchantOrderId + params.bankCode + params.bankAccount + integerAmount.toString() + this.apiKey
5160
- );
5161
- const payload = {
5162
- merchantCode: this.merchantCode,
5163
- merchantOrderId: params.merchantOrderId,
5164
- bankCode: params.bankCode,
5165
- bankAccount: params.bankAccount,
5166
- amount: integerAmount,
5167
- purpose: params.purpose,
5168
- senderName: params.senderName || "",
5169
- senderPhone: params.senderPhone || "",
5170
- callbackUrl: params.callbackUrl || "",
5278
+ {
5279
+ paymentMethod: "bca_va",
5280
+ code: "bca_va",
5281
+ paymentName: "BCA Virtual Account (Bank Transfer)",
5282
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5283
+ totalFee: "IDR 4,000",
5284
+ category: "Virtual Account"
5285
+ },
5286
+ {
5287
+ paymentMethod: "mandiri_va",
5288
+ code: "mandiri_va",
5289
+ paymentName: "Mandiri Virtual Account (Bank Transfer)",
5290
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5291
+ totalFee: "IDR 4,000",
5292
+ category: "Virtual Account"
5293
+ },
5294
+ {
5295
+ paymentMethod: "bni_va",
5296
+ code: "bni_va",
5297
+ paymentName: "BNI Virtual Account (Bank Transfer)",
5298
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5299
+ totalFee: "IDR 4,000",
5300
+ category: "Virtual Account"
5301
+ },
5302
+ {
5303
+ paymentMethod: "bri_va",
5304
+ code: "bri_va",
5305
+ paymentName: "BRI Virtual Account (Bank Transfer)",
5306
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5307
+ totalFee: "IDR 4,000",
5308
+ category: "Virtual Account"
5309
+ },
5310
+ {
5311
+ paymentMethod: "permata_va",
5312
+ code: "permata_va",
5313
+ paymentName: "Permata Virtual Account (Bank Transfer)",
5314
+ paymentImage: "https://stripe.com/img/v3/home/social.png",
5315
+ totalFee: "IDR 4,000",
5316
+ category: "Virtual Account"
5317
+ }
5318
+ ];
5319
+ const categories = {};
5320
+ for (const item of staticMethods) {
5321
+ if (!categories[item.category]) {
5322
+ categories[item.category] = [];
5323
+ }
5324
+ categories[item.category].push(item);
5325
+ }
5326
+ return {
5327
+ success: true,
5328
+ provider: "stripe",
5329
+ methods: staticMethods,
5330
+ categories,
5331
+ rawResponse: staticMethods
5332
+ };
5333
+ }
5334
+ async checkTransaction(params, config) {
5335
+ const { merchantOrderId } = params;
5336
+ const secretKey = config.apiKey || config.serverKey || config.secretKey || "";
5337
+ const baseUrl = this.getBaseUrl();
5338
+ let endpoint = `/checkout/sessions/${encodeURIComponent(merchantOrderId)}`;
5339
+ if (merchantOrderId.startsWith("pi_")) {
5340
+ endpoint = `/payment_intents/${encodeURIComponent(merchantOrderId)}`;
5341
+ }
5342
+ const url = `${baseUrl}${endpoint}`;
5343
+ const headers = {
5344
+ "Authorization": `Bearer ${secretKey}`,
5345
+ "Accept": "application/json"
5346
+ };
5347
+ try {
5348
+ const response = await fetch(url, {
5349
+ method: "GET",
5350
+ headers
5351
+ });
5352
+ const text = await response.text();
5353
+ let data = null;
5354
+ try {
5355
+ data = JSON.parse(text);
5356
+ } catch (e) {
5357
+ }
5358
+ if (!response.ok || !data || data.error) {
5359
+ return {
5360
+ success: false,
5361
+ provider: "stripe",
5362
+ orderId: merchantOrderId,
5363
+ reference: "",
5364
+ amount: 0,
5365
+ statusCode: response.status.toString(),
5366
+ status: "failed",
5367
+ isPaid: false,
5368
+ isPending: false,
5369
+ isFailed: true,
5370
+ isExpired: false,
5371
+ statusMessage: data?.error?.message || `HTTP error! Status: ${response.status}`,
5372
+ error: data?.error?.message || `HTTP error! Status: ${response.status}`,
5373
+ rawResponse: data
5374
+ };
5375
+ }
5376
+ const paymentStatus = (data.payment_status || data.status || "").toLowerCase();
5377
+ const isPaid = paymentStatus === "paid" || paymentStatus === "succeeded" || paymentStatus === "complete";
5378
+ const isPending = paymentStatus === "unpaid" || paymentStatus === "processing" || paymentStatus === "requires_action";
5379
+ const isExpired = paymentStatus === "expired";
5380
+ const isFailed = !isPaid && !isPending && !isExpired;
5381
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5382
+ return {
5383
+ success: true,
5384
+ provider: "stripe",
5385
+ orderId: data.metadata?.order_id || data.client_reference_id || data.id || merchantOrderId,
5386
+ reference: data.id || "",
5387
+ amount: data.amount_total ? Number(data.amount_total) : data.amount ? Number(data.amount) : 0,
5388
+ statusCode: paymentStatus,
5389
+ status,
5390
+ isPaid,
5391
+ isPending,
5392
+ isFailed,
5393
+ isExpired,
5394
+ statusMessage: paymentStatus,
5395
+ paymentType: data.payment_method_types?.[0] || "card",
5396
+ transactionTime: data.created ? new Date(data.created * 1e3) : void 0,
5397
+ rawResponse: data
5398
+ };
5399
+ } catch (e) {
5400
+ return {
5401
+ success: false,
5402
+ provider: "stripe",
5403
+ orderId: merchantOrderId,
5404
+ reference: "",
5405
+ amount: 0,
5406
+ statusCode: "ERROR",
5407
+ status: "failed",
5408
+ isPaid: false,
5409
+ isPending: false,
5410
+ isFailed: true,
5411
+ isExpired: false,
5412
+ statusMessage: e.message || "Failed to check transaction status in Stripe",
5413
+ error: e.message || "Failed to check transaction status in Stripe",
5414
+ rawResponse: null
5415
+ };
5416
+ }
5417
+ }
5418
+ };
5419
+
5420
+ // src/providers/paypal/signature.ts
5421
+ function buildPaypalBasicAuth(clientId, clientSecret) {
5422
+ return Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
5423
+ }
5424
+ function verifyPaypalWebhookSimple(transmissionId, timestamp, webhookId, body, transmissionSig, certUrl) {
5425
+ return !!(transmissionId && timestamp && webhookId && transmissionSig && certUrl);
5426
+ }
5427
+ function serializePaypalParams(obj) {
5428
+ return Object.entries(obj).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
5429
+ }
5430
+
5431
+ // src/providers/paypal/provider.ts
5432
+ var PaypalProvider = class extends BasePaymentProvider {
5433
+ name = "paypal";
5434
+ getSandbox(config) {
5435
+ return config.sandbox !== false;
5436
+ }
5437
+ getBaseUrl(config) {
5438
+ return this.getSandbox(config) ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
5439
+ }
5440
+ /** OAuth2 Client Credentials — dapatkan access token */
5441
+ async getAccessToken(config) {
5442
+ const clientId = config.clientKey || config.merchantCode || config.merchantId || "";
5443
+ const clientSecret = config.apiKey || config.secretKey || "";
5444
+ const auth = buildPaypalBasicAuth(clientId, clientSecret);
5445
+ const baseUrl = this.getBaseUrl(config);
5446
+ const response = await fetch(`${baseUrl}/v1/oauth2/token`, {
5447
+ method: "POST",
5448
+ headers: {
5449
+ "Authorization": `Basic ${auth}`,
5450
+ "Content-Type": "application/x-www-form-urlencoded"
5451
+ },
5452
+ body: "grant_type=client_credentials"
5453
+ });
5454
+ const text = await response.text();
5455
+ let data = null;
5456
+ try {
5457
+ data = JSON.parse(text);
5458
+ } catch (e) {
5459
+ }
5460
+ if (!response.ok || !data?.access_token) {
5461
+ throw new Error(data?.error_description || `Failed to get PayPal access token: ${response.status}`);
5462
+ }
5463
+ return data.access_token;
5464
+ }
5465
+ async createInvoice(params, config) {
5466
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
5467
+ const currency = (params.currency || "USD").toUpperCase();
5468
+ let accessToken;
5469
+ try {
5470
+ accessToken = await this.getAccessToken(config);
5471
+ } catch (e) {
5472
+ return { success: false, provider: "paypal", orderId, amount, error: e.message, rawResponse: null };
5473
+ }
5474
+ const baseUrl = this.getBaseUrl(config);
5475
+ const amountFormatted = (amount / 100).toFixed(2);
5476
+ const isDirect = !!params.paymentMethod;
5477
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5478
+ const cancelUrl = returnUrl || config.returnUrl || "https://example.com/payment/cancel";
5479
+ const body = {
5480
+ intent: isDirect ? "CAPTURE" : "CAPTURE",
5481
+ purchase_units: [
5482
+ {
5483
+ reference_id: orderId,
5484
+ description: productDetails,
5485
+ amount: {
5486
+ currency_code: currency,
5487
+ value: amountFormatted
5488
+ }
5489
+ }
5490
+ ],
5491
+ application_context: {
5492
+ return_url: successUrl,
5493
+ cancel_url: cancelUrl,
5494
+ brand_name: productDetails,
5495
+ user_action: "PAY_NOW"
5496
+ }
5497
+ };
5498
+ if (isDirect) {
5499
+ body.application_context.shipping_preference = "NO_SHIPPING";
5500
+ }
5501
+ if (callbackUrl || config.callbackUrl) {
5502
+ }
5503
+ try {
5504
+ const response = await fetch(`${baseUrl}/v2/checkout/orders`, {
5505
+ method: "POST",
5506
+ headers: {
5507
+ "Authorization": `Bearer ${accessToken}`,
5508
+ "Content-Type": "application/json",
5509
+ "PayPal-Request-Id": orderId,
5510
+ "Prefer": "return=representation"
5511
+ },
5512
+ body: JSON.stringify(body)
5513
+ });
5514
+ const text = await response.text();
5515
+ let data = null;
5516
+ try {
5517
+ data = JSON.parse(text);
5518
+ } catch (e) {
5519
+ }
5520
+ if (!response.ok || !data || data.name) {
5521
+ return {
5522
+ success: false,
5523
+ provider: "paypal",
5524
+ orderId,
5525
+ amount,
5526
+ rawResponse: data,
5527
+ error: data?.message || `HTTP error! Status: ${response.status}`
5528
+ };
5529
+ }
5530
+ const approveLink = data.links?.find((l) => l.rel === "approve" || l.rel === "payer-action");
5531
+ const paymentUrl = approveLink?.href || "";
5532
+ return {
5533
+ success: true,
5534
+ provider: "paypal",
5535
+ orderId,
5536
+ amount,
5537
+ reference: data.id,
5538
+ paymentUrl,
5539
+ rawResponse: data
5540
+ };
5541
+ } catch (e) {
5542
+ return { success: false, provider: "paypal", orderId, amount, error: e.message, rawResponse: null };
5543
+ }
5544
+ }
5545
+ async verifyCallback(body, config) {
5546
+ const eventType = body?.event_type || body?.event_name || "";
5547
+ const resource = body?.resource || {};
5548
+ const orderId = resource.reference_id || resource.purchase_units?.[0]?.reference_id || resource.supplementary_data?.related_ids?.order_id || resource.id || "";
5549
+ const amount = Number(resource.amount?.value || resource.purchase_units?.[0]?.amount?.value || 0) * 100;
5550
+ const statusRaw = (resource.status || "").toUpperCase();
5551
+ const isPaid = statusRaw === "COMPLETED" || eventType === "PAYMENT.CAPTURE.COMPLETED";
5552
+ const isPending = statusRaw === "PENDING" || eventType === "PAYMENT.CAPTURE.PENDING";
5553
+ const isExpired = statusRaw === "EXPIRED" || eventType === "CHECKOUT.ORDER.EXPIRED";
5554
+ const isFailed = !isPaid && !isPending && !isExpired && (statusRaw === "DENIED" || statusRaw === "FAILED" || eventType.includes("FAILED") || eventType.includes("DENIED"));
5555
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5556
+ return {
5557
+ isValid: true,
5558
+ // Full cert-chain validation deferred to PayPal's verify API
5559
+ provider: "paypal",
5560
+ orderId: String(orderId),
5561
+ amount,
5562
+ status,
5563
+ isPaid,
5564
+ isPending,
5565
+ isFailed,
5566
+ isExpired,
5567
+ statusCode: eventType,
5568
+ rawPayload: body
5569
+ };
5570
+ }
5571
+ async getPaymentMethods(params, config) {
5572
+ const methods = [
5573
+ {
5574
+ paymentMethod: "credit_card",
5575
+ code: "card",
5576
+ paymentName: "Credit / Debit Card (Visa, Mastercard, Amex)",
5577
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5578
+ totalFee: "3.49% + fixed fee",
5579
+ category: "Kartu Kredit"
5580
+ },
5581
+ {
5582
+ paymentMethod: "paypal",
5583
+ code: "paypal",
5584
+ paymentName: "PayPal Balance / PayPal Checkout",
5585
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5586
+ totalFee: "3.49% + fixed fee",
5587
+ category: "E-Wallet"
5588
+ },
5589
+ {
5590
+ paymentMethod: "paylater",
5591
+ code: "pay_later",
5592
+ paymentName: "PayPal Pay Later / Buy Now Pay Later",
5593
+ paymentImage: "https://www.paypalobjects.com/webstatic/icon/pp258.png",
5594
+ totalFee: "3.49% + fixed fee",
5595
+ category: "Paylater / Cicilan"
5596
+ }
5597
+ ];
5598
+ const categories = {};
5599
+ for (const item of methods) {
5600
+ if (!categories[item.category]) categories[item.category] = [];
5601
+ categories[item.category].push(item);
5602
+ }
5603
+ return { success: true, provider: "paypal", methods, categories, rawResponse: methods };
5604
+ }
5605
+ async checkTransaction(params, config) {
5606
+ const { merchantOrderId } = params;
5607
+ let accessToken;
5608
+ try {
5609
+ accessToken = await this.getAccessToken(config);
5610
+ } catch (e) {
5611
+ return {
5612
+ success: false,
5613
+ provider: "paypal",
5614
+ orderId: merchantOrderId,
5615
+ reference: "",
5616
+ amount: 0,
5617
+ statusCode: "AUTH_ERROR",
5618
+ status: "failed",
5619
+ isPaid: false,
5620
+ isPending: false,
5621
+ isFailed: true,
5622
+ isExpired: false,
5623
+ statusMessage: e.message,
5624
+ error: e.message,
5625
+ rawResponse: null
5626
+ };
5627
+ }
5628
+ const baseUrl = this.getBaseUrl(config);
5629
+ try {
5630
+ const response = await fetch(`${baseUrl}/v2/checkout/orders/${encodeURIComponent(merchantOrderId)}`, {
5631
+ method: "GET",
5632
+ headers: {
5633
+ "Authorization": `Bearer ${accessToken}`,
5634
+ "Content-Type": "application/json"
5635
+ }
5636
+ });
5637
+ const text = await response.text();
5638
+ let data = null;
5639
+ try {
5640
+ data = JSON.parse(text);
5641
+ } catch (e) {
5642
+ }
5643
+ if (!response.ok || !data || data.name) {
5644
+ return {
5645
+ success: false,
5646
+ provider: "paypal",
5647
+ orderId: merchantOrderId,
5648
+ reference: "",
5649
+ amount: 0,
5650
+ statusCode: response.status.toString(),
5651
+ status: "failed",
5652
+ isPaid: false,
5653
+ isPending: false,
5654
+ isFailed: true,
5655
+ isExpired: false,
5656
+ statusMessage: data?.message || "HTTP Error",
5657
+ error: data?.message,
5658
+ rawResponse: data
5659
+ };
5660
+ }
5661
+ const statusRaw = (data.status || "").toUpperCase();
5662
+ const isPaid = statusRaw === "COMPLETED";
5663
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED" || statusRaw === "CREATED";
5664
+ const isExpired = statusRaw === "VOIDED";
5665
+ const isFailed = !isPaid && !isPending && !isExpired;
5666
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5667
+ const amountValue = Number(data.purchase_units?.[0]?.amount?.value || 0) * 100;
5668
+ return {
5669
+ success: true,
5670
+ provider: "paypal",
5671
+ orderId: data.purchase_units?.[0]?.reference_id || merchantOrderId,
5672
+ reference: data.id || merchantOrderId,
5673
+ amount: amountValue,
5674
+ statusCode: statusRaw,
5675
+ status,
5676
+ isPaid,
5677
+ isPending,
5678
+ isFailed,
5679
+ isExpired,
5680
+ statusMessage: statusRaw,
5681
+ transactionTime: data.create_time ? new Date(data.create_time) : void 0,
5682
+ rawResponse: data
5683
+ };
5684
+ } catch (e) {
5685
+ return {
5686
+ success: false,
5687
+ provider: "paypal",
5688
+ orderId: merchantOrderId,
5689
+ reference: "",
5690
+ amount: 0,
5691
+ statusCode: "ERROR",
5692
+ status: "failed",
5693
+ isPaid: false,
5694
+ isPending: false,
5695
+ isFailed: true,
5696
+ isExpired: false,
5697
+ statusMessage: e.message,
5698
+ error: e.message,
5699
+ rawResponse: null
5700
+ };
5701
+ }
5702
+ }
5703
+ };
5704
+
5705
+ // src/providers/adyen/signature.ts
5706
+ var import_crypto16 = require("crypto");
5707
+ function verifyAdyenWebhook(notificationItem, hmacKey) {
5708
+ if (!hmacKey || !notificationItem) return false;
5709
+ try {
5710
+ const amount = notificationItem.amount || {};
5711
+ const fields = [
5712
+ notificationItem.pspReference || "",
5713
+ notificationItem.originalReference || "",
5714
+ notificationItem.merchantAccountCode || "",
5715
+ notificationItem.merchantReference || "",
5716
+ String(amount.value || ""),
5717
+ amount.currency || "",
5718
+ notificationItem.eventCode || "",
5719
+ notificationItem.success || ""
5720
+ ];
5721
+ const signedData = fields.join(":");
5722
+ const keyBytes = Buffer.from(hmacKey, "hex");
5723
+ const expected = (0, import_crypto16.createHmac)("sha256", keyBytes).update(signedData, "utf8").digest("base64");
5724
+ return expected === notificationItem.additionalData?.hmacSignature;
5725
+ } catch {
5726
+ return false;
5727
+ }
5728
+ }
5729
+
5730
+ // src/providers/adyen/provider.ts
5731
+ var AdyenProvider = class extends BasePaymentProvider {
5732
+ name = "adyen";
5733
+ getBaseUrl(config) {
5734
+ if (!config.sandbox) {
5735
+ const prefix = config.extra?.liveUrlPrefix || config.projectId || "";
5736
+ if (prefix) {
5737
+ return `https://${prefix}-checkout-live.adyenpayments.com/checkout`;
5738
+ }
5739
+ }
5740
+ return "https://checkout-test.adyen.com";
5741
+ }
5742
+ async createInvoice(params, config) {
5743
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
5744
+ const apiKey = config.apiKey || config.secretKey || "";
5745
+ const merchantAccount = config.merchantCode || config.merchantId || config.extra?.merchantAccount || "";
5746
+ const currency = (params.currency || "USD").toUpperCase();
5747
+ const baseUrl = this.getBaseUrl(config);
5748
+ const isDirect = !!params.paymentMethod;
5749
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5750
+ try {
5751
+ if (isDirect) {
5752
+ const url = `${baseUrl}/v68/payments`;
5753
+ const body = {
5754
+ merchantAccount,
5755
+ reference: orderId,
5756
+ amount: { value: amount, currency },
5757
+ returnUrl: successUrl,
5758
+ shopperEmail: customer?.email,
5759
+ shopperName: customer?.name ? { firstName: customer.name.split(" ")[0], lastName: customer.name.split(" ").slice(1).join(" ") || "-" } : void 0,
5760
+ shopperReference: customer?.email || orderId,
5761
+ additionalData: { allow3DS2: true },
5762
+ metadata: { order_id: orderId },
5763
+ ...params.providerParams
5764
+ };
5765
+ const response = await fetch(url, {
5766
+ method: "POST",
5767
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
5768
+ body: JSON.stringify(body)
5769
+ });
5770
+ const text = await response.text();
5771
+ let data = null;
5772
+ try {
5773
+ data = JSON.parse(text);
5774
+ } catch (e) {
5775
+ }
5776
+ if (!response.ok || !data || data.status >= 400) {
5777
+ return { success: false, provider: "adyen", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
5778
+ }
5779
+ const isPaid = data.resultCode === "Authorised";
5780
+ const isPending = data.resultCode === "Pending" || data.resultCode === "RedirectShopper" || data.resultCode === "IdentifyShopper" || data.resultCode === "ChallengeShopper";
5781
+ return {
5782
+ success: true,
5783
+ provider: "adyen",
5784
+ orderId,
5785
+ amount,
5786
+ reference: data.pspReference || data.merchantReference,
5787
+ paymentUrl: data.action?.url || data.redirect?.url || void 0,
5788
+ rawResponse: data
5789
+ };
5790
+ } else {
5791
+ const url = `${baseUrl}/v68/sessions`;
5792
+ const body = {
5793
+ merchantAccount,
5794
+ reference: orderId,
5795
+ amount: { value: amount, currency },
5796
+ returnUrl: successUrl,
5797
+ countryCode: config.extra?.countryCode || "US",
5798
+ shopperLocale: config.extra?.shopperLocale || "en-US",
5799
+ shopperEmail: customer?.email,
5800
+ shopperReference: customer?.email || orderId,
5801
+ metadata: { order_id: orderId },
5802
+ ...params.providerParams
5803
+ };
5804
+ const response = await fetch(url, {
5805
+ method: "POST",
5806
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
5807
+ body: JSON.stringify(body)
5808
+ });
5809
+ const text = await response.text();
5810
+ let data = null;
5811
+ try {
5812
+ data = JSON.parse(text);
5813
+ } catch (e) {
5814
+ }
5815
+ if (!response.ok || !data || data.status >= 400) {
5816
+ return { success: false, provider: "adyen", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
5817
+ }
5818
+ return {
5819
+ success: true,
5820
+ provider: "adyen",
5821
+ orderId,
5822
+ amount,
5823
+ reference: data.id,
5824
+ paymentUrl: data.url,
5825
+ paymentCode: data.sessionData,
5826
+ rawResponse: data
5827
+ };
5828
+ }
5829
+ } catch (e) {
5830
+ return { success: false, provider: "adyen", orderId, amount, error: e.message, rawResponse: null };
5831
+ }
5832
+ }
5833
+ async verifyCallback(body, config) {
5834
+ const hmacKey = config.extra?.hmacKey || config.secretKey || "";
5835
+ const notificationItems = body?.notificationItems || [body];
5836
+ const item = notificationItems[0]?.NotificationRequestItem || notificationItems[0] || body;
5837
+ const isValid = hmacKey ? verifyAdyenWebhook(item, hmacKey) : true;
5838
+ const eventCode = (item.eventCode || "").toUpperCase();
5839
+ const success = item.success === "true" || item.success === true;
5840
+ const orderId = item.merchantReference || item.pspReference || "";
5841
+ const amount = item.amount?.value ? Number(item.amount.value) : 0;
5842
+ const isPaid = eventCode === "AUTHORISATION" && success;
5843
+ const isPending = eventCode === "PENDING" || eventCode === "OFFER_CLOSED";
5844
+ const isExpired = eventCode === "EXPIRED" || eventCode === "CANCEL";
5845
+ const isFailed = !isPaid && !isPending && !isExpired && (!success || eventCode === "REFUSAL");
5846
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5847
+ return {
5848
+ isValid,
5849
+ provider: "adyen",
5850
+ orderId: String(orderId),
5851
+ amount,
5852
+ status,
5853
+ isPaid,
5854
+ isPending,
5855
+ isFailed,
5856
+ isExpired,
5857
+ statusCode: eventCode,
5858
+ rawPayload: body
5859
+ };
5860
+ }
5861
+ async getPaymentMethods(params, config) {
5862
+ const methods = [
5863
+ { 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" },
5864
+ { 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" },
5865
+ { 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" },
5866
+ { 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" },
5867
+ { 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" },
5868
+ { 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" },
5869
+ { 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" }
5870
+ ];
5871
+ const categories = {};
5872
+ for (const item of methods) {
5873
+ if (!categories[item.category]) categories[item.category] = [];
5874
+ categories[item.category].push(item);
5875
+ }
5876
+ return { success: true, provider: "adyen", methods, categories, rawResponse: methods };
5877
+ }
5878
+ async checkTransaction(params, config) {
5879
+ const { merchantOrderId } = params;
5880
+ const apiKey = config.apiKey || config.secretKey || "";
5881
+ const merchantAccount = config.merchantCode || config.merchantId || "";
5882
+ const baseUrl = this.getBaseUrl(config);
5883
+ try {
5884
+ const response = await fetch(`${baseUrl}/v68/payments/${encodeURIComponent(merchantOrderId)}`, {
5885
+ method: "GET",
5886
+ headers: { "X-API-Key": apiKey, "Content-Type": "application/json" }
5887
+ });
5888
+ const text = await response.text();
5889
+ let data = null;
5890
+ try {
5891
+ data = JSON.parse(text);
5892
+ } catch (e) {
5893
+ }
5894
+ if (!response.ok || !data) {
5895
+ return {
5896
+ success: false,
5897
+ provider: "adyen",
5898
+ orderId: merchantOrderId,
5899
+ reference: "",
5900
+ amount: 0,
5901
+ statusCode: response.status.toString(),
5902
+ status: "failed",
5903
+ isPaid: false,
5904
+ isPending: false,
5905
+ isFailed: true,
5906
+ isExpired: false,
5907
+ statusMessage: data?.message || "HTTP Error",
5908
+ error: data?.message,
5909
+ rawResponse: data
5910
+ };
5911
+ }
5912
+ const resultCode = (data.resultCode || data.status || "").toUpperCase();
5913
+ const isPaid = resultCode === "AUTHORISED" || resultCode === "SETTLED";
5914
+ const isPending = resultCode === "PENDING" || resultCode === "RECEIVED" || resultCode === "REDIRECTSHOPPER";
5915
+ const isExpired = resultCode === "EXPIRED" || resultCode === "CANCELLED";
5916
+ const isFailed = !isPaid && !isPending && !isExpired;
5917
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
5918
+ return {
5919
+ success: true,
5920
+ provider: "adyen",
5921
+ orderId: data.merchantReference || merchantOrderId,
5922
+ reference: data.pspReference || merchantOrderId,
5923
+ amount: data.amount?.value ? Number(data.amount.value) : 0,
5924
+ statusCode: resultCode,
5925
+ status,
5926
+ isPaid,
5927
+ isPending,
5928
+ isFailed,
5929
+ isExpired,
5930
+ statusMessage: resultCode,
5931
+ rawResponse: data
5932
+ };
5933
+ } catch (e) {
5934
+ return {
5935
+ success: false,
5936
+ provider: "adyen",
5937
+ orderId: merchantOrderId,
5938
+ reference: "",
5939
+ amount: 0,
5940
+ statusCode: "ERROR",
5941
+ status: "failed",
5942
+ isPaid: false,
5943
+ isPending: false,
5944
+ isFailed: true,
5945
+ isExpired: false,
5946
+ statusMessage: e.message,
5947
+ error: e.message,
5948
+ rawResponse: null
5949
+ };
5950
+ }
5951
+ }
5952
+ };
5953
+
5954
+ // src/providers/checkoutcom/signature.ts
5955
+ var import_crypto17 = require("crypto");
5956
+ function verifyCheckoutComWebhook(body, signatureHeader, secret) {
5957
+ if (!secret || !signatureHeader || !body) return false;
5958
+ try {
5959
+ const expected = (0, import_crypto17.createHmac)("sha256", secret).update(body, "utf8").digest("hex");
5960
+ const provided = signatureHeader.replace(/^sha256=/, "");
5961
+ return expected === provided;
5962
+ } catch {
5963
+ return false;
5964
+ }
5965
+ }
5966
+
5967
+ // src/providers/checkoutcom/provider.ts
5968
+ var CheckoutComProvider = class extends BasePaymentProvider {
5969
+ name = "checkoutcom";
5970
+ getBaseUrl(config) {
5971
+ return config.sandbox !== false ? "https://api.sandbox.checkout.com" : "https://api.checkout.com";
5972
+ }
5973
+ async createInvoice(params, config) {
5974
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
5975
+ const secretKey = config.apiKey || config.secretKey || "";
5976
+ const currency = (params.currency || "USD").toUpperCase();
5977
+ const baseUrl = this.getBaseUrl(config);
5978
+ const isDirect = !!params.paymentMethod;
5979
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
5980
+ try {
5981
+ if (isDirect) {
5982
+ const url = `${baseUrl}/payments`;
5983
+ const body = {
5984
+ amount,
5985
+ currency,
5986
+ reference: orderId,
5987
+ description: productDetails,
5988
+ customer: { email: customer?.email, name: customer?.name },
5989
+ success_url: successUrl,
5990
+ failure_url: successUrl,
5991
+ metadata: { order_id: orderId },
5992
+ ...params.providerParams
5993
+ };
5994
+ const response = await fetch(url, {
5995
+ method: "POST",
5996
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" },
5997
+ body: JSON.stringify(body)
5998
+ });
5999
+ const text = await response.text();
6000
+ let data = null;
6001
+ try {
6002
+ data = JSON.parse(text);
6003
+ } catch (e) {
6004
+ }
6005
+ if (!response.ok || !data || data.error_codes) {
6006
+ return { success: false, provider: "checkoutcom", orderId, amount, rawResponse: data, error: (data?.error_codes || []).join(", ") || `HTTP ${response.status}` };
6007
+ }
6008
+ return {
6009
+ success: true,
6010
+ provider: "checkoutcom",
6011
+ orderId,
6012
+ amount: data.amount || amount,
6013
+ reference: data.id,
6014
+ paymentUrl: data._links?.redirect?.href,
6015
+ rawResponse: data
6016
+ };
6017
+ } else {
6018
+ const url = `${baseUrl}/payment-links`;
6019
+ const body = {
6020
+ amount,
6021
+ currency,
6022
+ reference: orderId,
6023
+ description: productDetails,
6024
+ customer: { email: customer?.email, name: customer?.name },
6025
+ return_url: successUrl,
6026
+ metadata: { order_id: orderId },
6027
+ ...params.providerParams
6028
+ };
6029
+ const response = await fetch(url, {
6030
+ method: "POST",
6031
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" },
6032
+ body: JSON.stringify(body)
6033
+ });
6034
+ const text = await response.text();
6035
+ let data = null;
6036
+ try {
6037
+ data = JSON.parse(text);
6038
+ } catch (e) {
6039
+ }
6040
+ if (!response.ok || !data || data.error_codes) {
6041
+ return { success: false, provider: "checkoutcom", orderId, amount, rawResponse: data, error: (data?.error_codes || []).join(", ") || `HTTP ${response.status}` };
6042
+ }
6043
+ return {
6044
+ success: true,
6045
+ provider: "checkoutcom",
6046
+ orderId,
6047
+ amount,
6048
+ reference: data.id,
6049
+ paymentUrl: data._links?.redirect?.href || data.reference,
6050
+ rawResponse: data
6051
+ };
6052
+ }
6053
+ } catch (e) {
6054
+ return { success: false, provider: "checkoutcom", orderId, amount, error: e.message, rawResponse: null };
6055
+ }
6056
+ }
6057
+ async verifyCallback(body, config) {
6058
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
6059
+ const signatureHeader = config.extra?.signatureHeader || "";
6060
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6061
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6062
+ const isValid = signatureHeader ? verifyCheckoutComWebhook(rawBody, signatureHeader, webhookSecret) : true;
6063
+ const eventType = parsedBody?.type || "";
6064
+ const data = parsedBody?.data || parsedBody;
6065
+ const orderId = data?.reference || data?.metadata?.order_id || data?.id || "";
6066
+ const amount = Number(data?.amount || 0);
6067
+ const isPaid = eventType === "payment_approved" || eventType === "payment_captured" || data?.approved === true;
6068
+ const isPending = eventType === "payment_pending" || eventType === "payment_voided";
6069
+ const isExpired = eventType === "payment_expired";
6070
+ const isFailed = eventType === "payment_declined" || eventType === "payment_capture_declined";
6071
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6072
+ return {
6073
+ isValid,
6074
+ provider: "checkoutcom",
6075
+ orderId: String(orderId),
6076
+ amount,
6077
+ status,
6078
+ isPaid,
6079
+ isPending,
6080
+ isFailed,
6081
+ isExpired,
6082
+ statusCode: eventType,
6083
+ rawPayload: parsedBody
6084
+ };
6085
+ }
6086
+ async getPaymentMethods(params, config) {
6087
+ const methods = [
6088
+ { 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" },
6089
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6090
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6091
+ { paymentMethod: "paypal", code: "paypal", paymentName: "PayPal", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Variable", category: "E-Wallet" },
6092
+ { paymentMethod: "klarna", code: "klarna", paymentName: "Klarna Pay Later", paymentImage: "https://checkout.com/favicon.ico", totalFee: "Variable", category: "Paylater / Cicilan" },
6093
+ { paymentMethod: "sofort", code: "sofort", paymentName: "Sofort / SEPA", paymentImage: "https://checkout.com/favicon.ico", totalFee: "0.8% + \u20AC0.25", category: "Virtual Account" }
6094
+ ];
6095
+ const categories = {};
6096
+ for (const item of methods) {
6097
+ if (!categories[item.category]) categories[item.category] = [];
6098
+ categories[item.category].push(item);
6099
+ }
6100
+ return { success: true, provider: "checkoutcom", methods, categories, rawResponse: methods };
6101
+ }
6102
+ async checkTransaction(params, config) {
6103
+ const { merchantOrderId } = params;
6104
+ const secretKey = config.apiKey || config.secretKey || "";
6105
+ const baseUrl = this.getBaseUrl(config);
6106
+ try {
6107
+ const response = await fetch(`${baseUrl}/payments/${encodeURIComponent(merchantOrderId)}`, {
6108
+ method: "GET",
6109
+ headers: { "Authorization": `Bearer ${secretKey}`, "Content-Type": "application/json" }
6110
+ });
6111
+ const text = await response.text();
6112
+ let data = null;
6113
+ try {
6114
+ data = JSON.parse(text);
6115
+ } catch (e) {
6116
+ }
6117
+ if (!response.ok || !data) {
6118
+ return {
6119
+ success: false,
6120
+ provider: "checkoutcom",
6121
+ orderId: merchantOrderId,
6122
+ reference: "",
6123
+ amount: 0,
6124
+ statusCode: response.status.toString(),
6125
+ status: "failed",
6126
+ isPaid: false,
6127
+ isPending: false,
6128
+ isFailed: true,
6129
+ isExpired: false,
6130
+ statusMessage: "HTTP Error",
6131
+ rawResponse: data
6132
+ };
6133
+ }
6134
+ const statusRaw = (data.status || "").toLowerCase();
6135
+ const isPaid = statusRaw === "authorized" || statusRaw === "captured";
6136
+ const isPending = statusRaw === "pending" || statusRaw === "card_verified";
6137
+ const isExpired = statusRaw === "expired" || statusRaw === "voided";
6138
+ const isFailed = statusRaw === "declined" || statusRaw === "failed";
6139
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6140
+ return {
6141
+ success: true,
6142
+ provider: "checkoutcom",
6143
+ orderId: data.reference || merchantOrderId,
6144
+ reference: data.id || merchantOrderId,
6145
+ amount: Number(data.amount || 0),
6146
+ statusCode: statusRaw,
6147
+ status,
6148
+ isPaid,
6149
+ isPending,
6150
+ isFailed,
6151
+ isExpired,
6152
+ statusMessage: statusRaw,
6153
+ paymentType: data.payment_type || "card",
6154
+ transactionTime: data.requested_on ? new Date(data.requested_on) : void 0,
6155
+ rawResponse: data
6156
+ };
6157
+ } catch (e) {
6158
+ return {
6159
+ success: false,
6160
+ provider: "checkoutcom",
6161
+ orderId: merchantOrderId,
6162
+ reference: "",
6163
+ amount: 0,
6164
+ statusCode: "ERROR",
6165
+ status: "failed",
6166
+ isPaid: false,
6167
+ isPending: false,
6168
+ isFailed: true,
6169
+ isExpired: false,
6170
+ statusMessage: e.message,
6171
+ error: e.message,
6172
+ rawResponse: null
6173
+ };
6174
+ }
6175
+ }
6176
+ };
6177
+
6178
+ // src/providers/razorpay/signature.ts
6179
+ var import_crypto18 = require("crypto");
6180
+ function verifyRazorpayWebhook(rawBody, signature, webhookSecret) {
6181
+ if (!webhookSecret || !signature || !rawBody) return false;
6182
+ try {
6183
+ const expected = (0, import_crypto18.createHmac)("sha256", webhookSecret).update(rawBody).digest("hex");
6184
+ return expected === signature;
6185
+ } catch {
6186
+ return false;
6187
+ }
6188
+ }
6189
+ function buildRazorpayBasicAuth(keyId, keySecret) {
6190
+ return Buffer.from(`${keyId}:${keySecret}`).toString("base64");
6191
+ }
6192
+
6193
+ // src/providers/razorpay/provider.ts
6194
+ var RazorpayProvider = class extends BasePaymentProvider {
6195
+ name = "razorpay";
6196
+ getBaseUrl() {
6197
+ return "https://api.razorpay.com/v1";
6198
+ }
6199
+ buildHeaders(config) {
6200
+ const keyId = config.clientKey || config.merchantCode || config.merchantId || "";
6201
+ const keySecret = config.apiKey || config.secretKey || "";
6202
+ return {
6203
+ "Authorization": `Basic ${buildRazorpayBasicAuth(keyId, keySecret)}`,
6204
+ "Content-Type": "application/json"
6205
+ };
6206
+ }
6207
+ async createInvoice(params, config) {
6208
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
6209
+ const currency = (params.currency || "INR").toUpperCase();
6210
+ const baseUrl = this.getBaseUrl();
6211
+ const headers = this.buildHeaders(config);
6212
+ const isDirect = !!params.paymentMethod;
6213
+ try {
6214
+ if (isDirect) {
6215
+ const body = {
6216
+ amount,
6217
+ currency,
6218
+ receipt: orderId,
6219
+ notes: { order_id: orderId, product: productDetails },
6220
+ ...params.providerParams
6221
+ };
6222
+ const response = await fetch(`${baseUrl}/orders`, {
6223
+ method: "POST",
6224
+ headers,
6225
+ body: JSON.stringify(body)
6226
+ });
6227
+ const text = await response.text();
6228
+ let data = null;
6229
+ try {
6230
+ data = JSON.parse(text);
6231
+ } catch (e) {
6232
+ }
6233
+ if (!response.ok || !data || data.error) {
6234
+ return { success: false, provider: "razorpay", orderId, amount, rawResponse: data, error: data?.error?.description || `HTTP ${response.status}` };
6235
+ }
6236
+ return {
6237
+ success: true,
6238
+ provider: "razorpay",
6239
+ orderId,
6240
+ amount: data.amount || amount,
6241
+ reference: data.id,
6242
+ paymentCode: data.id,
6243
+ rawResponse: data
6244
+ };
6245
+ } else {
6246
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6247
+ const body = {
6248
+ amount,
6249
+ currency,
6250
+ description: productDetails,
6251
+ reference_id: orderId,
6252
+ customer: { name: customer?.name, email: customer?.email, contact: customer?.phone || "" },
6253
+ notify: { sms: false, email: !!customer?.email },
6254
+ reminder_enable: false,
6255
+ callback_url: callbackUrl || config.callbackUrl || successUrl,
6256
+ callback_method: "get",
6257
+ notes: { order_id: orderId },
6258
+ ...params.providerParams
6259
+ };
6260
+ const response = await fetch(`${baseUrl}/payment_links`, {
6261
+ method: "POST",
6262
+ headers,
6263
+ body: JSON.stringify(body)
6264
+ });
6265
+ const text = await response.text();
6266
+ let data = null;
6267
+ try {
6268
+ data = JSON.parse(text);
6269
+ } catch (e) {
6270
+ }
6271
+ if (!response.ok || !data || data.error) {
6272
+ return { success: false, provider: "razorpay", orderId, amount, rawResponse: data, error: data?.error?.description || `HTTP ${response.status}` };
6273
+ }
6274
+ return {
6275
+ success: true,
6276
+ provider: "razorpay",
6277
+ orderId,
6278
+ amount: data.amount || amount,
6279
+ reference: data.id,
6280
+ paymentUrl: data.short_url,
6281
+ rawResponse: data
6282
+ };
6283
+ }
6284
+ } catch (e) {
6285
+ return { success: false, provider: "razorpay", orderId, amount, error: e.message, rawResponse: null };
6286
+ }
6287
+ }
6288
+ async verifyCallback(body, config) {
6289
+ const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
6290
+ const signatureHeader = config.extra?.signatureHeader || "";
6291
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6292
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6293
+ const isValid = signatureHeader ? verifyRazorpayWebhook(rawBody, signatureHeader, webhookSecret) : true;
6294
+ const eventType = parsedBody?.event || "";
6295
+ const payload = parsedBody?.payload;
6296
+ const paymentEntity = payload?.payment?.entity || payload?.payment_link?.entity || parsedBody;
6297
+ const orderId = paymentEntity?.notes?.order_id || paymentEntity?.order_id || paymentEntity?.reference_id || paymentEntity?.id || "";
6298
+ const amount = Number(paymentEntity?.amount || 0);
6299
+ const statusRaw = (paymentEntity?.status || "").toLowerCase();
6300
+ const isPaid = eventType === "payment.captured" || eventType === "payment_link.paid" || statusRaw === "captured";
6301
+ const isPending = eventType === "payment.authorized" || statusRaw === "authorized" || statusRaw === "created";
6302
+ const isExpired = eventType === "payment_link.expired" || statusRaw === "expired";
6303
+ const isFailed = eventType === "payment.failed" || statusRaw === "failed";
6304
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6305
+ return {
6306
+ isValid,
6307
+ provider: "razorpay",
6308
+ orderId: String(orderId),
6309
+ amount,
6310
+ status,
6311
+ isPaid,
6312
+ isPending,
6313
+ isFailed,
6314
+ isExpired,
6315
+ statusCode: eventType || statusRaw,
6316
+ rawPayload: parsedBody
6317
+ };
6318
+ }
6319
+ async getPaymentMethods(params, config) {
6320
+ const methods = [
6321
+ { paymentMethod: "credit_card", code: "card", paymentName: "Credit / Debit Card", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "2% + GST", category: "Kartu Kredit" },
6322
+ { paymentMethod: "upi", code: "upi", paymentName: "UPI (GPay, PhonePe, Paytm)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Free", category: "QRIS" },
6323
+ { paymentMethod: "netbanking", code: "netbanking", paymentName: "Net Banking (50+ banks)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "\u20B910", category: "Virtual Account" },
6324
+ { paymentMethod: "wallet", code: "wallet", paymentName: "Wallets (Paytm, PhonePe, etc.)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Variable", category: "E-Wallet" },
6325
+ { paymentMethod: "emi", code: "emi", paymentName: "EMI (Card / Cardless)", paymentImage: "https://razorpay.com/favicon.ico", totalFee: "Bank charge", category: "Paylater / Cicilan" }
6326
+ ];
6327
+ const categories = {};
6328
+ for (const item of methods) {
6329
+ if (!categories[item.category]) categories[item.category] = [];
6330
+ categories[item.category].push(item);
6331
+ }
6332
+ return { success: true, provider: "razorpay", methods, categories, rawResponse: methods };
6333
+ }
6334
+ async checkTransaction(params, config) {
6335
+ const { merchantOrderId } = params;
6336
+ const baseUrl = this.getBaseUrl();
6337
+ const headers = this.buildHeaders(config);
6338
+ try {
6339
+ const endpoint = merchantOrderId.startsWith("plink_") ? `/payment_links/${encodeURIComponent(merchantOrderId)}` : `/payments/${encodeURIComponent(merchantOrderId)}`;
6340
+ const response = await fetch(`${baseUrl}${endpoint}`, { method: "GET", headers });
6341
+ const text = await response.text();
6342
+ let data = null;
6343
+ try {
6344
+ data = JSON.parse(text);
6345
+ } catch (e) {
6346
+ }
6347
+ if (!response.ok || !data || data.error) {
6348
+ return {
6349
+ success: false,
6350
+ provider: "razorpay",
6351
+ orderId: merchantOrderId,
6352
+ reference: "",
6353
+ amount: 0,
6354
+ statusCode: response.status.toString(),
6355
+ status: "failed",
6356
+ isPaid: false,
6357
+ isPending: false,
6358
+ isFailed: true,
6359
+ isExpired: false,
6360
+ statusMessage: data?.error?.description || "HTTP Error",
6361
+ rawResponse: data
6362
+ };
6363
+ }
6364
+ const statusRaw = (data.status || "").toLowerCase();
6365
+ const isPaid = statusRaw === "captured" || statusRaw === "paid";
6366
+ const isPending = statusRaw === "authorized" || statusRaw === "created";
6367
+ const isExpired = statusRaw === "expired";
6368
+ const isFailed = statusRaw === "failed";
6369
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6370
+ return {
6371
+ success: true,
6372
+ provider: "razorpay",
6373
+ orderId: data.notes?.order_id || data.reference_id || merchantOrderId,
6374
+ reference: data.id || merchantOrderId,
6375
+ amount: Number(data.amount || 0),
6376
+ statusCode: statusRaw,
6377
+ status,
6378
+ isPaid,
6379
+ isPending,
6380
+ isFailed,
6381
+ isExpired,
6382
+ statusMessage: statusRaw,
6383
+ paymentType: data.method || "card",
6384
+ transactionTime: data.created_at ? new Date(data.created_at * 1e3) : void 0,
6385
+ rawResponse: data
6386
+ };
6387
+ } catch (e) {
6388
+ return {
6389
+ success: false,
6390
+ provider: "razorpay",
6391
+ orderId: merchantOrderId,
6392
+ reference: "",
6393
+ amount: 0,
6394
+ statusCode: "ERROR",
6395
+ status: "failed",
6396
+ isPaid: false,
6397
+ isPending: false,
6398
+ isFailed: true,
6399
+ isExpired: false,
6400
+ statusMessage: e.message,
6401
+ error: e.message,
6402
+ rawResponse: null
6403
+ };
6404
+ }
6405
+ }
6406
+ };
6407
+
6408
+ // src/providers/square/signature.ts
6409
+ var import_crypto19 = require("crypto");
6410
+ function verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) {
6411
+ if (!signatureKey || !signatureHeader || !rawBody) return false;
6412
+ try {
6413
+ const payload = notificationUrl + rawBody;
6414
+ const expected = (0, import_crypto19.createHmac)("sha256", signatureKey).update(payload).digest("base64");
6415
+ return expected === signatureHeader;
6416
+ } catch {
6417
+ return false;
6418
+ }
6419
+ }
6420
+
6421
+ // src/providers/square/provider.ts
6422
+ var SquareProvider = class extends BasePaymentProvider {
6423
+ name = "square";
6424
+ getBaseUrl(config) {
6425
+ return config.sandbox !== false ? "https://connect.squareupsandbox.com" : "https://connect.squareup.com";
6426
+ }
6427
+ buildHeaders(config) {
6428
+ return {
6429
+ "Authorization": `Bearer ${config.apiKey || config.secretKey || ""}`,
6430
+ "Content-Type": "application/json",
6431
+ "Square-Version": "2024-01-17"
6432
+ };
6433
+ }
6434
+ async createInvoice(params, config) {
6435
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
6436
+ const currency = (params.currency || "USD").toUpperCase();
6437
+ const locationId = config.extra?.locationId || config.projectId || "";
6438
+ const baseUrl = this.getBaseUrl(config);
6439
+ const headers = this.buildHeaders(config);
6440
+ const isDirect = !!params.paymentMethod;
6441
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6442
+ try {
6443
+ if (isDirect) {
6444
+ const sourceId = params.providerParams?.sourceId || params.providerParams?.nonce || "cnon:card-nonce-ok";
6445
+ const body = {
6446
+ idempotency_key: orderId,
6447
+ source_id: sourceId,
6448
+ amount_money: { amount, currency },
6449
+ reference_id: orderId,
6450
+ note: productDetails,
6451
+ buyer_email_address: customer?.email,
6452
+ ...params.providerParams
6453
+ };
6454
+ const response = await fetch(`${baseUrl}/v2/payments`, {
6455
+ method: "POST",
6456
+ headers,
6457
+ body: JSON.stringify(body)
6458
+ });
6459
+ const text = await response.text();
6460
+ let data = null;
6461
+ try {
6462
+ data = JSON.parse(text);
6463
+ } catch (e) {
6464
+ }
6465
+ if (!response.ok || !data || data.errors?.length) {
6466
+ return { success: false, provider: "square", orderId, amount, rawResponse: data, error: data?.errors?.[0]?.detail || `HTTP ${response.status}` };
6467
+ }
6468
+ const payment = data.payment || data;
6469
+ return {
6470
+ success: true,
6471
+ provider: "square",
6472
+ orderId,
6473
+ amount: payment.amount_money?.amount || amount,
6474
+ reference: payment.id,
6475
+ rawResponse: data
6476
+ };
6477
+ } else {
6478
+ const body = {
6479
+ idempotency_key: orderId,
6480
+ order: {
6481
+ location_id: locationId,
6482
+ reference_id: orderId,
6483
+ line_items: [
6484
+ {
6485
+ name: productDetails,
6486
+ quantity: "1",
6487
+ base_price_money: { amount, currency }
6488
+ }
6489
+ ]
6490
+ },
6491
+ checkout_options: {
6492
+ redirect_url: successUrl,
6493
+ ask_for_shipping_address: false
6494
+ },
6495
+ pre_populated_data: {
6496
+ buyer_email: customer?.email
6497
+ },
6498
+ ...params.providerParams
6499
+ };
6500
+ const response = await fetch(`${baseUrl}/v2/online-checkout/payment-links`, {
6501
+ method: "POST",
6502
+ headers,
6503
+ body: JSON.stringify(body)
6504
+ });
6505
+ const text = await response.text();
6506
+ let data = null;
6507
+ try {
6508
+ data = JSON.parse(text);
6509
+ } catch (e) {
6510
+ }
6511
+ if (!response.ok || !data || data.errors?.length) {
6512
+ return { success: false, provider: "square", orderId, amount, rawResponse: data, error: data?.errors?.[0]?.detail || `HTTP ${response.status}` };
6513
+ }
6514
+ const link = data.payment_link || data;
6515
+ return {
6516
+ success: true,
6517
+ provider: "square",
6518
+ orderId,
6519
+ amount,
6520
+ reference: link.id,
6521
+ paymentUrl: link.url,
6522
+ rawResponse: data
6523
+ };
6524
+ }
6525
+ } catch (e) {
6526
+ return { success: false, provider: "square", orderId, amount, error: e.message, rawResponse: null };
6527
+ }
6528
+ }
6529
+ async verifyCallback(body, config) {
6530
+ const signatureKey = config.extra?.webhookSignatureKey || config.secretKey || "";
6531
+ const signatureHeader = config.extra?.signatureHeader || "";
6532
+ const notificationUrl = config.callbackUrl || config.extra?.notificationUrl || "";
6533
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6534
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6535
+ const isValid = signatureHeader ? verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) : true;
6536
+ const eventType = parsedBody?.type || "";
6537
+ const data = parsedBody?.data?.object || parsedBody?.data || parsedBody;
6538
+ const payment = data?.payment || data;
6539
+ const orderId = payment?.reference_id || payment?.order_id || payment?.id || "";
6540
+ const amount = Number(payment?.amount_money?.amount || 0);
6541
+ const statusRaw = (payment?.status || "").toUpperCase();
6542
+ const isPaid = statusRaw === "COMPLETED" || eventType === "payment.completed";
6543
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED";
6544
+ const isFailed = statusRaw === "FAILED" || statusRaw === "CANCELED";
6545
+ const isExpired = eventType === "payment.expired";
6546
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6547
+ return {
6548
+ isValid,
6549
+ provider: "square",
6550
+ orderId: String(orderId),
6551
+ amount,
6552
+ status,
6553
+ isPaid,
6554
+ isPending,
6555
+ isFailed,
6556
+ isExpired,
6557
+ statusCode: eventType || statusRaw,
6558
+ rawPayload: parsedBody
6559
+ };
6560
+ }
6561
+ async getPaymentMethods(params, config) {
6562
+ const methods = [
6563
+ { 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" },
6564
+ { paymentMethod: "apple_pay", code: "applepay", paymentName: "Apple Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6565
+ { paymentMethod: "google_pay", code: "googlepay", paymentName: "Google Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6566
+ { paymentMethod: "cash_app", code: "cashapp", paymentName: "Cash App Pay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "2.9% + $0.30", category: "E-Wallet" },
6567
+ { paymentMethod: "afterpay", code: "afterpay", paymentName: "Afterpay / Clearpay", paymentImage: "https://squareup.com/favicon.ico", totalFee: "6% + $0.30", category: "Paylater / Cicilan" }
6568
+ ];
6569
+ const categories = {};
6570
+ for (const item of methods) {
6571
+ if (!categories[item.category]) categories[item.category] = [];
6572
+ categories[item.category].push(item);
6573
+ }
6574
+ return { success: true, provider: "square", methods, categories, rawResponse: methods };
6575
+ }
6576
+ async checkTransaction(params, config) {
6577
+ const { merchantOrderId } = params;
6578
+ const baseUrl = this.getBaseUrl(config);
6579
+ const headers = this.buildHeaders(config);
6580
+ try {
6581
+ const response = await fetch(`${baseUrl}/v2/payments/${encodeURIComponent(merchantOrderId)}`, {
6582
+ method: "GET",
6583
+ headers
6584
+ });
6585
+ const text = await response.text();
6586
+ let data = null;
6587
+ try {
6588
+ data = JSON.parse(text);
6589
+ } catch (e) {
6590
+ }
6591
+ if (!response.ok || !data || data.errors?.length) {
6592
+ return {
6593
+ success: false,
6594
+ provider: "square",
6595
+ orderId: merchantOrderId,
6596
+ reference: "",
6597
+ amount: 0,
6598
+ statusCode: response.status.toString(),
6599
+ status: "failed",
6600
+ isPaid: false,
6601
+ isPending: false,
6602
+ isFailed: true,
6603
+ isExpired: false,
6604
+ statusMessage: data?.errors?.[0]?.detail || "HTTP Error",
6605
+ rawResponse: data
6606
+ };
6607
+ }
6608
+ const payment = data.payment || data;
6609
+ const statusRaw = (payment.status || "").toUpperCase();
6610
+ const isPaid = statusRaw === "COMPLETED";
6611
+ const isPending = statusRaw === "PENDING" || statusRaw === "APPROVED";
6612
+ const isExpired = statusRaw === "CANCELED";
6613
+ const isFailed = statusRaw === "FAILED";
6614
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
6615
+ return {
6616
+ success: true,
6617
+ provider: "square",
6618
+ orderId: payment.reference_id || merchantOrderId,
6619
+ reference: payment.id || merchantOrderId,
6620
+ amount: Number(payment.amount_money?.amount || 0),
6621
+ statusCode: statusRaw,
6622
+ status,
6623
+ isPaid,
6624
+ isPending,
6625
+ isFailed,
6626
+ isExpired,
6627
+ statusMessage: statusRaw,
6628
+ paymentType: payment.source_type || "card",
6629
+ transactionTime: payment.created_at ? new Date(payment.created_at) : void 0,
6630
+ rawResponse: data
6631
+ };
6632
+ } catch (e) {
6633
+ return {
6634
+ success: false,
6635
+ provider: "square",
6636
+ orderId: merchantOrderId,
6637
+ reference: "",
6638
+ amount: 0,
6639
+ statusCode: "ERROR",
6640
+ status: "failed",
6641
+ isPaid: false,
6642
+ isPending: false,
6643
+ isFailed: true,
6644
+ isExpired: false,
6645
+ statusMessage: e.message,
6646
+ error: e.message,
6647
+ rawResponse: null
6648
+ };
6649
+ }
6650
+ }
6651
+ };
6652
+
6653
+ // src/providers/payu/signature.ts
6654
+ var import_crypto20 = require("crypto");
6655
+ function verifyPayuWebhook(rawBody, signatureHeader, md5Key) {
6656
+ if (!md5Key || !signatureHeader || !rawBody) return false;
6657
+ try {
6658
+ const parts = {};
6659
+ for (const part of signatureHeader.split(";")) {
6660
+ const [k, v] = part.split("=");
6661
+ if (k && v) parts[k.trim()] = v.trim();
6662
+ }
6663
+ const providedSig = parts["signature"];
6664
+ const algorithm = (parts["algorithm"] || "MD5").toUpperCase();
6665
+ if (algorithm === "MD5") {
6666
+ const expected = (0, import_crypto20.createHash)("md5").update(rawBody + md5Key).digest("hex");
6667
+ return expected === providedSig;
6668
+ } else if (algorithm === "SHA-256") {
6669
+ const expected = (0, import_crypto20.createHash)("sha256").update(rawBody + md5Key).digest("hex");
6670
+ return expected === providedSig;
6671
+ }
6672
+ return false;
6673
+ } catch {
6674
+ return false;
6675
+ }
6676
+ }
6677
+ function buildPayuBasicAuth(clientId, clientSecret) {
6678
+ return Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
6679
+ }
6680
+
6681
+ // src/providers/payu/provider.ts
6682
+ var PayuProvider = class extends BasePaymentProvider {
6683
+ name = "payu";
6684
+ getBaseUrl(config) {
6685
+ return config.sandbox !== false ? "https://secure.snd.payu.com" : "https://secure.payu.com";
6686
+ }
6687
+ /** OAuth2 Bearer Token untuk PayU */
6688
+ async getAccessToken(config) {
6689
+ const clientId = config.extra?.oauthClientId || config.clientKey || "";
6690
+ const clientSecret = config.extra?.oauthClientSecret || config.apiKey || config.secretKey || "";
6691
+ if (!clientId || !clientSecret) {
6692
+ return "";
6693
+ }
6694
+ const baseUrl = this.getBaseUrl(config);
6695
+ const response = await fetch(`${baseUrl}/pl/standard/user/oauth/authorize`, {
6696
+ method: "POST",
6697
+ headers: {
6698
+ "Authorization": `Basic ${buildPayuBasicAuth(clientId, clientSecret)}`,
6699
+ "Content-Type": "application/x-www-form-urlencoded"
6700
+ },
6701
+ body: "grant_type=client_credentials"
6702
+ });
6703
+ const text = await response.text();
6704
+ let data = null;
6705
+ try {
6706
+ data = JSON.parse(text);
6707
+ } catch (e) {
6708
+ }
6709
+ if (!response.ok || !data?.access_token) {
6710
+ throw new Error(data?.error_description || `Failed to get PayU access token: ${response.status}`);
6711
+ }
6712
+ return data.access_token;
6713
+ }
6714
+ async createInvoice(params, config) {
6715
+ const { orderId, amount, productDetails, customer, returnUrl, callbackUrl } = params;
6716
+ const currency = (params.currency || "PLN").toUpperCase();
6717
+ const posId = config.merchantCode || config.merchantId || config.extra?.posId || "";
6718
+ const baseUrl = this.getBaseUrl(config);
6719
+ let accessToken;
6720
+ try {
6721
+ accessToken = await this.getAccessToken(config);
6722
+ } catch (e) {
6723
+ return { success: false, provider: "payu", orderId, amount, error: e.message, rawResponse: null };
6724
+ }
6725
+ const isDirect = !!params.paymentMethod;
6726
+ const continueUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
6727
+ const notifyUrl = callbackUrl || config.callbackUrl || "";
6728
+ const body = {
6729
+ notifyUrl,
6730
+ customerIp: params.providerParams?.customerIp || "127.0.0.1",
6731
+ merchantPosId: posId,
6732
+ description: productDetails,
6733
+ currencyCode: currency,
6734
+ totalAmount: amount.toString(),
6735
+ extOrderId: orderId,
6736
+ continueUrl,
6737
+ buyer: {
6738
+ email: customer?.email,
6739
+ firstName: customer?.name?.split(" ")[0],
6740
+ lastName: customer?.name?.split(" ").slice(1).join(" ") || "-",
6741
+ phone: customer?.phone,
6742
+ language: "en"
6743
+ },
6744
+ products: [
6745
+ { name: productDetails, unitPrice: amount.toString(), quantity: "1" }
6746
+ ],
6747
+ ...params.providerParams
6748
+ };
6749
+ if (isDirect && params.paymentMethod) {
6750
+ body.payMethods = {
6751
+ payMethod: {
6752
+ type: "PBL",
6753
+ value: params.paymentMethod
6754
+ // e.g. "blik", "c" (card), "ap" (Apple Pay)
6755
+ }
6756
+ };
6757
+ }
6758
+ try {
6759
+ const response = await fetch(`${baseUrl}/api/v2_1/orders`, {
6760
+ method: "POST",
6761
+ headers: {
6762
+ "Authorization": `Bearer ${accessToken}`,
6763
+ "Content-Type": "application/json"
6764
+ },
6765
+ body: JSON.stringify(body),
6766
+ redirect: "manual"
6767
+ // PayU responds with 302
6768
+ });
6769
+ const text = await response.text();
6770
+ let data = null;
6771
+ try {
6772
+ data = JSON.parse(text);
6773
+ } catch (e) {
6774
+ }
6775
+ if (response.status === 302 || response.headers.get("location")) {
6776
+ const location = response.headers.get("location") || "";
6777
+ return {
6778
+ success: true,
6779
+ provider: "payu",
6780
+ orderId,
6781
+ amount,
6782
+ reference: data?.orderId || orderId,
6783
+ paymentUrl: location,
6784
+ rawResponse: data
6785
+ };
6786
+ }
6787
+ if (!response.ok || !data || data.status?.statusCode === "ERROR") {
6788
+ return { success: false, provider: "payu", orderId, amount, rawResponse: data, error: data?.status?.statusDesc || `HTTP ${response.status}` };
6789
+ }
6790
+ return {
6791
+ success: true,
6792
+ provider: "payu",
6793
+ orderId,
6794
+ amount,
6795
+ reference: data.orderId || orderId,
6796
+ paymentUrl: data.redirectUri,
6797
+ rawResponse: data
6798
+ };
6799
+ } catch (e) {
6800
+ return { success: false, provider: "payu", orderId, amount, error: e.message, rawResponse: null };
6801
+ }
6802
+ }
6803
+ async verifyCallback(body, config) {
6804
+ const md5Key = config.extra?.md5Key || config.apiKey || config.secretKey || "";
6805
+ const signatureHeader = config.extra?.signatureHeader || "";
6806
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
6807
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
6808
+ const isValid = signatureHeader ? verifyPayuWebhook(rawBody, signatureHeader, md5Key) : true;
6809
+ const order = parsedBody?.order || parsedBody;
6810
+ const orderId = order.extOrderId || order.orderId || "";
6811
+ const amount = Number(order.totalAmount || 0);
6812
+ const statusRaw = (order.status || "").toUpperCase();
6813
+ const isPaid = statusRaw === "COMPLETED";
6814
+ const isPending = statusRaw === "PENDING" || statusRaw === "WAITING_FOR_CONFIRMATION";
6815
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REJECTED";
6816
+ const isExpired = false;
6817
+ const status = isPaid ? "paid" : isPending ? "pending" : "failed";
6818
+ return {
6819
+ isValid,
6820
+ provider: "payu",
6821
+ orderId: String(orderId),
6822
+ amount,
6823
+ status,
6824
+ isPaid,
6825
+ isPending,
6826
+ isFailed,
6827
+ isExpired,
6828
+ statusCode: statusRaw,
6829
+ rawPayload: parsedBody
6830
+ };
6831
+ }
6832
+ async getPaymentMethods(params, config) {
6833
+ const methods = [
6834
+ { paymentMethod: "credit_card", code: "c", paymentName: "Credit / Debit Card", paymentImage: "https://payu.com/favicon.ico", totalFee: "1.5%+", category: "Kartu Kredit" },
6835
+ { paymentMethod: "blik", code: "blik", paymentName: "BLIK (Poland)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Fixed fee", category: "E-Wallet" },
6836
+ { paymentMethod: "apple_pay", code: "ap", paymentName: "Apple Pay", paymentImage: "https://payu.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6837
+ { paymentMethod: "google_pay", code: "gp", paymentName: "Google Pay", paymentImage: "https://payu.com/favicon.ico", totalFee: "Card fee", category: "E-Wallet" },
6838
+ { paymentMethod: "bank_transfer", code: "t", paymentName: "Online Bank Transfer (50+ banks)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Fixed fee", category: "Virtual Account" },
6839
+ { paymentMethod: "installment", code: "ai", paymentName: "Installments (PayU)", paymentImage: "https://payu.com/favicon.ico", totalFee: "Bank rate", category: "Paylater / Cicilan" }
6840
+ ];
6841
+ const categories = {};
6842
+ for (const item of methods) {
6843
+ if (!categories[item.category]) categories[item.category] = [];
6844
+ categories[item.category].push(item);
6845
+ }
6846
+ return { success: true, provider: "payu", methods, categories, rawResponse: methods };
6847
+ }
6848
+ async checkTransaction(params, config) {
6849
+ const { merchantOrderId } = params;
6850
+ const baseUrl = this.getBaseUrl(config);
6851
+ let accessToken;
6852
+ try {
6853
+ accessToken = await this.getAccessToken(config);
6854
+ } catch (e) {
6855
+ return {
6856
+ success: false,
6857
+ provider: "payu",
6858
+ orderId: merchantOrderId,
6859
+ reference: "",
6860
+ amount: 0,
6861
+ statusCode: "AUTH_ERROR",
6862
+ status: "failed",
6863
+ isPaid: false,
6864
+ isPending: false,
6865
+ isFailed: true,
6866
+ isExpired: false,
6867
+ statusMessage: e.message,
6868
+ error: e.message,
6869
+ rawResponse: null
6870
+ };
6871
+ }
6872
+ try {
6873
+ const response = await fetch(`${baseUrl}/api/v2_1/orders/${encodeURIComponent(merchantOrderId)}`, {
6874
+ method: "GET",
6875
+ headers: { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json" }
6876
+ });
6877
+ const text = await response.text();
6878
+ let data = null;
6879
+ try {
6880
+ data = JSON.parse(text);
6881
+ } catch (e) {
6882
+ }
6883
+ if (!response.ok || !data) {
6884
+ return {
6885
+ success: false,
6886
+ provider: "payu",
6887
+ orderId: merchantOrderId,
6888
+ reference: "",
6889
+ amount: 0,
6890
+ statusCode: response.status.toString(),
6891
+ status: "failed",
6892
+ isPaid: false,
6893
+ isPending: false,
6894
+ isFailed: true,
6895
+ isExpired: false,
6896
+ statusMessage: "HTTP Error",
6897
+ rawResponse: data
6898
+ };
6899
+ }
6900
+ const order = data.orders?.[0] || data;
6901
+ const statusRaw = (order.status || "").toUpperCase();
6902
+ const isPaid = statusRaw === "COMPLETED";
6903
+ const isPending = statusRaw === "PENDING" || statusRaw === "WAITING_FOR_CONFIRMATION";
6904
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REJECTED";
6905
+ const isExpired = false;
6906
+ const status = isPaid ? "paid" : isPending ? "pending" : "failed";
6907
+ return {
6908
+ success: true,
6909
+ provider: "payu",
6910
+ orderId: order.extOrderId || merchantOrderId,
6911
+ reference: order.orderId || merchantOrderId,
6912
+ amount: Number(order.totalAmount || 0),
6913
+ statusCode: statusRaw,
6914
+ status,
6915
+ isPaid,
6916
+ isPending,
6917
+ isFailed,
6918
+ isExpired,
6919
+ statusMessage: statusRaw,
6920
+ transactionTime: order.orderCreateDate ? new Date(order.orderCreateDate) : void 0,
6921
+ rawResponse: data
6922
+ };
6923
+ } catch (e) {
6924
+ return {
6925
+ success: false,
6926
+ provider: "payu",
6927
+ orderId: merchantOrderId,
6928
+ reference: "",
6929
+ amount: 0,
6930
+ statusCode: "ERROR",
6931
+ status: "failed",
6932
+ isPaid: false,
6933
+ isPending: false,
6934
+ isFailed: true,
6935
+ isExpired: false,
6936
+ statusMessage: e.message,
6937
+ error: e.message,
6938
+ rawResponse: null
6939
+ };
6940
+ }
6941
+ }
6942
+ };
6943
+
6944
+ // src/providers/braintree/signature.ts
6945
+ var import_crypto21 = require("crypto");
6946
+ function verifyBraintreeWebhook(btSignature, btPayload, privateKey) {
6947
+ if (!privateKey || !btSignature || !btPayload) return false;
6948
+ try {
6949
+ const parts = btSignature.split("|");
6950
+ if (parts.length < 2) return false;
6951
+ const providedHmac = parts[1];
6952
+ const payload = Buffer.from(btPayload, "base64").toString("utf8");
6953
+ const secretHash = (0, import_crypto21.createHash)("sha1").update(privateKey).digest("hex");
6954
+ const expected = (0, import_crypto21.createHmac)("sha1", secretHash).update(payload).digest("hex");
6955
+ return expected === providedHmac;
6956
+ } catch {
6957
+ return false;
6958
+ }
6959
+ }
6960
+ function buildBraintreeBasicAuth(publicKey, privateKey) {
6961
+ return Buffer.from(`${publicKey}:${privateKey}`).toString("base64");
6962
+ }
6963
+
6964
+ // src/providers/braintree/provider.ts
6965
+ var BraintreeProvider = class extends BasePaymentProvider {
6966
+ name = "braintree";
6967
+ getBaseUrl(config) {
6968
+ const merchantId = config.merchantCode || config.merchantId || "";
6969
+ const base = config.sandbox !== false ? "https://api.sandbox.braintreegateway.com" : "https://api.braintreegateway.com";
6970
+ return `${base}/merchants/${merchantId}`;
6971
+ }
6972
+ buildHeaders(config) {
6973
+ const publicKey = config.clientKey || config.extra?.publicKey || "";
6974
+ const privateKey = config.apiKey || config.secretKey || "";
6975
+ return {
6976
+ "Authorization": `Basic ${buildBraintreeBasicAuth(publicKey, privateKey)}`,
6977
+ "Content-Type": "application/json",
6978
+ "Braintree-Version": "2019-01-01"
6979
+ };
6980
+ }
6981
+ async createInvoice(params, config) {
6982
+ const { orderId, amount, productDetails, customer } = params;
6983
+ const currency = (params.currency || "USD").toUpperCase();
6984
+ const baseUrl = this.getBaseUrl(config);
6985
+ const headers = this.buildHeaders(config);
6986
+ const isDirect = !!params.paymentMethod;
6987
+ try {
6988
+ if (isDirect) {
6989
+ const paymentMethodNonce = params.providerParams?.nonce || params.providerParams?.paymentMethodNonce || "fake-valid-nonce";
6990
+ const body = {
6991
+ transaction: {
6992
+ amount: (amount / 100).toFixed(2),
6993
+ payment_method_nonce: paymentMethodNonce,
6994
+ order_id: orderId,
6995
+ currency_iso_code: currency,
6996
+ options: { submit_for_settlement: true },
6997
+ customer: { first_name: customer?.name, email: customer?.email },
6998
+ custom_fields: { order_id: orderId },
6999
+ ...params.providerParams
7000
+ }
7001
+ };
7002
+ const response = await fetch(`${baseUrl}/transactions`, {
7003
+ method: "POST",
7004
+ headers,
7005
+ body: JSON.stringify(body)
7006
+ });
7007
+ const text = await response.text();
7008
+ let data = null;
7009
+ try {
7010
+ data = JSON.parse(text);
7011
+ } catch (e) {
7012
+ }
7013
+ if (!response.ok || data?.apiErrorResponse) {
7014
+ return { success: false, provider: "braintree", orderId, amount, rawResponse: data, error: data?.apiErrorResponse?.message || `HTTP ${response.status}` };
7015
+ }
7016
+ const tx = data?.transaction || data;
7017
+ const statusRaw = (tx.status || "").toLowerCase();
7018
+ return {
7019
+ success: statusRaw === "submitted_for_settlement" || statusRaw === "settling" || statusRaw === "settled",
7020
+ provider: "braintree",
7021
+ orderId,
7022
+ amount: Math.round(Number(tx.amount || amount / 100) * 100),
7023
+ reference: tx.id,
7024
+ rawResponse: data
7025
+ };
7026
+ } else {
7027
+ const body = { client_token: { customer_id: customer?.email || orderId } };
7028
+ const response = await fetch(`${baseUrl}/client_token`, {
7029
+ method: "POST",
7030
+ headers,
7031
+ body: JSON.stringify(body)
7032
+ });
7033
+ const text = await response.text();
7034
+ let data = null;
7035
+ try {
7036
+ data = JSON.parse(text);
7037
+ } catch (e) {
7038
+ }
7039
+ if (!response.ok || !data?.clientToken) {
7040
+ return { success: false, provider: "braintree", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
7041
+ }
7042
+ return {
7043
+ success: true,
7044
+ provider: "braintree",
7045
+ orderId,
7046
+ amount,
7047
+ reference: orderId,
7048
+ paymentCode: data.clientToken,
7049
+ // Frontend uses this token for Drop-in UI
7050
+ rawResponse: data
7051
+ };
7052
+ }
7053
+ } catch (e) {
7054
+ return { success: false, provider: "braintree", orderId, amount, error: e.message, rawResponse: null };
7055
+ }
7056
+ }
7057
+ async verifyCallback(body, config) {
7058
+ const privateKey = config.apiKey || config.secretKey || "";
7059
+ const btSignature = config.extra?.btSignature || "";
7060
+ const btPayload = config.extra?.btPayload || "";
7061
+ const isValid = btSignature && btPayload ? verifyBraintreeWebhook(btSignature, btPayload, privateKey) : true;
7062
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
7063
+ const subject = parsedBody?.subject || parsedBody;
7064
+ const transaction = subject?.transaction || subject?.disbursement || parsedBody;
7065
+ const kind = parsedBody?.kind || parsedBody?.event || "";
7066
+ const orderId = transaction?.orderId || transaction?.order_id || transaction?.id || "";
7067
+ const amount = Math.round(Number(transaction?.amount || 0) * 100);
7068
+ const statusRaw = (transaction?.status || "").toLowerCase();
7069
+ const isPaid = kind === "transaction_settled" || kind === "transaction_disbursed" || statusRaw === "settled";
7070
+ const isPending = kind === "transaction_settlement_declined" || statusRaw === "submitted_for_settlement" || statusRaw === "settling";
7071
+ const isFailed = kind === "transaction_failed" || statusRaw === "failed" || statusRaw === "voided";
7072
+ const isExpired = statusRaw === "expired";
7073
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7074
+ return {
7075
+ isValid,
7076
+ provider: "braintree",
7077
+ orderId: String(orderId),
7078
+ amount,
7079
+ status,
7080
+ isPaid,
7081
+ isPending,
7082
+ isFailed,
7083
+ isExpired,
7084
+ statusCode: kind || statusRaw,
7085
+ rawPayload: parsedBody
7086
+ };
7087
+ }
7088
+ async getPaymentMethods(params, config) {
7089
+ const methods = [
7090
+ { 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" },
7091
+ { paymentMethod: "paypal", code: "PayPalAccount", paymentName: "PayPal (via Drop-in UI)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "3.49% + fixed", category: "E-Wallet" },
7092
+ { paymentMethod: "apple_pay", code: "ApplePayCard", paymentName: "Apple Pay", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "Card network fee", category: "E-Wallet" },
7093
+ { paymentMethod: "google_pay", code: "AndroidPayCard", paymentName: "Google Pay", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "Card network fee", category: "E-Wallet" },
7094
+ { paymentMethod: "venmo", code: "VenmoAccount", paymentName: "Venmo (US only)", paymentImage: "https://www.braintreepayments.com/favicon.ico", totalFee: "1.9% + $0.10", category: "E-Wallet" }
7095
+ ];
7096
+ const categories = {};
7097
+ for (const item of methods) {
7098
+ if (!categories[item.category]) categories[item.category] = [];
7099
+ categories[item.category].push(item);
7100
+ }
7101
+ return { success: true, provider: "braintree", methods, categories, rawResponse: methods };
7102
+ }
7103
+ async checkTransaction(params, config) {
7104
+ const { merchantOrderId } = params;
7105
+ const baseUrl = this.getBaseUrl(config);
7106
+ const headers = this.buildHeaders(config);
7107
+ try {
7108
+ const response = await fetch(`${baseUrl}/transactions/${encodeURIComponent(merchantOrderId)}`, {
7109
+ method: "GET",
7110
+ headers
7111
+ });
7112
+ const text = await response.text();
7113
+ let data = null;
7114
+ try {
7115
+ data = JSON.parse(text);
7116
+ } catch (e) {
7117
+ }
7118
+ if (!response.ok || !data) {
7119
+ return {
7120
+ success: false,
7121
+ provider: "braintree",
7122
+ orderId: merchantOrderId,
7123
+ reference: "",
7124
+ amount: 0,
7125
+ statusCode: response.status.toString(),
7126
+ status: "failed",
7127
+ isPaid: false,
7128
+ isPending: false,
7129
+ isFailed: true,
7130
+ isExpired: false,
7131
+ statusMessage: "HTTP Error",
7132
+ rawResponse: data
7133
+ };
7134
+ }
7135
+ const tx = data.transaction || data;
7136
+ const statusRaw = (tx.status || "").toLowerCase();
7137
+ const isPaid = statusRaw === "settled" || statusRaw === "settling";
7138
+ const isPending = statusRaw === "submitted_for_settlement" || statusRaw === "authorized";
7139
+ const isExpired = statusRaw === "expired";
7140
+ const isFailed = statusRaw === "failed" || statusRaw === "voided";
7141
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7142
+ return {
7143
+ success: true,
7144
+ provider: "braintree",
7145
+ orderId: tx.orderId || merchantOrderId,
7146
+ reference: tx.id || merchantOrderId,
7147
+ amount: Math.round(Number(tx.amount || 0) * 100),
7148
+ statusCode: statusRaw,
7149
+ status,
7150
+ isPaid,
7151
+ isPending,
7152
+ isFailed,
7153
+ isExpired,
7154
+ statusMessage: statusRaw,
7155
+ paymentType: tx.paymentInstrumentType || "card",
7156
+ transactionTime: tx.createdAt ? new Date(tx.createdAt) : void 0,
7157
+ rawResponse: data
7158
+ };
7159
+ } catch (e) {
7160
+ return {
7161
+ success: false,
7162
+ provider: "braintree",
7163
+ orderId: merchantOrderId,
7164
+ reference: "",
7165
+ amount: 0,
7166
+ statusCode: "ERROR",
7167
+ status: "failed",
7168
+ isPaid: false,
7169
+ isPending: false,
7170
+ isFailed: true,
7171
+ isExpired: false,
7172
+ statusMessage: e.message,
7173
+ error: e.message,
7174
+ rawResponse: null
7175
+ };
7176
+ }
7177
+ }
7178
+ };
7179
+
7180
+ // src/providers/twocheckout/signature.ts
7181
+ var import_crypto22 = require("crypto");
7182
+ function buildTwoCheckoutAuth(merchantCode, secretKey) {
7183
+ const date = Math.floor(Date.now() / 1e3).toString();
7184
+ const raw = merchantCode + date;
7185
+ const hmac = (0, import_crypto22.createHmac)("sha256", secretKey).update(raw).digest("hex");
7186
+ const header = `code="${merchantCode}" date="${date}" hash="${hmac}"`;
7187
+ return { header, date };
7188
+ }
7189
+ function verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, providedHash) {
7190
+ if (!secretWord || !providedHash) return false;
7191
+ try {
7192
+ const raw = secretWord + saleId + productId + invoiceId;
7193
+ const expected = (0, import_crypto22.createHash)("md5").update(raw).digest("hex").toUpperCase();
7194
+ return expected === (providedHash || "").toUpperCase();
7195
+ } catch {
7196
+ return false;
7197
+ }
7198
+ }
7199
+
7200
+ // src/providers/twocheckout/provider.ts
7201
+ var TwoCheckoutProvider = class extends BasePaymentProvider {
7202
+ name = "twocheckout";
7203
+ getBaseUrl(config) {
7204
+ return config.sandbox !== false ? "https://api.sandbox.2checkout.com/rest" : "https://api.2checkout.com/rest";
7205
+ }
7206
+ buildHeaders(config) {
7207
+ const merchantCode = config.merchantCode || config.merchantId || "";
7208
+ const secretKey = config.apiKey || config.secretKey || "";
7209
+ const { header } = buildTwoCheckoutAuth(merchantCode, secretKey);
7210
+ return {
7211
+ "X-Avangate-Authentication": header,
7212
+ "Content-Type": "application/json",
7213
+ "Accept": "application/json"
7214
+ };
7215
+ }
7216
+ async createInvoice(params, config) {
7217
+ const { orderId, amount, productDetails, customer, returnUrl } = params;
7218
+ const currency = (params.currency || "USD").toUpperCase();
7219
+ const baseUrl = this.getBaseUrl(config);
7220
+ const headers = this.buildHeaders(config);
7221
+ const isDirect = !!params.paymentMethod;
7222
+ const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
7223
+ const body = {
7224
+ Currency: currency,
7225
+ Language: "en",
7226
+ Country: config.extra?.country || "US",
7227
+ CustomerIP: params.providerParams?.customerIp || "127.0.0.1",
7228
+ Source: "API",
7229
+ MerchantReference: orderId,
7230
+ Items: [
7231
+ {
7232
+ Name: productDetails,
7233
+ Quantity: 1,
7234
+ Price: { Amount: (amount / 100).toFixed(2), Type: "CUSTOM" },
7235
+ Type: "PRODUCT",
7236
+ IsDynamic: true,
7237
+ Tangible: false
7238
+ }
7239
+ ],
7240
+ BillingDetails: {
7241
+ FirstName: customer?.name?.split(" ")[0] || "Customer",
7242
+ LastName: customer?.name?.split(" ").slice(1).join(" ") || "Name",
7243
+ Email: customer?.email,
7244
+ Country: config.extra?.country || "US",
7245
+ Address1: config.extra?.address || "N/A",
7246
+ City: config.extra?.city || "N/A",
7247
+ State: config.extra?.state || "",
7248
+ Zip: config.extra?.zip || "00000"
7249
+ },
7250
+ ...params.providerParams
7251
+ };
7252
+ if (!isDirect) {
7253
+ body.PaymentDetails = { Type: "EES_TOKEN_PAYMENT", Currency: currency };
7254
+ } else {
7255
+ body.PaymentDetails = { Type: params.paymentMethod === "paypal" ? "PAYPAL" : "EES_TOKEN_PAYMENT", Currency: currency };
7256
+ }
7257
+ try {
7258
+ const response = await fetch(`${baseUrl}/6.0/orders`, {
7259
+ method: "POST",
7260
+ headers,
7261
+ body: JSON.stringify(body)
7262
+ });
7263
+ const text = await response.text();
7264
+ let data = null;
7265
+ try {
7266
+ data = JSON.parse(text);
7267
+ } catch (e) {
7268
+ }
7269
+ if (!response.ok || !data || data.error_code) {
7270
+ return { success: false, provider: "twocheckout", orderId, amount, rawResponse: data, error: data?.message || `HTTP ${response.status}` };
7271
+ }
7272
+ const paymentUrl = data.PaymentDetails?.PaymentMethod?.RedirectURL || data.PaymentDetails?.PaymentMethod?.Href || `${successUrl}?ref=${data.RefNo}`;
7273
+ return {
7274
+ success: true,
7275
+ provider: "twocheckout",
7276
+ orderId,
7277
+ amount,
7278
+ reference: data.RefNo || data.OrderNo?.toString(),
7279
+ paymentUrl,
7280
+ rawResponse: data
7281
+ };
7282
+ } catch (e) {
7283
+ return { success: false, provider: "twocheckout", orderId, amount, error: e.message, rawResponse: null };
7284
+ }
7285
+ }
7286
+ async verifyCallback(body, config) {
7287
+ const secretWord = config.extra?.secretWord || config.apiKey || "";
7288
+ const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
7289
+ const saleId = parsedBody?.SALE_ID || parsedBody?.sale_id || "";
7290
+ const productId = parsedBody?.IPN_PID?.[0] || parsedBody?.product_id || "";
7291
+ const invoiceId = parsedBody?.IPN_PNAME?.[0] || parsedBody?.invoice_id || "";
7292
+ const providedHash = parsedBody?.HASH || parsedBody?.hash || "";
7293
+ const isValid = secretWord ? verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, providedHash) : true;
7294
+ const orderId = parsedBody?.REFNOEXT || parsedBody?.ext_ref_no || parsedBody?.SALE_ID || "";
7295
+ const amount = Math.round(Number(parsedBody?.IPN_TOTAL_GENERAL || parsedBody?.total || 0) * 100);
7296
+ const statusRaw = (parsedBody?.ORDERSTATUS || parsedBody?.order_status || "").toUpperCase();
7297
+ const isPaid = statusRaw === "COMPLETE" || statusRaw === "COMPLETE_MANUAL";
7298
+ const isPending = statusRaw === "PENDING" || statusRaw === "PURCHASE_PENDING";
7299
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REFUND" || statusRaw === "FRAUD";
7300
+ const isExpired = statusRaw === "EXPIRED";
7301
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7302
+ return {
7303
+ isValid,
7304
+ provider: "twocheckout",
7305
+ orderId: String(orderId),
7306
+ amount,
7307
+ status,
7308
+ isPaid,
7309
+ isPending,
7310
+ isFailed,
7311
+ isExpired,
7312
+ statusCode: statusRaw,
7313
+ rawPayload: parsedBody
7314
+ };
7315
+ }
7316
+ async getPaymentMethods(params, config) {
7317
+ const methods = [
7318
+ { 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" },
7319
+ { paymentMethod: "paypal", code: "PAYPAL", paymentName: "PayPal", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "3.5% + $0.35", category: "E-Wallet" },
7320
+ { paymentMethod: "wire_transfer", code: "WIRE", paymentName: "Wire Transfer / Bank Transfer", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "Fixed fee", category: "Virtual Account" },
7321
+ { paymentMethod: "paylater", code: "PAY_LATER", paymentName: "Buy Now Pay Later (Klarna)", paymentImage: "https://www.2checkout.com/favicon.ico", totalFee: "Variable", category: "Paylater / Cicilan" }
7322
+ ];
7323
+ const categories = {};
7324
+ for (const item of methods) {
7325
+ if (!categories[item.category]) categories[item.category] = [];
7326
+ categories[item.category].push(item);
7327
+ }
7328
+ return { success: true, provider: "twocheckout", methods, categories, rawResponse: methods };
7329
+ }
7330
+ async checkTransaction(params, config) {
7331
+ const { merchantOrderId } = params;
7332
+ const baseUrl = this.getBaseUrl(config);
7333
+ const headers = this.buildHeaders(config);
7334
+ try {
7335
+ const response = await fetch(`${baseUrl}/6.0/orders/${encodeURIComponent(merchantOrderId)}`, {
7336
+ method: "GET",
7337
+ headers
7338
+ });
7339
+ const text = await response.text();
7340
+ let data = null;
7341
+ try {
7342
+ data = JSON.parse(text);
7343
+ } catch (e) {
7344
+ }
7345
+ if (!response.ok || !data || data.error_code) {
7346
+ return {
7347
+ success: false,
7348
+ provider: "twocheckout",
7349
+ orderId: merchantOrderId,
7350
+ reference: "",
7351
+ amount: 0,
7352
+ statusCode: response.status.toString(),
7353
+ status: "failed",
7354
+ isPaid: false,
7355
+ isPending: false,
7356
+ isFailed: true,
7357
+ isExpired: false,
7358
+ statusMessage: data?.message || "HTTP Error",
7359
+ rawResponse: data
7360
+ };
7361
+ }
7362
+ const statusRaw = (data.Status || "").toUpperCase();
7363
+ const isPaid = statusRaw === "COMPLETE";
7364
+ const isPending = statusRaw === "PENDING" || statusRaw === "PURCHASE_PENDING";
7365
+ const isExpired = statusRaw === "EXPIRED";
7366
+ const isFailed = statusRaw === "CANCELED" || statusRaw === "REFUND";
7367
+ const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
7368
+ return {
7369
+ success: true,
7370
+ provider: "twocheckout",
7371
+ orderId: data.ExternalReference || merchantOrderId,
7372
+ reference: data.RefNo?.toString() || merchantOrderId,
7373
+ amount: Math.round(Number(data.GrossAmount || 0) * 100),
7374
+ statusCode: statusRaw,
7375
+ status,
7376
+ isPaid,
7377
+ isPending,
7378
+ isFailed,
7379
+ isExpired,
7380
+ statusMessage: statusRaw,
7381
+ transactionTime: data.OrderDate ? new Date(data.OrderDate) : void 0,
7382
+ rawResponse: data
7383
+ };
7384
+ } catch (e) {
7385
+ return {
7386
+ success: false,
7387
+ provider: "twocheckout",
7388
+ orderId: merchantOrderId,
7389
+ reference: "",
7390
+ amount: 0,
7391
+ statusCode: "ERROR",
7392
+ status: "failed",
7393
+ isPaid: false,
7394
+ isPending: false,
7395
+ isFailed: true,
7396
+ isExpired: false,
7397
+ statusMessage: e.message,
7398
+ error: e.message,
7399
+ rawResponse: null
7400
+ };
7401
+ }
7402
+ }
7403
+ };
7404
+
7405
+ // src/clients/duitku.ts
7406
+ var DuitkuClient = class {
7407
+ merchantCode;
7408
+ apiKey;
7409
+ sandbox;
7410
+ constructor(config) {
7411
+ this.merchantCode = config.merchantCode || "";
7412
+ this.apiKey = config.apiKey || config.serverKey || "";
7413
+ this.sandbox = !!config.sandbox;
7414
+ }
7415
+ getPassportBaseUrl() {
7416
+ return this.sandbox ? "https://sandbox.duitku.com/webapi" : "https://passport.duitku.com/webapi";
7417
+ }
7418
+ getApiBaseUrl() {
7419
+ return this.sandbox ? "https://api-sandbox.duitku.com" : "https://api-prod.duitku.com";
7420
+ }
7421
+ /**
7422
+ * Request helper generic dengan kalkulasi signature Duitku otomatis
7423
+ */
7424
+ async request(method, endpoint, body = {}, options) {
7425
+ const baseUrl = options?.baseUrl === "api" ? this.getApiBaseUrl() : this.getPassportBaseUrl();
7426
+ const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint}`;
7427
+ const timestamp = Date.now().toString();
7428
+ const headerSignature = sha256(this.merchantCode + timestamp + this.apiKey);
7429
+ const headers = {
7430
+ "Content-Type": "application/json",
7431
+ "Accept": "application/json",
7432
+ "x-duitku-signature": headerSignature,
7433
+ "x-duitku-timestamp": timestamp,
7434
+ "x-duitku-merchantcode": this.merchantCode,
7435
+ ...options?.customHeaders
7436
+ };
7437
+ const fetchOptions = {
7438
+ method,
7439
+ headers
7440
+ };
7441
+ if (method === "POST" && body) {
7442
+ fetchOptions.body = JSON.stringify(body);
7443
+ }
7444
+ const response = await fetch(url, fetchOptions);
7445
+ const text = await response.text();
7446
+ let data = null;
7447
+ try {
7448
+ data = JSON.parse(text);
7449
+ } catch (e) {
7450
+ }
7451
+ if (!response.ok) {
7452
+ throw new Error(data?.Message || data?.statusMessage || data?.responseMessage || `HTTP error! Status: ${response.status} - ${text}`);
7453
+ }
7454
+ return data || text;
7455
+ }
7456
+ // ─── TRANSACTIONS & PAYMENT METHODS ──────────────────────────────────────────
7457
+ /**
7458
+ * Cek status transaksi pembayaran berdasarkan merchant order ID
7459
+ */
7460
+ async checkTransaction(merchantOrderId) {
7461
+ const { bodySignature } = getDuitkuStatusSignatures(
7462
+ this.merchantCode,
7463
+ merchantOrderId,
7464
+ this.apiKey
7465
+ );
7466
+ return this.request(
7467
+ "POST",
7468
+ "/api/merchant/transactionStatus",
7469
+ {
7470
+ merchantCode: this.merchantCode,
7471
+ merchantOrderId,
7472
+ signature: bodySignature
7473
+ },
7474
+ { baseUrl: "api" }
7475
+ );
7476
+ }
7477
+ /**
7478
+ * Ambil daftar channel pembayaran aktif dan kalkulasi fee dinamis
7479
+ */
7480
+ async getPaymentMethods(amount = 1e4) {
7481
+ const integerAmount = Math.round(amount);
7482
+ const datetime = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
7483
+ const signature = getDuitkuPaymentMethodsSignature(this.merchantCode, integerAmount, datetime, this.apiKey);
7484
+ return this.request("POST", "/api/merchant/paymentmethod/getpaymentmethod", {
7485
+ merchantcode: this.merchantCode,
7486
+ amount: integerAmount,
7487
+ datetime,
7488
+ signature
7489
+ });
7490
+ }
7491
+ // ─── DISBURSEMENT & BALANCE INQUIRY ──────────────────────────────────────────
7492
+ /**
7493
+ * Cek saldo merchant (Balance Inquiry)
7494
+ */
7495
+ async checkBalance() {
7496
+ const timestamp = Date.now().toString();
7497
+ const signature = sha256(this.merchantCode + timestamp + this.apiKey);
7498
+ try {
7499
+ const data = await this.request(
7500
+ "POST",
7501
+ "/api/merchant/checkBalance",
7502
+ {
7503
+ merchantCode: this.merchantCode,
7504
+ signature
7505
+ },
7506
+ { baseUrl: "api" }
7507
+ );
7508
+ return {
7509
+ success: data.responseCode === "00" || data.statusCode === "00",
7510
+ balance: data.balance ? Number(data.balance) : void 0,
7511
+ rawResponse: data
7512
+ };
7513
+ } catch (e) {
7514
+ return {
7515
+ success: false,
7516
+ rawResponse: null,
7517
+ error: e.message || "Failed to check Duitku merchant balance"
7518
+ };
7519
+ }
7520
+ }
7521
+ /**
7522
+ * Mengambil daftar bank yang didukung untuk transfer / penarikan dana
7523
+ */
7524
+ async listBanks() {
7525
+ const timestamp = Date.now().toString();
7526
+ const signature = sha256(this.merchantCode + timestamp + this.apiKey);
7527
+ return this.request(
7528
+ "POST",
7529
+ "/api/disbursement/listBank",
7530
+ {
7531
+ merchantCode: this.merchantCode,
7532
+ signature
7533
+ },
7534
+ { baseUrl: "api" }
7535
+ );
7536
+ }
7537
+ /**
7538
+ * Validasi nama pemilik rekening bank sebelum eksekusi transfer (Bank Account Inquiry)
7539
+ */
7540
+ async inquiryBankAccount(bankCode, bankAccount) {
7541
+ const timestamp = Date.now().toString();
7542
+ const signature = sha256(this.merchantCode + bankCode + bankAccount + this.apiKey);
7543
+ return this.request(
7544
+ "POST",
7545
+ "/api/disbursement/inquiry",
7546
+ {
7547
+ merchantCode: this.merchantCode,
7548
+ bankCode,
7549
+ bankAccount,
7550
+ signature
7551
+ },
7552
+ { baseUrl: "api" }
7553
+ );
7554
+ }
7555
+ /**
7556
+ * Eksekusi transfer dana / payout (Disbursement Transfer)
7557
+ */
7558
+ async disburse(params) {
7559
+ const integerAmount = Math.round(params.amount);
7560
+ const signature = sha256(
7561
+ this.merchantCode + params.merchantOrderId + params.bankCode + params.bankAccount + integerAmount.toString() + this.apiKey
7562
+ );
7563
+ const payload = {
7564
+ merchantCode: this.merchantCode,
7565
+ merchantOrderId: params.merchantOrderId,
7566
+ bankCode: params.bankCode,
7567
+ bankAccount: params.bankAccount,
7568
+ amount: integerAmount,
7569
+ purpose: params.purpose,
7570
+ senderName: params.senderName || "",
7571
+ senderPhone: params.senderPhone || "",
7572
+ callbackUrl: params.callbackUrl || "",
5171
7573
  signature
5172
7574
  };
5173
- return this.request("POST", "/api/disbursement/transfer", payload, { baseUrl: "api" });
7575
+ return this.request("POST", "/api/disbursement/transfer", payload, { baseUrl: "api" });
7576
+ }
7577
+ /**
7578
+ * Cek status disbursement berdasarkan merchant order ID
7579
+ */
7580
+ async checkDisbursementStatus(merchantOrderId) {
7581
+ const signature = sha256(this.merchantCode + merchantOrderId + this.apiKey);
7582
+ return this.request(
7583
+ "POST",
7584
+ "/api/disbursement/checkStatus",
7585
+ {
7586
+ merchantCode: this.merchantCode,
7587
+ merchantOrderId,
7588
+ signature
7589
+ },
7590
+ { baseUrl: "api" }
7591
+ );
7592
+ }
7593
+ };
7594
+
7595
+ // src/clients/ipaymu.ts
7596
+ var IpaymuClient = class {
7597
+ va;
7598
+ apiKey;
7599
+ sandbox;
7600
+ constructor(config) {
7601
+ this.va = config.merchantCode || config.merchantId || "";
7602
+ this.apiKey = config.apiKey || config.serverKey || "";
7603
+ this.sandbox = !!config.sandbox;
7604
+ }
7605
+ getBaseUrl() {
7606
+ return this.sandbox ? "https://sandbox.ipaymu.com/api/v2" : "https://my.ipaymu.com/api/v2";
7607
+ }
7608
+ /**
7609
+ * Helper request bertanda tangan iPaymu v2
7610
+ */
7611
+ async request(method, endpoint, body) {
7612
+ const url = `${this.getBaseUrl()}${endpoint}`;
7613
+ const { signature, timestamp } = generateIpaymuSignature(method, this.va, this.apiKey, body);
7614
+ const headers = {
7615
+ "Content-Type": "application/json",
7616
+ "Accept": "application/json",
7617
+ "va": this.va,
7618
+ "signature": signature,
7619
+ "timestamp": timestamp
7620
+ };
7621
+ const fetchOptions = {
7622
+ method,
7623
+ headers
7624
+ };
7625
+ if (method === "POST" && body) {
7626
+ fetchOptions.body = JSON.stringify(body);
7627
+ }
7628
+ const response = await fetch(url, fetchOptions);
7629
+ const text = await response.text();
7630
+ let data = null;
7631
+ try {
7632
+ data = JSON.parse(text);
7633
+ } catch (e) {
7634
+ }
7635
+ if (!response.ok) {
7636
+ throw new Error(data?.Message || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
7637
+ }
7638
+ return data;
7639
+ }
7640
+ /**
7641
+ * Cek saldo merchant iPaymu
7642
+ */
7643
+ async checkBalance() {
7644
+ try {
7645
+ const payload = { account: this.va };
7646
+ const data = await this.request("POST", "/balance", payload);
7647
+ const success = data.Status === 200 || data.status === 200;
7648
+ const balance = data.Data?.MerchantBalance ? Number(data.Data.MerchantBalance) : void 0;
7649
+ return {
7650
+ success,
7651
+ balance,
7652
+ rawResponse: data
7653
+ };
7654
+ } catch (e) {
7655
+ return {
7656
+ success: false,
7657
+ rawResponse: null,
7658
+ error: e.message || "Failed to check iPaymu balance"
7659
+ };
7660
+ }
7661
+ }
7662
+ /**
7663
+ * Cek detail transaksi iPaymu
7664
+ */
7665
+ async checkTransaction(transactionId) {
7666
+ return this.request("POST", "/transaction", { transactionId });
7667
+ }
7668
+ };
7669
+
7670
+ // src/clients/xendit.ts
7671
+ var XenditClient = class {
7672
+ apiKey;
7673
+ constructor(config) {
7674
+ this.apiKey = config.apiKey || config.secretKey || config.serverKey || "";
7675
+ }
7676
+ getBaseUrl() {
7677
+ return "https://api.xendit.co";
7678
+ }
7679
+ /**
7680
+ * HTTP Request helper bertanda tangan Basic Auth Xendit
7681
+ */
7682
+ async request(method, endpoint, body) {
7683
+ const url = endpoint.startsWith("http") ? endpoint : `${this.getBaseUrl()}${endpoint}`;
7684
+ const authHeader = getXenditAuthHeader(this.apiKey);
7685
+ const headers = {
7686
+ "Content-Type": "application/json",
7687
+ "Accept": "application/json",
7688
+ "Authorization": authHeader
7689
+ };
7690
+ const fetchOptions = {
7691
+ method,
7692
+ headers
7693
+ };
7694
+ if ((method === "POST" || method === "PATCH") && body) {
7695
+ fetchOptions.body = JSON.stringify(body);
7696
+ }
7697
+ const response = await fetch(url, fetchOptions);
7698
+ const text = await response.text();
7699
+ let data = null;
7700
+ try {
7701
+ data = JSON.parse(text);
7702
+ } catch (e) {
7703
+ }
7704
+ if (!response.ok) {
7705
+ throw new Error(data?.message || data?.error_code || `HTTP error! Status: ${response.status} - ${text}`);
7706
+ }
7707
+ return data;
7708
+ }
7709
+ /**
7710
+ * Cek Saldo Merchant Xendit
7711
+ */
7712
+ async checkBalance(accountType = "CASH") {
7713
+ try {
7714
+ const data = await this.request("GET", `/balance?account_type=${accountType}`);
7715
+ return {
7716
+ success: data.balance !== void 0,
7717
+ balance: data.balance !== void 0 ? Number(data.balance) : void 0,
7718
+ rawResponse: data
7719
+ };
7720
+ } catch (e) {
7721
+ return {
7722
+ success: false,
7723
+ rawResponse: null,
7724
+ error: e.message || "Failed to check Xendit balance"
7725
+ };
7726
+ }
7727
+ }
7728
+ /**
7729
+ * Memaksa sebuah invoice kadaluwarsa (Expire Invoice)
7730
+ */
7731
+ async expireInvoice(invoiceId) {
7732
+ return this.request("POST", `/invoices/${invoiceId}/expire!`);
7733
+ }
7734
+ /**
7735
+ * Eksekusi transfer dana / disbursement
7736
+ */
7737
+ async createDisbursement(params) {
7738
+ return this.request("POST", "/disbursements", {
7739
+ external_id: params.externalId,
7740
+ bank_code: params.bankCode,
7741
+ account_holder_name: params.accountHolderName,
7742
+ account_number: params.accountNumber,
7743
+ description: params.description,
7744
+ amount: Math.round(params.amount)
7745
+ });
7746
+ }
7747
+ };
7748
+
7749
+ // src/clients/doku.ts
7750
+ var DokuClient = class {
7751
+ clientId;
7752
+ secretKey;
7753
+ sandbox;
7754
+ constructor(config) {
7755
+ this.clientId = config.merchantCode || config.clientId || config.clientKey || "";
7756
+ this.secretKey = config.apiKey || config.secretKey || config.serverKey || "";
7757
+ this.sandbox = !!config.sandbox;
7758
+ }
7759
+ getBaseUrl() {
7760
+ return this.sandbox ? "https://api-sandbox.doku.com" : "https://api.doku.com";
7761
+ }
7762
+ /**
7763
+ * Helper request bertanda tangan DOKU Jokul v2
7764
+ */
7765
+ async request(method, endpoint, body) {
7766
+ const url = `${this.getBaseUrl()}${endpoint}`;
7767
+ const headers = generateDokuHeaders(this.clientId, this.secretKey, endpoint, body);
7768
+ const fetchOptions = {
7769
+ method,
7770
+ headers: {
7771
+ "Content-Type": "application/json",
7772
+ ...headers
7773
+ }
7774
+ };
7775
+ if (method === "POST" && body) {
7776
+ fetchOptions.body = JSON.stringify(body);
7777
+ }
7778
+ const response = await fetch(url, fetchOptions);
7779
+ const text = await response.text();
7780
+ let data = null;
7781
+ try {
7782
+ data = JSON.parse(text);
7783
+ } catch (e) {
7784
+ }
7785
+ if (!response.ok) {
7786
+ throw new Error(data?.error?.message || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
7787
+ }
7788
+ return data;
5174
7789
  }
5175
7790
  /**
5176
- * Cek status disbursement berdasarkan merchant order ID
7791
+ * Cek status transaksi pesanan di DOKU
5177
7792
  */
5178
- async checkDisbursementStatus(merchantOrderId) {
5179
- const signature = sha256(this.merchantCode + merchantOrderId + this.apiKey);
5180
- return this.request(
5181
- "POST",
5182
- "/api/disbursement/checkStatus",
5183
- {
5184
- merchantCode: this.merchantCode,
5185
- merchantOrderId,
5186
- signature
5187
- },
5188
- { baseUrl: "api" }
5189
- );
7793
+ async checkTransaction(invoiceNumber) {
7794
+ return this.request("GET", `/orders/v1/status/${invoiceNumber}`);
5190
7795
  }
5191
7796
  };
5192
7797
 
5193
- // src/clients/ipaymu.ts
5194
- var IpaymuClient = class {
5195
- va;
5196
- apiKey;
7798
+ // src/clients/prismalink.ts
7799
+ var PrismalinkClient = class {
7800
+ merchantId;
7801
+ secretKey;
5197
7802
  sandbox;
5198
7803
  constructor(config) {
5199
- this.va = config.merchantCode || config.merchantId || "";
5200
- this.apiKey = config.apiKey || config.serverKey || "";
7804
+ this.merchantId = config.merchantCode || config.merchantId || "";
7805
+ this.secretKey = config.apiKey || config.secretKey || config.serverKey || "";
5201
7806
  this.sandbox = !!config.sandbox;
5202
7807
  }
5203
7808
  getBaseUrl() {
5204
- return this.sandbox ? "https://sandbox.ipaymu.com/api/v2" : "https://my.ipaymu.com/api/v2";
7809
+ return this.sandbox ? "https://sandbox-api.prismalink.co.id" : "https://api.prismalink.co.id";
5205
7810
  }
5206
7811
  /**
5207
- * Helper request bertanda tangan iPaymu v2
7812
+ * Helper HTTP Request ke API PrismaLink
5208
7813
  */
5209
7814
  async request(method, endpoint, body) {
5210
7815
  const url = `${this.getBaseUrl()}${endpoint}`;
5211
- const { signature, timestamp } = generateIpaymuSignature(method, this.va, this.apiKey, body);
5212
- const headers = {
5213
- "Content-Type": "application/json",
5214
- "Accept": "application/json",
5215
- "va": this.va,
5216
- "signature": signature,
5217
- "timestamp": timestamp
5218
- };
5219
7816
  const fetchOptions = {
5220
7817
  method,
5221
- headers
7818
+ headers: {
7819
+ "Content-Type": "application/json",
7820
+ "Accept": "application/json"
7821
+ }
5222
7822
  };
5223
7823
  if (method === "POST" && body) {
5224
7824
  fetchOptions.body = JSON.stringify(body);
@@ -5231,68 +7831,165 @@ var IpaymuClient = class {
5231
7831
  } catch (e) {
5232
7832
  }
5233
7833
  if (!response.ok) {
5234
- throw new Error(data?.Message || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
7834
+ throw new Error(data?.message || data?.response_message || `HTTP error! Status: ${response.status} - ${text}`);
5235
7835
  }
5236
7836
  return data;
5237
7837
  }
5238
7838
  /**
5239
- * Cek saldo merchant iPaymu
7839
+ * Cek status transaksi pesanan di PrismaLink
5240
7840
  */
5241
- async checkBalance() {
7841
+ async checkTransaction(orderId) {
7842
+ const signature = generatePrismalinkSignature(this.merchantId, orderId, 0, this.secretKey);
7843
+ return this.request("POST", "/api/v1/payment/status", {
7844
+ merchant_id: this.merchantId,
7845
+ order_id: orderId,
7846
+ signature
7847
+ });
7848
+ }
7849
+ };
7850
+
7851
+ // src/clients/faspay.ts
7852
+ var FaspayClient = class {
7853
+ merchantId;
7854
+ userId;
7855
+ password;
7856
+ sandbox;
7857
+ constructor(config) {
7858
+ this.merchantId = config.merchantCode || config.merchantId || "";
7859
+ this.userId = config.clientKey || config.userId || config.extra?.userId || this.merchantId;
7860
+ this.password = config.apiKey || config.password || config.serverKey || config.secretKey || "";
7861
+ this.sandbox = !!config.sandbox;
7862
+ }
7863
+ getBaseUrl() {
7864
+ return this.sandbox ? "https://sandbox.faspay.co.id" : "https://web.faspay.co.id";
7865
+ }
7866
+ /**
7867
+ * Helper HTTP Request ke endpoint Faspay
7868
+ */
7869
+ async request(endpoint, payload) {
7870
+ const url = `${this.getBaseUrl()}${endpoint}`;
7871
+ const response = await fetch(url, {
7872
+ method: "POST",
7873
+ headers: {
7874
+ "Content-Type": "application/json",
7875
+ "Accept": "application/json"
7876
+ },
7877
+ body: JSON.stringify(payload)
7878
+ });
7879
+ const text = await response.text();
7880
+ let data = null;
5242
7881
  try {
5243
- const payload = { account: this.va };
5244
- const data = await this.request("POST", "/balance", payload);
5245
- const success = data.Status === 200 || data.status === 200;
5246
- const balance = data.Data?.MerchantBalance ? Number(data.Data.MerchantBalance) : void 0;
5247
- return {
5248
- success,
5249
- balance,
5250
- rawResponse: data
5251
- };
7882
+ data = JSON.parse(text);
5252
7883
  } catch (e) {
5253
- return {
5254
- success: false,
5255
- rawResponse: null,
5256
- error: e.message || "Failed to check iPaymu balance"
5257
- };
5258
7884
  }
7885
+ if (!response.ok) {
7886
+ throw new Error(data?.response_desc || data?.response_message || `HTTP error! Status: ${response.status} - ${text}`);
7887
+ }
7888
+ return data;
5259
7889
  }
5260
7890
  /**
5261
- * Cek detail transaksi iPaymu
7891
+ * Cek status pembayaran tagihan Faspay
5262
7892
  */
5263
- async checkTransaction(transactionId) {
5264
- return this.request("POST", "/transaction", { transactionId });
7893
+ async checkTransaction(billNo) {
7894
+ const signature = generateFaspaySignature(this.userId, this.password, billNo);
7895
+ return this.request("/cvr/100004/10", {
7896
+ request: "Inquiry Payment Status",
7897
+ merchant_id: this.merchantId,
7898
+ bill_no: billNo,
7899
+ signature
7900
+ });
7901
+ }
7902
+ /**
7903
+ * Batalkan tagihan pembayaran Faspay
7904
+ */
7905
+ async cancelTransaction(billNo, paymentChannel) {
7906
+ const signature = generateFaspaySignature(this.userId, this.password, billNo);
7907
+ return this.request("/cvr/100005/10", {
7908
+ request: "Cancel Transaction",
7909
+ merchant_id: this.merchantId,
7910
+ bill_no: billNo,
7911
+ payment_channel: paymentChannel,
7912
+ signature
7913
+ });
5265
7914
  }
5266
7915
  };
5267
7916
 
5268
- // src/clients/xendit.ts
5269
- var XenditClient = class {
5270
- apiKey;
7917
+ // src/clients/finpay.ts
7918
+ var FinpayClient = class {
7919
+ merchantId;
7920
+ merchantKey;
7921
+ sandbox;
5271
7922
  constructor(config) {
5272
- this.apiKey = config.apiKey || config.secretKey || config.serverKey || "";
7923
+ this.merchantId = config.merchantCode || config.merchantId || "";
7924
+ this.merchantKey = config.apiKey || config.merchantKey || config.serverKey || config.secretKey || "";
7925
+ this.sandbox = !!config.sandbox;
5273
7926
  }
5274
7927
  getBaseUrl() {
5275
- return "https://api.xendit.co";
7928
+ return this.sandbox ? "https://sandbox.finpay.co.id" : "https://api.finpay.id";
5276
7929
  }
5277
7930
  /**
5278
- * HTTP Request helper bertanda tangan Basic Auth Xendit
7931
+ * Helper HTTP Request ke Finpay API
5279
7932
  */
5280
- async request(method, endpoint, body) {
5281
- const url = endpoint.startsWith("http") ? endpoint : `${this.getBaseUrl()}${endpoint}`;
5282
- const authHeader = getXenditAuthHeader(this.apiKey);
5283
- const headers = {
5284
- "Content-Type": "application/json",
5285
- "Accept": "application/json",
5286
- "Authorization": authHeader
5287
- };
5288
- const fetchOptions = {
5289
- method,
5290
- headers
5291
- };
5292
- if ((method === "POST" || method === "PATCH") && body) {
5293
- fetchOptions.body = JSON.stringify(body);
7933
+ async request(endpoint, payload) {
7934
+ const url = `${this.getBaseUrl()}${endpoint}`;
7935
+ const response = await fetch(url, {
7936
+ method: "POST",
7937
+ headers: {
7938
+ "Content-Type": "application/json",
7939
+ "Accept": "application/json"
7940
+ },
7941
+ body: JSON.stringify(payload)
7942
+ });
7943
+ const text = await response.text();
7944
+ let data = null;
7945
+ try {
7946
+ data = JSON.parse(text);
7947
+ } catch (e) {
5294
7948
  }
5295
- const response = await fetch(url, fetchOptions);
7949
+ if (!response.ok) {
7950
+ throw new Error(data?.response_desc || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
7951
+ }
7952
+ return data;
7953
+ }
7954
+ /**
7955
+ * Cek status transaksi pembayaran Finpay
7956
+ */
7957
+ async checkTransaction(orderId) {
7958
+ const signature = generateFinpaySignature(this.merchantId, orderId, 0, this.merchantKey);
7959
+ return this.request("/pg/payment/status", {
7960
+ merchant_id: this.merchantId,
7961
+ order_id: orderId,
7962
+ signature
7963
+ });
7964
+ }
7965
+ };
7966
+
7967
+ // src/clients/nicepay.ts
7968
+ var NicepayClient = class {
7969
+ iMid;
7970
+ merchantKey;
7971
+ sandbox;
7972
+ constructor(config) {
7973
+ this.iMid = config.merchantCode || config.merchantId || config.iMid || "";
7974
+ this.merchantKey = config.apiKey || config.merchantKey || config.serverKey || config.secretKey || "";
7975
+ this.sandbox = !!config.sandbox;
7976
+ }
7977
+ getBaseUrl() {
7978
+ return this.sandbox ? "https://dev.nicepay.co.id/nicepay" : "https://www.nicepay.co.id/nicepay";
7979
+ }
7980
+ /**
7981
+ * Helper HTTP Request ke Nicepay API
7982
+ */
7983
+ async request(endpoint, payload) {
7984
+ const url = `${this.getBaseUrl()}${endpoint}`;
7985
+ const response = await fetch(url, {
7986
+ method: "POST",
7987
+ headers: {
7988
+ "Content-Type": "application/json",
7989
+ "Accept": "application/json"
7990
+ },
7991
+ body: JSON.stringify(payload)
7992
+ });
5296
7993
  const text = await response.text();
5297
7994
  let data = null;
5298
7995
  try {
@@ -5300,75 +7997,64 @@ var XenditClient = class {
5300
7997
  } catch (e) {
5301
7998
  }
5302
7999
  if (!response.ok) {
5303
- throw new Error(data?.message || data?.error_code || `HTTP error! Status: ${response.status} - ${text}`);
8000
+ throw new Error(data?.resultMsg || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
5304
8001
  }
5305
8002
  return data;
5306
8003
  }
5307
8004
  /**
5308
- * Cek Saldo Merchant Xendit
5309
- */
5310
- async checkBalance(accountType = "CASH") {
5311
- try {
5312
- const data = await this.request("GET", `/balance?account_type=${accountType}`);
5313
- return {
5314
- success: data.balance !== void 0,
5315
- balance: data.balance !== void 0 ? Number(data.balance) : void 0,
5316
- rawResponse: data
5317
- };
5318
- } catch (e) {
5319
- return {
5320
- success: false,
5321
- rawResponse: null,
5322
- error: e.message || "Failed to check Xendit balance"
5323
- };
5324
- }
5325
- }
5326
- /**
5327
- * Memaksa sebuah invoice kadaluwarsa (Expire Invoice)
8005
+ * Cek status transaksi pembayaran di Nicepay
5328
8006
  */
5329
- async expireInvoice(invoiceId) {
5330
- return this.request("POST", `/invoices/${invoiceId}/expire!`);
8007
+ async checkTransaction(referenceNo, amount = 0) {
8008
+ const timeStamp = formatNicepayTimestamp();
8009
+ const merchantToken = generateNicepayToken(timeStamp, this.iMid, referenceNo, amount, this.merchantKey);
8010
+ return this.request("/api/oneStepTransInquiry.do", {
8011
+ timeStamp,
8012
+ iMid: this.iMid,
8013
+ referenceNo,
8014
+ amt: String(amount),
8015
+ merchantToken
8016
+ });
5331
8017
  }
5332
8018
  /**
5333
- * Eksekusi transfer dana / disbursement
8019
+ * Batalkan transaksi di Nicepay
5334
8020
  */
5335
- async createDisbursement(params) {
5336
- return this.request("POST", "/disbursements", {
5337
- external_id: params.externalId,
5338
- bank_code: params.bankCode,
5339
- account_holder_name: params.accountHolderName,
5340
- account_number: params.accountNumber,
5341
- description: params.description,
5342
- amount: Math.round(params.amount)
8021
+ async cancelTransaction(tXid, payMethod, cancelMsg = "User Cancel") {
8022
+ const timeStamp = formatNicepayTimestamp();
8023
+ const merchantToken = sha256(`${timeStamp}${this.iMid}${tXid}0${this.merchantKey}`);
8024
+ return this.request("/api/oneStepTransCancel.do", {
8025
+ timeStamp,
8026
+ iMid: this.iMid,
8027
+ tXid,
8028
+ payMethod,
8029
+ cancelType: "1",
8030
+ cancelMsg,
8031
+ merchantToken
5343
8032
  });
5344
8033
  }
5345
8034
  };
5346
8035
 
5347
- // src/clients/doku.ts
5348
- var DokuClient = class {
5349
- clientId;
5350
- secretKey;
8036
+ // src/clients/oy.ts
8037
+ var OyClient = class {
8038
+ username;
8039
+ apiKey;
5351
8040
  sandbox;
5352
8041
  constructor(config) {
5353
- this.clientId = config.merchantCode || config.clientId || config.clientKey || "";
5354
- this.secretKey = config.apiKey || config.secretKey || config.serverKey || "";
8042
+ this.username = config.clientKey || config.username || config.merchantCode || "";
8043
+ this.apiKey = config.apiKey || config.serverKey || config.secretKey || "";
5355
8044
  this.sandbox = !!config.sandbox;
5356
8045
  }
5357
8046
  getBaseUrl() {
5358
- return this.sandbox ? "https://api-sandbox.doku.com" : "https://api.doku.com";
8047
+ return this.sandbox ? "https://api-stg.oyindonesia.com/api" : "https://api.oyindonesia.com/api";
5359
8048
  }
5360
8049
  /**
5361
- * Helper request bertanda tangan DOKU Jokul v2
8050
+ * Helper HTTP Request ke OY! Bisnis API
5362
8051
  */
5363
8052
  async request(method, endpoint, body) {
5364
8053
  const url = `${this.getBaseUrl()}${endpoint}`;
5365
- const headers = generateDokuHeaders(this.clientId, this.secretKey, endpoint, body);
8054
+ const headers = generateOyHeaders(this.username, this.apiKey);
5366
8055
  const fetchOptions = {
5367
8056
  method,
5368
- headers: {
5369
- "Content-Type": "application/json",
5370
- ...headers
5371
- }
8057
+ headers
5372
8058
  };
5373
8059
  if (method === "POST" && body) {
5374
8060
  fetchOptions.body = JSON.stringify(body);
@@ -5381,45 +8067,61 @@ var DokuClient = class {
5381
8067
  } catch (e) {
5382
8068
  }
5383
8069
  if (!response.ok) {
5384
- throw new Error(data?.error?.message || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
8070
+ throw new Error(data?.status?.message || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
5385
8071
  }
5386
8072
  return data;
5387
8073
  }
5388
8074
  /**
5389
- * Cek status transaksi pesanan di DOKU
8075
+ * Cek status transaksi pembayaran
5390
8076
  */
5391
- async checkTransaction(invoiceNumber) {
5392
- return this.request("GET", `/orders/v1/status/${invoiceNumber}`);
8077
+ async checkTransaction(partnerTxId) {
8078
+ return this.request("GET", `/payment-checkout/status?partner_tx_id=${encodeURIComponent(partnerTxId)}&send_callback=false`);
8079
+ }
8080
+ /**
8081
+ * Cek saldo akun OY! Bisnis
8082
+ */
8083
+ async checkBalance() {
8084
+ return this.request("GET", "/balance");
8085
+ }
8086
+ /**
8087
+ * Kirim dana / Transfer uang (Disbursement / Remittance)
8088
+ */
8089
+ async remit(params) {
8090
+ return this.request("POST", "/remit", {
8091
+ recipient_bank: params.recipientBank,
8092
+ recipient_account: params.recipientAccount,
8093
+ amount: params.amount,
8094
+ note: params.note || "Disbursement",
8095
+ partner_trx_id: params.partnerTrxId
8096
+ });
5393
8097
  }
5394
8098
  };
5395
8099
 
5396
- // src/clients/prismalink.ts
5397
- var PrismalinkClient = class {
5398
- merchantId;
8100
+ // src/clients/stripe.ts
8101
+ var StripeClient = class {
5399
8102
  secretKey;
5400
- sandbox;
5401
8103
  constructor(config) {
5402
- this.merchantId = config.merchantCode || config.merchantId || "";
5403
- this.secretKey = config.apiKey || config.secretKey || config.serverKey || "";
5404
- this.sandbox = !!config.sandbox;
8104
+ this.secretKey = config.apiKey || config.serverKey || config.secretKey || "";
5405
8105
  }
5406
8106
  getBaseUrl() {
5407
- return this.sandbox ? "https://sandbox-api.prismalink.co.id" : "https://api.prismalink.co.id";
8107
+ return "https://api.stripe.com/v1";
5408
8108
  }
5409
8109
  /**
5410
- * Helper HTTP Request ke API PrismaLink
8110
+ * Helper HTTP Request ke Stripe API
5411
8111
  */
5412
8112
  async request(method, endpoint, body) {
5413
8113
  const url = `${this.getBaseUrl()}${endpoint}`;
8114
+ const headers = {
8115
+ "Authorization": `Bearer ${this.secretKey}`,
8116
+ "Accept": "application/json"
8117
+ };
5414
8118
  const fetchOptions = {
5415
8119
  method,
5416
- headers: {
5417
- "Content-Type": "application/json",
5418
- "Accept": "application/json"
5419
- }
8120
+ headers
5420
8121
  };
5421
8122
  if (method === "POST" && body) {
5422
- fetchOptions.body = JSON.stringify(body);
8123
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
8124
+ fetchOptions.body = serializeStripeParams(body);
5423
8125
  }
5424
8126
  const response = await fetch(url, fetchOptions);
5425
8127
  const text = await response.text();
@@ -5428,270 +8130,567 @@ var PrismalinkClient = class {
5428
8130
  data = JSON.parse(text);
5429
8131
  } catch (e) {
5430
8132
  }
5431
- if (!response.ok) {
5432
- throw new Error(data?.message || data?.response_message || `HTTP error! Status: ${response.status} - ${text}`);
8133
+ if (!response.ok || data?.error) {
8134
+ throw new Error(data?.error?.message || `HTTP error! Status: ${response.status} - ${text}`);
5433
8135
  }
5434
8136
  return data;
5435
8137
  }
5436
8138
  /**
5437
- * Cek status transaksi pesanan di PrismaLink
8139
+ * Ambil detail Checkout Session
5438
8140
  */
5439
- async checkTransaction(orderId) {
5440
- const signature = generatePrismalinkSignature(this.merchantId, orderId, 0, this.secretKey);
5441
- return this.request("POST", "/api/v1/payment/status", {
5442
- merchant_id: this.merchantId,
5443
- order_id: orderId,
5444
- signature
5445
- });
8141
+ async retrieveCheckoutSession(sessionId) {
8142
+ return this.request("GET", `/checkout/sessions/${encodeURIComponent(sessionId)}`);
8143
+ }
8144
+ /**
8145
+ * Ambil detail Payment Intent
8146
+ */
8147
+ async retrievePaymentIntent(paymentIntentId) {
8148
+ return this.request("GET", `/payment_intents/${encodeURIComponent(paymentIntentId)}`);
8149
+ }
8150
+ /**
8151
+ * Cek saldo akun Stripe (Balance)
8152
+ */
8153
+ async checkBalance() {
8154
+ return this.request("GET", "/balance");
8155
+ }
8156
+ /**
8157
+ * Buat refund dana
8158
+ */
8159
+ async createRefund(paymentIntentId, amount) {
8160
+ const payload = {
8161
+ payment_intent: paymentIntentId
8162
+ };
8163
+ if (amount) {
8164
+ payload.amount = Math.round(amount);
8165
+ }
8166
+ return this.request("POST", "/refunds", payload);
5446
8167
  }
5447
8168
  };
5448
8169
 
5449
- // src/clients/faspay.ts
5450
- var FaspayClient = class {
5451
- merchantId;
5452
- userId;
5453
- password;
5454
- sandbox;
8170
+ // src/clients/paypal.ts
8171
+ var PaypalClient = class {
8172
+ config;
5455
8173
  constructor(config) {
5456
- this.merchantId = config.merchantCode || config.merchantId || "";
5457
- this.userId = config.clientKey || config.userId || config.extra?.userId || this.merchantId;
5458
- this.password = config.apiKey || config.password || config.serverKey || config.secretKey || "";
5459
- this.sandbox = !!config.sandbox;
8174
+ this.config = config;
5460
8175
  }
5461
8176
  getBaseUrl() {
5462
- return this.sandbox ? "https://sandbox.faspay.co.id" : "https://web.faspay.co.id";
8177
+ return this.config.sandbox !== false ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
5463
8178
  }
5464
- /**
5465
- * Helper HTTP Request ke endpoint Faspay
5466
- */
5467
- async request(endpoint, payload) {
5468
- const url = `${this.getBaseUrl()}${endpoint}`;
5469
- const response = await fetch(url, {
8179
+ async getAccessToken() {
8180
+ const clientId = this.config.clientKey || this.config.merchantCode || this.config.merchantId || "";
8181
+ const clientSecret = this.config.apiKey || this.config.secretKey || "";
8182
+ const auth = buildPaypalBasicAuth(clientId, clientSecret);
8183
+ const response = await fetch(`${this.getBaseUrl()}/v1/oauth2/token`, {
5470
8184
  method: "POST",
5471
- headers: {
5472
- "Content-Type": "application/json",
5473
- "Accept": "application/json"
5474
- },
5475
- body: JSON.stringify(payload)
8185
+ headers: { "Authorization": `Basic ${auth}`, "Content-Type": "application/x-www-form-urlencoded" },
8186
+ body: "grant_type=client_credentials"
5476
8187
  });
5477
- const text = await response.text();
5478
- let data = null;
5479
- try {
5480
- data = JSON.parse(text);
5481
- } catch (e) {
8188
+ const data = await response.json();
8189
+ if (!data?.access_token) throw new Error(data?.error_description || "Failed to get PayPal access token");
8190
+ return data.access_token;
8191
+ }
8192
+ /** Ambil detail order PayPal berdasarkan Order ID */
8193
+ async getOrder(orderId) {
8194
+ const token = await this.getAccessToken();
8195
+ const response = await fetch(`${this.getBaseUrl()}/v2/checkout/orders/${orderId}`, {
8196
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8197
+ });
8198
+ return response.json();
8199
+ }
8200
+ /** Capture order PayPal (mengeksekusi pembayaran yang sudah diapprove buyer) */
8201
+ async captureOrder(orderId) {
8202
+ const token = await this.getAccessToken();
8203
+ const response = await fetch(`${this.getBaseUrl()}/v2/checkout/orders/${orderId}/capture`, {
8204
+ method: "POST",
8205
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8206
+ body: "{}"
8207
+ });
8208
+ return response.json();
8209
+ }
8210
+ /** Refund capture PayPal */
8211
+ async refundCapture(captureId, amount, currency) {
8212
+ const token = await this.getAccessToken();
8213
+ const body = {};
8214
+ if (amount && currency) {
8215
+ body.amount = { value: (amount / 100).toFixed(2), currency_code: currency };
8216
+ body.note_to_payer = "Refund";
5482
8217
  }
5483
- if (!response.ok) {
5484
- throw new Error(data?.response_desc || data?.response_message || `HTTP error! Status: ${response.status} - ${text}`);
8218
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/captures/${captureId}/refund`, {
8219
+ method: "POST",
8220
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8221
+ body: JSON.stringify(body)
8222
+ });
8223
+ return response.json();
8224
+ }
8225
+ /** Cek saldo akun PayPal merchant (hanya tersedia di account via Seller REST API) */
8226
+ async checkBalance() {
8227
+ const token = await this.getAccessToken();
8228
+ const response = await fetch(`${this.getBaseUrl()}/v1/reporting/balances`, {
8229
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8230
+ });
8231
+ return response.json();
8232
+ }
8233
+ /** Verifikasi webhook via PayPal Webhook Verification API */
8234
+ async verifyWebhookSignature(webhookId, body, headers) {
8235
+ const token = await this.getAccessToken();
8236
+ const verifyBody = {
8237
+ auth_algo: headers["paypal-auth-algo"],
8238
+ cert_url: headers["paypal-cert-url"],
8239
+ transmission_id: headers["paypal-transmission-id"],
8240
+ transmission_sig: headers["paypal-transmission-sig"],
8241
+ transmission_time: headers["paypal-transmission-time"],
8242
+ webhook_id: webhookId,
8243
+ webhook_event: typeof body === "string" ? JSON.parse(body) : body
8244
+ };
8245
+ const response = await fetch(`${this.getBaseUrl()}/v1/notifications/verify-webhook-signature`, {
8246
+ method: "POST",
8247
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8248
+ body: JSON.stringify(verifyBody)
8249
+ });
8250
+ const data = await response.json();
8251
+ return data?.verification_status === "SUCCESS";
8252
+ }
8253
+ };
8254
+
8255
+ // src/clients/adyen.ts
8256
+ var AdyenClient = class {
8257
+ config;
8258
+ constructor(config) {
8259
+ this.config = config;
8260
+ }
8261
+ getBaseUrl() {
8262
+ if (this.config.sandbox === false) {
8263
+ const prefix = this.config.extra?.liveUrlPrefix || this.config.projectId || "";
8264
+ if (prefix) return `https://${prefix}-checkout-live.adyenpayments.com/checkout`;
5485
8265
  }
5486
- return data;
8266
+ return "https://checkout-test.adyen.com";
8267
+ }
8268
+ buildHeaders() {
8269
+ return {
8270
+ "X-API-Key": this.config.apiKey || this.config.secretKey || "",
8271
+ "Content-Type": "application/json"
8272
+ };
8273
+ }
8274
+ /** Ambil detail payment berdasarkan PSP Reference */
8275
+ async getPaymentDetails(pspReference) {
8276
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}`, {
8277
+ method: "GET",
8278
+ headers: this.buildHeaders()
8279
+ });
8280
+ return response.json();
8281
+ }
8282
+ /** Batalkan payment (sebelum capture) */
8283
+ async cancelPayment(pspReference, merchantAccount) {
8284
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8285
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/cancels`, {
8286
+ method: "POST",
8287
+ headers: this.buildHeaders(),
8288
+ body: JSON.stringify({ merchantAccount: account })
8289
+ });
8290
+ return response.json();
8291
+ }
8292
+ /** Refund payment yang sudah di-capture */
8293
+ async refundPayment(pspReference, amount, currency, merchantAccount) {
8294
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8295
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/refunds`, {
8296
+ method: "POST",
8297
+ headers: this.buildHeaders(),
8298
+ body: JSON.stringify({
8299
+ merchantAccount: account,
8300
+ amount: { value: amount, currency }
8301
+ })
8302
+ });
8303
+ return response.json();
8304
+ }
8305
+ /** Capture authorized payment */
8306
+ async capturePayment(pspReference, amount, currency, merchantAccount) {
8307
+ const account = merchantAccount || this.config.merchantCode || this.config.merchantId || "";
8308
+ const response = await fetch(`${this.getBaseUrl()}/v68/payments/${pspReference}/captures`, {
8309
+ method: "POST",
8310
+ headers: this.buildHeaders(),
8311
+ body: JSON.stringify({
8312
+ merchantAccount: account,
8313
+ amount: { value: amount, currency }
8314
+ })
8315
+ });
8316
+ return response.json();
8317
+ }
8318
+ /** Ambil daftar payment methods yang tersedia */
8319
+ async getAvailablePaymentMethods(merchantAccount, countryCode, currency, amount) {
8320
+ const response = await fetch(`${this.getBaseUrl()}/v68/paymentMethods`, {
8321
+ method: "POST",
8322
+ headers: this.buildHeaders(),
8323
+ body: JSON.stringify({ merchantAccount, countryCode, channel: "Web", amount: { value: amount, currency } })
8324
+ });
8325
+ return response.json();
8326
+ }
8327
+ };
8328
+
8329
+ // src/clients/checkoutcom.ts
8330
+ var CheckoutComClient = class {
8331
+ config;
8332
+ constructor(config) {
8333
+ this.config = config;
8334
+ }
8335
+ getBaseUrl() {
8336
+ return this.config.sandbox !== false ? "https://api.sandbox.checkout.com" : "https://api.checkout.com";
8337
+ }
8338
+ buildHeaders() {
8339
+ return {
8340
+ "Authorization": `Bearer ${this.config.apiKey || this.config.secretKey || ""}`,
8341
+ "Content-Type": "application/json"
8342
+ };
8343
+ }
8344
+ /** Ambil detail payment berdasarkan Payment ID */
8345
+ async getPaymentDetails(paymentId) {
8346
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}`, {
8347
+ method: "GET",
8348
+ headers: this.buildHeaders()
8349
+ });
8350
+ return response.json();
8351
+ }
8352
+ /** Void (batalkan) payment yang belum di-capture */
8353
+ async voidPayment(paymentId, reference) {
8354
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/voids`, {
8355
+ method: "POST",
8356
+ headers: this.buildHeaders(),
8357
+ body: JSON.stringify({ reference })
8358
+ });
8359
+ return response.json();
8360
+ }
8361
+ /** Refund payment yang sudah di-capture */
8362
+ async refundPayment(paymentId, amount, reference) {
8363
+ const body = { reference };
8364
+ if (amount) body.amount = amount;
8365
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/refunds`, {
8366
+ method: "POST",
8367
+ headers: this.buildHeaders(),
8368
+ body: JSON.stringify(body)
8369
+ });
8370
+ return response.json();
8371
+ }
8372
+ /** Cek saldo merchant di Checkout.com */
8373
+ async checkBalance() {
8374
+ const response = await fetch(`${this.getBaseUrl()}/balances`, {
8375
+ method: "GET",
8376
+ headers: this.buildHeaders()
8377
+ });
8378
+ return response.json();
8379
+ }
8380
+ /** Ambil daftar payment links */
8381
+ async listPaymentLinks() {
8382
+ const response = await fetch(`${this.getBaseUrl()}/payment-links`, {
8383
+ method: "GET",
8384
+ headers: this.buildHeaders()
8385
+ });
8386
+ return response.json();
8387
+ }
8388
+ };
8389
+
8390
+ // src/clients/razorpay.ts
8391
+ var RazorpayClient = class {
8392
+ config;
8393
+ constructor(config) {
8394
+ this.config = config;
8395
+ }
8396
+ getBaseUrl() {
8397
+ return "https://api.razorpay.com/v1";
8398
+ }
8399
+ buildHeaders() {
8400
+ const keyId = this.config.clientKey || this.config.merchantCode || this.config.merchantId || "";
8401
+ const keySecret = this.config.apiKey || this.config.secretKey || "";
8402
+ return {
8403
+ "Authorization": `Basic ${buildRazorpayBasicAuth(keyId, keySecret)}`,
8404
+ "Content-Type": "application/json"
8405
+ };
8406
+ }
8407
+ /** Ambil detail payment */
8408
+ async fetchPayment(paymentId) {
8409
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}`, {
8410
+ method: "GET",
8411
+ headers: this.buildHeaders()
8412
+ });
8413
+ return response.json();
8414
+ }
8415
+ /** Capture authorized payment */
8416
+ async capturePayment(paymentId, amount, currency) {
8417
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/capture`, {
8418
+ method: "POST",
8419
+ headers: this.buildHeaders(),
8420
+ body: JSON.stringify({ amount, currency: currency || "INR" })
8421
+ });
8422
+ return response.json();
5487
8423
  }
5488
- /**
5489
- * Cek status pembayaran tagihan Faspay
5490
- */
5491
- async checkTransaction(billNo) {
5492
- const signature = generateFaspaySignature(this.userId, this.password, billNo);
5493
- return this.request("/cvr/100004/10", {
5494
- request: "Inquiry Payment Status",
5495
- merchant_id: this.merchantId,
5496
- bill_no: billNo,
5497
- signature
8424
+ /** Buat refund untuk payment */
8425
+ async createRefund(paymentId, amount, notes) {
8426
+ const body = { notes };
8427
+ if (amount) body.amount = amount;
8428
+ const response = await fetch(`${this.getBaseUrl()}/payments/${paymentId}/refund`, {
8429
+ method: "POST",
8430
+ headers: this.buildHeaders(),
8431
+ body: JSON.stringify(body)
5498
8432
  });
8433
+ return response.json();
5499
8434
  }
5500
- /**
5501
- * Batalkan tagihan pembayaran Faspay
5502
- */
5503
- async cancelTransaction(billNo, paymentChannel) {
5504
- const signature = generateFaspaySignature(this.userId, this.password, billNo);
5505
- return this.request("/cvr/100005/10", {
5506
- request: "Cancel Transaction",
5507
- merchant_id: this.merchantId,
5508
- bill_no: billNo,
5509
- payment_channel: paymentChannel,
5510
- signature
8435
+ /** Cek saldo akun Razorpay */
8436
+ async checkBalance() {
8437
+ const response = await fetch(`${this.getBaseUrl()}/balance`, {
8438
+ method: "GET",
8439
+ headers: this.buildHeaders()
5511
8440
  });
8441
+ return response.json();
8442
+ }
8443
+ /** Ambil daftar semua payment */
8444
+ async listPayments(from, to, count) {
8445
+ const params = new URLSearchParams();
8446
+ if (from) params.set("from", from.toString());
8447
+ if (to) params.set("to", to.toString());
8448
+ if (count) params.set("count", count.toString());
8449
+ const response = await fetch(`${this.getBaseUrl()}/payments?${params}`, {
8450
+ method: "GET",
8451
+ headers: this.buildHeaders()
8452
+ });
8453
+ return response.json();
5512
8454
  }
5513
8455
  };
5514
8456
 
5515
- // src/clients/finpay.ts
5516
- var FinpayClient = class {
5517
- merchantId;
5518
- merchantKey;
5519
- sandbox;
8457
+ // src/clients/square.ts
8458
+ var SquareClient = class {
8459
+ config;
5520
8460
  constructor(config) {
5521
- this.merchantId = config.merchantCode || config.merchantId || "";
5522
- this.merchantKey = config.apiKey || config.merchantKey || config.serverKey || config.secretKey || "";
5523
- this.sandbox = !!config.sandbox;
8461
+ this.config = config;
5524
8462
  }
5525
8463
  getBaseUrl() {
5526
- return this.sandbox ? "https://sandbox.finpay.co.id" : "https://api.finpay.id";
8464
+ return this.config.sandbox !== false ? "https://connect.squareupsandbox.com" : "https://connect.squareup.com";
5527
8465
  }
5528
- /**
5529
- * Helper HTTP Request ke Finpay API
5530
- */
5531
- async request(endpoint, payload) {
5532
- const url = `${this.getBaseUrl()}${endpoint}`;
5533
- const response = await fetch(url, {
8466
+ buildHeaders() {
8467
+ return {
8468
+ "Authorization": `Bearer ${this.config.apiKey || this.config.secretKey || ""}`,
8469
+ "Content-Type": "application/json",
8470
+ "Square-Version": "2024-01-17"
8471
+ };
8472
+ }
8473
+ /** Ambil detail payment Square */
8474
+ async getPayment(paymentId) {
8475
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/${paymentId}`, {
8476
+ method: "GET",
8477
+ headers: this.buildHeaders()
8478
+ });
8479
+ return response.json();
8480
+ }
8481
+ /** Batalkan payment Square */
8482
+ async cancelPayment(paymentId) {
8483
+ const response = await fetch(`${this.getBaseUrl()}/v2/payments/${paymentId}/cancel`, {
5534
8484
  method: "POST",
5535
- headers: {
5536
- "Content-Type": "application/json",
5537
- "Accept": "application/json"
5538
- },
5539
- body: JSON.stringify(payload)
8485
+ headers: this.buildHeaders(),
8486
+ body: "{}"
5540
8487
  });
5541
- const text = await response.text();
5542
- let data = null;
5543
- try {
5544
- data = JSON.parse(text);
5545
- } catch (e) {
5546
- }
5547
- if (!response.ok) {
5548
- throw new Error(data?.response_desc || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
5549
- }
5550
- return data;
8488
+ return response.json();
5551
8489
  }
5552
- /**
5553
- * Cek status transaksi pembayaran Finpay
5554
- */
5555
- async checkTransaction(orderId) {
5556
- const signature = generateFinpaySignature(this.merchantId, orderId, 0, this.merchantKey);
5557
- return this.request("/pg/payment/status", {
5558
- merchant_id: this.merchantId,
5559
- order_id: orderId,
5560
- signature
8490
+ /** Refund payment Square */
8491
+ async refundPayment(paymentId, amount, currency, idempotencyKey, reason) {
8492
+ const response = await fetch(`${this.getBaseUrl()}/v2/refunds`, {
8493
+ method: "POST",
8494
+ headers: this.buildHeaders(),
8495
+ body: JSON.stringify({
8496
+ idempotency_key: idempotencyKey,
8497
+ payment_id: paymentId,
8498
+ amount_money: { amount, currency },
8499
+ reason
8500
+ })
5561
8501
  });
8502
+ return response.json();
8503
+ }
8504
+ /** Ambil saldo location Square */
8505
+ async retrieveBalance(locationId) {
8506
+ const id = locationId || this.config.extra?.locationId || this.config.projectId || "";
8507
+ const response = await fetch(`${this.getBaseUrl()}/v2/locations/${id}`, {
8508
+ method: "GET",
8509
+ headers: this.buildHeaders()
8510
+ });
8511
+ return response.json();
8512
+ }
8513
+ /** List semua locations merchant */
8514
+ async listLocations() {
8515
+ const response = await fetch(`${this.getBaseUrl()}/v2/locations`, {
8516
+ method: "GET",
8517
+ headers: this.buildHeaders()
8518
+ });
8519
+ return response.json();
5562
8520
  }
5563
8521
  };
5564
8522
 
5565
- // src/clients/nicepay.ts
5566
- var NicepayClient = class {
5567
- iMid;
5568
- merchantKey;
5569
- sandbox;
8523
+ // src/clients/payu.ts
8524
+ var PayuClient = class {
8525
+ config;
8526
+ accessToken = null;
5570
8527
  constructor(config) {
5571
- this.iMid = config.merchantCode || config.merchantId || config.iMid || "";
5572
- this.merchantKey = config.apiKey || config.merchantKey || config.serverKey || config.secretKey || "";
5573
- this.sandbox = !!config.sandbox;
8528
+ this.config = config;
5574
8529
  }
5575
8530
  getBaseUrl() {
5576
- return this.sandbox ? "https://dev.nicepay.co.id/nicepay" : "https://www.nicepay.co.id/nicepay";
8531
+ return this.config.sandbox !== false ? "https://secure.snd.payu.com" : "https://secure.payu.com";
5577
8532
  }
5578
- /**
5579
- * Helper HTTP Request ke Nicepay API
5580
- */
5581
- async request(endpoint, payload) {
5582
- const url = `${this.getBaseUrl()}${endpoint}`;
5583
- const response = await fetch(url, {
8533
+ async getToken() {
8534
+ if (this.accessToken) return this.accessToken;
8535
+ const clientId = this.config.extra?.oauthClientId || this.config.clientKey || "";
8536
+ const clientSecret = this.config.extra?.oauthClientSecret || this.config.apiKey || this.config.secretKey || "";
8537
+ const response = await fetch(`${this.getBaseUrl()}/pl/standard/user/oauth/authorize`, {
5584
8538
  method: "POST",
5585
- headers: {
5586
- "Content-Type": "application/json",
5587
- "Accept": "application/json"
5588
- },
5589
- body: JSON.stringify(payload)
8539
+ headers: { "Authorization": `Basic ${buildPayuBasicAuth(clientId, clientSecret)}`, "Content-Type": "application/x-www-form-urlencoded" },
8540
+ body: "grant_type=client_credentials"
5590
8541
  });
5591
- const text = await response.text();
5592
- let data = null;
5593
- try {
5594
- data = JSON.parse(text);
5595
- } catch (e) {
5596
- }
5597
- if (!response.ok) {
5598
- throw new Error(data?.resultMsg || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
5599
- }
5600
- return data;
8542
+ const data = await response.json();
8543
+ if (!data?.access_token) throw new Error("Failed to get PayU access token");
8544
+ this.accessToken = data.access_token;
8545
+ return this.accessToken;
8546
+ }
8547
+ /** Ambil detail order PayU */
8548
+ async getOrder(orderId) {
8549
+ const token = await this.getToken();
8550
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}`, {
8551
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8552
+ });
8553
+ return response.json();
8554
+ }
8555
+ /** Batalkan order PayU */
8556
+ async cancelOrder(orderId) {
8557
+ const token = await this.getToken();
8558
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}`, {
8559
+ method: "DELETE",
8560
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }
8561
+ });
8562
+ return response.json();
8563
+ }
8564
+ /** Refund order PayU */
8565
+ async refundOrder(orderId, amount, description) {
8566
+ const token = await this.getToken();
8567
+ const body = { refund: { description: description || "Refund" } };
8568
+ if (amount) body.refund.amount = amount;
8569
+ const response = await fetch(`${this.getBaseUrl()}/api/v2_1/orders/${orderId}/refunds`, {
8570
+ method: "POST",
8571
+ headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
8572
+ body: JSON.stringify(body)
8573
+ });
8574
+ return response.json();
5601
8575
  }
5602
- /**
5603
- * Cek status transaksi pembayaran di Nicepay
5604
- */
5605
- async checkTransaction(referenceNo, amount = 0) {
5606
- const timeStamp = formatNicepayTimestamp();
5607
- const merchantToken = generateNicepayToken(timeStamp, this.iMid, referenceNo, amount, this.merchantKey);
5608
- return this.request("/api/oneStepTransInquiry.do", {
5609
- timeStamp,
5610
- iMid: this.iMid,
5611
- referenceNo,
5612
- amt: String(amount),
5613
- merchantToken
8576
+ };
8577
+
8578
+ // src/clients/braintree.ts
8579
+ var BraintreeClient = class {
8580
+ config;
8581
+ constructor(config) {
8582
+ this.config = config;
8583
+ }
8584
+ getBaseUrl() {
8585
+ const merchantId = this.config.merchantCode || this.config.merchantId || "";
8586
+ const base = this.config.sandbox !== false ? "https://api.sandbox.braintreegateway.com" : "https://api.braintreegateway.com";
8587
+ return `${base}/merchants/${merchantId}`;
8588
+ }
8589
+ buildHeaders() {
8590
+ const publicKey = this.config.clientKey || this.config.extra?.publicKey || "";
8591
+ const privateKey = this.config.apiKey || this.config.secretKey || "";
8592
+ return {
8593
+ "Authorization": `Basic ${buildBraintreeBasicAuth(publicKey, privateKey)}`,
8594
+ "Content-Type": "application/json",
8595
+ "Braintree-Version": "2019-01-01"
8596
+ };
8597
+ }
8598
+ /** Generate Client Token untuk frontend Drop-in UI */
8599
+ async getClientToken(customerId) {
8600
+ const body = {};
8601
+ if (customerId) body.client_token = { customer_id: customerId };
8602
+ const response = await fetch(`${this.getBaseUrl()}/client_token`, {
8603
+ method: "POST",
8604
+ headers: this.buildHeaders(),
8605
+ body: JSON.stringify(body)
5614
8606
  });
8607
+ const data = await response.json();
8608
+ return data.clientToken || "";
8609
+ }
8610
+ /** Ambil detail transaction */
8611
+ async findTransaction(transactionId) {
8612
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}`, {
8613
+ method: "GET",
8614
+ headers: this.buildHeaders()
8615
+ });
8616
+ return response.json();
5615
8617
  }
5616
- /**
5617
- * Batalkan transaksi di Nicepay
5618
- */
5619
- async cancelTransaction(tXid, payMethod, cancelMsg = "User Cancel") {
5620
- const timeStamp = formatNicepayTimestamp();
5621
- const merchantToken = sha256(`${timeStamp}${this.iMid}${tXid}0${this.merchantKey}`);
5622
- return this.request("/api/oneStepTransCancel.do", {
5623
- timeStamp,
5624
- iMid: this.iMid,
5625
- tXid,
5626
- payMethod,
5627
- cancelType: "1",
5628
- cancelMsg,
5629
- merchantToken
8618
+ /** Refund transaction Braintree */
8619
+ async refundTransaction(transactionId, amount) {
8620
+ const body = {};
8621
+ if (amount) body.transaction = { amount: (amount / 100).toFixed(2) };
8622
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}/refund`, {
8623
+ method: "POST",
8624
+ headers: this.buildHeaders(),
8625
+ body: JSON.stringify(body)
5630
8626
  });
8627
+ return response.json();
8628
+ }
8629
+ /** Void (batalkan) transaction sebelum settlement */
8630
+ async voidTransaction(transactionId) {
8631
+ const response = await fetch(`${this.getBaseUrl()}/transactions/${transactionId}/void`, {
8632
+ method: "PUT",
8633
+ headers: this.buildHeaders(),
8634
+ body: "{}"
8635
+ });
8636
+ return response.json();
5631
8637
  }
5632
8638
  };
5633
8639
 
5634
- // src/clients/oy.ts
5635
- var OyClient = class {
5636
- username;
5637
- apiKey;
5638
- sandbox;
8640
+ // src/clients/twocheckout.ts
8641
+ var TwoCheckoutClient = class {
8642
+ config;
5639
8643
  constructor(config) {
5640
- this.username = config.clientKey || config.username || config.merchantCode || "";
5641
- this.apiKey = config.apiKey || config.serverKey || config.secretKey || "";
5642
- this.sandbox = !!config.sandbox;
8644
+ this.config = config;
5643
8645
  }
5644
8646
  getBaseUrl() {
5645
- return this.sandbox ? "https://api-stg.oyindonesia.com/api" : "https://api.oyindonesia.com/api";
8647
+ return this.config.sandbox !== false ? "https://api.sandbox.2checkout.com/rest" : "https://api.2checkout.com/rest";
5646
8648
  }
5647
- /**
5648
- * Helper HTTP Request ke OY! Bisnis API
5649
- */
5650
- async request(method, endpoint, body) {
5651
- const url = `${this.getBaseUrl()}${endpoint}`;
5652
- const headers = generateOyHeaders(this.username, this.apiKey);
5653
- const fetchOptions = {
5654
- method,
5655
- headers
8649
+ buildHeaders() {
8650
+ const merchantCode = this.config.merchantCode || this.config.merchantId || "";
8651
+ const secretKey = this.config.apiKey || this.config.secretKey || "";
8652
+ const { header } = buildTwoCheckoutAuth(merchantCode, secretKey);
8653
+ return {
8654
+ "X-Avangate-Authentication": header,
8655
+ "Content-Type": "application/json",
8656
+ "Accept": "application/json"
5656
8657
  };
5657
- if (method === "POST" && body) {
5658
- fetchOptions.body = JSON.stringify(body);
5659
- }
5660
- const response = await fetch(url, fetchOptions);
5661
- const text = await response.text();
5662
- let data = null;
5663
- try {
5664
- data = JSON.parse(text);
5665
- } catch (e) {
5666
- }
5667
- if (!response.ok) {
5668
- throw new Error(data?.status?.message || data?.message || `HTTP error! Status: ${response.status} - ${text}`);
5669
- }
5670
- return data;
5671
8658
  }
5672
- /**
5673
- * Cek status transaksi pembayaran
5674
- */
5675
- async checkTransaction(partnerTxId) {
5676
- return this.request("GET", `/payment-checkout/status?partner_tx_id=${encodeURIComponent(partnerTxId)}&send_callback=false`);
8659
+ /** Ambil detail order 2Checkout berdasarkan Reference Number */
8660
+ async getOrder(refNo) {
8661
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders/${refNo}`, {
8662
+ method: "GET",
8663
+ headers: this.buildHeaders()
8664
+ });
8665
+ return response.json();
5677
8666
  }
5678
- /**
5679
- * Cek saldo akun OY! Bisnis
5680
- */
5681
- async checkBalance() {
5682
- return this.request("GET", "/balance");
8667
+ /** Refund order 2Checkout */
8668
+ async refundOrder(refNo, amount, comment) {
8669
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders/${refNo}/refund`, {
8670
+ method: "POST",
8671
+ headers: this.buildHeaders(),
8672
+ body: JSON.stringify({ amount, comment: comment || "Refund", reason: "NOT_SATISFIED" })
8673
+ });
8674
+ return response.json();
5683
8675
  }
5684
- /**
5685
- * Kirim dana / Transfer uang (Disbursement / Remittance)
5686
- */
5687
- async remit(params) {
5688
- return this.request("POST", "/remit", {
5689
- recipient_bank: params.recipientBank,
5690
- recipient_account: params.recipientAccount,
5691
- amount: params.amount,
5692
- note: params.note || "Disbursement",
5693
- partner_trx_id: params.partnerTrxId
8676
+ /** Ambil detail subscription */
8677
+ async getSubscription(subscriptionRef) {
8678
+ const response = await fetch(`${this.getBaseUrl()}/6.0/subscriptions/${subscriptionRef}`, {
8679
+ method: "GET",
8680
+ headers: this.buildHeaders()
8681
+ });
8682
+ return response.json();
8683
+ }
8684
+ /** List semua orders merchant */
8685
+ async listOrders(page, limit) {
8686
+ const params = new URLSearchParams({
8687
+ Pagination: JSON.stringify({ Page: page || 1, Limit: limit || 10 })
8688
+ });
8689
+ const response = await fetch(`${this.getBaseUrl()}/6.0/orders?${params}`, {
8690
+ method: "GET",
8691
+ headers: this.buildHeaders()
5694
8692
  });
8693
+ return response.json();
5695
8694
  }
5696
8695
  };
5697
8696
 
@@ -5709,6 +8708,15 @@ var PaymentManager = class {
5709
8708
  this.registerProvider(new FinpayProvider());
5710
8709
  this.registerProvider(new NicepayProvider());
5711
8710
  this.registerProvider(new OyProvider());
8711
+ this.registerProvider(new StripeProvider());
8712
+ this.registerProvider(new PaypalProvider());
8713
+ this.registerProvider(new AdyenProvider());
8714
+ this.registerProvider(new CheckoutComProvider());
8715
+ this.registerProvider(new RazorpayProvider());
8716
+ this.registerProvider(new SquareProvider());
8717
+ this.registerProvider(new PayuProvider());
8718
+ this.registerProvider(new BraintreeProvider());
8719
+ this.registerProvider(new TwoCheckoutProvider());
5712
8720
  }
5713
8721
  registerProvider(provider) {
5714
8722
  this.providers.set(provider.name.toLowerCase(), provider);
@@ -5720,6 +8728,7 @@ var PaymentManager = class {
5720
8728
  }
5721
8729
  return provider;
5722
8730
  }
8731
+ // ─── Indonesian Provider Getters ──────────────────────────────────────────
5723
8732
  getMidtransProvider() {
5724
8733
  return this.getProvider("midtrans");
5725
8734
  }
@@ -5780,6 +8789,62 @@ var PaymentManager = class {
5780
8789
  getOyClient(config) {
5781
8790
  return new OyClient(config);
5782
8791
  }
8792
+ // ─── International Provider Getters ─────────────────────────────────────
8793
+ getStripeProvider() {
8794
+ return this.getProvider("stripe");
8795
+ }
8796
+ getStripeClient(config) {
8797
+ return new StripeClient(config);
8798
+ }
8799
+ getPaypalProvider() {
8800
+ return this.getProvider("paypal");
8801
+ }
8802
+ getPaypalClient(config) {
8803
+ return new PaypalClient(config);
8804
+ }
8805
+ getAdyenProvider() {
8806
+ return this.getProvider("adyen");
8807
+ }
8808
+ getAdyenClient(config) {
8809
+ return new AdyenClient(config);
8810
+ }
8811
+ getCheckoutComProvider() {
8812
+ return this.getProvider("checkoutcom");
8813
+ }
8814
+ getCheckoutComClient(config) {
8815
+ return new CheckoutComClient(config);
8816
+ }
8817
+ getRazorpayProvider() {
8818
+ return this.getProvider("razorpay");
8819
+ }
8820
+ getRazorpayClient(config) {
8821
+ return new RazorpayClient(config);
8822
+ }
8823
+ getSquareProvider() {
8824
+ return this.getProvider("square");
8825
+ }
8826
+ getSquareClient(config) {
8827
+ return new SquareClient(config);
8828
+ }
8829
+ getPayuProvider() {
8830
+ return this.getProvider("payu");
8831
+ }
8832
+ getPayuClient(config) {
8833
+ return new PayuClient(config);
8834
+ }
8835
+ getBraintreeProvider() {
8836
+ return this.getProvider("braintree");
8837
+ }
8838
+ getBraintreeClient(config) {
8839
+ return new BraintreeClient(config);
8840
+ }
8841
+ getTwoCheckoutProvider() {
8842
+ return this.getProvider("twocheckout");
8843
+ }
8844
+ getTwoCheckoutClient(config) {
8845
+ return new TwoCheckoutClient(config);
8846
+ }
8847
+ // ─── Unified Operations ──────────────────────────────────────────────────
5783
8848
  async createInvoice(providerName, params, config) {
5784
8849
  const provider = this.getProvider(providerName);
5785
8850
  return provider.createInvoice(params, config);
@@ -5837,6 +8902,24 @@ function resolveConfigFromEnv(customConfig) {
5837
8902
  sandbox = env.NICEPAY_SANDBOX === "true" || env.NICEPAY_SANDBOX === "1";
5838
8903
  } else if (env.OY_SANDBOX !== void 0) {
5839
8904
  sandbox = env.OY_SANDBOX === "true" || env.OY_SANDBOX === "1";
8905
+ } else if (env.STRIPE_SANDBOX !== void 0) {
8906
+ sandbox = env.STRIPE_SANDBOX === "true" || env.STRIPE_SANDBOX === "1";
8907
+ } else if (env.PAYPAL_SANDBOX !== void 0) {
8908
+ sandbox = env.PAYPAL_SANDBOX === "true" || env.PAYPAL_SANDBOX === "1";
8909
+ } else if (env.ADYEN_SANDBOX !== void 0) {
8910
+ sandbox = env.ADYEN_SANDBOX === "true" || env.ADYEN_SANDBOX === "1";
8911
+ } else if (env.CHECKOUTCOM_SANDBOX !== void 0) {
8912
+ sandbox = env.CHECKOUTCOM_SANDBOX === "true" || env.CHECKOUTCOM_SANDBOX === "1";
8913
+ } else if (env.RAZORPAY_SANDBOX !== void 0) {
8914
+ sandbox = env.RAZORPAY_SANDBOX === "true" || env.RAZORPAY_SANDBOX === "1";
8915
+ } else if (env.SQUARE_SANDBOX !== void 0) {
8916
+ sandbox = env.SQUARE_SANDBOX === "true" || env.SQUARE_SANDBOX === "1";
8917
+ } else if (env.PAYU_SANDBOX !== void 0) {
8918
+ sandbox = env.PAYU_SANDBOX === "true" || env.PAYU_SANDBOX === "1";
8919
+ } else if (env.BRAINTREE_SANDBOX !== void 0) {
8920
+ sandbox = env.BRAINTREE_SANDBOX === "true" || env.BRAINTREE_SANDBOX === "1";
8921
+ } else if (env.TWOCHECKOUT_SANDBOX !== void 0) {
8922
+ sandbox = env.TWOCHECKOUT_SANDBOX === "true" || env.TWOCHECKOUT_SANDBOX === "1";
5840
8923
  } else {
5841
8924
  sandbox = env.NODE_ENV !== "production";
5842
8925
  }
@@ -5862,6 +8945,24 @@ function resolveConfigFromEnv(customConfig) {
5862
8945
  apiKey = env.NICEPAY_KEY || env.NICEPAY_MERCHANT_KEY || env.NICEPAY_SECRET_KEY || env.NICEPAY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
5863
8946
  } else if (provider === "oy" || provider === "oyindonesia") {
5864
8947
  apiKey = env.OY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8948
+ } else if (provider === "stripe") {
8949
+ apiKey = env.STRIPE_SECRET_KEY || env.STRIPE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8950
+ } else if (provider === "paypal") {
8951
+ apiKey = env.PAYPAL_CLIENT_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8952
+ } else if (provider === "adyen") {
8953
+ apiKey = env.ADYEN_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8954
+ } else if (provider === "checkoutcom") {
8955
+ apiKey = env.CHECKOUTCOM_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8956
+ } else if (provider === "razorpay") {
8957
+ apiKey = env.RAZORPAY_KEY_SECRET || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8958
+ } else if (provider === "square") {
8959
+ apiKey = env.SQUARE_ACCESS_TOKEN || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8960
+ } else if (provider === "payu") {
8961
+ apiKey = env.PAYU_MD5_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8962
+ } else if (provider === "braintree") {
8963
+ apiKey = env.BRAINTREE_PRIVATE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
8964
+ } else if (provider === "twocheckout" || provider === "2checkout") {
8965
+ apiKey = env.TWOCHECKOUT_SECRET_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
5865
8966
  } else {
5866
8967
  apiKey = env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.PG_SECRET_KEY || env.BUAYAR_SECRET_KEY;
5867
8968
  }
@@ -5896,25 +8997,66 @@ function resolveConfigFromEnv(customConfig) {
5896
8997
  } else if (provider === "oy" || provider === "oyindonesia") {
5897
8998
  merchantCode = merchantCode || env.OY_USERNAME || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
5898
8999
  clientKey = clientKey || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
9000
+ } else if (provider === "stripe") {
9001
+ clientKey = clientKey || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.BUAYAR_CLIENT_KEY || env.BUAYAR_PUBLIC_KEY;
9002
+ merchantCode = merchantCode || clientKey || "stripe";
9003
+ } else if (provider === "paypal") {
9004
+ clientKey = clientKey || env.PAYPAL_CLIENT_ID || env.BUAYAR_CLIENT_KEY;
9005
+ merchantCode = merchantCode || env.PAYPAL_CLIENT_ID || env.BUAYAR_MERCHANT_CODE;
9006
+ } else if (provider === "adyen") {
9007
+ clientKey = clientKey || env.ADYEN_CLIENT_KEY || env.BUAYAR_CLIENT_KEY;
9008
+ merchantCode = merchantCode || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_CODE;
9009
+ merchantId = merchantId || env.ADYEN_MERCHANT_ACCOUNT || env.BUAYAR_MERCHANT_ID;
9010
+ } else if (provider === "checkoutcom") {
9011
+ clientKey = clientKey || env.CHECKOUTCOM_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9012
+ merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE;
9013
+ } else if (provider === "razorpay") {
9014
+ clientKey = clientKey || env.RAZORPAY_KEY_ID || env.BUAYAR_CLIENT_KEY;
9015
+ merchantCode = merchantCode || env.RAZORPAY_KEY_ID || env.BUAYAR_MERCHANT_CODE;
9016
+ } else if (provider === "square") {
9017
+ clientKey = clientKey || env.SQUARE_APPLICATION_ID || env.BUAYAR_CLIENT_KEY;
9018
+ merchantCode = merchantCode || env.SQUARE_APPLICATION_ID || env.BUAYAR_MERCHANT_CODE;
9019
+ } else if (provider === "payu") {
9020
+ merchantCode = merchantCode || env.PAYU_POS_ID || env.BUAYAR_MERCHANT_CODE;
9021
+ merchantId = merchantId || env.PAYU_POS_ID;
9022
+ } else if (provider === "braintree") {
9023
+ clientKey = clientKey || env.BRAINTREE_PUBLIC_KEY || env.BUAYAR_CLIENT_KEY;
9024
+ merchantCode = merchantCode || env.BRAINTREE_MERCHANT_ID || env.BUAYAR_MERCHANT_CODE;
9025
+ merchantId = merchantId || env.BRAINTREE_MERCHANT_ID;
9026
+ } else if (provider === "twocheckout" || provider === "2checkout") {
9027
+ merchantCode = merchantCode || env.TWOCHECKOUT_MERCHANT_CODE || env.BUAYAR_MERCHANT_CODE;
9028
+ merchantId = merchantId || env.TWOCHECKOUT_MERCHANT_CODE;
5899
9029
  } else {
5900
9030
  merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
5901
9031
  }
5902
- const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID;
5903
- const publicKey = customConfig?.publicKey || env.BUAYAR_PUBLIC_KEY || env.PG_PUBLIC_KEY || env.PUBLIC_KEY;
5904
- const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY;
5905
- 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;
9032
+ const projectId = customConfig?.projectId || env.BUAYAR_PROJECT_ID || env.PG_PROJECT_ID || env.PROJECT_ID || env.SQUARE_LOCATION_ID;
9033
+ 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;
9034
+ const privateKey = customConfig?.privateKey || env.BUAYAR_PRIVATE_KEY || env.PG_PRIVATE_KEY || env.PRIVATE_KEY || env.BRAINTREE_PRIVATE_KEY;
9035
+ 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 || env.PAYPAL_CLIENT_SECRET || env.CHECKOUTCOM_SECRET_KEY || env.RAZORPAY_KEY_SECRET || env.SQUARE_ACCESS_TOKEN || env.BRAINTREE_PRIVATE_KEY || env.TWOCHECKOUT_SECRET_KEY;
5906
9036
  const callbackUrl = customConfig?.callbackUrl || env.BUAYAR_CALLBACK_URL || env.PG_CALLBACK_URL || env.PAYMENT_CALLBACK_URL;
5907
9037
  const returnUrl = customConfig?.returnUrl || env.BUAYAR_RETURN_URL || env.PG_RETURN_URL || env.PAYMENT_RETURN_URL;
5908
9038
  const extra = {
5909
9039
  webhookToken: env.XENDIT_WEBHOOK_TOKEN || env.BUAYAR_WEBHOOK_TOKEN,
9040
+ webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.CHECKOUTCOM_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
5910
9041
  merchantName: env.FASPAY_MERCHANT_NAME || env.BUAYAR_MERCHANT_NAME,
5911
9042
  userId: env.FASPAY_USER_ID,
5912
9043
  iMid: env.NICEPAY_IMID,
5913
9044
  username: env.OY_USERNAME,
9045
+ hmacKey: env.ADYEN_HMAC_KEY,
9046
+ liveUrlPrefix: env.ADYEN_LIVE_URL_PREFIX,
9047
+ webhookId: env.PAYPAL_WEBHOOK_ID,
9048
+ merchantAccount: env.ADYEN_MERCHANT_ACCOUNT,
9049
+ md5Key: env.PAYU_MD5_KEY,
9050
+ oauthClientId: env.PAYU_OAUTH_CLIENT_ID,
9051
+ oauthClientSecret: env.PAYU_OAUTH_CLIENT_SECRET,
9052
+ locationId: env.SQUARE_LOCATION_ID,
9053
+ webhookSignatureKey: env.SQUARE_WEBHOOK_SIGNATURE_KEY,
9054
+ publicKey: env.BRAINTREE_PUBLIC_KEY || env.ADYEN_CLIENT_KEY,
9055
+ secretWord: env.TWOCHECKOUT_SECRET_WORD,
5914
9056
  ...customConfig?.extra
5915
9057
  };
5916
9058
  return {
5917
- provider: provider === "oyindonesia" ? "oy" : provider,
9059
+ provider: provider === "oyindonesia" ? "oy" : provider === "2checkout" ? "twocheckout" : provider,
5918
9060
  apiKey: apiKey || "",
5919
9061
  serverKey: apiKey || "",
5920
9062
  secretKey: secretKey || apiKey || "",
@@ -5952,7 +9094,7 @@ var Buayar = class {
5952
9094
  this.config = resolveConfigFromEnv({ ...this.config, ...config });
5953
9095
  }
5954
9096
  /**
5955
- * Dapatkan nama provider aktif ('midtrans' | 'duitku' | 'ipaymu' | 'xendit' | 'doku' | 'prismalink' | 'faspay' | 'finpay' | 'nicepay' | 'oy' | ...)
9097
+ * Dapatkan nama provider aktif
5956
9098
  */
5957
9099
  get provider() {
5958
9100
  return this.config.provider || "midtrans";
@@ -6000,6 +9142,40 @@ var Buayar = class {
6000
9142
  */
6001
9143
  async verifyWebhook(payload, headers, configOverride) {
6002
9144
  const mergedConfig = { ...this.config, ...configOverride };
9145
+ if (headers) {
9146
+ const stripeSig = headers["stripe-signature"] || headers["Stripe-Signature"];
9147
+ if (stripeSig) {
9148
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9149
+ mergedConfig.extra.signatureHeader = Array.isArray(stripeSig) ? stripeSig[0] : stripeSig;
9150
+ }
9151
+ const ckoSig = headers["cko-signature"] || headers["Cko-Signature"];
9152
+ if (ckoSig) {
9153
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9154
+ mergedConfig.extra.signatureHeader = Array.isArray(ckoSig) ? ckoSig[0] : ckoSig;
9155
+ }
9156
+ const rzpSig = headers["x-razorpay-signature"] || headers["X-Razorpay-Signature"];
9157
+ if (rzpSig) {
9158
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9159
+ mergedConfig.extra.signatureHeader = Array.isArray(rzpSig) ? rzpSig[0] : rzpSig;
9160
+ }
9161
+ const squareSig = headers["x-square-hmacsha256-signature"] || headers["x-square-signature"];
9162
+ if (squareSig) {
9163
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9164
+ mergedConfig.extra.signatureHeader = Array.isArray(squareSig) ? squareSig[0] : squareSig;
9165
+ }
9166
+ const payuSig = headers["openpayu-signature"] || headers["OpenPayU-Signature"];
9167
+ if (payuSig) {
9168
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9169
+ mergedConfig.extra.signatureHeader = Array.isArray(payuSig) ? payuSig[0] : payuSig;
9170
+ }
9171
+ const btSig = headers["bt_signature"];
9172
+ const btPayload = headers["bt_payload"];
9173
+ if (btSig && btPayload) {
9174
+ if (!mergedConfig.extra) mergedConfig.extra = {};
9175
+ mergedConfig.extra.btSignature = Array.isArray(btSig) ? btSig[0] : btSig;
9176
+ mergedConfig.extra.btPayload = Array.isArray(btPayload) ? btPayload[0] : btPayload;
9177
+ }
9178
+ }
6003
9179
  let providerName = configOverride?.provider || this.provider;
6004
9180
  if (payload) {
6005
9181
  if (payload.signature_key && payload.transaction_status) {
@@ -6020,8 +9196,28 @@ var Buayar = class {
6020
9196
  providerName = "oy";
6021
9197
  } else if (payload.merchant_id && payload.order_id && payload.signature) {
6022
9198
  providerName = "prismalink";
9199
+ } else if (payload.object === "event" || payload.type && payload.data?.object && payload.api_version) {
9200
+ providerName = "stripe";
9201
+ } else if (payload.event && payload.payload?.payment?.entity) {
9202
+ providerName = "razorpay";
6023
9203
  } else if (payload.external_id || payload.event?.startsWith("payment.") || payload.event?.startsWith("qr.") || payload.data?.reference_id) {
6024
9204
  providerName = "xendit";
9205
+ } else if (payload.event_type && payload.resource && (payload.event_type.startsWith("PAYMENT.") || payload.event_type.startsWith("CHECKOUT.ORDER."))) {
9206
+ providerName = "paypal";
9207
+ } else if (payload.notificationItems || payload.merchantAccountCode && payload.pspReference && payload.eventCode) {
9208
+ providerName = "adyen";
9209
+ } else if (payload.type && payload.data?._links && (payload.type.startsWith("payment_") || payload.type.startsWith("refund_"))) {
9210
+ providerName = "checkoutcom";
9211
+ } else if (payload.event && payload.payload?.payment?.entity) {
9212
+ providerName = "razorpay";
9213
+ } else if (payload.type && payload.data?.object?.status && payload.merchant_id) {
9214
+ providerName = "square";
9215
+ } else if (payload.order && payload.order?.status && payload.order?.extOrderId) {
9216
+ providerName = "payu";
9217
+ } else if (payload.kind && payload.subject?.transaction) {
9218
+ providerName = "braintree";
9219
+ } else if (payload.HASH && payload.REFNOEXT && payload.IPN_PID) {
9220
+ providerName = "twocheckout";
6025
9221
  }
6026
9222
  }
6027
9223
  return this.manager.verifyCallback(providerName, payload, mergedConfig);
@@ -6029,71 +9225,74 @@ var Buayar = class {
6029
9225
  async handleWebhook(payload, headers, configOverride) {
6030
9226
  return this.verifyWebhook(payload, headers, configOverride);
6031
9227
  }
9228
+ // ─── Indonesian Provider Client Getters ───────────────────────────────────
6032
9229
  getMidtransClient(configOverride) {
6033
- return new MidtransClient({
6034
- ...this.config,
6035
- ...configOverride
6036
- });
9230
+ return new MidtransClient({ ...this.config, ...configOverride });
6037
9231
  }
6038
9232
  getDuitkuClient(configOverride) {
6039
- return new DuitkuClient({
6040
- ...this.config,
6041
- ...configOverride
6042
- });
9233
+ return new DuitkuClient({ ...this.config, ...configOverride });
6043
9234
  }
6044
9235
  getIpaymuClient(configOverride) {
6045
- return new IpaymuClient({
6046
- ...this.config,
6047
- ...configOverride
6048
- });
9236
+ return new IpaymuClient({ ...this.config, ...configOverride });
6049
9237
  }
6050
9238
  getXenditClient(configOverride) {
6051
- return new XenditClient({
6052
- ...this.config,
6053
- ...configOverride
6054
- });
9239
+ return new XenditClient({ ...this.config, ...configOverride });
6055
9240
  }
6056
9241
  getDokuClient(configOverride) {
6057
- return new DokuClient({
6058
- ...this.config,
6059
- ...configOverride
6060
- });
9242
+ return new DokuClient({ ...this.config, ...configOverride });
6061
9243
  }
6062
9244
  getPrismalinkClient(configOverride) {
6063
- return new PrismalinkClient({
6064
- ...this.config,
6065
- ...configOverride
6066
- });
9245
+ return new PrismalinkClient({ ...this.config, ...configOverride });
6067
9246
  }
6068
9247
  getFaspayClient(configOverride) {
6069
- return new FaspayClient({
6070
- ...this.config,
6071
- ...configOverride
6072
- });
9248
+ return new FaspayClient({ ...this.config, ...configOverride });
6073
9249
  }
6074
9250
  getFinpayClient(configOverride) {
6075
- return new FinpayClient({
6076
- ...this.config,
6077
- ...configOverride
6078
- });
9251
+ return new FinpayClient({ ...this.config, ...configOverride });
6079
9252
  }
6080
9253
  getNicepayClient(configOverride) {
6081
- return new NicepayClient({
6082
- ...this.config,
6083
- ...configOverride
6084
- });
9254
+ return new NicepayClient({ ...this.config, ...configOverride });
6085
9255
  }
6086
9256
  getOyClient(configOverride) {
6087
- return new OyClient({
6088
- ...this.config,
6089
- ...configOverride
6090
- });
9257
+ return new OyClient({ ...this.config, ...configOverride });
9258
+ }
9259
+ // ─── International Provider Client Getters ────────────────────────────────
9260
+ getStripeClient(configOverride) {
9261
+ return new StripeClient({ ...this.config, ...configOverride });
9262
+ }
9263
+ getPaypalClient(configOverride) {
9264
+ return new PaypalClient({ ...this.config, ...configOverride });
9265
+ }
9266
+ getAdyenClient(configOverride) {
9267
+ return new AdyenClient({ ...this.config, ...configOverride });
9268
+ }
9269
+ getCheckoutComClient(configOverride) {
9270
+ return new CheckoutComClient({ ...this.config, ...configOverride });
9271
+ }
9272
+ getRazorpayClient(configOverride) {
9273
+ return new RazorpayClient({ ...this.config, ...configOverride });
9274
+ }
9275
+ getSquareClient(configOverride) {
9276
+ return new SquareClient({ ...this.config, ...configOverride });
9277
+ }
9278
+ getPayuClient(configOverride) {
9279
+ return new PayuClient({ ...this.config, ...configOverride });
9280
+ }
9281
+ getBraintreeClient(configOverride) {
9282
+ return new BraintreeClient({ ...this.config, ...configOverride });
9283
+ }
9284
+ getTwoCheckoutClient(configOverride) {
9285
+ return new TwoCheckoutClient({ ...this.config, ...configOverride });
6091
9286
  }
6092
9287
  };
6093
9288
  var buayar = new Buayar();
6094
9289
  // Annotate the CommonJS export names for ESM import in node:
6095
9290
  0 && (module.exports = {
9291
+ AdyenClient,
9292
+ AdyenProvider,
6096
9293
  BasePaymentProvider,
9294
+ BraintreeClient,
9295
+ BraintreeProvider,
6097
9296
  Buayar,
6098
9297
  CANONICAL_TO_DOKU,
6099
9298
  CANONICAL_TO_DUITKU,
@@ -6104,8 +9303,11 @@ var buayar = new Buayar();
6104
9303
  CANONICAL_TO_NICEPAY,
6105
9304
  CANONICAL_TO_OY,
6106
9305
  CANONICAL_TO_PRISMALINK,
9306
+ CANONICAL_TO_STRIPE,
6107
9307
  CANONICAL_TO_XENDIT,
6108
9308
  CORE_API_METHODS,
9309
+ CheckoutComClient,
9310
+ CheckoutComProvider,
6109
9311
  DUITKU_TO_CANONICAL,
6110
9312
  DokuClient,
6111
9313
  DokuProvider,
@@ -6126,12 +9328,29 @@ var buayar = new Buayar();
6126
9328
  OyClient,
6127
9329
  OyProvider,
6128
9330
  PaymentManager,
9331
+ PaypalClient,
9332
+ PaypalProvider,
9333
+ PayuClient,
9334
+ PayuProvider,
6129
9335
  PrismalinkClient,
6130
9336
  PrismalinkProvider,
9337
+ RazorpayClient,
9338
+ RazorpayProvider,
9339
+ SquareClient,
9340
+ SquareProvider,
9341
+ StripeClient,
9342
+ StripeProvider,
9343
+ TwoCheckoutClient,
9344
+ TwoCheckoutProvider,
6131
9345
  XenditClient,
6132
9346
  XenditProvider,
6133
9347
  buayar,
9348
+ buildBraintreeBasicAuth,
6134
9349
  buildCoreChargePayload,
9350
+ buildPaypalBasicAuth,
9351
+ buildPayuBasicAuth,
9352
+ buildRazorpayBasicAuth,
9353
+ buildTwoCheckoutAuth,
6135
9354
  formatNicepayTimestamp,
6136
9355
  generateDokuHeaders,
6137
9356
  generateFaspaySignature,
@@ -6151,6 +9370,8 @@ var buayar = new Buayar();
6151
9370
  paymentManager,
6152
9371
  resolveConfigFromEnv,
6153
9372
  safeCompare,
9373
+ serializePaypalParams,
9374
+ serializeStripeParams,
6154
9375
  sha256,
6155
9376
  sha512,
6156
9377
  toCanonicalPaymentMethod,
@@ -6162,7 +9383,11 @@ var buayar = new Buayar();
6162
9383
  toNicepayPaymentMethod,
6163
9384
  toOyPaymentMethod,
6164
9385
  toPrismalinkPaymentMethod,
9386
+ toStripePaymentMethod,
6165
9387
  toXenditPaymentMethod,
9388
+ verifyAdyenWebhook,
9389
+ verifyBraintreeWebhook,
9390
+ verifyCheckoutComWebhook,
6166
9391
  verifyDokuWebhookSignature,
6167
9392
  verifyDuitkuCallbackSignature,
6168
9393
  verifyFaspaySignature,
@@ -6170,6 +9395,12 @@ var buayar = new Buayar();
6170
9395
  verifyIpaymuCallback,
6171
9396
  verifyNicepayWebhook,
6172
9397
  verifyOyWebhook,
9398
+ verifyPaypalWebhookSimple,
9399
+ verifyPayuWebhook,
6173
9400
  verifyPrismalinkSignature,
9401
+ verifyRazorpayWebhook,
9402
+ verifySquareWebhook,
9403
+ verifyStripeWebhook,
9404
+ verifyTwoCheckoutWebhook,
6174
9405
  verifyXenditWebhookToken
6175
9406
  });