@zendfi/sdk 1.0.2 → 1.0.3
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/{chunk-3ACJUM6V.mjs → chunk-6CFQXFNR.mjs} +0 -1
- package/dist/{chunk-DAJL2Q36.mjs → chunk-B5LO34Q6.mjs} +20 -24
- package/dist/express.d.mts +1 -2
- package/dist/express.d.ts +1 -2
- package/dist/express.js +0 -1
- package/dist/express.mjs +1 -1
- package/dist/helpers/index.d.mts +0 -1
- package/dist/helpers/index.d.ts +0 -1
- package/dist/helpers/index.js +20 -24
- package/dist/helpers/index.mjs +1 -1
- package/dist/index.d.mts +14 -9
- package/dist/index.d.ts +14 -9
- package/dist/index.js +230 -85
- package/dist/index.mjs +212 -62
- package/dist/nextjs.d.mts +1 -2
- package/dist/nextjs.d.ts +1 -2
- package/dist/nextjs.js +0 -1
- package/dist/nextjs.mjs +1 -1
- package/dist/{webhook-handler-61UWBtDI.d.mts → webhook-handler-hUfWh-_Y.d.mts} +102 -8
- package/dist/{webhook-handler-61UWBtDI.d.ts → webhook-handler-hUfWh-_Y.d.ts} +102 -8
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
processWebhook
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6CFQXFNR.mjs";
|
|
4
4
|
import {
|
|
5
5
|
DevTools,
|
|
6
6
|
PerformanceMonitor,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
TransactionPoller,
|
|
9
9
|
WalletConnector,
|
|
10
10
|
createWalletHook
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-B5LO34Q6.mjs";
|
|
12
12
|
import {
|
|
13
13
|
__require
|
|
14
14
|
} from "./chunk-Y6FXYEAI.mjs";
|
|
@@ -145,12 +145,12 @@ var ConfigLoader = class {
|
|
|
145
145
|
const env = this.detectEnvironment();
|
|
146
146
|
if (mode === "live" && env === "development") {
|
|
147
147
|
console.warn(
|
|
148
|
-
"
|
|
148
|
+
"Warning: Using a live API key (zfi_live_) in development environment. This will create real mainnet transactions. Use a test key (zfi_test_) for devnet testing."
|
|
149
149
|
);
|
|
150
150
|
}
|
|
151
151
|
if (mode === "test" && env === "production") {
|
|
152
152
|
console.warn(
|
|
153
|
-
"
|
|
153
|
+
"Warning: Using a test API key (zfi_test_) in production environment. This will create devnet transactions only. Use a live key (zfi_live_) for mainnet."
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
@@ -252,10 +252,10 @@ var ZendFiError2 = class _ZendFiError extends Error {
|
|
|
252
252
|
let message = `[${this.code}] ${this.message}`;
|
|
253
253
|
if (this.suggestion) {
|
|
254
254
|
message += `
|
|
255
|
-
|
|
255
|
+
Suggestion: ${this.suggestion}`;
|
|
256
256
|
}
|
|
257
257
|
message += `
|
|
258
|
-
|
|
258
|
+
Docs: ${this.docs_url}`;
|
|
259
259
|
return message;
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
@@ -279,7 +279,7 @@ var AuthenticationError2 = class extends ZendFiError2 {
|
|
|
279
279
|
code,
|
|
280
280
|
message,
|
|
281
281
|
type: "authentication_error",
|
|
282
|
-
suggestion: suggestion || "Check your API key in the dashboard at https://
|
|
282
|
+
suggestion: suggestion || "Check your API key in the dashboard at https://dashboard.zendfi.tech",
|
|
283
283
|
statusCode: 401
|
|
284
284
|
});
|
|
285
285
|
this.name = "AuthenticationError";
|
|
@@ -387,25 +387,19 @@ function createZendFiError(statusCode, responseBody, message) {
|
|
|
387
387
|
return new ApiError(errorMessage, errorCode, statusCode, responseBody);
|
|
388
388
|
}
|
|
389
389
|
var ERROR_CODES = {
|
|
390
|
-
// Authentication
|
|
391
390
|
INVALID_API_KEY: "invalid_api_key",
|
|
392
391
|
API_KEY_EXPIRED: "api_key_expired",
|
|
393
392
|
API_KEY_REVOKED: "api_key_revoked",
|
|
394
|
-
// Payment
|
|
395
393
|
INSUFFICIENT_BALANCE: "insufficient_balance",
|
|
396
394
|
PAYMENT_DECLINED: "payment_declined",
|
|
397
395
|
PAYMENT_EXPIRED: "payment_expired",
|
|
398
396
|
INVALID_AMOUNT: "invalid_amount",
|
|
399
397
|
INVALID_CURRENCY: "invalid_currency",
|
|
400
|
-
// Validation
|
|
401
398
|
MISSING_REQUIRED_FIELD: "missing_required_field",
|
|
402
399
|
INVALID_PARAMETER: "invalid_parameter",
|
|
403
|
-
// Network
|
|
404
400
|
NETWORK_ERROR: "network_error",
|
|
405
401
|
TIMEOUT: "timeout",
|
|
406
|
-
// Rate limiting
|
|
407
402
|
RATE_LIMIT_EXCEEDED: "rate_limit_exceeded",
|
|
408
|
-
// Webhook
|
|
409
403
|
WEBHOOK_SIGNATURE_INVALID: "webhook_signature_invalid",
|
|
410
404
|
WEBHOOK_TIMESTAMP_TOO_OLD: "webhook_timestamp_too_old"
|
|
411
405
|
};
|
|
@@ -932,6 +926,18 @@ function verifyWebhookSignature(payload, signature, secret) {
|
|
|
932
926
|
}
|
|
933
927
|
|
|
934
928
|
// src/embedded-checkout.ts
|
|
929
|
+
var Icons = {
|
|
930
|
+
clipboard: `<svg class="icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" /></svg>`,
|
|
931
|
+
checkCircle: `<svg class="icon icon-lg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>`,
|
|
932
|
+
xCircle: `<svg class="icon icon-lg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>`,
|
|
933
|
+
check: `<svg class="icon icon-sm" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" /></svg>`,
|
|
934
|
+
refresh: `<svg class="icon icon-sm" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" /></svg>`,
|
|
935
|
+
clock: `<svg class="icon icon-sm" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>`,
|
|
936
|
+
loader: `<svg class="icon icon-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>`,
|
|
937
|
+
bank: `<svg class="icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 21v-8.25M15.75 21v-8.25M8.25 21v-8.25M3 9l9-6 9 6m-1.5 12V10.332A48.36 48.36 0 0012 9.75c-2.551 0-5.056.2-7.5.582V21M3 21h18M12 6.75h.008v.008H12V6.75z" /></svg>`,
|
|
938
|
+
clocklg: `<svg class="icon icon-lg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>`,
|
|
939
|
+
hammer: `<svg class="icon" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 11-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 004.486-6.336l-3.276 3.277a3.004 3.004 0 01-2.25-2.25l3.276-3.276a4.5 4.5 0 00-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437l1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008z" /></svg>`
|
|
940
|
+
};
|
|
935
941
|
var ZendFiEmbeddedCheckout = class {
|
|
936
942
|
config;
|
|
937
943
|
container = null;
|
|
@@ -939,8 +945,6 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
939
945
|
pollInterval = null;
|
|
940
946
|
mounted = false;
|
|
941
947
|
paymentProcessed = false;
|
|
942
|
-
// Prevent duplicate success callbacks
|
|
943
|
-
// Bank payment state
|
|
944
948
|
bankPaymentState = {};
|
|
945
949
|
constructor(config) {
|
|
946
950
|
this.config = {
|
|
@@ -1154,13 +1158,28 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1154
1158
|
*/
|
|
1155
1159
|
renderHeader() {
|
|
1156
1160
|
if (!this.checkoutData) return "";
|
|
1161
|
+
const testnetBadge = this.checkoutData.solana_network === "devnet" || this.checkoutData.solana_network === "testnet" ? `<span style="font-size: 9px; font-weight: 500; color: #d97706; background: #fef3c7; padding: 2px 6px; border-radius: 4px; margin-left: 6px;">Testnet</span>` : "";
|
|
1157
1162
|
return `
|
|
1158
|
-
<div class="zendfi-checkout-header" style="padding: 24px; border-bottom: 1px solid #e5e7eb;">
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1163
|
+
<div class="zendfi-checkout-header" style="padding: 24px; text-align: center; border-bottom: 1px solid #e5e7eb;">
|
|
1164
|
+
<!-- Merchant Badge -->
|
|
1165
|
+
<div style="display: inline-flex; items-center; gap: 8px; padding: 6px 12px; background: white; border: 1px solid #e5e7eb; border-radius: 20px; margin-bottom: 16px;">
|
|
1166
|
+
<div style="width: 20px; height: 20px; border-radius: 50%; background: #1f2937; display: flex; align-items: center; justify-content: center;">
|
|
1167
|
+
<span style="font-size: 10px; font-weight: 600; color: white;">
|
|
1168
|
+
${this.checkoutData.merchant_name.charAt(0).toUpperCase()}
|
|
1169
|
+
</span>
|
|
1170
|
+
</div>
|
|
1171
|
+
<span style="font-size: 12px; font-weight: 500; color: #374151;">${this.checkoutData.merchant_name}</span>
|
|
1172
|
+
${testnetBadge}
|
|
1173
|
+
</div>
|
|
1174
|
+
|
|
1175
|
+
<!-- Amount -->
|
|
1176
|
+
<div style="font-size: 40px; font-weight: 600; color: #1f2937; margin-bottom: 4px;">
|
|
1177
|
+
$${this.checkoutData.amount_usd.toFixed(2)}
|
|
1178
|
+
</div>
|
|
1179
|
+
<p style="margin: 0; font-size: 13px; color: #6b7280;">${this.checkoutData.token} on Solana</p>
|
|
1180
|
+
|
|
1162
1181
|
${this.checkoutData.description ? `
|
|
1163
|
-
<p style="margin:
|
|
1182
|
+
<p style="margin: 12px auto 0; color: #9ca3af; font-size: 13px; max-width: 280px;">
|
|
1164
1183
|
${this.checkoutData.description}
|
|
1165
1184
|
</p>
|
|
1166
1185
|
` : ""}
|
|
@@ -1244,21 +1263,22 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1244
1263
|
renderQRCodeMethod() {
|
|
1245
1264
|
if (!this.checkoutData) return "";
|
|
1246
1265
|
return `
|
|
1247
|
-
<div class="zendfi-payment-method" style="padding:
|
|
1266
|
+
<div class="zendfi-payment-method" style="padding: 20px; border: 1px solid #e5e7eb; border-radius: 12px; margin-bottom: 16px; background: white; transition: all 0.2s;" onmouseover="this.style.borderColor='#d1d5db'; this.style.boxShadow='0 2px 8px rgba(0,0,0,0.05)';" onmouseout="this.style.borderColor='#e5e7eb'; this.style.boxShadow='none';">
|
|
1248
1267
|
<div style="text-align: center;">
|
|
1249
|
-
<
|
|
1250
|
-
|
|
1268
|
+
<h4 style="margin: 0 0 12px 0; font-size: 15px; font-weight: 600; color: #374151;">Scan QR Code</h4>
|
|
1269
|
+
<p style="font-size: 13px; color: #6b7280; margin-bottom: 16px;">
|
|
1270
|
+
Use any Solana wallet app
|
|
1251
1271
|
</p>
|
|
1252
|
-
<div id="zendfi-qr-container" style="display: flex; justify-content: center; margin-bottom: 16px;">
|
|
1272
|
+
<div id="zendfi-qr-container" style="display: flex; justify-content: center; margin-bottom: 16px; padding: 12px; background: #fafbfc; border-radius: 8px;">
|
|
1253
1273
|
<canvas id="zendfi-qr-code"></canvas>
|
|
1254
1274
|
</div>
|
|
1255
1275
|
<button
|
|
1256
1276
|
id="zendfi-copy-address"
|
|
1257
|
-
style="padding: 10px 20px; background: #f3f4f6; border: 1px solid #d1d5db; border-radius: 8px; cursor: pointer; font-size: 14px; color: #374151; transition: all 0.2s;"
|
|
1277
|
+
style="padding: 10px 20px; background: #f3f4f6; border: 1px solid #d1d5db; border-radius: 8px; cursor: pointer; font-size: 14px; color: #374151; font-weight: 500; transition: all 0.2s; display: inline-flex; align-items: center; gap: 6px;"
|
|
1258
1278
|
onmouseover="this.style.background='#e5e7eb'"
|
|
1259
1279
|
onmouseout="this.style.background='#f3f4f6'"
|
|
1260
1280
|
>
|
|
1261
|
-
|
|
1281
|
+
${Icons.clipboard} Copy Address
|
|
1262
1282
|
</button>
|
|
1263
1283
|
</div>
|
|
1264
1284
|
</div>
|
|
@@ -1268,15 +1288,16 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1268
1288
|
* Render browser wallet method
|
|
1269
1289
|
*/
|
|
1270
1290
|
renderWalletMethod() {
|
|
1291
|
+
const walletIcon = `<svg style="width: 20px; height: 20px; display: inline-block; vertical-align: middle; margin-right: 8px;" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21 12a2.25 2.25 0 00-2.25-2.25H15a3 3 0 11-6 0H5.25A2.25 2.25 0 003 12m18 0v6a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 18v-6m18 0V9M3 12V9m18 0a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 9m18 0V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v3" /></svg>`;
|
|
1271
1292
|
return `
|
|
1272
1293
|
<div class="zendfi-payment-method" style="margin-bottom: 16px;">
|
|
1273
1294
|
<button
|
|
1274
1295
|
id="zendfi-connect-wallet"
|
|
1275
|
-
style="width: 100%; padding: 16px; background:
|
|
1276
|
-
onmouseover="this.style.transform='translateY(-
|
|
1277
|
-
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0
|
|
1296
|
+
style="width: 100%; padding: 16px; background: #1f2937; color: white; border: none; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.2s; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); display: flex; align-items: center; justify-content: center;"
|
|
1297
|
+
onmouseover="this.style.transform='translateY(-1px)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)'; this.style.background='#111827';"
|
|
1298
|
+
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 2px 6px rgba(0, 0, 0, 0.1)'; this.style.background='#1f2937';"
|
|
1278
1299
|
>
|
|
1279
|
-
|
|
1300
|
+
${walletIcon} Connect Wallet
|
|
1280
1301
|
</button>
|
|
1281
1302
|
</div>
|
|
1282
1303
|
`;
|
|
@@ -1285,15 +1306,16 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1285
1306
|
* Render WalletConnect method
|
|
1286
1307
|
*/
|
|
1287
1308
|
renderWalletConnectMethod() {
|
|
1309
|
+
const qrIcon = `<svg style="width: 20px; height: 20px; display: inline-block; vertical-align: middle; margin-right: 8px;" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 4.875c0-.621.504-1.125 1.125-1.125h4.5c.621 0 1.125.504 1.125 1.125v4.5c0 .621-.504 1.125-1.125 1.125h-4.5A1.125 1.125 0 013.75 9.375v-4.5zM3.75 14.625c0-.621.504-1.125 1.125-1.125h4.5c.621 0 1.125.504 1.125 1.125v4.5c0 .621-.504 1.125-1.125 1.125h-4.5a1.125 1.125 0 01-1.125-1.125v-4.5zM13.5 4.875c0-.621.504-1.125 1.125-1.125h4.5c.621 0 1.125.504 1.125 1.125v4.5c0 .621-.504 1.125-1.125 1.125h-4.5A1.125 1.125 0 0113.5 9.375v-4.5z" /><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 6.75h.75v.75h-.75v-.75zM6.75 16.5h.75v.75h-.75v-.75zM16.5 6.75h.75v.75h-.75v-.75zM13.5 13.5h.75v.75h-.75v-.75zM13.5 19.5h.75v.75h-.75v-.75zM19.5 13.5h.75v.75h-.75v-.75zM19.5 19.5h.75v.75h-.75v-.75zM16.5 16.5h.75v.75h-.75v-.75z" /></svg>`;
|
|
1288
1310
|
return `
|
|
1289
|
-
<div class="zendfi-payment-method">
|
|
1311
|
+
<div class="zendfi-payment-method" style="margin-bottom: 16px;">
|
|
1290
1312
|
<button
|
|
1291
1313
|
id="zendfi-wallet-connect"
|
|
1292
|
-
style="width: 100%; padding: 16px; background: white; color: #1f2937; border: 2px solid #
|
|
1293
|
-
onmouseover="this.style.borderColor='#
|
|
1294
|
-
onmouseout="this.style.borderColor='#
|
|
1314
|
+
style="width: 100%; padding: 16px; background: white; color: #1f2937; border: 2px solid #d1d5db; border-radius: 12px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center;"
|
|
1315
|
+
onmouseover="this.style.borderColor='#9ca3af'; this.style.background='#f9fafb';"
|
|
1316
|
+
onmouseout="this.style.borderColor='#d1d5db'; this.style.background='white';"
|
|
1295
1317
|
>
|
|
1296
|
-
|
|
1318
|
+
${qrIcon} WalletConnect
|
|
1297
1319
|
</button>
|
|
1298
1320
|
</div>
|
|
1299
1321
|
`;
|
|
@@ -1306,13 +1328,13 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1306
1328
|
const isEmailStep = !this.bankPaymentState.orderId;
|
|
1307
1329
|
const isBankDetailsStep = !!this.bankPaymentState.bankDetails;
|
|
1308
1330
|
return `
|
|
1309
|
-
<div class="zendfi-payment-method" style="padding:
|
|
1331
|
+
<div class="zendfi-payment-method" style="padding: 20px; border: 2px solid #10b981; border-radius: 12px; margin-bottom: 16px; background: #f0fdf4; transition: all 0.2s;" onmouseover="this.style.boxShadow='0 2px 8px rgba(16,185,129,0.15)';" onmouseout="this.style.boxShadow='none';">
|
|
1310
1332
|
<div style="margin-bottom: 12px;">
|
|
1311
|
-
<h4 style="margin: 0 0 4px 0; font-size: 16px; font-weight: 600; color: #065f46; display: flex; align-items: center;">
|
|
1312
|
-
|
|
1333
|
+
<h4 style="margin: 0 0 4px 0; font-size: 16px; font-weight: 600; color: #065f46; display: flex; align-items: center; gap: 8px;">
|
|
1334
|
+
${Icons.bank} Pay with Bank Transfer
|
|
1313
1335
|
</h4>
|
|
1314
|
-
<p style="margin: 0; font-size:
|
|
1315
|
-
|
|
1336
|
+
<p style="margin: 0; font-size: 13px; color: #047857;">
|
|
1337
|
+
Nigerian bank account \u2022 Instant confirmation
|
|
1316
1338
|
</p>
|
|
1317
1339
|
</div>
|
|
1318
1340
|
|
|
@@ -1377,8 +1399,8 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1377
1399
|
return `
|
|
1378
1400
|
<div id="zendfi-bank-details-step">
|
|
1379
1401
|
<div style="background: white; border: 1px solid #d1d5db; border-radius: 8px; padding: 16px; margin-bottom: 16px;">
|
|
1380
|
-
<h5 style="margin: 0 0 12px 0; font-size: 14px; font-weight: 600; color: #374151;">
|
|
1381
|
-
|
|
1402
|
+
<h5 style="margin: 0 0 12px 0; font-size: 14px; font-weight: 600; color: #374151; display: flex; align-items: center; gap: 6px;">
|
|
1403
|
+
${Icons.bank} Transfer to this account:
|
|
1382
1404
|
</h5>
|
|
1383
1405
|
|
|
1384
1406
|
<div style="margin-bottom: 8px;">
|
|
@@ -1421,14 +1443,14 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1421
1443
|
<div style="color: #6b7280; font-size: 14px;" id="zendfi-bank-status-text">
|
|
1422
1444
|
Waiting for bank transfer... (<span id="zendfi-bank-timer">0:00</span>)
|
|
1423
1445
|
</div>
|
|
1424
|
-
<div style="font-size: 12px; color: #9ca3af; margin-top: 4px;">
|
|
1425
|
-
|
|
1446
|
+
<div style="font-size: 12px; color: #9ca3af; margin-top: 4px; display: inline-flex; align-items: center; gap: 4px;">
|
|
1447
|
+
${Icons.clock} Usually takes 10-30 seconds
|
|
1426
1448
|
</div>
|
|
1427
1449
|
<button
|
|
1428
1450
|
id="zendfi-refresh-status"
|
|
1429
|
-
style="margin-top: 12px; padding: 8px 16px; background: white; border: 1px solid #e5e7eb; border-radius: 8px; cursor: pointer; color: #6b7280; font-size: 14px;"
|
|
1451
|
+
style="margin-top: 12px; padding: 8px 16px; background: white; border: 1px solid #e5e7eb; border-radius: 8px; cursor: pointer; color: #6b7280; font-size: 14px; display: inline-flex; align-items: center; gap: 6px;"
|
|
1430
1452
|
>
|
|
1431
|
-
|
|
1453
|
+
${Icons.refresh} Refresh Status
|
|
1432
1454
|
</button>
|
|
1433
1455
|
</div>
|
|
1434
1456
|
</div>
|
|
@@ -1438,10 +1460,13 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1438
1460
|
* Render footer
|
|
1439
1461
|
*/
|
|
1440
1462
|
renderFooter() {
|
|
1463
|
+
const lockIcon = `<svg style="width: 14px; height: 14px; display: inline-block; vertical-align: middle; margin-right: 4px;" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z" /></svg>`;
|
|
1441
1464
|
return `
|
|
1442
1465
|
<div class="zendfi-checkout-footer" style="padding: 16px 24px; border-top: 1px solid #e5e7eb; text-align: center;">
|
|
1443
|
-
<p style="margin: 0; font-size: 12px; color: #9ca3af;">
|
|
1444
|
-
|
|
1466
|
+
<p style="margin: 0; font-size: 12px; color: #9ca3af; display: flex; align-items: center; justify-content: center; gap: 4px;">
|
|
1467
|
+
${lockIcon}
|
|
1468
|
+
<span>Secured by</span>
|
|
1469
|
+
<a href="https://zendfi.tech" target="_blank" style="color: #667eea; text-decoration: none; font-weight: 600; transition: opacity 0.2s;" onmouseover="this.style.opacity='0.7'" onmouseout="this.style.opacity='1'">ZendFi</a>
|
|
1445
1470
|
</p>
|
|
1446
1471
|
</div>
|
|
1447
1472
|
`;
|
|
@@ -1453,7 +1478,7 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1453
1478
|
if (!this.container) return;
|
|
1454
1479
|
this.container.innerHTML = `
|
|
1455
1480
|
<div class="zendfi-checkout-success" style="${this.getSuccessStyles()}">
|
|
1456
|
-
<div style="
|
|
1481
|
+
<div style="color: #10b981; margin-bottom: 16px;">${Icons.checkCircle}</div>
|
|
1457
1482
|
<h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600; color: #059669;">
|
|
1458
1483
|
Payment Successful!
|
|
1459
1484
|
</h3>
|
|
@@ -1463,6 +1488,91 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1463
1488
|
</div>
|
|
1464
1489
|
`;
|
|
1465
1490
|
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Render payment under review state
|
|
1493
|
+
*/
|
|
1494
|
+
renderUnderReview() {
|
|
1495
|
+
if (!this.container) return;
|
|
1496
|
+
const customerEmail = this.bankPaymentState.customerEmail || "unknown";
|
|
1497
|
+
const orderId = this.bankPaymentState.orderId || "N/A";
|
|
1498
|
+
this.container.innerHTML = `
|
|
1499
|
+
<div class="zendfi-checkout-under-review" style="padding: 32px 24px; text-align: center;">
|
|
1500
|
+
<div style="width: 64px; height: 64px; background: #fef3c7; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; color: #d97706;">
|
|
1501
|
+
${Icons.clock}
|
|
1502
|
+
</div>
|
|
1503
|
+
|
|
1504
|
+
<h3 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: #1f2937;">
|
|
1505
|
+
Payment Under Review
|
|
1506
|
+
</h3>
|
|
1507
|
+
<p style="margin: 0 0 24px 0; color: #6b7280; font-size: 14px; line-height: 1.5;">
|
|
1508
|
+
We're still processing your bank transfer. This is taking longer than usual.
|
|
1509
|
+
</p>
|
|
1510
|
+
|
|
1511
|
+
<!-- What's Happening -->
|
|
1512
|
+
<div style="background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 12px; padding: 16px; margin-bottom: 16px; text-align: left;">
|
|
1513
|
+
<h4 style="margin: 0 0 12px 0; font-size: 14px; font-weight: 600; color: #1e3a8a;">What's happening?</h4>
|
|
1514
|
+
<ul style="margin: 0; padding: 0 0 0 20px; font-size: 13px; color: #1e40af; line-height: 1.6;">
|
|
1515
|
+
<li style="margin-bottom: 8px;">Our team has been notified and is investigating</li>
|
|
1516
|
+
<li style="margin-bottom: 8px;">We're coordinating with our payment partner</li>
|
|
1517
|
+
<li>You'll receive an update via email within 24 hours</li>
|
|
1518
|
+
</ul>
|
|
1519
|
+
</div>
|
|
1520
|
+
|
|
1521
|
+
<!-- Guarantee -->
|
|
1522
|
+
<div style="background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 12px; padding: 16px; margin-bottom: 16px; text-align: left;">
|
|
1523
|
+
<div style="display: flex; align-items: start; gap: 12px;">
|
|
1524
|
+
<div style="color: #16a34a; flex-shrink: 0;">${Icons.checkCircle}</div>
|
|
1525
|
+
<div>
|
|
1526
|
+
<h4 style="margin: 0 0 4px 0; font-size: 14px; font-weight: 600; color: #15803d;">You're Protected</h4>
|
|
1527
|
+
<p style="margin: 0; font-size: 13px; color: #166534; line-height: 1.5;">
|
|
1528
|
+
If we can't deliver your USDC, you'll receive a <strong>full refund</strong> to your bank account within 3-5 business days.
|
|
1529
|
+
</p>
|
|
1530
|
+
</div>
|
|
1531
|
+
</div>
|
|
1532
|
+
</div>
|
|
1533
|
+
|
|
1534
|
+
<!-- Contact Support -->
|
|
1535
|
+
<div style="background: #f9fafb; border-radius: 12px; padding: 16px; text-align: left;">
|
|
1536
|
+
<h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 600; color: #1f2937;">Need help?</h4>
|
|
1537
|
+
<p style="margin: 0 0 12px 0; font-size: 13px; color: #6b7280;">
|
|
1538
|
+
Contact our support team if you have questions:
|
|
1539
|
+
</p>
|
|
1540
|
+
<a
|
|
1541
|
+
href="mailto:tosinoyinboblessed@gmail.com?subject=Payment%20Review%20-%20${orderId}&body=Order%20ID:%20${orderId}%0AEmail:%20${customerEmail}"
|
|
1542
|
+
style="display: block; width: 100%; padding: 12px; background: #1f2937; color: white; text-decoration: none; border-radius: 8px; font-size: 14px; font-weight: 600; text-align: center; transition: background 0.2s;"
|
|
1543
|
+
onmouseover="this.style.background='#111827'"
|
|
1544
|
+
onmouseout="this.style.background='#1f2937'"
|
|
1545
|
+
>
|
|
1546
|
+
Email Support
|
|
1547
|
+
</a>
|
|
1548
|
+
<p style="margin: 12px 0 0 0; font-size: 12px; color: #9ca3af; text-align: center;">
|
|
1549
|
+
Reference: ${orderId.slice(0, 8)}
|
|
1550
|
+
</p>
|
|
1551
|
+
</div>
|
|
1552
|
+
</div>
|
|
1553
|
+
`;
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Handle payment timeout (15 minutes)
|
|
1557
|
+
*/
|
|
1558
|
+
handlePaymentTimeout() {
|
|
1559
|
+
if (this.bankPaymentState.pollingInterval) {
|
|
1560
|
+
clearInterval(this.bankPaymentState.pollingInterval);
|
|
1561
|
+
this.bankPaymentState.pollingInterval = void 0;
|
|
1562
|
+
}
|
|
1563
|
+
if (this.bankPaymentState.timerInterval) {
|
|
1564
|
+
clearInterval(this.bankPaymentState.timerInterval);
|
|
1565
|
+
}
|
|
1566
|
+
this.renderUnderReview();
|
|
1567
|
+
this.config.onError({
|
|
1568
|
+
code: "PAYMENT_TIMEOUT",
|
|
1569
|
+
message: "Payment is taking longer than expected and is now under review",
|
|
1570
|
+
details: {
|
|
1571
|
+
orderId: this.bankPaymentState.orderId,
|
|
1572
|
+
customerEmail: this.bankPaymentState.customerEmail
|
|
1573
|
+
}
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1466
1576
|
/**
|
|
1467
1577
|
* Render error state
|
|
1468
1578
|
*/
|
|
@@ -1470,7 +1580,7 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1470
1580
|
if (!this.container) return;
|
|
1471
1581
|
this.container.innerHTML = `
|
|
1472
1582
|
<div class="zendfi-checkout-error" style="${this.getErrorStyles()}">
|
|
1473
|
-
<div style="
|
|
1583
|
+
<div style="color: #ef4444; margin-bottom: 16px;">${Icons.xCircle}</div>
|
|
1474
1584
|
<h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600; color: #dc2626;">
|
|
1475
1585
|
Payment Failed
|
|
1476
1586
|
</h3>
|
|
@@ -1492,9 +1602,9 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1492
1602
|
if (copyBtn && this.checkoutData) {
|
|
1493
1603
|
copyBtn.addEventListener("click", () => {
|
|
1494
1604
|
navigator.clipboard.writeText(this.checkoutData.wallet_address);
|
|
1495
|
-
copyBtn.
|
|
1605
|
+
copyBtn.innerHTML = `${Icons.check} Copied!`;
|
|
1496
1606
|
setTimeout(() => {
|
|
1497
|
-
copyBtn.
|
|
1607
|
+
copyBtn.innerHTML = `${Icons.clipboard} Copy Address`;
|
|
1498
1608
|
}, 2e3);
|
|
1499
1609
|
});
|
|
1500
1610
|
}
|
|
@@ -1542,13 +1652,13 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1542
1652
|
}
|
|
1543
1653
|
const connectBtn = document.getElementById("zendfi-connect-wallet");
|
|
1544
1654
|
if (connectBtn) {
|
|
1545
|
-
connectBtn.
|
|
1655
|
+
connectBtn.innerHTML = `${Icons.loader} Connecting...`;
|
|
1546
1656
|
connectBtn.disabled = true;
|
|
1547
1657
|
}
|
|
1548
1658
|
await provider.connect();
|
|
1549
1659
|
const publicKey = provider.publicKey.toString();
|
|
1550
1660
|
if (connectBtn) {
|
|
1551
|
-
connectBtn.
|
|
1661
|
+
connectBtn.innerHTML = `${Icons.hammer} Building transaction...`;
|
|
1552
1662
|
}
|
|
1553
1663
|
const response = await fetch(
|
|
1554
1664
|
`${this.config.apiUrl}/api/v1/payments/${this.checkoutData.payment_id}/build-transaction`,
|
|
@@ -1566,14 +1676,14 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1566
1676
|
}
|
|
1567
1677
|
const { transaction: transactionBase64, is_gasless } = await response.json();
|
|
1568
1678
|
if (connectBtn) {
|
|
1569
|
-
connectBtn.
|
|
1679
|
+
connectBtn.innerHTML = `${Icons.loader} Signing...`;
|
|
1570
1680
|
}
|
|
1571
1681
|
const solanaWeb3 = window.solanaWeb3;
|
|
1572
1682
|
const transactionBuffer = Uint8Array.from(atob(transactionBase64), (c) => c.charCodeAt(0));
|
|
1573
1683
|
const transaction = solanaWeb3.Transaction.from(transactionBuffer);
|
|
1574
1684
|
const signedTransaction = await provider.signTransaction(transaction);
|
|
1575
1685
|
if (connectBtn) {
|
|
1576
|
-
connectBtn.
|
|
1686
|
+
connectBtn.innerHTML = `${Icons.loader} Submitting...`;
|
|
1577
1687
|
}
|
|
1578
1688
|
if (is_gasless) {
|
|
1579
1689
|
const serialized = signedTransaction.serialize();
|
|
@@ -1613,13 +1723,13 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1613
1723
|
}
|
|
1614
1724
|
}
|
|
1615
1725
|
if (connectBtn) {
|
|
1616
|
-
connectBtn.
|
|
1726
|
+
connectBtn.innerHTML = `${Icons.loader} Confirming...`;
|
|
1617
1727
|
}
|
|
1618
1728
|
} catch (error) {
|
|
1619
1729
|
console.error("Wallet connection error:", error);
|
|
1620
1730
|
const connectBtn = document.getElementById("zendfi-connect-wallet");
|
|
1621
1731
|
if (connectBtn) {
|
|
1622
|
-
connectBtn.textContent = "
|
|
1732
|
+
connectBtn.textContent = "Connect Wallet";
|
|
1623
1733
|
connectBtn.disabled = false;
|
|
1624
1734
|
}
|
|
1625
1735
|
this.config.onError({
|
|
@@ -1682,6 +1792,38 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1682
1792
|
@keyframes zendfi-spin {
|
|
1683
1793
|
to { transform: rotate(360deg); }
|
|
1684
1794
|
}
|
|
1795
|
+
|
|
1796
|
+
.zendfi-embedded-checkout .icon {
|
|
1797
|
+
width: 20px;
|
|
1798
|
+
height: 20px;
|
|
1799
|
+
display: inline-block;
|
|
1800
|
+
vertical-align: middle;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
.zendfi-embedded-checkout .icon-sm {
|
|
1804
|
+
width: 16px;
|
|
1805
|
+
height: 16px;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
.zendfi-embedded-checkout .icon-lg {
|
|
1809
|
+
width: 64px;
|
|
1810
|
+
height: 64px;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
.zendfi-embedded-checkout .icon-spin {
|
|
1814
|
+
animation: zendfi-spin 0.8s linear infinite;
|
|
1815
|
+
width: 40px;
|
|
1816
|
+
height: 40px;
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
.zendfi-spinner {
|
|
1820
|
+
width: 40px;
|
|
1821
|
+
height: 40px;
|
|
1822
|
+
border: 4px solid #f3f4f6;
|
|
1823
|
+
border-top-color: #667eea;
|
|
1824
|
+
border-radius: 50%;
|
|
1825
|
+
animation: zendfi-spin 0.8s linear infinite;
|
|
1826
|
+
}
|
|
1685
1827
|
`;
|
|
1686
1828
|
document.head.appendChild(style);
|
|
1687
1829
|
}
|
|
@@ -1733,9 +1875,10 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1733
1875
|
font-family: ${theme.fontFamily};
|
|
1734
1876
|
background: ${theme.backgroundColor};
|
|
1735
1877
|
border-radius: ${theme.borderRadius};
|
|
1736
|
-
|
|
1878
|
+
border: 1px solid #e5e7eb;
|
|
1879
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
|
1737
1880
|
overflow: hidden;
|
|
1738
|
-
max-width:
|
|
1881
|
+
max-width: 480px;
|
|
1739
1882
|
margin: 0 auto;
|
|
1740
1883
|
`.replace(/\s+/g, " ").trim();
|
|
1741
1884
|
}
|
|
@@ -1792,7 +1935,9 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1792
1935
|
otp,
|
|
1793
1936
|
fiat_amount: this.checkoutData.amount_usd,
|
|
1794
1937
|
currency: this.checkoutData.currency,
|
|
1795
|
-
payment_link_id: this.checkoutData.payment_link_id
|
|
1938
|
+
payment_link_id: this.checkoutData.payment_link_id,
|
|
1939
|
+
amount_ngn: this.checkoutData.amount_ngn,
|
|
1940
|
+
payer_service_charge: this.checkoutData.payer_service_charge
|
|
1796
1941
|
})
|
|
1797
1942
|
});
|
|
1798
1943
|
if (!response.ok) {
|
|
@@ -1822,7 +1967,8 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1822
1967
|
body: JSON.stringify({
|
|
1823
1968
|
customer_email: email,
|
|
1824
1969
|
fiat_amount: this.checkoutData.amount_usd,
|
|
1825
|
-
payment_link_id: this.checkoutData.payment_link_id
|
|
1970
|
+
payment_link_id: this.checkoutData.payment_link_id,
|
|
1971
|
+
amount_ngn: this.checkoutData.amount_ngn
|
|
1826
1972
|
})
|
|
1827
1973
|
});
|
|
1828
1974
|
if (!response.ok) {
|
|
@@ -1848,6 +1994,7 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1848
1994
|
startBankStatusPolling() {
|
|
1849
1995
|
if (!this.bankPaymentState.orderId) return;
|
|
1850
1996
|
let startTime = Date.now();
|
|
1997
|
+
const TIMEOUT_MS = 15 * 60 * 1e3;
|
|
1851
1998
|
const timerInterval = setInterval(() => {
|
|
1852
1999
|
const elapsed = Math.floor((Date.now() - startTime) / 1e3);
|
|
1853
2000
|
const minutes = Math.floor(elapsed / 60);
|
|
@@ -1856,6 +2003,9 @@ var ZendFiEmbeddedCheckout = class {
|
|
|
1856
2003
|
if (timerEl) {
|
|
1857
2004
|
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
1858
2005
|
}
|
|
2006
|
+
if (Date.now() - startTime > TIMEOUT_MS) {
|
|
2007
|
+
this.handlePaymentTimeout();
|
|
2008
|
+
}
|
|
1859
2009
|
}, 1e3);
|
|
1860
2010
|
const pollInterval = setInterval(async () => {
|
|
1861
2011
|
await this.checkBankPaymentStatus();
|
package/dist/nextjs.d.mts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { W as WebhookHandlerConfig, a as WebhookHandlers } from './webhook-handler-
|
|
1
|
+
import { W as WebhookHandlerConfig, a as WebhookHandlers } from './webhook-handler-hUfWh-_Y.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Next.js Webhook Handler for App Router
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
8
|
-
* // app/api/webhooks/zendfi/route.ts
|
|
9
8
|
* import { createNextWebhookHandler } from '@zendfi/sdk/nextjs';
|
|
10
9
|
*
|
|
11
10
|
* export const POST = createNextWebhookHandler({
|
package/dist/nextjs.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { W as WebhookHandlerConfig, a as WebhookHandlers } from './webhook-handler-
|
|
1
|
+
import { W as WebhookHandlerConfig, a as WebhookHandlers } from './webhook-handler-hUfWh-_Y.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Next.js Webhook Handler for App Router
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
8
|
-
* // app/api/webhooks/zendfi/route.ts
|
|
9
8
|
* import { createNextWebhookHandler } from '@zendfi/sdk/nextjs';
|
|
10
9
|
*
|
|
11
10
|
* export const POST = createNextWebhookHandler({
|
package/dist/nextjs.js
CHANGED
|
@@ -150,7 +150,6 @@ async function processWebhook(a, b, c) {
|
|
|
150
150
|
isProcessed: cfg.isProcessed,
|
|
151
151
|
onProcessed: cfg.onProcessed,
|
|
152
152
|
onError: cfg.onError,
|
|
153
|
-
// Forward compatibility for alternate names and flags
|
|
154
153
|
enableDeduplication: cfg.enableDeduplication,
|
|
155
154
|
checkDuplicate: cfg.checkDuplicate,
|
|
156
155
|
markProcessed: cfg.markProcessed
|