@crediblemark/buayar 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/dist/index.d.mts +68 -2
- package/dist/index.d.ts +68 -2
- package/dist/index.js +497 -4
- package/dist/index.mjs +491 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ __export(index_exports, {
|
|
|
41
41
|
CANONICAL_TO_NICEPAY: () => CANONICAL_TO_NICEPAY,
|
|
42
42
|
CANONICAL_TO_OY: () => CANONICAL_TO_OY,
|
|
43
43
|
CANONICAL_TO_PRISMALINK: () => CANONICAL_TO_PRISMALINK,
|
|
44
|
+
CANONICAL_TO_STRIPE: () => CANONICAL_TO_STRIPE,
|
|
44
45
|
CANONICAL_TO_XENDIT: () => CANONICAL_TO_XENDIT,
|
|
45
46
|
CORE_API_METHODS: () => CORE_API_METHODS,
|
|
46
47
|
DUITKU_TO_CANONICAL: () => DUITKU_TO_CANONICAL,
|
|
@@ -65,6 +66,8 @@ __export(index_exports, {
|
|
|
65
66
|
PaymentManager: () => PaymentManager,
|
|
66
67
|
PrismalinkClient: () => PrismalinkClient,
|
|
67
68
|
PrismalinkProvider: () => PrismalinkProvider,
|
|
69
|
+
StripeClient: () => StripeClient,
|
|
70
|
+
StripeProvider: () => StripeProvider,
|
|
68
71
|
XenditClient: () => XenditClient,
|
|
69
72
|
XenditProvider: () => XenditProvider,
|
|
70
73
|
buayar: () => buayar,
|
|
@@ -88,6 +91,7 @@ __export(index_exports, {
|
|
|
88
91
|
paymentManager: () => paymentManager,
|
|
89
92
|
resolveConfigFromEnv: () => resolveConfigFromEnv,
|
|
90
93
|
safeCompare: () => safeCompare,
|
|
94
|
+
serializeStripeParams: () => serializeStripeParams,
|
|
91
95
|
sha256: () => sha256,
|
|
92
96
|
sha512: () => sha512,
|
|
93
97
|
toCanonicalPaymentMethod: () => toCanonicalPaymentMethod,
|
|
@@ -99,6 +103,7 @@ __export(index_exports, {
|
|
|
99
103
|
toNicepayPaymentMethod: () => toNicepayPaymentMethod,
|
|
100
104
|
toOyPaymentMethod: () => toOyPaymentMethod,
|
|
101
105
|
toPrismalinkPaymentMethod: () => toPrismalinkPaymentMethod,
|
|
106
|
+
toStripePaymentMethod: () => toStripePaymentMethod,
|
|
102
107
|
toXenditPaymentMethod: () => toXenditPaymentMethod,
|
|
103
108
|
verifyDokuWebhookSignature: () => verifyDokuWebhookSignature,
|
|
104
109
|
verifyDuitkuCallbackSignature: () => verifyDuitkuCallbackSignature,
|
|
@@ -108,6 +113,7 @@ __export(index_exports, {
|
|
|
108
113
|
verifyNicepayWebhook: () => verifyNicepayWebhook,
|
|
109
114
|
verifyOyWebhook: () => verifyOyWebhook,
|
|
110
115
|
verifyPrismalinkSignature: () => verifyPrismalinkSignature,
|
|
116
|
+
verifyStripeWebhook: () => verifyStripeWebhook,
|
|
111
117
|
verifyXenditWebhookToken: () => verifyXenditWebhookToken
|
|
112
118
|
});
|
|
113
119
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -395,6 +401,17 @@ var CANONICAL_TO_OY = {
|
|
|
395
401
|
alfamart: { type: "cstore", channel: "alfamart" },
|
|
396
402
|
indomaret: { type: "cstore", channel: "indomaret" }
|
|
397
403
|
};
|
|
404
|
+
var CANONICAL_TO_STRIPE = {
|
|
405
|
+
credit_card: "card",
|
|
406
|
+
qris: "qris",
|
|
407
|
+
gopay_qris: "qris",
|
|
408
|
+
shopeepay_qris: "qris",
|
|
409
|
+
bca_va: "customer_balance",
|
|
410
|
+
mandiri_va: "customer_balance",
|
|
411
|
+
bni_va: "customer_balance",
|
|
412
|
+
bri_va: "customer_balance",
|
|
413
|
+
permata_va: "customer_balance"
|
|
414
|
+
};
|
|
398
415
|
function toDuitkuPaymentMethod(code) {
|
|
399
416
|
if (!code) return void 0;
|
|
400
417
|
const lower = code.toLowerCase().trim();
|
|
@@ -482,6 +499,14 @@ function toOyPaymentMethod(code) {
|
|
|
482
499
|
}
|
|
483
500
|
return void 0;
|
|
484
501
|
}
|
|
502
|
+
function toStripePaymentMethod(code) {
|
|
503
|
+
if (!code) return void 0;
|
|
504
|
+
const lower = code.toLowerCase().trim();
|
|
505
|
+
if (CANONICAL_TO_STRIPE[lower]) {
|
|
506
|
+
return CANONICAL_TO_STRIPE[lower];
|
|
507
|
+
}
|
|
508
|
+
return lower;
|
|
509
|
+
}
|
|
485
510
|
function toCanonicalPaymentMethod(provider, code) {
|
|
486
511
|
if (!code) return "";
|
|
487
512
|
const upper = code.toUpperCase().trim();
|
|
@@ -489,7 +514,7 @@ function toCanonicalPaymentMethod(provider, code) {
|
|
|
489
514
|
if (provider.toLowerCase() === "duitku" && DUITKU_TO_CANONICAL[upper]) {
|
|
490
515
|
return DUITKU_TO_CANONICAL[upper];
|
|
491
516
|
}
|
|
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]) {
|
|
517
|
+
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
518
|
return lower;
|
|
494
519
|
}
|
|
495
520
|
return lower;
|
|
@@ -5000,6 +5025,368 @@ var OyProvider = class extends BasePaymentProvider {
|
|
|
5000
5025
|
}
|
|
5001
5026
|
};
|
|
5002
5027
|
|
|
5028
|
+
// src/providers/stripe/signature.ts
|
|
5029
|
+
function serializeStripeParams(obj, prefix = "") {
|
|
5030
|
+
const pairs = [];
|
|
5031
|
+
if (obj === null || obj === void 0) {
|
|
5032
|
+
return "";
|
|
5033
|
+
}
|
|
5034
|
+
for (const key of Object.keys(obj)) {
|
|
5035
|
+
const val = obj[key];
|
|
5036
|
+
if (val === void 0 || val === null) continue;
|
|
5037
|
+
const fullKey = prefix ? `${prefix}[${key}]` : key;
|
|
5038
|
+
if (typeof val === "object" && !(val instanceof Date)) {
|
|
5039
|
+
const nested = serializeStripeParams(val, fullKey);
|
|
5040
|
+
if (nested) pairs.push(nested);
|
|
5041
|
+
} else {
|
|
5042
|
+
pairs.push(`${encodeURIComponent(fullKey)}=${encodeURIComponent(String(val))}`);
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
5045
|
+
return pairs.join("&");
|
|
5046
|
+
}
|
|
5047
|
+
function verifyStripeWebhook(rawPayload, signatureHeader, webhookSecret, toleranceSeconds = 300) {
|
|
5048
|
+
if (!signatureHeader || !webhookSecret) {
|
|
5049
|
+
return true;
|
|
5050
|
+
}
|
|
5051
|
+
const items = signatureHeader.split(",");
|
|
5052
|
+
let timestamp = "";
|
|
5053
|
+
const signatures = [];
|
|
5054
|
+
for (const item of items) {
|
|
5055
|
+
const [key, value] = item.trim().split("=");
|
|
5056
|
+
if (key === "t") {
|
|
5057
|
+
timestamp = value;
|
|
5058
|
+
} else if (key === "v1") {
|
|
5059
|
+
signatures.push(value);
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
if (!timestamp || signatures.length === 0) {
|
|
5063
|
+
return false;
|
|
5064
|
+
}
|
|
5065
|
+
const payloadString = typeof rawPayload === "string" ? rawPayload : JSON.stringify(rawPayload);
|
|
5066
|
+
const signedPayload = `${timestamp}.${payloadString}`;
|
|
5067
|
+
const expectedSignature = hmacSha256(signedPayload, webhookSecret);
|
|
5068
|
+
return signatures.some((sig) => safeCompare(sig.toLowerCase(), expectedSignature.toLowerCase()));
|
|
5069
|
+
}
|
|
5070
|
+
|
|
5071
|
+
// src/providers/stripe/provider.ts
|
|
5072
|
+
var StripeProvider = class extends BasePaymentProvider {
|
|
5073
|
+
name = "stripe";
|
|
5074
|
+
getBaseUrl() {
|
|
5075
|
+
return "https://api.stripe.com/v1";
|
|
5076
|
+
}
|
|
5077
|
+
async createInvoice(params, config) {
|
|
5078
|
+
const { orderId, amount, productDetails, customer, returnUrl } = params;
|
|
5079
|
+
const secretKey = config.apiKey || config.serverKey || config.secretKey || "";
|
|
5080
|
+
const integerAmount = Math.round(amount);
|
|
5081
|
+
const stripeMethod = toStripePaymentMethod(params.paymentMethod);
|
|
5082
|
+
const isDirect = !!params.paymentMethod;
|
|
5083
|
+
const baseUrl = this.getBaseUrl();
|
|
5084
|
+
const headers = {
|
|
5085
|
+
"Authorization": `Bearer ${secretKey}`,
|
|
5086
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
5087
|
+
};
|
|
5088
|
+
try {
|
|
5089
|
+
if (isDirect) {
|
|
5090
|
+
const url = `${baseUrl}/payment_intents`;
|
|
5091
|
+
const payload = {
|
|
5092
|
+
amount: integerAmount,
|
|
5093
|
+
currency: (params.currency || "idr").toLowerCase(),
|
|
5094
|
+
description: productDetails,
|
|
5095
|
+
receipt_email: customer?.email,
|
|
5096
|
+
payment_method_types: [stripeMethod || "card"],
|
|
5097
|
+
metadata: {
|
|
5098
|
+
order_id: orderId,
|
|
5099
|
+
customer_name: customer?.name
|
|
5100
|
+
},
|
|
5101
|
+
...params.providerParams
|
|
5102
|
+
};
|
|
5103
|
+
const response = await fetch(url, {
|
|
5104
|
+
method: "POST",
|
|
5105
|
+
headers,
|
|
5106
|
+
body: serializeStripeParams(payload)
|
|
5107
|
+
});
|
|
5108
|
+
const text = await response.text();
|
|
5109
|
+
let data = null;
|
|
5110
|
+
try {
|
|
5111
|
+
data = JSON.parse(text);
|
|
5112
|
+
} catch (e) {
|
|
5113
|
+
}
|
|
5114
|
+
if (!response.ok || !data || data.error) {
|
|
5115
|
+
return {
|
|
5116
|
+
success: false,
|
|
5117
|
+
provider: "stripe",
|
|
5118
|
+
orderId,
|
|
5119
|
+
amount: integerAmount,
|
|
5120
|
+
rawResponse: data,
|
|
5121
|
+
error: data?.error?.message || `HTTP error! Status: ${response.status} - ${text}`
|
|
5122
|
+
};
|
|
5123
|
+
}
|
|
5124
|
+
return {
|
|
5125
|
+
success: true,
|
|
5126
|
+
provider: "stripe",
|
|
5127
|
+
orderId,
|
|
5128
|
+
amount: data.amount ? Number(data.amount) : integerAmount,
|
|
5129
|
+
reference: data.id,
|
|
5130
|
+
paymentCode: data.client_secret,
|
|
5131
|
+
rawResponse: data
|
|
5132
|
+
};
|
|
5133
|
+
} else {
|
|
5134
|
+
const url = `${baseUrl}/checkout/sessions`;
|
|
5135
|
+
const successUrl = returnUrl || config.returnUrl || "https://example.com/payment/success";
|
|
5136
|
+
const cancelUrl = returnUrl || config.returnUrl || "https://example.com/payment/cancel";
|
|
5137
|
+
const payload = {
|
|
5138
|
+
mode: "payment",
|
|
5139
|
+
client_reference_id: orderId,
|
|
5140
|
+
customer_email: customer?.email,
|
|
5141
|
+
line_items: [
|
|
5142
|
+
{
|
|
5143
|
+
price_data: {
|
|
5144
|
+
currency: (params.currency || "idr").toLowerCase(),
|
|
5145
|
+
product_data: {
|
|
5146
|
+
name: productDetails
|
|
5147
|
+
},
|
|
5148
|
+
unit_amount: integerAmount
|
|
5149
|
+
},
|
|
5150
|
+
quantity: 1
|
|
5151
|
+
}
|
|
5152
|
+
],
|
|
5153
|
+
metadata: {
|
|
5154
|
+
order_id: orderId
|
|
5155
|
+
},
|
|
5156
|
+
success_url: successUrl,
|
|
5157
|
+
cancel_url: cancelUrl,
|
|
5158
|
+
...params.providerParams
|
|
5159
|
+
};
|
|
5160
|
+
const response = await fetch(url, {
|
|
5161
|
+
method: "POST",
|
|
5162
|
+
headers,
|
|
5163
|
+
body: serializeStripeParams(payload)
|
|
5164
|
+
});
|
|
5165
|
+
const text = await response.text();
|
|
5166
|
+
let data = null;
|
|
5167
|
+
try {
|
|
5168
|
+
data = JSON.parse(text);
|
|
5169
|
+
} catch (e) {
|
|
5170
|
+
}
|
|
5171
|
+
if (!response.ok || !data || data.error) {
|
|
5172
|
+
return {
|
|
5173
|
+
success: false,
|
|
5174
|
+
provider: "stripe",
|
|
5175
|
+
orderId,
|
|
5176
|
+
amount: integerAmount,
|
|
5177
|
+
rawResponse: data,
|
|
5178
|
+
error: data?.error?.message || `HTTP error! Status: ${response.status} - ${text}`
|
|
5179
|
+
};
|
|
5180
|
+
}
|
|
5181
|
+
return {
|
|
5182
|
+
success: true,
|
|
5183
|
+
provider: "stripe",
|
|
5184
|
+
orderId: data.client_reference_id || orderId,
|
|
5185
|
+
amount: data.amount_total ? Number(data.amount_total) : integerAmount,
|
|
5186
|
+
reference: data.id,
|
|
5187
|
+
paymentUrl: data.url,
|
|
5188
|
+
rawResponse: data
|
|
5189
|
+
};
|
|
5190
|
+
}
|
|
5191
|
+
} catch (e) {
|
|
5192
|
+
return {
|
|
5193
|
+
success: false,
|
|
5194
|
+
provider: "stripe",
|
|
5195
|
+
orderId,
|
|
5196
|
+
amount: integerAmount,
|
|
5197
|
+
rawResponse: null,
|
|
5198
|
+
error: e.message || "Failed to make request to Stripe API"
|
|
5199
|
+
};
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
async verifyCallback(body, config) {
|
|
5203
|
+
const webhookSecret = config.extra?.webhookSecret || config.secretKey || "";
|
|
5204
|
+
const signatureHeader = config.extra?.signatureHeader || "";
|
|
5205
|
+
const isValid = verifyStripeWebhook(body, signatureHeader, webhookSecret);
|
|
5206
|
+
const eventType = body.type || "";
|
|
5207
|
+
const obj = body.data?.object || body;
|
|
5208
|
+
const orderId = obj.metadata?.order_id || obj.client_reference_id || obj.id || "";
|
|
5209
|
+
const amount = obj.amount_total || obj.amount || 0;
|
|
5210
|
+
const paymentStatus = (obj.payment_status || obj.status || "").toLowerCase();
|
|
5211
|
+
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";
|
|
5212
|
+
const isPending = paymentStatus === "unpaid" || paymentStatus === "processing" || paymentStatus === "requires_action";
|
|
5213
|
+
const isExpired = paymentStatus === "expired" || eventType === "checkout.session.expired";
|
|
5214
|
+
const isFailed = !isPaid && !isPending && !isExpired;
|
|
5215
|
+
const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
|
|
5216
|
+
return {
|
|
5217
|
+
isValid,
|
|
5218
|
+
provider: "stripe",
|
|
5219
|
+
orderId: String(orderId),
|
|
5220
|
+
amount: Number(amount) || 0,
|
|
5221
|
+
status,
|
|
5222
|
+
isPaid,
|
|
5223
|
+
isPending,
|
|
5224
|
+
isFailed,
|
|
5225
|
+
isExpired,
|
|
5226
|
+
statusCode: eventType || paymentStatus,
|
|
5227
|
+
rawPayload: body
|
|
5228
|
+
};
|
|
5229
|
+
}
|
|
5230
|
+
async getPaymentMethods(params, config) {
|
|
5231
|
+
const staticMethods = [
|
|
5232
|
+
{
|
|
5233
|
+
paymentMethod: "credit_card",
|
|
5234
|
+
code: "credit_card",
|
|
5235
|
+
paymentName: "Credit / Debit Card (Visa, Mastercard, JCB, Amex)",
|
|
5236
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5237
|
+
totalFee: "2.9% + IDR 2,000",
|
|
5238
|
+
category: "Kartu Kredit"
|
|
5239
|
+
},
|
|
5240
|
+
{
|
|
5241
|
+
paymentMethod: "qris",
|
|
5242
|
+
code: "qris",
|
|
5243
|
+
paymentName: "QRIS (Indonesia)",
|
|
5244
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5245
|
+
totalFee: "0.7%",
|
|
5246
|
+
category: "QRIS"
|
|
5247
|
+
},
|
|
5248
|
+
{
|
|
5249
|
+
paymentMethod: "bca_va",
|
|
5250
|
+
code: "bca_va",
|
|
5251
|
+
paymentName: "BCA Virtual Account (Bank Transfer)",
|
|
5252
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5253
|
+
totalFee: "IDR 4,000",
|
|
5254
|
+
category: "Virtual Account"
|
|
5255
|
+
},
|
|
5256
|
+
{
|
|
5257
|
+
paymentMethod: "mandiri_va",
|
|
5258
|
+
code: "mandiri_va",
|
|
5259
|
+
paymentName: "Mandiri Virtual Account (Bank Transfer)",
|
|
5260
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5261
|
+
totalFee: "IDR 4,000",
|
|
5262
|
+
category: "Virtual Account"
|
|
5263
|
+
},
|
|
5264
|
+
{
|
|
5265
|
+
paymentMethod: "bni_va",
|
|
5266
|
+
code: "bni_va",
|
|
5267
|
+
paymentName: "BNI Virtual Account (Bank Transfer)",
|
|
5268
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5269
|
+
totalFee: "IDR 4,000",
|
|
5270
|
+
category: "Virtual Account"
|
|
5271
|
+
},
|
|
5272
|
+
{
|
|
5273
|
+
paymentMethod: "bri_va",
|
|
5274
|
+
code: "bri_va",
|
|
5275
|
+
paymentName: "BRI Virtual Account (Bank Transfer)",
|
|
5276
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5277
|
+
totalFee: "IDR 4,000",
|
|
5278
|
+
category: "Virtual Account"
|
|
5279
|
+
},
|
|
5280
|
+
{
|
|
5281
|
+
paymentMethod: "permata_va",
|
|
5282
|
+
code: "permata_va",
|
|
5283
|
+
paymentName: "Permata Virtual Account (Bank Transfer)",
|
|
5284
|
+
paymentImage: "https://stripe.com/img/v3/home/social.png",
|
|
5285
|
+
totalFee: "IDR 4,000",
|
|
5286
|
+
category: "Virtual Account"
|
|
5287
|
+
}
|
|
5288
|
+
];
|
|
5289
|
+
const categories = {};
|
|
5290
|
+
for (const item of staticMethods) {
|
|
5291
|
+
if (!categories[item.category]) {
|
|
5292
|
+
categories[item.category] = [];
|
|
5293
|
+
}
|
|
5294
|
+
categories[item.category].push(item);
|
|
5295
|
+
}
|
|
5296
|
+
return {
|
|
5297
|
+
success: true,
|
|
5298
|
+
provider: "stripe",
|
|
5299
|
+
methods: staticMethods,
|
|
5300
|
+
categories,
|
|
5301
|
+
rawResponse: staticMethods
|
|
5302
|
+
};
|
|
5303
|
+
}
|
|
5304
|
+
async checkTransaction(params, config) {
|
|
5305
|
+
const { merchantOrderId } = params;
|
|
5306
|
+
const secretKey = config.apiKey || config.serverKey || config.secretKey || "";
|
|
5307
|
+
const baseUrl = this.getBaseUrl();
|
|
5308
|
+
let endpoint = `/checkout/sessions/${encodeURIComponent(merchantOrderId)}`;
|
|
5309
|
+
if (merchantOrderId.startsWith("pi_")) {
|
|
5310
|
+
endpoint = `/payment_intents/${encodeURIComponent(merchantOrderId)}`;
|
|
5311
|
+
}
|
|
5312
|
+
const url = `${baseUrl}${endpoint}`;
|
|
5313
|
+
const headers = {
|
|
5314
|
+
"Authorization": `Bearer ${secretKey}`,
|
|
5315
|
+
"Accept": "application/json"
|
|
5316
|
+
};
|
|
5317
|
+
try {
|
|
5318
|
+
const response = await fetch(url, {
|
|
5319
|
+
method: "GET",
|
|
5320
|
+
headers
|
|
5321
|
+
});
|
|
5322
|
+
const text = await response.text();
|
|
5323
|
+
let data = null;
|
|
5324
|
+
try {
|
|
5325
|
+
data = JSON.parse(text);
|
|
5326
|
+
} catch (e) {
|
|
5327
|
+
}
|
|
5328
|
+
if (!response.ok || !data || data.error) {
|
|
5329
|
+
return {
|
|
5330
|
+
success: false,
|
|
5331
|
+
provider: "stripe",
|
|
5332
|
+
orderId: merchantOrderId,
|
|
5333
|
+
reference: "",
|
|
5334
|
+
amount: 0,
|
|
5335
|
+
statusCode: response.status.toString(),
|
|
5336
|
+
status: "failed",
|
|
5337
|
+
isPaid: false,
|
|
5338
|
+
isPending: false,
|
|
5339
|
+
isFailed: true,
|
|
5340
|
+
isExpired: false,
|
|
5341
|
+
statusMessage: data?.error?.message || `HTTP error! Status: ${response.status}`,
|
|
5342
|
+
error: data?.error?.message || `HTTP error! Status: ${response.status}`,
|
|
5343
|
+
rawResponse: data
|
|
5344
|
+
};
|
|
5345
|
+
}
|
|
5346
|
+
const paymentStatus = (data.payment_status || data.status || "").toLowerCase();
|
|
5347
|
+
const isPaid = paymentStatus === "paid" || paymentStatus === "succeeded" || paymentStatus === "complete";
|
|
5348
|
+
const isPending = paymentStatus === "unpaid" || paymentStatus === "processing" || paymentStatus === "requires_action";
|
|
5349
|
+
const isExpired = paymentStatus === "expired";
|
|
5350
|
+
const isFailed = !isPaid && !isPending && !isExpired;
|
|
5351
|
+
const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
|
|
5352
|
+
return {
|
|
5353
|
+
success: true,
|
|
5354
|
+
provider: "stripe",
|
|
5355
|
+
orderId: data.metadata?.order_id || data.client_reference_id || data.id || merchantOrderId,
|
|
5356
|
+
reference: data.id || "",
|
|
5357
|
+
amount: data.amount_total ? Number(data.amount_total) : data.amount ? Number(data.amount) : 0,
|
|
5358
|
+
statusCode: paymentStatus,
|
|
5359
|
+
status,
|
|
5360
|
+
isPaid,
|
|
5361
|
+
isPending,
|
|
5362
|
+
isFailed,
|
|
5363
|
+
isExpired,
|
|
5364
|
+
statusMessage: paymentStatus,
|
|
5365
|
+
paymentType: data.payment_method_types?.[0] || "card",
|
|
5366
|
+
transactionTime: data.created ? new Date(data.created * 1e3) : void 0,
|
|
5367
|
+
rawResponse: data
|
|
5368
|
+
};
|
|
5369
|
+
} catch (e) {
|
|
5370
|
+
return {
|
|
5371
|
+
success: false,
|
|
5372
|
+
provider: "stripe",
|
|
5373
|
+
orderId: merchantOrderId,
|
|
5374
|
+
reference: "",
|
|
5375
|
+
amount: 0,
|
|
5376
|
+
statusCode: "ERROR",
|
|
5377
|
+
status: "failed",
|
|
5378
|
+
isPaid: false,
|
|
5379
|
+
isPending: false,
|
|
5380
|
+
isFailed: true,
|
|
5381
|
+
isExpired: false,
|
|
5382
|
+
statusMessage: e.message || "Failed to check transaction status in Stripe",
|
|
5383
|
+
error: e.message || "Failed to check transaction status in Stripe",
|
|
5384
|
+
rawResponse: null
|
|
5385
|
+
};
|
|
5386
|
+
}
|
|
5387
|
+
}
|
|
5388
|
+
};
|
|
5389
|
+
|
|
5003
5390
|
// src/clients/duitku.ts
|
|
5004
5391
|
var DuitkuClient = class {
|
|
5005
5392
|
merchantCode;
|
|
@@ -5695,6 +6082,76 @@ var OyClient = class {
|
|
|
5695
6082
|
}
|
|
5696
6083
|
};
|
|
5697
6084
|
|
|
6085
|
+
// src/clients/stripe.ts
|
|
6086
|
+
var StripeClient = class {
|
|
6087
|
+
secretKey;
|
|
6088
|
+
constructor(config) {
|
|
6089
|
+
this.secretKey = config.apiKey || config.serverKey || config.secretKey || "";
|
|
6090
|
+
}
|
|
6091
|
+
getBaseUrl() {
|
|
6092
|
+
return "https://api.stripe.com/v1";
|
|
6093
|
+
}
|
|
6094
|
+
/**
|
|
6095
|
+
* Helper HTTP Request ke Stripe API
|
|
6096
|
+
*/
|
|
6097
|
+
async request(method, endpoint, body) {
|
|
6098
|
+
const url = `${this.getBaseUrl()}${endpoint}`;
|
|
6099
|
+
const headers = {
|
|
6100
|
+
"Authorization": `Bearer ${this.secretKey}`,
|
|
6101
|
+
"Accept": "application/json"
|
|
6102
|
+
};
|
|
6103
|
+
const fetchOptions = {
|
|
6104
|
+
method,
|
|
6105
|
+
headers
|
|
6106
|
+
};
|
|
6107
|
+
if (method === "POST" && body) {
|
|
6108
|
+
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
6109
|
+
fetchOptions.body = serializeStripeParams(body);
|
|
6110
|
+
}
|
|
6111
|
+
const response = await fetch(url, fetchOptions);
|
|
6112
|
+
const text = await response.text();
|
|
6113
|
+
let data = null;
|
|
6114
|
+
try {
|
|
6115
|
+
data = JSON.parse(text);
|
|
6116
|
+
} catch (e) {
|
|
6117
|
+
}
|
|
6118
|
+
if (!response.ok || data?.error) {
|
|
6119
|
+
throw new Error(data?.error?.message || `HTTP error! Status: ${response.status} - ${text}`);
|
|
6120
|
+
}
|
|
6121
|
+
return data;
|
|
6122
|
+
}
|
|
6123
|
+
/**
|
|
6124
|
+
* Ambil detail Checkout Session
|
|
6125
|
+
*/
|
|
6126
|
+
async retrieveCheckoutSession(sessionId) {
|
|
6127
|
+
return this.request("GET", `/checkout/sessions/${encodeURIComponent(sessionId)}`);
|
|
6128
|
+
}
|
|
6129
|
+
/**
|
|
6130
|
+
* Ambil detail Payment Intent
|
|
6131
|
+
*/
|
|
6132
|
+
async retrievePaymentIntent(paymentIntentId) {
|
|
6133
|
+
return this.request("GET", `/payment_intents/${encodeURIComponent(paymentIntentId)}`);
|
|
6134
|
+
}
|
|
6135
|
+
/**
|
|
6136
|
+
* Cek saldo akun Stripe (Balance)
|
|
6137
|
+
*/
|
|
6138
|
+
async checkBalance() {
|
|
6139
|
+
return this.request("GET", "/balance");
|
|
6140
|
+
}
|
|
6141
|
+
/**
|
|
6142
|
+
* Buat refund dana
|
|
6143
|
+
*/
|
|
6144
|
+
async createRefund(paymentIntentId, amount) {
|
|
6145
|
+
const payload = {
|
|
6146
|
+
payment_intent: paymentIntentId
|
|
6147
|
+
};
|
|
6148
|
+
if (amount) {
|
|
6149
|
+
payload.amount = Math.round(amount);
|
|
6150
|
+
}
|
|
6151
|
+
return this.request("POST", "/refunds", payload);
|
|
6152
|
+
}
|
|
6153
|
+
};
|
|
6154
|
+
|
|
5698
6155
|
// src/core/manager.ts
|
|
5699
6156
|
var PaymentManager = class {
|
|
5700
6157
|
providers = /* @__PURE__ */ new Map();
|
|
@@ -5709,6 +6166,7 @@ var PaymentManager = class {
|
|
|
5709
6166
|
this.registerProvider(new FinpayProvider());
|
|
5710
6167
|
this.registerProvider(new NicepayProvider());
|
|
5711
6168
|
this.registerProvider(new OyProvider());
|
|
6169
|
+
this.registerProvider(new StripeProvider());
|
|
5712
6170
|
}
|
|
5713
6171
|
registerProvider(provider) {
|
|
5714
6172
|
this.providers.set(provider.name.toLowerCase(), provider);
|
|
@@ -5780,6 +6238,12 @@ var PaymentManager = class {
|
|
|
5780
6238
|
getOyClient(config) {
|
|
5781
6239
|
return new OyClient(config);
|
|
5782
6240
|
}
|
|
6241
|
+
getStripeProvider() {
|
|
6242
|
+
return this.getProvider("stripe");
|
|
6243
|
+
}
|
|
6244
|
+
getStripeClient(config) {
|
|
6245
|
+
return new StripeClient(config);
|
|
6246
|
+
}
|
|
5783
6247
|
async createInvoice(providerName, params, config) {
|
|
5784
6248
|
const provider = this.getProvider(providerName);
|
|
5785
6249
|
return provider.createInvoice(params, config);
|
|
@@ -5837,6 +6301,8 @@ function resolveConfigFromEnv(customConfig) {
|
|
|
5837
6301
|
sandbox = env.NICEPAY_SANDBOX === "true" || env.NICEPAY_SANDBOX === "1";
|
|
5838
6302
|
} else if (env.OY_SANDBOX !== void 0) {
|
|
5839
6303
|
sandbox = env.OY_SANDBOX === "true" || env.OY_SANDBOX === "1";
|
|
6304
|
+
} else if (env.STRIPE_SANDBOX !== void 0) {
|
|
6305
|
+
sandbox = env.STRIPE_SANDBOX === "true" || env.STRIPE_SANDBOX === "1";
|
|
5840
6306
|
} else {
|
|
5841
6307
|
sandbox = env.NODE_ENV !== "production";
|
|
5842
6308
|
}
|
|
@@ -5862,6 +6328,8 @@ function resolveConfigFromEnv(customConfig) {
|
|
|
5862
6328
|
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
6329
|
} else if (provider === "oy" || provider === "oyindonesia") {
|
|
5864
6330
|
apiKey = env.OY_API_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
|
|
6331
|
+
} else if (provider === "stripe") {
|
|
6332
|
+
apiKey = env.STRIPE_SECRET_KEY || env.STRIPE_KEY || env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY;
|
|
5865
6333
|
} else {
|
|
5866
6334
|
apiKey = env.BUAYAR_API_KEY || env.PG_API_KEY || env.PAYMENT_API_KEY || env.PG_SECRET_KEY || env.BUAYAR_SECRET_KEY;
|
|
5867
6335
|
}
|
|
@@ -5896,17 +6364,21 @@ function resolveConfigFromEnv(customConfig) {
|
|
|
5896
6364
|
} else if (provider === "oy" || provider === "oyindonesia") {
|
|
5897
6365
|
merchantCode = merchantCode || env.OY_USERNAME || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
|
|
5898
6366
|
clientKey = clientKey || env.OY_USERNAME || env.BUAYAR_CLIENT_KEY;
|
|
6367
|
+
} else if (provider === "stripe") {
|
|
6368
|
+
clientKey = clientKey || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY || env.BUAYAR_CLIENT_KEY || env.BUAYAR_PUBLIC_KEY;
|
|
6369
|
+
merchantCode = merchantCode || clientKey || "stripe";
|
|
5899
6370
|
} else {
|
|
5900
6371
|
merchantCode = merchantCode || env.BUAYAR_MERCHANT_CODE || env.PG_MERCHANT_CODE || env.PAYMENT_MERCHANT_CODE;
|
|
5901
6372
|
}
|
|
5902
6373
|
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;
|
|
6374
|
+
const publicKey = customConfig?.publicKey || env.BUAYAR_PUBLIC_KEY || env.PG_PUBLIC_KEY || env.PUBLIC_KEY || env.STRIPE_PUBLIC_KEY || env.STRIPE_PUBLISHABLE_KEY;
|
|
5904
6375
|
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;
|
|
6376
|
+
const secretKey = customConfig?.secretKey || env.BUAYAR_SECRET_KEY || env.PG_SECRET_KEY || env.SECRET_KEY || env.XENDIT_SECRET_KEY || env.DOKU_SECRET_KEY || env.PRISMALINK_SECRET_KEY || env.FASPAY_PASSWORD || env.FINPAY_MERCHANT_KEY || env.NICEPAY_KEY || env.OY_API_KEY || env.STRIPE_SECRET_KEY;
|
|
5906
6377
|
const callbackUrl = customConfig?.callbackUrl || env.BUAYAR_CALLBACK_URL || env.PG_CALLBACK_URL || env.PAYMENT_CALLBACK_URL;
|
|
5907
6378
|
const returnUrl = customConfig?.returnUrl || env.BUAYAR_RETURN_URL || env.PG_RETURN_URL || env.PAYMENT_RETURN_URL;
|
|
5908
6379
|
const extra = {
|
|
5909
6380
|
webhookToken: env.XENDIT_WEBHOOK_TOKEN || env.BUAYAR_WEBHOOK_TOKEN,
|
|
6381
|
+
webhookSecret: env.STRIPE_WEBHOOK_SECRET || env.BUAYAR_WEBHOOK_SECRET,
|
|
5910
6382
|
merchantName: env.FASPAY_MERCHANT_NAME || env.BUAYAR_MERCHANT_NAME,
|
|
5911
6383
|
userId: env.FASPAY_USER_ID,
|
|
5912
6384
|
iMid: env.NICEPAY_IMID,
|
|
@@ -5952,7 +6424,7 @@ var Buayar = class {
|
|
|
5952
6424
|
this.config = resolveConfigFromEnv({ ...this.config, ...config });
|
|
5953
6425
|
}
|
|
5954
6426
|
/**
|
|
5955
|
-
* Dapatkan nama provider aktif ('midtrans' | 'duitku' | 'ipaymu' | 'xendit' | 'doku' | 'prismalink' | 'faspay' | 'finpay' | 'nicepay' | 'oy' | ...)
|
|
6427
|
+
* Dapatkan nama provider aktif ('midtrans' | 'duitku' | 'ipaymu' | 'xendit' | 'doku' | 'prismalink' | 'faspay' | 'finpay' | 'nicepay' | 'oy' | 'stripe' | ...)
|
|
5956
6428
|
*/
|
|
5957
6429
|
get provider() {
|
|
5958
6430
|
return this.config.provider || "midtrans";
|
|
@@ -6000,6 +6472,13 @@ var Buayar = class {
|
|
|
6000
6472
|
*/
|
|
6001
6473
|
async verifyWebhook(payload, headers, configOverride) {
|
|
6002
6474
|
const mergedConfig = { ...this.config, ...configOverride };
|
|
6475
|
+
if (headers) {
|
|
6476
|
+
const sigHeader = headers["stripe-signature"] || headers["Stripe-Signature"];
|
|
6477
|
+
if (sigHeader) {
|
|
6478
|
+
if (!mergedConfig.extra) mergedConfig.extra = {};
|
|
6479
|
+
mergedConfig.extra.signatureHeader = Array.isArray(sigHeader) ? sigHeader[0] : sigHeader;
|
|
6480
|
+
}
|
|
6481
|
+
}
|
|
6003
6482
|
let providerName = configOverride?.provider || this.provider;
|
|
6004
6483
|
if (payload) {
|
|
6005
6484
|
if (payload.signature_key && payload.transaction_status) {
|
|
@@ -6020,6 +6499,8 @@ var Buayar = class {
|
|
|
6020
6499
|
providerName = "oy";
|
|
6021
6500
|
} else if (payload.merchant_id && payload.order_id && payload.signature) {
|
|
6022
6501
|
providerName = "prismalink";
|
|
6502
|
+
} else if (payload.object === "event" || payload.type && payload.data?.object && payload.api_version) {
|
|
6503
|
+
providerName = "stripe";
|
|
6023
6504
|
} else if (payload.external_id || payload.event?.startsWith("payment.") || payload.event?.startsWith("qr.") || payload.data?.reference_id) {
|
|
6024
6505
|
providerName = "xendit";
|
|
6025
6506
|
}
|
|
@@ -6089,6 +6570,12 @@ var Buayar = class {
|
|
|
6089
6570
|
...configOverride
|
|
6090
6571
|
});
|
|
6091
6572
|
}
|
|
6573
|
+
getStripeClient(configOverride) {
|
|
6574
|
+
return new StripeClient({
|
|
6575
|
+
...this.config,
|
|
6576
|
+
...configOverride
|
|
6577
|
+
});
|
|
6578
|
+
}
|
|
6092
6579
|
};
|
|
6093
6580
|
var buayar = new Buayar();
|
|
6094
6581
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -6104,6 +6591,7 @@ var buayar = new Buayar();
|
|
|
6104
6591
|
CANONICAL_TO_NICEPAY,
|
|
6105
6592
|
CANONICAL_TO_OY,
|
|
6106
6593
|
CANONICAL_TO_PRISMALINK,
|
|
6594
|
+
CANONICAL_TO_STRIPE,
|
|
6107
6595
|
CANONICAL_TO_XENDIT,
|
|
6108
6596
|
CORE_API_METHODS,
|
|
6109
6597
|
DUITKU_TO_CANONICAL,
|
|
@@ -6128,6 +6616,8 @@ var buayar = new Buayar();
|
|
|
6128
6616
|
PaymentManager,
|
|
6129
6617
|
PrismalinkClient,
|
|
6130
6618
|
PrismalinkProvider,
|
|
6619
|
+
StripeClient,
|
|
6620
|
+
StripeProvider,
|
|
6131
6621
|
XenditClient,
|
|
6132
6622
|
XenditProvider,
|
|
6133
6623
|
buayar,
|
|
@@ -6151,6 +6641,7 @@ var buayar = new Buayar();
|
|
|
6151
6641
|
paymentManager,
|
|
6152
6642
|
resolveConfigFromEnv,
|
|
6153
6643
|
safeCompare,
|
|
6644
|
+
serializeStripeParams,
|
|
6154
6645
|
sha256,
|
|
6155
6646
|
sha512,
|
|
6156
6647
|
toCanonicalPaymentMethod,
|
|
@@ -6162,6 +6653,7 @@ var buayar = new Buayar();
|
|
|
6162
6653
|
toNicepayPaymentMethod,
|
|
6163
6654
|
toOyPaymentMethod,
|
|
6164
6655
|
toPrismalinkPaymentMethod,
|
|
6656
|
+
toStripePaymentMethod,
|
|
6165
6657
|
toXenditPaymentMethod,
|
|
6166
6658
|
verifyDokuWebhookSignature,
|
|
6167
6659
|
verifyDuitkuCallbackSignature,
|
|
@@ -6171,5 +6663,6 @@ var buayar = new Buayar();
|
|
|
6171
6663
|
verifyNicepayWebhook,
|
|
6172
6664
|
verifyOyWebhook,
|
|
6173
6665
|
verifyPrismalinkSignature,
|
|
6666
|
+
verifyStripeWebhook,
|
|
6174
6667
|
verifyXenditWebhookToken
|
|
6175
6668
|
});
|