strapi-plugin-payone-provider 1.5.4 → 1.5.5
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.
|
@@ -498,16 +498,28 @@ const ApplePayButton = ({
|
|
|
498
498
|
merchantSessionPromise.then(session => {
|
|
499
499
|
console.log("[Apple Pay] Merchant session received:", {
|
|
500
500
|
hasMerchantIdentifier: !!session.merchantIdentifier,
|
|
501
|
+
merchantIdentifier: session.merchantIdentifier,
|
|
501
502
|
domainName: session.domainName,
|
|
502
|
-
displayName: session.displayName
|
|
503
|
+
displayName: session.displayName,
|
|
504
|
+
epochTimestamp: session.epochTimestamp,
|
|
505
|
+
expiresAt: session.expiresAt,
|
|
506
|
+
fullSession: session
|
|
503
507
|
});
|
|
508
|
+
|
|
509
|
+
// Validate merchant session
|
|
510
|
+
if (!session || (!session.merchantIdentifier && !session.merchantSessionIdentifier)) {
|
|
511
|
+
console.error("[Apple Pay] Invalid merchant session - missing merchantIdentifier");
|
|
512
|
+
console.error("[Apple Pay] Session object:", JSON.stringify(session, null, 2));
|
|
513
|
+
throw new Error("Invalid merchant session: missing merchantIdentifier");
|
|
514
|
+
}
|
|
504
515
|
}).catch(err => {
|
|
505
516
|
console.error("[Apple Pay] Merchant session error:", err);
|
|
506
|
-
//
|
|
517
|
+
// Re-throw so Payment Request API knows validation failed
|
|
518
|
+
throw err;
|
|
507
519
|
});
|
|
508
520
|
|
|
509
521
|
// Complete with the merchant session promise
|
|
510
|
-
// If
|
|
522
|
+
// If the promise rejects, Payment Request API will close the dialog
|
|
511
523
|
event.complete(merchantSessionPromise);
|
|
512
524
|
} catch (error) {
|
|
513
525
|
console.error("[Apple Pay] Merchant validation error:", error);
|
|
@@ -550,17 +562,42 @@ const ApplePayButton = ({
|
|
|
550
562
|
let response;
|
|
551
563
|
try {
|
|
552
564
|
response = await request.show();
|
|
565
|
+
console.log("[Apple Pay] Payment sheet shown successfully");
|
|
553
566
|
} catch (error) {
|
|
554
|
-
console.error("[Apple Pay] Error showing payment sheet:",
|
|
567
|
+
console.error("[Apple Pay] Error showing payment sheet:", {
|
|
568
|
+
name: error.name,
|
|
569
|
+
message: error.message,
|
|
570
|
+
stack: error.stack
|
|
571
|
+
});
|
|
572
|
+
|
|
555
573
|
// Check if error is due to cancellation (user cancelled)
|
|
556
|
-
|
|
574
|
+
// Payment Request API throws "AbortError" when user cancels
|
|
575
|
+
if (error.name === 'AbortError' ||
|
|
576
|
+
(error.message && (
|
|
577
|
+
error.message.includes('Cancelled') ||
|
|
578
|
+
error.message.includes('cancel') ||
|
|
579
|
+
error.message.includes('abort')
|
|
580
|
+
))) {
|
|
557
581
|
console.log("[Apple Pay] User cancelled the payment");
|
|
558
582
|
// Don't call onError for user cancellation
|
|
559
583
|
return;
|
|
560
584
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
585
|
+
|
|
586
|
+
// If it's a merchant validation error, log it specifically
|
|
587
|
+
if (error.message && (
|
|
588
|
+
error.message.includes('merchant') ||
|
|
589
|
+
error.message.includes('validation') ||
|
|
590
|
+
error.message.includes('identifier')
|
|
591
|
+
)) {
|
|
592
|
+
console.error("[Apple Pay] Merchant validation failed - this may cause the dialog to close");
|
|
593
|
+
if (typeof onError === 'function') {
|
|
594
|
+
onError(new Error("Merchant validation failed. Please check your Apple Pay configuration and merchant identifier in Payone settings."));
|
|
595
|
+
}
|
|
596
|
+
} else {
|
|
597
|
+
// For other errors, call onError
|
|
598
|
+
if (typeof onError === 'function') {
|
|
599
|
+
onError(error);
|
|
600
|
+
}
|
|
564
601
|
}
|
|
565
602
|
return;
|
|
566
603
|
}
|
package/package.json
CHANGED
|
@@ -214,43 +214,168 @@ const validateApplePayMerchant = async (strapi, params) => {
|
|
|
214
214
|
strapi.log.info("[Apple Pay] Session initialization result:", {
|
|
215
215
|
status: sessionResponse.status || sessionResponse.Status,
|
|
216
216
|
hasMerchantIdentifier: !!(sessionResponse.merchantIdentifier || sessionResponse.merchantSessionIdentifier),
|
|
217
|
+
hasApplePaySession: !!(sessionResponse["add_paydata[applepay_payment_session]"] ||
|
|
218
|
+
sessionResponse["add_paydata[applepay_payment_session]"] ||
|
|
219
|
+
sessionResponse.add_paydata?.applepay_payment_session),
|
|
217
220
|
fullResponse: JSON.stringify(sessionResponse, null, 2)
|
|
218
221
|
});
|
|
219
222
|
|
|
220
|
-
// If session initialization is successful,
|
|
221
|
-
// Payone
|
|
223
|
+
// If session initialization is successful, extract merchant session from Payone response
|
|
224
|
+
// Payone returns: add_paydata[applepay_payment_session] = BASE64 encoded merchant session
|
|
222
225
|
// Check for both uppercase and lowercase status
|
|
223
226
|
const responseStatus = sessionResponse.status || sessionResponse.Status;
|
|
224
|
-
if (responseStatus === "APPROVED" || responseStatus === "
|
|
225
|
-
responseStatus === "approved" || responseStatus === "
|
|
226
|
-
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
strapi.log.info("[Apple Pay] Merchant session created:", {
|
|
248
|
-
merchantIdentifier: merchantSession.merchantIdentifier,
|
|
249
|
-
domainName: merchantSession.domainName,
|
|
250
|
-
expiresAt: new Date(merchantSession.expiresAt).toISOString()
|
|
227
|
+
if (responseStatus === "APPROVED" || responseStatus === "OK" ||
|
|
228
|
+
responseStatus === "approved" || responseStatus === "ok") {
|
|
229
|
+
|
|
230
|
+
// Extract BASE64 encoded merchant session from Payone response
|
|
231
|
+
// Payone returns it in: add_paydata[applepay_payment_session]
|
|
232
|
+
// Try all possible variations of the field name
|
|
233
|
+
const applePaySessionBase64 =
|
|
234
|
+
sessionResponse["add_paydata[applepay_payment_session]"] ||
|
|
235
|
+
sessionResponse["add_paydata[applepay_payment_session]"] ||
|
|
236
|
+
sessionResponse["add_paydata_applepay_payment_session"] ||
|
|
237
|
+
sessionResponse.add_paydata?.applepay_payment_session ||
|
|
238
|
+
sessionResponse.add_paydata?.["applepay_payment_session"] ||
|
|
239
|
+
sessionResponse["addPaydata[applepay_payment_session]"] ||
|
|
240
|
+
sessionResponse["addPaydata_applepay_payment_session"] ||
|
|
241
|
+
null;
|
|
242
|
+
|
|
243
|
+
strapi.log.info("[Apple Pay] Checking for merchant session in response:", {
|
|
244
|
+
hasWorkorderid: !!sessionResponse.workorderid,
|
|
245
|
+
workorderid: sessionResponse.workorderid,
|
|
246
|
+
allKeys: Object.keys(sessionResponse).filter(k => k.includes('applepay') || k.includes('session') || k.includes('paydata')),
|
|
247
|
+
responseKeys: Object.keys(sessionResponse)
|
|
251
248
|
});
|
|
252
249
|
|
|
253
|
-
|
|
250
|
+
strapi.log.info("[Apple Pay] Extracted Apple Pay session data:", {
|
|
251
|
+
hasBase64Session: !!applePaySessionBase64,
|
|
252
|
+
sessionLength: applePaySessionBase64?.length,
|
|
253
|
+
workorderid: sessionResponse.workorderid
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
if (applePaySessionBase64) {
|
|
257
|
+
try {
|
|
258
|
+
// Decode BASE64 merchant session
|
|
259
|
+
const merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
|
|
260
|
+
const merchantSession = JSON.parse(merchantSessionJson);
|
|
261
|
+
|
|
262
|
+
strapi.log.info("[Apple Pay] Decoded merchant session:", {
|
|
263
|
+
merchantIdentifier: merchantSession.merchantIdentifier,
|
|
264
|
+
domainName: merchantSession.domainName,
|
|
265
|
+
displayName: merchantSession.displayName,
|
|
266
|
+
hasEpochTimestamp: !!merchantSession.epochTimestamp,
|
|
267
|
+
hasExpiresAt: !!merchantSession.expiresAt,
|
|
268
|
+
fullSession: merchantSession
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Validate decoded merchant session
|
|
272
|
+
if (!merchantSession.merchantIdentifier) {
|
|
273
|
+
strapi.log.warn("[Apple Pay] Decoded merchant session missing merchantIdentifier, using fallback");
|
|
274
|
+
// Use fallback merchant identifier
|
|
275
|
+
merchantSession.merchantIdentifier = settings.merchantIdentifier ||
|
|
276
|
+
settings.mid ||
|
|
277
|
+
settings.portalid ||
|
|
278
|
+
`merchant.${domainName}`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Ensure epochTimestamp and expiresAt are in seconds (not milliseconds)
|
|
282
|
+
if (merchantSession.epochTimestamp && merchantSession.epochTimestamp > 1000000000000) {
|
|
283
|
+
// If timestamp is in milliseconds, convert to seconds
|
|
284
|
+
merchantSession.epochTimestamp = Math.floor(merchantSession.epochTimestamp / 1000);
|
|
285
|
+
}
|
|
286
|
+
if (merchantSession.expiresAt && merchantSession.expiresAt > 1000000000000) {
|
|
287
|
+
// If timestamp is in milliseconds, convert to seconds
|
|
288
|
+
merchantSession.expiresAt = Math.floor(merchantSession.expiresAt / 1000);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Validate final merchant session
|
|
292
|
+
if (!merchantSession.merchantIdentifier || merchantSession.merchantIdentifier === 'undefined' || merchantSession.merchantIdentifier === 'null') {
|
|
293
|
+
throw new Error("Decoded merchant session has invalid merchantIdentifier");
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
strapi.log.info("[Apple Pay] Validated merchant session:", {
|
|
297
|
+
merchantIdentifier: merchantSession.merchantIdentifier,
|
|
298
|
+
domainName: merchantSession.domainName,
|
|
299
|
+
epochTimestamp: merchantSession.epochTimestamp,
|
|
300
|
+
expiresAt: merchantSession.expiresAt
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
return merchantSession;
|
|
304
|
+
} catch (decodeError) {
|
|
305
|
+
strapi.log.error("[Apple Pay] Failed to decode merchant session:", {
|
|
306
|
+
error: decodeError.message,
|
|
307
|
+
base64Length: applePaySessionBase64?.length,
|
|
308
|
+
base64Preview: applePaySessionBase64?.substring(0, 100)
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// If decoding fails, we cannot proceed - merchant session is invalid
|
|
312
|
+
throw new Error(`Failed to decode Apple Pay merchant session: ${decodeError.message}`);
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
// If no session data in response, we need to create a valid merchant session
|
|
316
|
+
// According to Payone docs, merchant identifier should be obtained from PMI
|
|
317
|
+
// after domain verification and onboarding
|
|
318
|
+
strapi.log.warn("[Apple Pay] No Apple Pay session data in response, creating merchant session from settings");
|
|
319
|
+
|
|
320
|
+
// Get merchant identifier from settings
|
|
321
|
+
// According to Payone docs, merchant identifier should be visible in PMI after onboarding
|
|
322
|
+
// Path: CONFIGURATION/PAYMENT PORTALS - choose an onboarded Portal - Payment type configuration tab
|
|
323
|
+
let merchantIdentifier = settings.merchantIdentifier ||
|
|
324
|
+
settings.mid ||
|
|
325
|
+
settings.portalid;
|
|
326
|
+
|
|
327
|
+
// If still no merchant identifier, try to construct one from domain
|
|
328
|
+
// But this is not ideal - merchant identifier should come from Payone PMI
|
|
329
|
+
if (!merchantIdentifier) {
|
|
330
|
+
strapi.log.warn("[Apple Pay] No merchant identifier found in settings, using domain-based fallback");
|
|
331
|
+
merchantIdentifier = `merchant.${domainName}`;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Ensure merchant identifier is a string and not empty
|
|
335
|
+
merchantIdentifier = merchantIdentifier.toString().trim();
|
|
336
|
+
if (!merchantIdentifier || merchantIdentifier === 'undefined' || merchantIdentifier === 'null') {
|
|
337
|
+
strapi.log.error("[Apple Pay] Invalid merchant identifier:", merchantIdentifier);
|
|
338
|
+
throw new Error("Merchant identifier is invalid. Please configure a valid merchant identifier in Payone Merchant Interface (PMI) after Apple Pay onboarding. Path: CONFIGURATION → PAYMENT PORTALS → [Your Portal] → Payment type configuration tab");
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Create a valid merchant session object
|
|
342
|
+
// This format is required by Apple Pay Payment Request API
|
|
343
|
+
// IMPORTANT: epochTimestamp and expiresAt must be in seconds (Unix timestamp), not milliseconds
|
|
344
|
+
const merchantSession = {
|
|
345
|
+
epochTimestamp: Math.floor(Date.now() / 1000), // Unix timestamp in seconds
|
|
346
|
+
expiresAt: Math.floor((Date.now() + (5 * 60 * 1000)) / 1000), // 5 minutes from now, in seconds
|
|
347
|
+
merchantSessionIdentifier: `merchant.${domainName}`,
|
|
348
|
+
nonce: generateNonce(),
|
|
349
|
+
merchantIdentifier: merchantIdentifier, // Already validated and converted to string
|
|
350
|
+
domainName: domainName,
|
|
351
|
+
displayName: merchantName
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// Validate merchant session before returning
|
|
355
|
+
if (!merchantSession.merchantIdentifier || merchantSession.merchantIdentifier === 'undefined' || merchantSession.merchantIdentifier === 'null') {
|
|
356
|
+
strapi.log.error("[Apple Pay] Created merchant session is missing or invalid merchantIdentifier!", {
|
|
357
|
+
merchantIdentifier: merchantSession.merchantIdentifier,
|
|
358
|
+
settings: {
|
|
359
|
+
hasMerchantIdentifier: !!settings.merchantIdentifier,
|
|
360
|
+
hasMid: !!settings.mid,
|
|
361
|
+
hasPortalid: !!settings.portalid,
|
|
362
|
+
mid: settings.mid,
|
|
363
|
+
portalid: settings.portalid
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
throw new Error("Merchant identifier is required but not found in settings. Please configure merchant identifier in Payone Merchant Interface (PMI) after Apple Pay onboarding.");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
strapi.log.info("[Apple Pay] Created merchant session from settings:", {
|
|
370
|
+
merchantIdentifier: merchantSession.merchantIdentifier,
|
|
371
|
+
domainName: merchantSession.domainName,
|
|
372
|
+
displayName: merchantSession.displayName,
|
|
373
|
+
epochTimestamp: merchantSession.epochTimestamp,
|
|
374
|
+
expiresAt: merchantSession.expiresAt
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
return merchantSession;
|
|
378
|
+
}
|
|
254
379
|
}
|
|
255
380
|
|
|
256
381
|
// If initialization failed, return empty object
|
|
@@ -24,8 +24,20 @@ const parseResponse = (responseText, logger) => {
|
|
|
24
24
|
const params = new URLSearchParams(responseText);
|
|
25
25
|
const response = {};
|
|
26
26
|
for (const [key, value] of params) {
|
|
27
|
+
// Store both lowercase and original case
|
|
27
28
|
response[key.toLowerCase()] = value;
|
|
28
29
|
response[key] = value;
|
|
30
|
+
|
|
31
|
+
// Also handle add_paydata fields with brackets
|
|
32
|
+
// Payone returns: add_paydata[applepay_payment_session]=BASE64_STRING
|
|
33
|
+
// URLSearchParams handles brackets, but we need to ensure we can access it
|
|
34
|
+
if (key.includes('add_paydata') || key.includes('addPaydata')) {
|
|
35
|
+
// Store with original key format
|
|
36
|
+
response[key] = value;
|
|
37
|
+
// Also try normalized versions
|
|
38
|
+
const normalizedKey = key.replace(/\[/g, '_').replace(/\]/g, '');
|
|
39
|
+
response[normalizedKey] = value;
|
|
40
|
+
}
|
|
29
41
|
}
|
|
30
42
|
return response;
|
|
31
43
|
};
|