@crediblemark/buayar 0.5.1 → 0.6.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.d.mts +131 -1
- package/dist/index.d.ts +131 -1
- package/dist/index.js +509 -25
- package/dist/index.mjs +484 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ __export(index_exports, {
|
|
|
78
78
|
PrismalinkProvider: () => PrismalinkProvider,
|
|
79
79
|
RazorpayClient: () => RazorpayClient,
|
|
80
80
|
RazorpayProvider: () => RazorpayProvider,
|
|
81
|
+
SnapClient: () => SnapClient,
|
|
81
82
|
SquareClient: () => SquareClient,
|
|
82
83
|
SquareProvider: () => SquareProvider,
|
|
83
84
|
StripeClient: () => StripeClient,
|
|
@@ -101,6 +102,8 @@ __export(index_exports, {
|
|
|
101
102
|
generateNicepayToken: () => generateNicepayToken,
|
|
102
103
|
generateOyHeaders: () => generateOyHeaders,
|
|
103
104
|
generatePrismalinkSignature: () => generatePrismalinkSignature,
|
|
105
|
+
generateSnapAsymmetricSignature: () => generateSnapAsymmetricSignature,
|
|
106
|
+
generateSnapSymmetricSignature: () => generateSnapSymmetricSignature,
|
|
104
107
|
getDuitkuInquirySignatures: () => getDuitkuInquirySignatures,
|
|
105
108
|
getDuitkuPaymentMethodsSignature: () => getDuitkuPaymentMethodsSignature,
|
|
106
109
|
getDuitkuStatusSignatures: () => getDuitkuStatusSignatures,
|
|
@@ -108,6 +111,7 @@ __export(index_exports, {
|
|
|
108
111
|
getXenditAuthHeader: () => getXenditAuthHeader,
|
|
109
112
|
hmacSha256: () => hmacSha256,
|
|
110
113
|
md5: () => md5,
|
|
114
|
+
minifyJson: () => minifyJson,
|
|
111
115
|
parseCoreChargeResponse: () => parseCoreChargeResponse,
|
|
112
116
|
paymentManager: () => paymentManager,
|
|
113
117
|
resolveConfigFromEnv: () => resolveConfigFromEnv,
|
|
@@ -115,7 +119,10 @@ __export(index_exports, {
|
|
|
115
119
|
serializePaypalParams: () => serializePaypalParams,
|
|
116
120
|
serializeStripeParams: () => serializeStripeParams,
|
|
117
121
|
sha256: () => sha256,
|
|
122
|
+
sha256Hex: () => sha256Hex,
|
|
118
123
|
sha512: () => sha512,
|
|
124
|
+
snapExternalId: () => snapExternalId,
|
|
125
|
+
snapTimestamp: () => snapTimestamp,
|
|
119
126
|
toCanonicalPaymentMethod: () => toCanonicalPaymentMethod,
|
|
120
127
|
toDokuPaymentMethod: () => toDokuPaymentMethod,
|
|
121
128
|
toDuitkuPaymentMethod: () => toDuitkuPaymentMethod,
|
|
@@ -141,6 +148,7 @@ __export(index_exports, {
|
|
|
141
148
|
verifyPayuWebhook: () => verifyPayuWebhook,
|
|
142
149
|
verifyPrismalinkSignature: () => verifyPrismalinkSignature,
|
|
143
150
|
verifyRazorpayWebhook: () => verifyRazorpayWebhook,
|
|
151
|
+
verifySnapWebhookSignature: () => verifySnapWebhookSignature,
|
|
144
152
|
verifySquareWebhook: () => verifySquareWebhook,
|
|
145
153
|
verifyStripeWebhook: () => verifyStripeWebhook,
|
|
146
154
|
verifyTwoCheckoutWebhook: () => verifyTwoCheckoutWebhook,
|
|
@@ -2563,12 +2571,218 @@ Digest:${digest}`;
|
|
|
2563
2571
|
return safeCompare(incomingSignature, expectedSignature);
|
|
2564
2572
|
}
|
|
2565
2573
|
|
|
2574
|
+
// src/providers/doku/snap.ts
|
|
2575
|
+
var import_crypto8 = __toESM(require("crypto"));
|
|
2576
|
+
function snapTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
2577
|
+
const wib = new Date(date.getTime() + 7 * 60 * 60 * 1e3);
|
|
2578
|
+
return wib.toISOString().slice(0, 19) + "+07:00";
|
|
2579
|
+
}
|
|
2580
|
+
function minifyJson(obj) {
|
|
2581
|
+
return JSON.stringify(obj);
|
|
2582
|
+
}
|
|
2583
|
+
function sha256Hex(body) {
|
|
2584
|
+
const raw = typeof body === "string" ? body : minifyJson(body);
|
|
2585
|
+
return import_crypto8.default.createHash("sha256").update(raw).digest("hex").toLowerCase();
|
|
2586
|
+
}
|
|
2587
|
+
function generateSnapSymmetricSignature(clientSecret, method, endpointUrl, accessToken, body, timestamp) {
|
|
2588
|
+
const hash = sha256Hex(body);
|
|
2589
|
+
const stringToSign = `${method}:${endpointUrl}:${accessToken}:${hash}:${timestamp}`;
|
|
2590
|
+
return import_crypto8.default.createHmac("sha512", clientSecret).update(stringToSign).digest("base64");
|
|
2591
|
+
}
|
|
2592
|
+
function generateSnapAsymmetricSignature(privateKey, clientId, timestamp) {
|
|
2593
|
+
const stringToSign = `${clientId}|${timestamp}`;
|
|
2594
|
+
const key = import_crypto8.default.createPrivateKey(normalizePem(privateKey));
|
|
2595
|
+
return import_crypto8.default.sign("RSA-SHA256", Buffer.from(stringToSign, "utf8"), key).toString("base64");
|
|
2596
|
+
}
|
|
2597
|
+
function normalizePem(key) {
|
|
2598
|
+
const trimmed = key.trim();
|
|
2599
|
+
if (trimmed.includes("-----BEGIN")) {
|
|
2600
|
+
return trimmed;
|
|
2601
|
+
}
|
|
2602
|
+
return [
|
|
2603
|
+
"-----BEGIN PRIVATE KEY-----",
|
|
2604
|
+
trimmed.replace(/\s+/g, "").match(/.{1,64}/g)?.join("\n") || trimmed,
|
|
2605
|
+
"-----END PRIVATE KEY-----"
|
|
2606
|
+
].join("\n");
|
|
2607
|
+
}
|
|
2608
|
+
function snapExternalId(prefix = "") {
|
|
2609
|
+
return `${prefix}${Date.now()}${Math.floor(Math.random() * 1e3)}`;
|
|
2610
|
+
}
|
|
2611
|
+
function verifySnapWebhookSignature(headers, body, clientSecret, endpointUrl = "/api/payment/webhook") {
|
|
2612
|
+
if (!clientSecret) return false;
|
|
2613
|
+
const incoming = headers["x-signature"] || headers["X-SIGNATURE"] || headers["signature"] || headers["Signature"] || "";
|
|
2614
|
+
if (!incoming) return false;
|
|
2615
|
+
const timestamp = headers["x-timestamp"] || headers["X-TIMESTAMP"] || headers["timestamp"] || headers["Timestamp"] || snapTimestamp();
|
|
2616
|
+
const computed = generateSnapSymmetricSignature(
|
|
2617
|
+
clientSecret,
|
|
2618
|
+
"POST",
|
|
2619
|
+
endpointUrl,
|
|
2620
|
+
"",
|
|
2621
|
+
body,
|
|
2622
|
+
timestamp
|
|
2623
|
+
);
|
|
2624
|
+
return safeCompare(incoming, computed);
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
// src/clients/snap.ts
|
|
2628
|
+
var SnapClient = class {
|
|
2629
|
+
options;
|
|
2630
|
+
token = null;
|
|
2631
|
+
tokenExpiry = 0;
|
|
2632
|
+
constructor(options) {
|
|
2633
|
+
this.options = {
|
|
2634
|
+
clientId: options.clientId || options.merchantCode || "",
|
|
2635
|
+
clientSecret: options.clientSecret || options.apiKey || options.serverKey || options.secretKey || "",
|
|
2636
|
+
privateKey: options.privateKey,
|
|
2637
|
+
sandbox: !!options.sandbox,
|
|
2638
|
+
merchantId: options.merchantId,
|
|
2639
|
+
terminalId: options.terminalId,
|
|
2640
|
+
partnerServiceId: options.partnerServiceId,
|
|
2641
|
+
channelId: options.channelId || "H2H"
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
get baseUrl() {
|
|
2645
|
+
return this.options.sandbox ? "https://api-sandbox.doku.com" : "https://api.doku.com";
|
|
2646
|
+
}
|
|
2647
|
+
get isConfigured() {
|
|
2648
|
+
return Boolean(this.options.clientId && this.options.clientSecret);
|
|
2649
|
+
}
|
|
2650
|
+
/**
|
|
2651
|
+
* Get (cached) B2B access token. Mints a new one when expired.
|
|
2652
|
+
*/
|
|
2653
|
+
async getAccessToken() {
|
|
2654
|
+
const now = Date.now();
|
|
2655
|
+
if (this.token && now < this.tokenExpiry) {
|
|
2656
|
+
return this.token;
|
|
2657
|
+
}
|
|
2658
|
+
const { clientId, clientSecret, privateKey } = this.options;
|
|
2659
|
+
if (!privateKey) {
|
|
2660
|
+
throw new Error("DOKU SNAP: RSA privateKey required to obtain B2B access token");
|
|
2661
|
+
}
|
|
2662
|
+
const endpoint = "/authorization/v1/access-token/b2b";
|
|
2663
|
+
const timestamp = snapTimestamp();
|
|
2664
|
+
const signature = generateSnapAsymmetricSignature(privateKey, clientId, timestamp);
|
|
2665
|
+
const response = await fetch(this.baseUrl + endpoint, {
|
|
2666
|
+
method: "POST",
|
|
2667
|
+
headers: {
|
|
2668
|
+
"Content-Type": "application/json",
|
|
2669
|
+
"X-CLIENT-KEY": clientId,
|
|
2670
|
+
"X-TIMESTAMP": timestamp,
|
|
2671
|
+
"X-SIGNATURE": signature
|
|
2672
|
+
},
|
|
2673
|
+
body: JSON.stringify({ grantType: "client_credentials" })
|
|
2674
|
+
});
|
|
2675
|
+
const text = await response.text();
|
|
2676
|
+
let data = null;
|
|
2677
|
+
try {
|
|
2678
|
+
data = JSON.parse(text);
|
|
2679
|
+
} catch {
|
|
2680
|
+
}
|
|
2681
|
+
if (!response.ok || !data?.accessToken) {
|
|
2682
|
+
throw new Error(data?.responseMessage || data?.message || `DOKU SNAP get-token failed: HTTP ${response.status} - ${text}`);
|
|
2683
|
+
}
|
|
2684
|
+
if (!clientSecret) {
|
|
2685
|
+
}
|
|
2686
|
+
this.token = data.accessToken;
|
|
2687
|
+
const expiresIn = Number(data.expiresIn || 900);
|
|
2688
|
+
this.tokenExpiry = now + (expiresIn - 30) * 1e3;
|
|
2689
|
+
return this.token;
|
|
2690
|
+
}
|
|
2691
|
+
clearToken() {
|
|
2692
|
+
this.token = null;
|
|
2693
|
+
this.tokenExpiry = 0;
|
|
2694
|
+
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Perform a signed SNAP transaction request.
|
|
2697
|
+
* @param method GET/POST
|
|
2698
|
+
* @param endpoint request-target path (e.g. /virtual-accounts/...)
|
|
2699
|
+
* @param body request body (object)
|
|
2700
|
+
* @param opts extra headers (X-DEVICE-ID, X-IP-ADDRESS, etc.)
|
|
2701
|
+
*/
|
|
2702
|
+
async request(method, endpoint, body, opts = {}) {
|
|
2703
|
+
const { clientId, clientSecret, channelId } = this.options;
|
|
2704
|
+
if (!clientSecret) {
|
|
2705
|
+
throw new Error("DOKU SNAP: clientSecret (Secret Key) required for transaction signing");
|
|
2706
|
+
}
|
|
2707
|
+
const accessToken = await this.getAccessToken();
|
|
2708
|
+
const timestamp = snapTimestamp();
|
|
2709
|
+
const externalId = opts.externalId || snapExternalId();
|
|
2710
|
+
const payload = body === void 0 ? "" : body;
|
|
2711
|
+
const signature = generateSnapSymmetricSignature(
|
|
2712
|
+
clientSecret,
|
|
2713
|
+
method,
|
|
2714
|
+
endpoint,
|
|
2715
|
+
accessToken,
|
|
2716
|
+
payload,
|
|
2717
|
+
timestamp
|
|
2718
|
+
);
|
|
2719
|
+
const headers = {
|
|
2720
|
+
"Content-Type": "application/json",
|
|
2721
|
+
"X-PARTNER-ID": clientId,
|
|
2722
|
+
"X-EXTERNAL-ID": externalId,
|
|
2723
|
+
"X-TIMESTAMP": timestamp,
|
|
2724
|
+
"X-SIGNATURE": signature,
|
|
2725
|
+
"CHANNEL-ID": channelId || "H2H",
|
|
2726
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
2727
|
+
...opts.deviceId ? { "X-DEVICE-ID": opts.deviceId } : {},
|
|
2728
|
+
...opts.ipAddress ? { "X-IP-ADDRESS": opts.ipAddress } : {},
|
|
2729
|
+
...opts.extraHeaders || {}
|
|
2730
|
+
};
|
|
2731
|
+
const response = await fetch(this.baseUrl + endpoint, {
|
|
2732
|
+
method,
|
|
2733
|
+
headers,
|
|
2734
|
+
body: method === "POST" && body !== void 0 ? JSON.stringify(body) : void 0
|
|
2735
|
+
});
|
|
2736
|
+
const text = await response.text();
|
|
2737
|
+
let data = null;
|
|
2738
|
+
try {
|
|
2739
|
+
data = JSON.parse(text);
|
|
2740
|
+
} catch {
|
|
2741
|
+
}
|
|
2742
|
+
if (!response.ok) {
|
|
2743
|
+
const err = data?.responseMessage || data?.error?.message || data?.message || `HTTP ${response.status}`;
|
|
2744
|
+
throw new Error(`${err}${data?.responseCode ? ` (${data.responseCode})` : ""}`);
|
|
2745
|
+
}
|
|
2746
|
+
return data;
|
|
2747
|
+
}
|
|
2748
|
+
};
|
|
2749
|
+
|
|
2566
2750
|
// src/providers/doku/provider.ts
|
|
2567
2751
|
var DokuProvider = class extends BasePaymentProvider {
|
|
2568
2752
|
name = "doku";
|
|
2569
2753
|
getBaseUrl(sandbox) {
|
|
2570
2754
|
return sandbox ? "https://api-sandbox.doku.com" : "https://api.doku.com";
|
|
2571
2755
|
}
|
|
2756
|
+
/**
|
|
2757
|
+
* DETEKSI mode integrasi DOKU:
|
|
2758
|
+
* - SNAP : kredensial baru (Client ID `doku_...` + Secret Key `SK-...`) + opsional RSA privateKey
|
|
2759
|
+
* untuk Get Token B2B. Diaktifkan via extra.snap / extra.dokuMode="snap" / doku_ prefix.
|
|
2760
|
+
* - Legacy: Jokul v2 (Client-Id + Signature HMAC-SHA256), default jika bukan SNAP.
|
|
2761
|
+
*/
|
|
2762
|
+
isSnap(config) {
|
|
2763
|
+
if (config.extra?.snap === true || config.extra?.snap === "true") return true;
|
|
2764
|
+
if (config.extra?.dokuMode === "snap") return true;
|
|
2765
|
+
const clientId = String(config.merchantCode || config.merchantId || config.clientKey || "").trim().toLowerCase();
|
|
2766
|
+
return /^doku[_:-]/.test(clientId);
|
|
2767
|
+
}
|
|
2768
|
+
buildSnap(config) {
|
|
2769
|
+
const clientId = config.merchantCode || config.merchantId || config.clientKey || "";
|
|
2770
|
+
const clientSecret = config.apiKey || config.serverKey || config.secretKey || "";
|
|
2771
|
+
return new SnapClient({
|
|
2772
|
+
clientId,
|
|
2773
|
+
clientSecret,
|
|
2774
|
+
privateKey: config.privateKey,
|
|
2775
|
+
sandbox: !!config.sandbox,
|
|
2776
|
+
merchantId: config.extra?.merchantId || config.projectId || "",
|
|
2777
|
+
terminalId: config.extra?.terminalId || "",
|
|
2778
|
+
partnerServiceId: config.extra?.partnerServiceId || "",
|
|
2779
|
+
channelId: config.extra?.channelId || "H2H"
|
|
2780
|
+
});
|
|
2781
|
+
}
|
|
2782
|
+
/** Helper: jumlah integer → format SNAP 2-desimal (".00"). */
|
|
2783
|
+
snapAmount(amount, currency = "IDR") {
|
|
2784
|
+
return { value: amount.toFixed(2), currency };
|
|
2785
|
+
}
|
|
2572
2786
|
async createInvoice(params, config) {
|
|
2573
2787
|
const { orderId, amount, productDetails, customer, returnUrl } = params;
|
|
2574
2788
|
const clientId = config.merchantCode || config.merchantId || config.clientKey || "";
|
|
@@ -2579,6 +2793,9 @@ var DokuProvider = class extends BasePaymentProvider {
|
|
|
2579
2793
|
const isDirect = !!dokuMethod;
|
|
2580
2794
|
const baseUrl = this.getBaseUrl(sandbox);
|
|
2581
2795
|
try {
|
|
2796
|
+
if (this.isSnap(config)) {
|
|
2797
|
+
return await this.createSnapInvoice(params, config, baseUrl);
|
|
2798
|
+
}
|
|
2582
2799
|
if (isDirect) {
|
|
2583
2800
|
const endpoint = dokuMethod.endpoint;
|
|
2584
2801
|
const url = `${baseUrl}${endpoint}`;
|
|
@@ -2766,7 +2983,178 @@ var DokuProvider = class extends BasePaymentProvider {
|
|
|
2766
2983
|
};
|
|
2767
2984
|
}
|
|
2768
2985
|
}
|
|
2986
|
+
/**
|
|
2987
|
+
* DOKU SNAP: buat transaksi (Create VA / Generate QRIS / e-Wallet Payment).
|
|
2988
|
+
* Autentikasi via B2B token + symmetric HMAC-SHA512 signature.
|
|
2989
|
+
*/
|
|
2990
|
+
async createSnapInvoice(params, config, baseUrl) {
|
|
2991
|
+
const { orderId, amount, productDetails, customer, returnUrl } = params;
|
|
2992
|
+
const snap = this.buildSnap(config);
|
|
2993
|
+
const integerAmount = Math.round(amount);
|
|
2994
|
+
const method = String(params.paymentMethod || "").toLowerCase();
|
|
2995
|
+
const bankMap = {
|
|
2996
|
+
bca: "VIRTUAL_ACCOUNT_BCA",
|
|
2997
|
+
mandiri: "VIRTUAL_ACCOUNT_BANK_MANDIRI",
|
|
2998
|
+
bri: "VIRTUAL_ACCOUNT_BRI",
|
|
2999
|
+
bni: "VIRTUAL_ACCOUNT_BNI",
|
|
3000
|
+
permata: "VIRTUAL_ACCOUNT_BANK_PERMATA",
|
|
3001
|
+
cimb: "VIRTUAL_ACCOUNT_BANK_CIMB",
|
|
3002
|
+
danamon: "VIRTUAL_ACCOUNT_BANK_DANAMON",
|
|
3003
|
+
bsi: "VIRTUAL_ACCOUNT_BANK_SYARIAH_MANDIRI",
|
|
3004
|
+
sinarmas: "VIRTUAL_ACCOUNT_SINARMAS",
|
|
3005
|
+
bjb: "VIRTUAL_ACCOUNT_BANK_BJB",
|
|
3006
|
+
btn: "VIRTUAL_ACCOUNT_BTN",
|
|
3007
|
+
bnc: "VIRTUAL_ACCOUNT_BNC"
|
|
3008
|
+
};
|
|
3009
|
+
const isVa = method.includes("_va");
|
|
3010
|
+
const isQris = method === "qris" || method.includes("qris");
|
|
3011
|
+
try {
|
|
3012
|
+
if (isVa) {
|
|
3013
|
+
return await this.snapCreateVA(params, config, snap, baseUrl, bankMap);
|
|
3014
|
+
}
|
|
3015
|
+
if (isQris) {
|
|
3016
|
+
return await this.snapGenerateQRIS(params, config, snap, baseUrl);
|
|
3017
|
+
}
|
|
3018
|
+
return await this.snapEWalletPayment(params, config, snap, baseUrl);
|
|
3019
|
+
} catch (e) {
|
|
3020
|
+
return {
|
|
3021
|
+
success: false,
|
|
3022
|
+
provider: "doku",
|
|
3023
|
+
orderId,
|
|
3024
|
+
amount: integerAmount,
|
|
3025
|
+
rawResponse: null,
|
|
3026
|
+
error: e.message || "Failed to make SNAP request to DOKU API"
|
|
3027
|
+
};
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
/** Create Virtual Account (SNAP) — DOKU Generate Payment Code. */
|
|
3031
|
+
async snapCreateVA(params, config, snap, baseUrl, bankMap) {
|
|
3032
|
+
const { orderId, amount, productDetails, customer } = params;
|
|
3033
|
+
const method = String(params.paymentMethod || "").toLowerCase();
|
|
3034
|
+
const bankKey = method.replace(/_va$/, "");
|
|
3035
|
+
const channel = config.extra?.vaChannel || bankMap[bankKey] || `VIRTUAL_ACCOUNT_${bankKey.toUpperCase()}`;
|
|
3036
|
+
const partnerServiceId = (config.extra?.partnerServiceId || "").replace(/\s/g, "");
|
|
3037
|
+
const customerNo = (config.extra?.customerNo || "").slice(0, 20) || String(Date.now()).slice(-12);
|
|
3038
|
+
const virtualAccountNo = (partnerServiceId + customerNo).slice(0, 28);
|
|
3039
|
+
const reusable = config.extra?.reusableStatus === true;
|
|
3040
|
+
const currency = params.currency || "IDR";
|
|
3041
|
+
const body = {
|
|
3042
|
+
partnerServiceId,
|
|
3043
|
+
customerNo,
|
|
3044
|
+
virtualAccountNo,
|
|
3045
|
+
virtualAccountName: customer.name || "Customer",
|
|
3046
|
+
virtualAccountEmail: customer.email,
|
|
3047
|
+
virtualAccountPhone: customer.phone,
|
|
3048
|
+
trxId: orderId,
|
|
3049
|
+
totalAmount: this.snapAmount(amount, currency),
|
|
3050
|
+
virtualAccountTrxType: "C",
|
|
3051
|
+
additionalInfo: {
|
|
3052
|
+
channel,
|
|
3053
|
+
virtualAccountConfig: { reusableStatus: reusable }
|
|
3054
|
+
}
|
|
3055
|
+
};
|
|
3056
|
+
if (params.providerParams) {
|
|
3057
|
+
Object.assign(body.additionalInfo.virtualAccountConfig, params.providerParams);
|
|
3058
|
+
}
|
|
3059
|
+
if (config.extra?.expiredDate) body.expiredDate = config.extra.expiredDate;
|
|
3060
|
+
const endpoint = "/virtual-accounts/bi-snap-va/v1.1/transfer-va/create-va";
|
|
3061
|
+
const data = await snap.request("POST", endpoint, body);
|
|
3062
|
+
const vaData = data.virtualAccountData || {};
|
|
3063
|
+
return {
|
|
3064
|
+
success: true,
|
|
3065
|
+
provider: "doku",
|
|
3066
|
+
orderId: vaData.trxId || orderId,
|
|
3067
|
+
amount: Number(vaData.totalAmount?.value || amount) || Math.round(amount),
|
|
3068
|
+
reference: vaData.virtualAccountNo || orderId,
|
|
3069
|
+
vaNumber: vaData.virtualAccountNo,
|
|
3070
|
+
vaBank: bankKey.toUpperCase(),
|
|
3071
|
+
paymentUrl: vaData.additionalInfo?.howToPayPage,
|
|
3072
|
+
expiresAt: vaData.expiredDate ? new Date(vaData.expiredDate) : void 0,
|
|
3073
|
+
rawResponse: data
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
/** Generate QRIS (SNAP) — dynamic QRIS MPM. */
|
|
3077
|
+
async snapGenerateQRIS(params, config, snap, baseUrl) {
|
|
3078
|
+
const { orderId, amount } = params;
|
|
3079
|
+
const currency = params.currency || "IDR";
|
|
3080
|
+
const merchantId = config.extra?.merchantId || config.projectId || "";
|
|
3081
|
+
const terminalId = config.extra?.terminalId || "0001";
|
|
3082
|
+
const body = {
|
|
3083
|
+
partnerReferenceNo: orderId,
|
|
3084
|
+
amount: this.snapAmount(amount, currency),
|
|
3085
|
+
merchantId,
|
|
3086
|
+
terminalId,
|
|
3087
|
+
validityPeriod: config.extra?.validityPeriod || new Date(Date.now() + 3600 * 1e3).toISOString(),
|
|
3088
|
+
additionalInfo: {
|
|
3089
|
+
postalCode: config.extra?.postalCode || "10110",
|
|
3090
|
+
feeType: 1
|
|
3091
|
+
}
|
|
3092
|
+
};
|
|
3093
|
+
if (params.providerParams) {
|
|
3094
|
+
Object.assign(body.additionalInfo, params.providerParams);
|
|
3095
|
+
}
|
|
3096
|
+
const endpoint = "/snap-adapter/b2b/v1.0/qr/qr-mpm-generate";
|
|
3097
|
+
const data = await snap.request("POST", endpoint, body);
|
|
3098
|
+
return {
|
|
3099
|
+
success: true,
|
|
3100
|
+
provider: "doku",
|
|
3101
|
+
orderId: data.partnerReferenceNo || orderId,
|
|
3102
|
+
amount: Number(data.amount?.value || amount) || Math.round(amount),
|
|
3103
|
+
reference: data.referenceNo || orderId,
|
|
3104
|
+
qrString: data.qrContent,
|
|
3105
|
+
rawResponse: data
|
|
3106
|
+
};
|
|
3107
|
+
}
|
|
3108
|
+
/** e-Wallet payment (SNAP) — DANA / OVO / ShopeePay via payment-host-to-host. */
|
|
3109
|
+
async snapEWalletPayment(params, config, snap, baseUrl) {
|
|
3110
|
+
const { orderId, amount } = params;
|
|
3111
|
+
const method = String(params.paymentMethod || "").toLowerCase();
|
|
3112
|
+
const currency = params.currency || "IDR";
|
|
3113
|
+
const returnUrl = params.returnUrl || config.returnUrl || "";
|
|
3114
|
+
const channelMap = {
|
|
3115
|
+
dana: "EMONEY_DANA_SNAP",
|
|
3116
|
+
ovo: "EMONEY_OVO_SNAP",
|
|
3117
|
+
shopeepay: "EMONEY_SHOPEEPAY_SNAP"
|
|
3118
|
+
};
|
|
3119
|
+
const channel = config.extra?.ewalletChannel || channelMap[method] || `EMONEY_${method.toUpperCase()}_SNAP`;
|
|
3120
|
+
const body = {
|
|
3121
|
+
partnerReferenceNo: orderId,
|
|
3122
|
+
amount: this.snapAmount(amount, currency),
|
|
3123
|
+
pointOfInitiation: "pc",
|
|
3124
|
+
urlParam: {
|
|
3125
|
+
url: returnUrl || "https://example.com/return",
|
|
3126
|
+
type: "PAY_RETURN",
|
|
3127
|
+
isDeepLink: "N"
|
|
3128
|
+
},
|
|
3129
|
+
additionalInfo: {
|
|
3130
|
+
channel,
|
|
3131
|
+
orderTitle: params.productDetails || `Pembayaran ${orderId}`,
|
|
3132
|
+
supportDeepLinkCheckoutUrl: "false"
|
|
3133
|
+
}
|
|
3134
|
+
};
|
|
3135
|
+
if (params.providerParams) {
|
|
3136
|
+
Object.assign(body.additionalInfo, params.providerParams);
|
|
3137
|
+
}
|
|
3138
|
+
const endpoint = "/direct-debit/core/v1/debit/payment-host-to-host";
|
|
3139
|
+
const data = await snap.request("POST", endpoint, body, {
|
|
3140
|
+
deviceId: config.extra?.deviceId,
|
|
3141
|
+
ipAddress: config.extra?.ipAddress
|
|
3142
|
+
});
|
|
3143
|
+
return {
|
|
3144
|
+
success: true,
|
|
3145
|
+
provider: "doku",
|
|
3146
|
+
orderId: data.partnerReferenceNo || orderId,
|
|
3147
|
+
amount: Number(data.amount?.value || amount) || Math.round(amount),
|
|
3148
|
+
reference: data.partnerReferenceNo || orderId,
|
|
3149
|
+
paymentUrl: data.webRedirectUrl || data.paymentUrl,
|
|
3150
|
+
rawResponse: data
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
2769
3153
|
async verifyCallback(body, config) {
|
|
3154
|
+
const headers = config.extra?.headers || {};
|
|
3155
|
+
if (this.isSnap(config)) {
|
|
3156
|
+
return this.verifySnapCallback(body, config, headers);
|
|
3157
|
+
}
|
|
2770
3158
|
const rawStatus = (body.transaction?.status || body.status || "").toUpperCase();
|
|
2771
3159
|
const isPaid = rawStatus === "SUCCESS" || rawStatus === "PAID" || rawStatus === "SETTLED";
|
|
2772
3160
|
const isPending = rawStatus === "PENDING";
|
|
@@ -2776,7 +3164,6 @@ var DokuProvider = class extends BasePaymentProvider {
|
|
|
2776
3164
|
const amount = body.order?.amount || body.amount || 0;
|
|
2777
3165
|
const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
|
|
2778
3166
|
const secretKey = config.secretKey || config.apiKey || "";
|
|
2779
|
-
const headers = config.extra?.headers || {};
|
|
2780
3167
|
const signature = headers["signature"] || headers["Signature"] || config.extra?.dokuSignature || config.extra?.signatureHeader;
|
|
2781
3168
|
const clientId = config.merchantCode || config.clientKey || "";
|
|
2782
3169
|
let isValid = true;
|
|
@@ -2797,6 +3184,40 @@ var DokuProvider = class extends BasePaymentProvider {
|
|
|
2797
3184
|
rawPayload: body
|
|
2798
3185
|
};
|
|
2799
3186
|
}
|
|
3187
|
+
/**
|
|
3188
|
+
* Verifikasi webhook / notifikasi DOKU SNAP.
|
|
3189
|
+
* Signature dibangun dengan symmetric HMAC-SHA512 (AccessToken kosong).
|
|
3190
|
+
*/
|
|
3191
|
+
verifySnapCallback(body, config, headers) {
|
|
3192
|
+
const clientSecret = config.apiKey || config.serverKey || config.secretKey || "";
|
|
3193
|
+
const endpointUrl = config.extra?.notificationPath || headers["x-path"] || config.extra?.headers?.["request-target"] || "/api/payment/webhook";
|
|
3194
|
+
let isValid = true;
|
|
3195
|
+
const incomingSig = headers["x-signature"] || headers["X-SIGNATURE"] || headers["signature"] || headers["Signature"] || "";
|
|
3196
|
+
if (incomingSig && clientSecret) {
|
|
3197
|
+
isValid = verifySnapWebhookSignature(headers, body, clientSecret, endpointUrl);
|
|
3198
|
+
}
|
|
3199
|
+
const explicitStatus = String(body.transactionStatus || body.status || body.latestTransactionStatus || "").toUpperCase();
|
|
3200
|
+
const isPaid = explicitStatus === "SUCCESS" || explicitStatus === "PAID" || explicitStatus === "SETTLED" || explicitStatus === "00" || !explicitStatus && Boolean(body.paidAmount?.value ?? body.totalAmount?.value);
|
|
3201
|
+
const isPending = explicitStatus === "PENDING" || explicitStatus === "11" || explicitStatus === "ONGOING";
|
|
3202
|
+
const isFailed = explicitStatus === "FAILED" || explicitStatus === "DECLINED" || Boolean(explicitStatus) && !isPaid && !isPending && explicitStatus !== "00";
|
|
3203
|
+
const isExpired = explicitStatus === "EXPIRED";
|
|
3204
|
+
const orderId = body.trxId || body.partnerReferenceNo || body.originalPartnerReferenceNo || body.order?.invoice_number || body.invoice_number || body.order_id || "";
|
|
3205
|
+
const paidValue = body.paidAmount?.value ?? body.totalAmount?.value ?? body.amount?.value ?? body.amount ?? 0;
|
|
3206
|
+
const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
|
|
3207
|
+
return {
|
|
3208
|
+
isValid,
|
|
3209
|
+
provider: "doku",
|
|
3210
|
+
orderId: String(orderId),
|
|
3211
|
+
amount: Number(paidValue) || 0,
|
|
3212
|
+
status,
|
|
3213
|
+
isPaid,
|
|
3214
|
+
isPending,
|
|
3215
|
+
isFailed,
|
|
3216
|
+
isExpired,
|
|
3217
|
+
statusCode: explicitStatus || "SUCCESS",
|
|
3218
|
+
rawPayload: body
|
|
3219
|
+
};
|
|
3220
|
+
}
|
|
2800
3221
|
async getPaymentMethods(params, config) {
|
|
2801
3222
|
const staticMethods = [
|
|
2802
3223
|
{
|
|
@@ -2956,6 +3377,9 @@ var DokuProvider = class extends BasePaymentProvider {
|
|
|
2956
3377
|
const clientId = config.merchantCode || config.merchantId || config.clientKey || "";
|
|
2957
3378
|
const secretKey = config.apiKey || config.serverKey || config.secretKey || "";
|
|
2958
3379
|
const sandbox = !!config.sandbox;
|
|
3380
|
+
if (this.isSnap(config)) {
|
|
3381
|
+
return this.snapCheckTransaction(params, config, clientId);
|
|
3382
|
+
}
|
|
2959
3383
|
const endpoint = `/orders/v1/status/${merchantOrderId}`;
|
|
2960
3384
|
const url = `${this.getBaseUrl(sandbox)}${endpoint}`;
|
|
2961
3385
|
const headers = generateDokuHeaders(clientId, secretKey, endpoint);
|
|
@@ -3033,6 +3457,58 @@ var DokuProvider = class extends BasePaymentProvider {
|
|
|
3033
3457
|
};
|
|
3034
3458
|
}
|
|
3035
3459
|
}
|
|
3460
|
+
/** Cek status transaksi SNAP (menggunakan Query QRIS bila ref berasal dari QRIS). */
|
|
3461
|
+
async snapCheckTransaction(params, config, clientId) {
|
|
3462
|
+
const { merchantOrderId } = params;
|
|
3463
|
+
const snap = this.buildSnap(config);
|
|
3464
|
+
try {
|
|
3465
|
+
const body = {
|
|
3466
|
+
originalPartnerReferenceNo: merchantOrderId,
|
|
3467
|
+
serviceCode: "47",
|
|
3468
|
+
merchantId: config.extra?.merchantId || config.projectId || ""
|
|
3469
|
+
};
|
|
3470
|
+
const data = await snap.request("POST", "/snap-adapter/b2b/v1.0/qr/qr-mpm-query", body);
|
|
3471
|
+
const txStatus = String(data.latestTransactionStatus || "").toUpperCase();
|
|
3472
|
+
const isPaid = txStatus === "SUCCESS" || txStatus === "00" || txStatus === "PAID" || txStatus === "SETTLED";
|
|
3473
|
+
const isPending = txStatus === "PENDING" || txStatus === "ONGOING" || txStatus === "11";
|
|
3474
|
+
const isExpired = txStatus === "EXPIRED";
|
|
3475
|
+
const isFailed = txStatus === "FAILED" || txStatus === "DECLINED" || Boolean(txStatus) && !isPaid && !isPending && !isExpired;
|
|
3476
|
+
const status = isPaid ? "paid" : isPending ? "pending" : isExpired ? "expired" : "failed";
|
|
3477
|
+
return {
|
|
3478
|
+
success: true,
|
|
3479
|
+
provider: "doku",
|
|
3480
|
+
orderId: data.originalPartnerReferenceNo || merchantOrderId,
|
|
3481
|
+
reference: data.originalReferenceNo || "",
|
|
3482
|
+
amount: Number(data.amount?.value || 0),
|
|
3483
|
+
statusCode: txStatus || String(data.responseCode || ""),
|
|
3484
|
+
status,
|
|
3485
|
+
isPaid,
|
|
3486
|
+
isPending,
|
|
3487
|
+
isFailed,
|
|
3488
|
+
isExpired,
|
|
3489
|
+
statusMessage: txStatus || data.responseMessage || "",
|
|
3490
|
+
paymentType: "QRIS",
|
|
3491
|
+
rawResponse: data
|
|
3492
|
+
};
|
|
3493
|
+
} catch (e) {
|
|
3494
|
+
return {
|
|
3495
|
+
success: false,
|
|
3496
|
+
provider: "doku",
|
|
3497
|
+
orderId: merchantOrderId,
|
|
3498
|
+
reference: "",
|
|
3499
|
+
amount: 0,
|
|
3500
|
+
statusCode: "ERROR",
|
|
3501
|
+
status: "failed",
|
|
3502
|
+
isPaid: false,
|
|
3503
|
+
isPending: false,
|
|
3504
|
+
isFailed: true,
|
|
3505
|
+
isExpired: false,
|
|
3506
|
+
statusMessage: e.message || "Failed to check SNAP transaction status",
|
|
3507
|
+
error: e.message || "Failed to check SNAP transaction status",
|
|
3508
|
+
rawResponse: null
|
|
3509
|
+
};
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3036
3512
|
};
|
|
3037
3513
|
|
|
3038
3514
|
// src/providers/prismalink/signature.ts
|
|
@@ -3426,15 +3902,15 @@ var PrismalinkProvider = class extends BasePaymentProvider {
|
|
|
3426
3902
|
};
|
|
3427
3903
|
|
|
3428
3904
|
// src/providers/faspay/signature.ts
|
|
3429
|
-
var
|
|
3905
|
+
var import_crypto11 = __toESM(require("crypto"));
|
|
3430
3906
|
function generateFaspaySignature(userId, password, billNo) {
|
|
3431
|
-
const md5Hash =
|
|
3432
|
-
return
|
|
3907
|
+
const md5Hash = import_crypto11.default.createHash("md5").update(`${userId}${password}${billNo}`).digest("hex");
|
|
3908
|
+
return import_crypto11.default.createHash("sha1").update(md5Hash).digest("hex");
|
|
3433
3909
|
}
|
|
3434
3910
|
function verifyFaspaySignature(userId, password, billNo, paymentStatusCode, incomingSignature) {
|
|
3435
3911
|
if (!incomingSignature || !password) return false;
|
|
3436
|
-
const md5Hash =
|
|
3437
|
-
const computed =
|
|
3912
|
+
const md5Hash = import_crypto11.default.createHash("md5").update(`${userId}${password}${billNo}${paymentStatusCode}`).digest("hex");
|
|
3913
|
+
const computed = import_crypto11.default.createHash("sha1").update(md5Hash).digest("hex");
|
|
3438
3914
|
const simpleComputed = generateFaspaySignature(userId, password, billNo);
|
|
3439
3915
|
return safeCompare(incomingSignature, computed) || safeCompare(incomingSignature, simpleComputed);
|
|
3440
3916
|
}
|
|
@@ -3847,10 +4323,10 @@ var FaspayProvider = class extends BasePaymentProvider {
|
|
|
3847
4323
|
};
|
|
3848
4324
|
|
|
3849
4325
|
// src/providers/finpay/signature.ts
|
|
3850
|
-
var
|
|
4326
|
+
var import_crypto13 = __toESM(require("crypto"));
|
|
3851
4327
|
function generateFinpaySignature(merchantId, orderId, amount, merchantKey) {
|
|
3852
4328
|
const data = `${merchantId}%${orderId}%${Math.round(amount)}%${merchantKey}`;
|
|
3853
|
-
return
|
|
4329
|
+
return import_crypto13.default.createHmac("sha512", merchantKey).update(data).digest("hex");
|
|
3854
4330
|
}
|
|
3855
4331
|
function verifyFinpaySignature(merchantId, orderId, amount, merchantKey, incomingSignature) {
|
|
3856
4332
|
if (!incomingSignature || !merchantKey) return false;
|
|
@@ -5747,7 +6223,7 @@ var PaypalProvider = class extends BasePaymentProvider {
|
|
|
5747
6223
|
};
|
|
5748
6224
|
|
|
5749
6225
|
// src/providers/adyen/signature.ts
|
|
5750
|
-
var
|
|
6226
|
+
var import_crypto18 = require("crypto");
|
|
5751
6227
|
function verifyAdyenWebhook(notificationItem, hmacKey) {
|
|
5752
6228
|
if (!hmacKey || !notificationItem) return false;
|
|
5753
6229
|
try {
|
|
@@ -5764,7 +6240,7 @@ function verifyAdyenWebhook(notificationItem, hmacKey) {
|
|
|
5764
6240
|
];
|
|
5765
6241
|
const signedData = fields.join(":");
|
|
5766
6242
|
const keyBytes = Buffer.from(hmacKey, "hex");
|
|
5767
|
-
const expected = (0,
|
|
6243
|
+
const expected = (0, import_crypto18.createHmac)("sha256", keyBytes).update(signedData, "utf8").digest("base64");
|
|
5768
6244
|
const provided = notificationItem.additionalData?.hmacSignature || "";
|
|
5769
6245
|
return safeCompare(expected, provided);
|
|
5770
6246
|
} catch {
|
|
@@ -5997,11 +6473,11 @@ var AdyenProvider = class extends BasePaymentProvider {
|
|
|
5997
6473
|
};
|
|
5998
6474
|
|
|
5999
6475
|
// src/providers/checkoutcom/signature.ts
|
|
6000
|
-
var
|
|
6476
|
+
var import_crypto20 = require("crypto");
|
|
6001
6477
|
function verifyCheckoutComWebhook(body, signatureHeader, secret) {
|
|
6002
6478
|
if (!secret || !signatureHeader || !body) return false;
|
|
6003
6479
|
try {
|
|
6004
|
-
const expected = (0,
|
|
6480
|
+
const expected = (0, import_crypto20.createHmac)("sha256", secret).update(body, "utf8").digest("hex");
|
|
6005
6481
|
const provided = signatureHeader.replace(/^sha256=/, "");
|
|
6006
6482
|
return safeCompare(expected, provided);
|
|
6007
6483
|
} catch {
|
|
@@ -6221,11 +6697,11 @@ var CheckoutComProvider = class extends BasePaymentProvider {
|
|
|
6221
6697
|
};
|
|
6222
6698
|
|
|
6223
6699
|
// src/providers/razorpay/signature.ts
|
|
6224
|
-
var
|
|
6700
|
+
var import_crypto22 = require("crypto");
|
|
6225
6701
|
function verifyRazorpayWebhook(rawBody, signature, webhookSecret) {
|
|
6226
6702
|
if (!webhookSecret || !signature || !rawBody) return false;
|
|
6227
6703
|
try {
|
|
6228
|
-
const expected = (0,
|
|
6704
|
+
const expected = (0, import_crypto22.createHmac)("sha256", webhookSecret).update(rawBody).digest("hex");
|
|
6229
6705
|
return safeCompare(expected, signature);
|
|
6230
6706
|
} catch {
|
|
6231
6707
|
return false;
|
|
@@ -6451,12 +6927,12 @@ var RazorpayProvider = class extends BasePaymentProvider {
|
|
|
6451
6927
|
};
|
|
6452
6928
|
|
|
6453
6929
|
// src/providers/square/signature.ts
|
|
6454
|
-
var
|
|
6930
|
+
var import_crypto24 = require("crypto");
|
|
6455
6931
|
function verifySquareWebhook(rawBody, signatureHeader, signatureKey, notificationUrl) {
|
|
6456
6932
|
if (!signatureKey || !signatureHeader || !rawBody) return false;
|
|
6457
6933
|
try {
|
|
6458
6934
|
const payload = notificationUrl + rawBody;
|
|
6459
|
-
const expected = (0,
|
|
6935
|
+
const expected = (0, import_crypto24.createHmac)("sha256", signatureKey).update(payload).digest("base64");
|
|
6460
6936
|
return safeCompare(expected, signatureHeader);
|
|
6461
6937
|
} catch {
|
|
6462
6938
|
return false;
|
|
@@ -6696,7 +7172,7 @@ var SquareProvider = class extends BasePaymentProvider {
|
|
|
6696
7172
|
};
|
|
6697
7173
|
|
|
6698
7174
|
// src/providers/payu/signature.ts
|
|
6699
|
-
var
|
|
7175
|
+
var import_crypto26 = require("crypto");
|
|
6700
7176
|
function verifyPayuWebhook(rawBody, signatureHeader, md5Key) {
|
|
6701
7177
|
if (!md5Key || !signatureHeader || !rawBody) return false;
|
|
6702
7178
|
try {
|
|
@@ -6709,10 +7185,10 @@ function verifyPayuWebhook(rawBody, signatureHeader, md5Key) {
|
|
|
6709
7185
|
const algorithm = (parts["algorithm"] || "MD5").toUpperCase();
|
|
6710
7186
|
if (!providedSig) return false;
|
|
6711
7187
|
if (algorithm === "MD5") {
|
|
6712
|
-
const expected = (0,
|
|
7188
|
+
const expected = (0, import_crypto26.createHash)("md5").update(rawBody + md5Key).digest("hex");
|
|
6713
7189
|
return safeCompare(expected, providedSig);
|
|
6714
7190
|
} else if (algorithm === "SHA-256") {
|
|
6715
|
-
const expected = (0,
|
|
7191
|
+
const expected = (0, import_crypto26.createHash)("sha256").update(rawBody + md5Key).digest("hex");
|
|
6716
7192
|
return safeCompare(expected, providedSig);
|
|
6717
7193
|
}
|
|
6718
7194
|
return false;
|
|
@@ -6988,7 +7464,7 @@ var PayuProvider = class extends BasePaymentProvider {
|
|
|
6988
7464
|
};
|
|
6989
7465
|
|
|
6990
7466
|
// src/providers/braintree/signature.ts
|
|
6991
|
-
var
|
|
7467
|
+
var import_crypto28 = require("crypto");
|
|
6992
7468
|
function verifyBraintreeWebhook(btSignature, btPayload, privateKey) {
|
|
6993
7469
|
if (!privateKey || !btSignature || !btPayload) return false;
|
|
6994
7470
|
try {
|
|
@@ -6996,8 +7472,8 @@ function verifyBraintreeWebhook(btSignature, btPayload, privateKey) {
|
|
|
6996
7472
|
if (parts.length < 2) return false;
|
|
6997
7473
|
const providedHmac = parts[1];
|
|
6998
7474
|
const payload = Buffer.from(btPayload, "base64").toString("utf8");
|
|
6999
|
-
const secretHash = (0,
|
|
7000
|
-
const expected = (0,
|
|
7475
|
+
const secretHash = (0, import_crypto28.createHash)("sha1").update(privateKey).digest("hex");
|
|
7476
|
+
const expected = (0, import_crypto28.createHmac)("sha1", secretHash).update(payload).digest("hex");
|
|
7001
7477
|
return safeCompare(expected, providedHmac);
|
|
7002
7478
|
} catch {
|
|
7003
7479
|
return false;
|
|
@@ -7224,11 +7700,11 @@ var BraintreeProvider = class extends BasePaymentProvider {
|
|
|
7224
7700
|
};
|
|
7225
7701
|
|
|
7226
7702
|
// src/providers/twocheckout/signature.ts
|
|
7227
|
-
var
|
|
7703
|
+
var import_crypto30 = require("crypto");
|
|
7228
7704
|
function buildTwoCheckoutAuth(merchantCode, secretKey) {
|
|
7229
7705
|
const date = Math.floor(Date.now() / 1e3).toString();
|
|
7230
7706
|
const raw = merchantCode + date;
|
|
7231
|
-
const hmac = (0,
|
|
7707
|
+
const hmac = (0, import_crypto30.createHmac)("sha256", secretKey).update(raw).digest("hex");
|
|
7232
7708
|
const header = `code="${merchantCode}" date="${date}" hash="${hmac}"`;
|
|
7233
7709
|
return { header, date };
|
|
7234
7710
|
}
|
|
@@ -7236,7 +7712,7 @@ function verifyTwoCheckoutWebhook(secretWord, saleId, productId, invoiceId, prov
|
|
|
7236
7712
|
if (!secretWord || !providedHash) return false;
|
|
7237
7713
|
try {
|
|
7238
7714
|
const raw = secretWord + saleId + productId + invoiceId;
|
|
7239
|
-
const expected = (0,
|
|
7715
|
+
const expected = (0, import_crypto30.createHash)("md5").update(raw).digest("hex");
|
|
7240
7716
|
return safeCompare(expected, providedHash);
|
|
7241
7717
|
} catch {
|
|
7242
7718
|
return false;
|
|
@@ -9593,6 +10069,7 @@ var buayar = new Buayar();
|
|
|
9593
10069
|
PrismalinkProvider,
|
|
9594
10070
|
RazorpayClient,
|
|
9595
10071
|
RazorpayProvider,
|
|
10072
|
+
SnapClient,
|
|
9596
10073
|
SquareClient,
|
|
9597
10074
|
SquareProvider,
|
|
9598
10075
|
StripeClient,
|
|
@@ -9616,6 +10093,8 @@ var buayar = new Buayar();
|
|
|
9616
10093
|
generateNicepayToken,
|
|
9617
10094
|
generateOyHeaders,
|
|
9618
10095
|
generatePrismalinkSignature,
|
|
10096
|
+
generateSnapAsymmetricSignature,
|
|
10097
|
+
generateSnapSymmetricSignature,
|
|
9619
10098
|
getDuitkuInquirySignatures,
|
|
9620
10099
|
getDuitkuPaymentMethodsSignature,
|
|
9621
10100
|
getDuitkuStatusSignatures,
|
|
@@ -9623,6 +10102,7 @@ var buayar = new Buayar();
|
|
|
9623
10102
|
getXenditAuthHeader,
|
|
9624
10103
|
hmacSha256,
|
|
9625
10104
|
md5,
|
|
10105
|
+
minifyJson,
|
|
9626
10106
|
parseCoreChargeResponse,
|
|
9627
10107
|
paymentManager,
|
|
9628
10108
|
resolveConfigFromEnv,
|
|
@@ -9630,7 +10110,10 @@ var buayar = new Buayar();
|
|
|
9630
10110
|
serializePaypalParams,
|
|
9631
10111
|
serializeStripeParams,
|
|
9632
10112
|
sha256,
|
|
10113
|
+
sha256Hex,
|
|
9633
10114
|
sha512,
|
|
10115
|
+
snapExternalId,
|
|
10116
|
+
snapTimestamp,
|
|
9634
10117
|
toCanonicalPaymentMethod,
|
|
9635
10118
|
toDokuPaymentMethod,
|
|
9636
10119
|
toDuitkuPaymentMethod,
|
|
@@ -9656,6 +10139,7 @@ var buayar = new Buayar();
|
|
|
9656
10139
|
verifyPayuWebhook,
|
|
9657
10140
|
verifyPrismalinkSignature,
|
|
9658
10141
|
verifyRazorpayWebhook,
|
|
10142
|
+
verifySnapWebhookSignature,
|
|
9659
10143
|
verifySquareWebhook,
|
|
9660
10144
|
verifyStripeWebhook,
|
|
9661
10145
|
verifyTwoCheckoutWebhook,
|