@payment-kit-js/vanilla 0.5.9 → 0.5.11
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/{airwallex-apple-pay-adapter-I_pnNYdy.d.mts → airwallex-apple-pay-adapter-BCYt7Jzc.d.mts} +2 -1
- package/dist/airwallex-apple-pay-adapter-BCYt7Jzc.d.mts.map +1 -0
- package/dist/{airwallex-apple-pay-adapter-BE15xREr.mjs → airwallex-apple-pay-adapter-BFsoDoSf.mjs} +6 -2
- package/dist/airwallex-apple-pay-adapter-BFsoDoSf.mjs.map +1 -0
- package/dist/{airwallex-google-pay-adapter-CHol_8f2.mjs → airwallex-google-pay-adapter-B5xmg7b8.mjs} +9 -5
- package/dist/airwallex-google-pay-adapter-B5xmg7b8.mjs.map +1 -0
- package/dist/{airwallex-google-pay-adapter-CY379Rre.d.mts → airwallex-google-pay-adapter-DvEB6t5i.d.mts} +4 -1
- package/dist/airwallex-google-pay-adapter-DvEB6t5i.d.mts.map +1 -0
- package/dist/cdn/paymentkit.js +1244 -139
- package/dist/cdn/paymentkit.js.map +4 -4
- package/dist/cdn/paymentkit.min.js +10 -10
- package/dist/cdn/paymentkit.min.js.map +4 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +7 -1
- package/dist/index.mjs.map +1 -1
- package/dist/payment-methods/airwallex-apple-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/airwallex-apple-pay-adapter.mjs +1 -1
- package/dist/payment-methods/airwallex-google-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/airwallex-google-pay-adapter.mjs +1 -1
- package/dist/payment-methods/apple-pay.d.mts +15 -1
- package/dist/payment-methods/apple-pay.d.mts.map +1 -1
- package/dist/payment-methods/apple-pay.mjs +45 -13
- package/dist/payment-methods/apple-pay.mjs.map +1 -1
- package/dist/payment-methods/card.d.mts.map +1 -1
- package/dist/payment-methods/card.mjs +115 -20
- package/dist/payment-methods/card.mjs.map +1 -1
- package/dist/payment-methods/google-pay.d.mts +19 -2
- package/dist/payment-methods/google-pay.d.mts.map +1 -1
- package/dist/payment-methods/google-pay.mjs +34 -14
- package/dist/payment-methods/google-pay.mjs.map +1 -1
- package/dist/payment-methods/stripe-google-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/stripe-google-pay-adapter.mjs +1 -1
- package/dist/{stripe-google-pay-adapter-CqcUEoM3.mjs → stripe-google-pay-adapter-3cx0KNjK.mjs} +7 -2
- package/dist/stripe-google-pay-adapter-3cx0KNjK.mjs.map +1 -0
- package/dist/{stripe-google-pay-adapter-C3NCBSO3.d.mts → stripe-google-pay-adapter-Bdox4xBq.d.mts} +2 -1
- package/dist/stripe-google-pay-adapter-Bdox4xBq.d.mts.map +1 -0
- package/package.json +4 -7
- package/dist/airwallex-apple-pay-adapter-BE15xREr.mjs.map +0 -1
- package/dist/airwallex-apple-pay-adapter-I_pnNYdy.d.mts.map +0 -1
- package/dist/airwallex-google-pay-adapter-CHol_8f2.mjs.map +0 -1
- package/dist/airwallex-google-pay-adapter-CY379Rre.d.mts.map +0 -1
- package/dist/stripe-google-pay-adapter-C3NCBSO3.d.mts.map +0 -1
- package/dist/stripe-google-pay-adapter-CqcUEoM3.mjs.map +0 -1
package/dist/cdn/paymentkit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PaymentKit.js v0.5.
|
|
2
|
+
* PaymentKit.js v0.5.11
|
|
3
3
|
* https://paymentkit.com
|
|
4
4
|
*
|
|
5
5
|
* @license MIT
|
|
@@ -42,7 +42,7 @@ var PaymentKit = (() => {
|
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
// package.json
|
|
45
|
-
var version = "0.5.
|
|
45
|
+
var version = "0.5.11";
|
|
46
46
|
|
|
47
47
|
// src/analytics/mock-adapter.ts
|
|
48
48
|
var MockAnalyticsAdapter = class {
|
|
@@ -6465,6 +6465,7 @@ var PaymentKit = (() => {
|
|
|
6465
6465
|
checkout_token: token,
|
|
6466
6466
|
api_base_url: apiBaseUrl
|
|
6467
6467
|
});
|
|
6468
|
+
Object.assign(iframe.style, { width: "0", height: "0", position: "absolute", visibility: "hidden" });
|
|
6468
6469
|
document.body.appendChild(iframe);
|
|
6469
6470
|
const connection = connectToTunnelXIframe(iframe, {});
|
|
6470
6471
|
const unmount = () => {
|
|
@@ -6597,9 +6598,214 @@ var PaymentKit = (() => {
|
|
|
6597
6598
|
};
|
|
6598
6599
|
var index_default = PaymentKit;
|
|
6599
6600
|
|
|
6600
|
-
// src/
|
|
6601
|
-
var
|
|
6602
|
-
|
|
6601
|
+
// src/payment-methods/airwallex-apple-pay-adapter.ts
|
|
6602
|
+
var AirwallexApplePayAdapter = class {
|
|
6603
|
+
constructor(mockScenario) {
|
|
6604
|
+
__publicField(this, "config", null);
|
|
6605
|
+
__publicField(this, "mockScenario");
|
|
6606
|
+
this.mockScenario = mockScenario ?? "none" /* None */;
|
|
6607
|
+
}
|
|
6608
|
+
/**
|
|
6609
|
+
* Initialize the adapter with payment configuration.
|
|
6610
|
+
* Returns true if Apple Pay is available on this device.
|
|
6611
|
+
*/
|
|
6612
|
+
initialize(config) {
|
|
6613
|
+
if (this.mockScenario !== "none" /* None */) {
|
|
6614
|
+
console.log("[MockApplePay:Airwallex] initialize called (mock mode)");
|
|
6615
|
+
this.config = config;
|
|
6616
|
+
return true;
|
|
6617
|
+
}
|
|
6618
|
+
if (typeof window === "undefined" || !window.ApplePaySession) {
|
|
6619
|
+
console.error("[ApplePay:Airwallex] ApplePaySession not available (not Safari or unsupported device)");
|
|
6620
|
+
return false;
|
|
6621
|
+
}
|
|
6622
|
+
this.config = config;
|
|
6623
|
+
return true;
|
|
6624
|
+
}
|
|
6625
|
+
/**
|
|
6626
|
+
* Check if the user can make a payment with Apple Pay.
|
|
6627
|
+
* Returns true if Apple Pay is set up on this device.
|
|
6628
|
+
*/
|
|
6629
|
+
async canMakePayment() {
|
|
6630
|
+
if (this.mockScenario !== "none" /* None */) {
|
|
6631
|
+
console.log("[MockApplePay:Airwallex] canMakePayment: true (mock mode)");
|
|
6632
|
+
return true;
|
|
6633
|
+
}
|
|
6634
|
+
if (!window.ApplePaySession) {
|
|
6635
|
+
return false;
|
|
6636
|
+
}
|
|
6637
|
+
try {
|
|
6638
|
+
const canMake = window.ApplePaySession.canMakePayments();
|
|
6639
|
+
console.log("[ApplePay:Airwallex] canMakePayments:", canMake);
|
|
6640
|
+
return canMake;
|
|
6641
|
+
} catch (error) {
|
|
6642
|
+
console.error("[ApplePay:Airwallex] canMakePayment error:", error);
|
|
6643
|
+
return false;
|
|
6644
|
+
}
|
|
6645
|
+
}
|
|
6646
|
+
/**
|
|
6647
|
+
* Convert atomic units (cents) to display format for Apple Pay.
|
|
6648
|
+
* Apple Pay expects a string like "10.00" for $10.00.
|
|
6649
|
+
*/
|
|
6650
|
+
formatAmount(amountAtom, currency) {
|
|
6651
|
+
const zeroDecimalCurrencies = [
|
|
6652
|
+
"BIF",
|
|
6653
|
+
"CLP",
|
|
6654
|
+
"DJF",
|
|
6655
|
+
"GNF",
|
|
6656
|
+
"ISK",
|
|
6657
|
+
"JPY",
|
|
6658
|
+
"KMF",
|
|
6659
|
+
"KRW",
|
|
6660
|
+
"PYG",
|
|
6661
|
+
"RWF",
|
|
6662
|
+
"UGX",
|
|
6663
|
+
"VND",
|
|
6664
|
+
"VUV",
|
|
6665
|
+
"XAF",
|
|
6666
|
+
"XOF",
|
|
6667
|
+
"XPF"
|
|
6668
|
+
];
|
|
6669
|
+
const isZeroDecimal = zeroDecimalCurrencies.includes(currency.toUpperCase());
|
|
6670
|
+
if (isZeroDecimal) {
|
|
6671
|
+
return amountAtom.toString();
|
|
6672
|
+
}
|
|
6673
|
+
return (amountAtom / 100).toFixed(2);
|
|
6674
|
+
}
|
|
6675
|
+
/**
|
|
6676
|
+
* Show the Apple Pay payment sheet and return the encrypted token.
|
|
6677
|
+
*
|
|
6678
|
+
* This uses the native ApplePaySession API with a two-step flow:
|
|
6679
|
+
* 1. onvalidatemerchant - Called by Apple to validate the merchant
|
|
6680
|
+
* The callback should call our backend which calls Airwallex's payment_session/start
|
|
6681
|
+
* 2. onpaymentauthorized - Called when user authorizes with Face ID/Touch ID
|
|
6682
|
+
* Returns the encrypted token for processing
|
|
6683
|
+
*
|
|
6684
|
+
* @param onMerchantValidation - Callback to validate merchant with backend
|
|
6685
|
+
* @returns Promise with token or error
|
|
6686
|
+
*/
|
|
6687
|
+
async showPaymentSheet(onMerchantValidation) {
|
|
6688
|
+
if (this.mockScenario === "success" /* Success */) {
|
|
6689
|
+
console.log("[MockApplePay:Airwallex] showPaymentSheet: returning mock success token");
|
|
6690
|
+
const mockToken = {
|
|
6691
|
+
paymentData: {
|
|
6692
|
+
version: "EC_v1",
|
|
6693
|
+
data: "MOCK_ENCRYPTED_DATA",
|
|
6694
|
+
signature: "MOCK_SIGNATURE",
|
|
6695
|
+
header: {
|
|
6696
|
+
ephemeralPublicKey: "MOCK_PUBLIC_KEY",
|
|
6697
|
+
publicKeyHash: "MOCK_HASH",
|
|
6698
|
+
transactionId: "mock_txn_123"
|
|
6699
|
+
}
|
|
6700
|
+
},
|
|
6701
|
+
paymentMethod: {
|
|
6702
|
+
displayName: "Visa 4242",
|
|
6703
|
+
network: "Visa",
|
|
6704
|
+
type: "debit"
|
|
6705
|
+
},
|
|
6706
|
+
transactionIdentifier: "MOCK_TXN_ID"
|
|
6707
|
+
};
|
|
6708
|
+
return {
|
|
6709
|
+
success: true,
|
|
6710
|
+
token: mockToken,
|
|
6711
|
+
payerEmail: "mock@example.com",
|
|
6712
|
+
complete: (status) => console.log(`[MockApplePay:Airwallex] complete: ${status}`)
|
|
6713
|
+
};
|
|
6714
|
+
}
|
|
6715
|
+
if (this.mockScenario === "cancelled" /* Cancelled */) {
|
|
6716
|
+
console.log("[MockApplePay:Airwallex] showPaymentSheet: returning mock cancelled");
|
|
6717
|
+
return { success: false, cancelled: true };
|
|
6718
|
+
}
|
|
6719
|
+
if (!this.config) {
|
|
6720
|
+
return { success: false, error: "Apple Pay not initialized" };
|
|
6721
|
+
}
|
|
6722
|
+
if (!window.ApplePaySession) {
|
|
6723
|
+
return { success: false, error: "ApplePaySession not available" };
|
|
6724
|
+
}
|
|
6725
|
+
const config = this.config;
|
|
6726
|
+
const amount = this.formatAmount(config.amount, config.currency);
|
|
6727
|
+
const paymentRequest = {
|
|
6728
|
+
countryCode: config.country.toUpperCase(),
|
|
6729
|
+
currencyCode: config.currency.toUpperCase(),
|
|
6730
|
+
supportedNetworks: ["visa", "masterCard", "amex", "discover"],
|
|
6731
|
+
merchantCapabilities: ["supports3DS"],
|
|
6732
|
+
total: {
|
|
6733
|
+
label: config.merchantName || "Total",
|
|
6734
|
+
amount,
|
|
6735
|
+
type: "final"
|
|
6736
|
+
},
|
|
6737
|
+
// Surface the payer's email so the backend can fill missing customer email.
|
|
6738
|
+
requiredBillingContactFields: ["email"]
|
|
6739
|
+
};
|
|
6740
|
+
return new Promise((resolve) => {
|
|
6741
|
+
try {
|
|
6742
|
+
const session = new window.ApplePaySession(3, paymentRequest);
|
|
6743
|
+
const STATUS_SUCCESS = window.ApplePaySession.STATUS_SUCCESS;
|
|
6744
|
+
const STATUS_FAILURE = window.ApplePaySession.STATUS_FAILURE;
|
|
6745
|
+
session.onvalidatemerchant = async (event) => {
|
|
6746
|
+
console.log("[ApplePay:Airwallex] onvalidatemerchant called", event.validationURL);
|
|
6747
|
+
try {
|
|
6748
|
+
const validationResult = await onMerchantValidation(event.validationURL);
|
|
6749
|
+
if (validationResult.error || !validationResult.merchantSession) {
|
|
6750
|
+
console.error("[ApplePay:Airwallex] Merchant validation failed:", validationResult.error);
|
|
6751
|
+
session.abort();
|
|
6752
|
+
resolve({
|
|
6753
|
+
success: false,
|
|
6754
|
+
error: validationResult.error || "Merchant validation failed"
|
|
6755
|
+
});
|
|
6756
|
+
return;
|
|
6757
|
+
}
|
|
6758
|
+
session.completeMerchantValidation(validationResult.merchantSession);
|
|
6759
|
+
console.log("[ApplePay:Airwallex] Merchant validation completed");
|
|
6760
|
+
} catch (error) {
|
|
6761
|
+
console.error("[ApplePay:Airwallex] Merchant validation error:", error);
|
|
6762
|
+
session.abort();
|
|
6763
|
+
resolve({
|
|
6764
|
+
success: false,
|
|
6765
|
+
error: `Merchant validation error: ${error}`
|
|
6766
|
+
});
|
|
6767
|
+
}
|
|
6768
|
+
};
|
|
6769
|
+
session.onpaymentauthorized = (event) => {
|
|
6770
|
+
console.log("[ApplePay:Airwallex] onpaymentauthorized called");
|
|
6771
|
+
const payment = event.payment;
|
|
6772
|
+
const token = {
|
|
6773
|
+
paymentData: payment.token.paymentData,
|
|
6774
|
+
paymentMethod: {
|
|
6775
|
+
displayName: payment.token.paymentMethod.displayName,
|
|
6776
|
+
network: payment.token.paymentMethod.network,
|
|
6777
|
+
type: payment.token.paymentMethod.type
|
|
6778
|
+
},
|
|
6779
|
+
transactionIdentifier: payment.token.transactionIdentifier
|
|
6780
|
+
};
|
|
6781
|
+
const payerEmail = payment.billingContact?.emailAddress ?? payment.shippingContact?.emailAddress ?? void 0;
|
|
6782
|
+
const complete = (status) => {
|
|
6783
|
+
console.log("[ApplePay:Airwallex] completing session with status:", status);
|
|
6784
|
+
const appleStatus = status === "success" ? STATUS_SUCCESS : STATUS_FAILURE;
|
|
6785
|
+
session.completePayment({ status: appleStatus });
|
|
6786
|
+
};
|
|
6787
|
+
resolve({
|
|
6788
|
+
success: true,
|
|
6789
|
+
token,
|
|
6790
|
+
payerEmail,
|
|
6791
|
+
complete
|
|
6792
|
+
});
|
|
6793
|
+
};
|
|
6794
|
+
session.oncancel = () => {
|
|
6795
|
+
console.log("[ApplePay:Airwallex] oncancel - user cancelled");
|
|
6796
|
+
resolve({ success: false, cancelled: true });
|
|
6797
|
+
};
|
|
6798
|
+
console.log("[ApplePay:Airwallex] Starting Apple Pay session");
|
|
6799
|
+
session.begin();
|
|
6800
|
+
} catch (error) {
|
|
6801
|
+
console.error("[ApplePay:Airwallex] Session creation error:", error);
|
|
6802
|
+
resolve({
|
|
6803
|
+
success: false,
|
|
6804
|
+
error: `Failed to create Apple Pay session: ${error}`
|
|
6805
|
+
});
|
|
6806
|
+
}
|
|
6807
|
+
});
|
|
6808
|
+
}
|
|
6603
6809
|
};
|
|
6604
6810
|
|
|
6605
6811
|
// src/utils/3ds-iframe-modal.ts
|
|
@@ -6725,91 +6931,863 @@ var PaymentKit = (() => {
|
|
|
6725
6931
|
resolve({ success: false, error: "Verification cancelled" });
|
|
6726
6932
|
}
|
|
6727
6933
|
};
|
|
6728
|
-
closeButton.onclick = handleCancel;
|
|
6729
|
-
const handleKeydown = (event) => {
|
|
6730
|
-
if (event.key === "Escape") {
|
|
6731
|
-
handleCancel();
|
|
6732
|
-
}
|
|
6733
|
-
if (event.key === "Tab") {
|
|
6734
|
-
event.preventDefault();
|
|
6735
|
-
if (document.activeElement === closeButton) {
|
|
6736
|
-
iframe.focus();
|
|
6737
|
-
} else {
|
|
6738
|
-
closeButton.focus();
|
|
6739
|
-
}
|
|
6740
|
-
}
|
|
6934
|
+
closeButton.onclick = handleCancel;
|
|
6935
|
+
const handleKeydown = (event) => {
|
|
6936
|
+
if (event.key === "Escape") {
|
|
6937
|
+
handleCancel();
|
|
6938
|
+
}
|
|
6939
|
+
if (event.key === "Tab") {
|
|
6940
|
+
event.preventDefault();
|
|
6941
|
+
if (document.activeElement === closeButton) {
|
|
6942
|
+
iframe.focus();
|
|
6943
|
+
} else {
|
|
6944
|
+
closeButton.focus();
|
|
6945
|
+
}
|
|
6946
|
+
}
|
|
6947
|
+
};
|
|
6948
|
+
window.addEventListener("keydown", handleKeydown);
|
|
6949
|
+
closeButton.focus();
|
|
6950
|
+
const handleMessage = (event) => {
|
|
6951
|
+
const messageResult = onMessage(event);
|
|
6952
|
+
if (messageResult.handled) {
|
|
6953
|
+
cleanupWithAnimation();
|
|
6954
|
+
resolve(messageResult.result);
|
|
6955
|
+
}
|
|
6956
|
+
};
|
|
6957
|
+
window.addEventListener("message", handleMessage);
|
|
6958
|
+
});
|
|
6959
|
+
}
|
|
6960
|
+
|
|
6961
|
+
// src/payment-methods/next-action-handlers.ts
|
|
6962
|
+
var sleep = (ms2) => new Promise((resolve) => setTimeout(resolve, ms2));
|
|
6963
|
+
var isStripeJsPresent = () => "Stripe" in window;
|
|
6964
|
+
var getLoadedStripe = async (publishableKey) => {
|
|
6965
|
+
for (let i2 = 0; i2 < 10; i2++) {
|
|
6966
|
+
if (isStripeJsPresent()) {
|
|
6967
|
+
break;
|
|
6968
|
+
}
|
|
6969
|
+
await sleep(500);
|
|
6970
|
+
}
|
|
6971
|
+
if (!isStripeJsPresent()) {
|
|
6972
|
+
throw new Error(
|
|
6973
|
+
'Stripe.js not loaded. Add this script tag to your HTML <head>:\n<script src="https://js.stripe.com/v3/"><\/script>'
|
|
6974
|
+
);
|
|
6975
|
+
}
|
|
6976
|
+
const stripe = new window.Stripe(publishableKey);
|
|
6977
|
+
return stripe;
|
|
6978
|
+
};
|
|
6979
|
+
var handleStripe3ds = async (nextAction) => {
|
|
6980
|
+
const { clientSecret, stripePk } = nextAction;
|
|
6981
|
+
const stripe = await getLoadedStripe(stripePk);
|
|
6982
|
+
const { error: stripeError } = await stripe.confirmCardPayment(clientSecret);
|
|
6983
|
+
if (stripeError) {
|
|
6984
|
+
console.error("[3DS:Stripe] Authentication failed:", stripeError.message);
|
|
6985
|
+
return { success: false, error: stripeError.message || "3DS authentication failed" };
|
|
6986
|
+
}
|
|
6987
|
+
return { success: true };
|
|
6988
|
+
};
|
|
6989
|
+
var handleAirwallex3ds = async (nextAction) => {
|
|
6990
|
+
return show3DSIframeModal({
|
|
6991
|
+
url: nextAction.url,
|
|
6992
|
+
size: { width: 605, height: 550 },
|
|
6993
|
+
onMessage: (event) => {
|
|
6994
|
+
if (event.data.type !== "3ds_complete") {
|
|
6995
|
+
return { handled: false };
|
|
6996
|
+
}
|
|
6997
|
+
const { isSuccess, error } = event.data;
|
|
6998
|
+
if (isSuccess) {
|
|
6999
|
+
return { handled: true, result: { success: true, data: {} } };
|
|
7000
|
+
} else {
|
|
7001
|
+
console.error("[3DS:Airwallex] Authentication failed:", error);
|
|
7002
|
+
return {
|
|
7003
|
+
handled: true,
|
|
7004
|
+
result: { success: false, error: error || "3DS authentication failed" }
|
|
7005
|
+
};
|
|
7006
|
+
}
|
|
7007
|
+
}
|
|
7008
|
+
});
|
|
7009
|
+
};
|
|
7010
|
+
var handleNextAction = async (nextAction) => {
|
|
7011
|
+
switch (nextAction.type) {
|
|
7012
|
+
case "stripe_3ds":
|
|
7013
|
+
return handleStripe3ds(nextAction);
|
|
7014
|
+
case "airwallex_3ds":
|
|
7015
|
+
return handleAirwallex3ds(nextAction);
|
|
7016
|
+
default:
|
|
7017
|
+
return { success: false, error: `Unknown next action type: ${nextAction.type}` };
|
|
7018
|
+
}
|
|
7019
|
+
};
|
|
7020
|
+
|
|
7021
|
+
// src/payment-methods/stripe-apple-pay-adapter.ts
|
|
7022
|
+
var StripeApplePayAdapter = class {
|
|
7023
|
+
constructor(mockScenario) {
|
|
7024
|
+
__publicField(this, "stripe", null);
|
|
7025
|
+
__publicField(this, "mockScenario");
|
|
7026
|
+
__publicField(this, "preparedPaymentRequest", null);
|
|
7027
|
+
this.mockScenario = mockScenario ?? "none" /* None */;
|
|
7028
|
+
}
|
|
7029
|
+
initialize(publishableKey) {
|
|
7030
|
+
switch (this.mockScenario) {
|
|
7031
|
+
case "none" /* None */: {
|
|
7032
|
+
console.log("[ApplePay] initialize called");
|
|
7033
|
+
if (!window.Stripe) {
|
|
7034
|
+
console.log("[ApplePay] Stripe.js not loaded");
|
|
7035
|
+
return false;
|
|
7036
|
+
}
|
|
7037
|
+
this.stripe = window.Stripe(publishableKey);
|
|
7038
|
+
const success = this.stripe !== null;
|
|
7039
|
+
console.log("[ApplePay] initialize result:", success);
|
|
7040
|
+
return success;
|
|
7041
|
+
}
|
|
7042
|
+
case "success" /* Success */:
|
|
7043
|
+
case "cancelled" /* Cancelled */: {
|
|
7044
|
+
console.log("[MockApplePay] initialize called");
|
|
7045
|
+
console.log("[MockApplePay] initialize result:", true);
|
|
7046
|
+
return true;
|
|
7047
|
+
}
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
/**
|
|
7051
|
+
* Check if Apple Pay is available on this device/browser.
|
|
7052
|
+
* Uses Stripe's PaymentRequest.canMakePayment() which is more reliable
|
|
7053
|
+
* than checking ApplePaySession directly.
|
|
7054
|
+
*/
|
|
7055
|
+
static isAvailable() {
|
|
7056
|
+
if (typeof window === "undefined" || !window.ApplePaySession) {
|
|
7057
|
+
console.log("[ApplePay] ApplePaySession not available");
|
|
7058
|
+
return false;
|
|
7059
|
+
}
|
|
7060
|
+
const canMakePayments = window.ApplePaySession.canMakePayments();
|
|
7061
|
+
console.log("[ApplePay] canMakePayments:", canMakePayments);
|
|
7062
|
+
return canMakePayments;
|
|
7063
|
+
}
|
|
7064
|
+
/**
|
|
7065
|
+
* Check availability using Stripe's PaymentRequest API.
|
|
7066
|
+
* This is more accurate as it checks Stripe's configuration too.
|
|
7067
|
+
*/
|
|
7068
|
+
async canMakePayment() {
|
|
7069
|
+
if (!this.stripe) {
|
|
7070
|
+
console.log("[ApplePay] Stripe not initialized");
|
|
7071
|
+
return null;
|
|
7072
|
+
}
|
|
7073
|
+
const pr2 = this.stripe.paymentRequest({
|
|
7074
|
+
country: "US",
|
|
7075
|
+
currency: "usd",
|
|
7076
|
+
total: { label: "Check", amount: 100 }
|
|
7077
|
+
});
|
|
7078
|
+
const result = await pr2.canMakePayment();
|
|
7079
|
+
console.log("[ApplePay] canMakePayment result:", result);
|
|
7080
|
+
if (!result) {
|
|
7081
|
+
return null;
|
|
7082
|
+
}
|
|
7083
|
+
return {
|
|
7084
|
+
applePay: result.applePay ?? false,
|
|
7085
|
+
googlePay: result.googlePay ?? false
|
|
7086
|
+
};
|
|
7087
|
+
}
|
|
7088
|
+
/**
|
|
7089
|
+
* Prepare a PaymentRequest for later use. Call this BEFORE the user clicks.
|
|
7090
|
+
* This creates the PaymentRequest and calls canMakePayment() to validate.
|
|
7091
|
+
*
|
|
7092
|
+
* @returns Promise with success status and whether Apple Pay is available
|
|
7093
|
+
*/
|
|
7094
|
+
async preparePaymentRequest(config) {
|
|
7095
|
+
if (this.mockScenario !== "none" /* None */) {
|
|
7096
|
+
console.log("[MockApplePay] preparePaymentRequest called");
|
|
7097
|
+
this.preparedConfig = config;
|
|
7098
|
+
return { success: true, applePay: true, googlePay: false };
|
|
7099
|
+
}
|
|
7100
|
+
console.log("[ApplePay] preparePaymentRequest called", config);
|
|
7101
|
+
if (!this.stripe) {
|
|
7102
|
+
return { success: false, error: "Stripe not initialized" };
|
|
7103
|
+
}
|
|
7104
|
+
const paymentRequest = this.stripe.paymentRequest({
|
|
7105
|
+
country: config.country,
|
|
7106
|
+
currency: config.currency.toLowerCase(),
|
|
7107
|
+
total: {
|
|
7108
|
+
label: config.total.label,
|
|
7109
|
+
amount: config.total.amount
|
|
7110
|
+
},
|
|
7111
|
+
requestPayerName: true,
|
|
7112
|
+
requestPayerEmail: true
|
|
7113
|
+
});
|
|
7114
|
+
const canMakePaymentResult = await paymentRequest.canMakePayment();
|
|
7115
|
+
console.log("[ApplePay] preparePaymentRequest canMakePayment:", canMakePaymentResult);
|
|
7116
|
+
if (!canMakePaymentResult) {
|
|
7117
|
+
return {
|
|
7118
|
+
success: false,
|
|
7119
|
+
error: "Payment methods not available on this device/browser",
|
|
7120
|
+
applePay: false,
|
|
7121
|
+
googlePay: false
|
|
7122
|
+
};
|
|
7123
|
+
}
|
|
7124
|
+
this.preparedPaymentRequest = paymentRequest;
|
|
7125
|
+
this.preparedConfig = config;
|
|
7126
|
+
return {
|
|
7127
|
+
success: true,
|
|
7128
|
+
applePay: canMakePaymentResult.applePay ?? false,
|
|
7129
|
+
googlePay: canMakePaymentResult.googlePay ?? false
|
|
7130
|
+
};
|
|
7131
|
+
}
|
|
7132
|
+
/**
|
|
7133
|
+
* Check if a PaymentRequest has been prepared and is ready to show.
|
|
7134
|
+
*/
|
|
7135
|
+
isPrepared() {
|
|
7136
|
+
return this.preparedPaymentRequest !== null || this.mockScenario !== "none" /* None */;
|
|
7137
|
+
}
|
|
7138
|
+
/**
|
|
7139
|
+
* Clear the prepared PaymentRequest.
|
|
7140
|
+
*/
|
|
7141
|
+
clearPrepared() {
|
|
7142
|
+
this.preparedPaymentRequest = null;
|
|
7143
|
+
this.preparedConfig = null;
|
|
7144
|
+
}
|
|
7145
|
+
/**
|
|
7146
|
+
* Show the prepared Apple Pay payment sheet.
|
|
7147
|
+
* MUST be called synchronously from a user click handler.
|
|
7148
|
+
* Call preparePaymentRequest() before the click to set up the PaymentRequest.
|
|
7149
|
+
*/
|
|
7150
|
+
showPreparedPaymentSheet() {
|
|
7151
|
+
switch (this.mockScenario) {
|
|
7152
|
+
case "none" /* None */: {
|
|
7153
|
+
console.log("[ApplePay] showPreparedPaymentSheet called");
|
|
7154
|
+
if (!this.preparedPaymentRequest) {
|
|
7155
|
+
console.error("[ApplePay] No prepared PaymentRequest! Call preparePaymentRequest() first.");
|
|
7156
|
+
return Promise.resolve({
|
|
7157
|
+
success: false,
|
|
7158
|
+
error: "PaymentRequest not prepared. Call preparePaymentRequest() before showing the sheet."
|
|
7159
|
+
});
|
|
7160
|
+
}
|
|
7161
|
+
const paymentRequest = this.preparedPaymentRequest;
|
|
7162
|
+
return new Promise((resolve) => {
|
|
7163
|
+
paymentRequest.on("paymentmethod", (evt) => {
|
|
7164
|
+
console.log("[ApplePay] paymentmethod event received", {
|
|
7165
|
+
paymentMethodId: evt.paymentMethod.id,
|
|
7166
|
+
payerEmail: evt.payerEmail,
|
|
7167
|
+
payerName: evt.payerName
|
|
7168
|
+
});
|
|
7169
|
+
this.preparedPaymentRequest = null;
|
|
7170
|
+
resolve({
|
|
7171
|
+
success: true,
|
|
7172
|
+
paymentMethodId: evt.paymentMethod.id,
|
|
7173
|
+
paymentMethodEvent: evt,
|
|
7174
|
+
billingDetails: {
|
|
7175
|
+
email: evt.payerEmail ?? void 0,
|
|
7176
|
+
name: evt.payerName ?? void 0,
|
|
7177
|
+
address: evt.paymentMethod.billing_details?.address ?? void 0
|
|
7178
|
+
}
|
|
7179
|
+
});
|
|
7180
|
+
});
|
|
7181
|
+
paymentRequest.on("cancel", () => {
|
|
7182
|
+
console.log("[ApplePay] cancel event - user cancelled");
|
|
7183
|
+
this.preparedPaymentRequest = null;
|
|
7184
|
+
resolve({ success: false, cancelled: true });
|
|
7185
|
+
});
|
|
7186
|
+
console.log("[ApplePay] showing payment sheet");
|
|
7187
|
+
paymentRequest.show();
|
|
7188
|
+
});
|
|
7189
|
+
}
|
|
7190
|
+
case "success" /* Success */: {
|
|
7191
|
+
console.log("[MockApplePay] showPreparedPaymentSheet: success");
|
|
7192
|
+
return new Promise((resolve) => {
|
|
7193
|
+
setTimeout(() => {
|
|
7194
|
+
resolve({
|
|
7195
|
+
success: true,
|
|
7196
|
+
paymentMethodId: "pm_mock_apple_pay_test",
|
|
7197
|
+
paymentMethodEvent: {
|
|
7198
|
+
complete: (status) => console.log(`[MockApplePay] complete: ${status}`),
|
|
7199
|
+
paymentMethod: {
|
|
7200
|
+
id: "pm_mock_apple_pay_test",
|
|
7201
|
+
object: "payment_method",
|
|
7202
|
+
type: "card",
|
|
7203
|
+
card: {
|
|
7204
|
+
brand: "visa",
|
|
7205
|
+
last4: "4242",
|
|
7206
|
+
exp_month: 12,
|
|
7207
|
+
exp_year: 2030
|
|
7208
|
+
},
|
|
7209
|
+
billing_details: {
|
|
7210
|
+
email: "test@example.com",
|
|
7211
|
+
name: "Test User"
|
|
7212
|
+
}
|
|
7213
|
+
},
|
|
7214
|
+
payerEmail: "test@example.com",
|
|
7215
|
+
payerName: "Test User"
|
|
7216
|
+
},
|
|
7217
|
+
billingDetails: {
|
|
7218
|
+
email: "test@example.com",
|
|
7219
|
+
name: "Test User"
|
|
7220
|
+
}
|
|
7221
|
+
});
|
|
7222
|
+
}, 500);
|
|
7223
|
+
});
|
|
7224
|
+
}
|
|
7225
|
+
case "cancelled" /* Cancelled */: {
|
|
7226
|
+
console.log("[MockApplePay] showPreparedPaymentSheet: cancelled");
|
|
7227
|
+
return new Promise((resolve) => {
|
|
7228
|
+
setTimeout(() => {
|
|
7229
|
+
resolve({ success: false, cancelled: true });
|
|
7230
|
+
}, 500);
|
|
7231
|
+
});
|
|
7232
|
+
}
|
|
7233
|
+
}
|
|
7234
|
+
}
|
|
7235
|
+
/**
|
|
7236
|
+
* @deprecated Use preparePaymentRequest() + showPreparedPaymentSheet() instead.
|
|
7237
|
+
* This method creates a new PaymentRequest and shows it, which doesn't work
|
|
7238
|
+
* with browser security requirements (show() must be called synchronously).
|
|
7239
|
+
*/
|
|
7240
|
+
async showPaymentSheet(config) {
|
|
7241
|
+
console.warn(
|
|
7242
|
+
"[ApplePay] showPaymentSheet is deprecated. Use preparePaymentRequest() + showPreparedPaymentSheet() instead."
|
|
7243
|
+
);
|
|
7244
|
+
const prepareResult = await this.preparePaymentRequest(config);
|
|
7245
|
+
if (!prepareResult.success) {
|
|
7246
|
+
return { success: false, error: prepareResult.error ?? "Failed to prepare payment request" };
|
|
7247
|
+
}
|
|
7248
|
+
return this.showPreparedPaymentSheet();
|
|
7249
|
+
}
|
|
7250
|
+
/**
|
|
7251
|
+
* Complete the payment flow in the Apple Pay sheet.
|
|
7252
|
+
* Call this after confirming the payment on the server.
|
|
7253
|
+
*
|
|
7254
|
+
* @param evt - The PaymentRequestPaymentMethodEvent from showPaymentSheet
|
|
7255
|
+
* @param status - 'success' or 'fail'
|
|
7256
|
+
*/
|
|
7257
|
+
completePayment(evt, status) {
|
|
7258
|
+
console.log("[ApplePay] completePayment:", status);
|
|
7259
|
+
evt.complete(status);
|
|
7260
|
+
}
|
|
7261
|
+
/**
|
|
7262
|
+
* Confirm PaymentIntent with the PaymentMethod.
|
|
7263
|
+
* This is called after showPaymentSheet to finalize the payment.
|
|
7264
|
+
*
|
|
7265
|
+
* @deprecated - Server-side confirmation is preferred. The backend should
|
|
7266
|
+
* call stripe.PaymentIntent.confirm() with the payment_method_id.
|
|
7267
|
+
*/
|
|
7268
|
+
async confirmPaymentIntent(clientSecret, paymentMethodId) {
|
|
7269
|
+
switch (this.mockScenario) {
|
|
7270
|
+
case "none" /* None */: {
|
|
7271
|
+
console.log("[ApplePay] confirmPaymentIntent called", {
|
|
7272
|
+
clientSecret: `${clientSecret.slice(0, 20)}...`,
|
|
7273
|
+
paymentMethodId
|
|
7274
|
+
});
|
|
7275
|
+
if (!this.stripe) {
|
|
7276
|
+
console.log("[ApplePay] confirmPaymentIntent: Stripe not initialized");
|
|
7277
|
+
return { success: false, error: "Stripe not initialized" };
|
|
7278
|
+
}
|
|
7279
|
+
const { error } = await this.stripe.confirmCardPayment(clientSecret, {
|
|
7280
|
+
payment_method: paymentMethodId
|
|
7281
|
+
});
|
|
7282
|
+
if (error) {
|
|
7283
|
+
console.log("[ApplePay] confirmPaymentIntent error:", error);
|
|
7284
|
+
return { success: false, error: error.message ?? "Payment failed" };
|
|
7285
|
+
}
|
|
7286
|
+
console.log("[ApplePay] confirmPaymentIntent success");
|
|
7287
|
+
return { success: true };
|
|
7288
|
+
}
|
|
7289
|
+
case "success" /* Success */: {
|
|
7290
|
+
console.log("[MockApplePay] confirmPaymentIntent called", { clientSecret, paymentMethodId });
|
|
7291
|
+
return { success: true };
|
|
7292
|
+
}
|
|
7293
|
+
case "cancelled" /* Cancelled */: {
|
|
7294
|
+
throw new Error("confirmPaymentIntent should not be called when scenario is Cancelled");
|
|
7295
|
+
}
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
};
|
|
7299
|
+
|
|
7300
|
+
// src/payment-methods/apple-pay.ts
|
|
7301
|
+
var preparedStripeState = null;
|
|
7302
|
+
async function apiCall(url, options, checkoutRequestId) {
|
|
7303
|
+
const headers = new Headers(options.headers);
|
|
7304
|
+
if (checkoutRequestId) {
|
|
7305
|
+
headers.set("x-request-id", checkoutRequestId);
|
|
7306
|
+
}
|
|
7307
|
+
const response = await fetch(url, { ...options, headers });
|
|
7308
|
+
if (!response.ok) {
|
|
7309
|
+
let errorMessage = `Request failed (${response.status})`;
|
|
7310
|
+
try {
|
|
7311
|
+
const errorData = await response.json();
|
|
7312
|
+
errorMessage = errorData.detail || errorMessage;
|
|
7313
|
+
} catch {
|
|
7314
|
+
errorMessage = response.statusText || errorMessage;
|
|
7315
|
+
}
|
|
7316
|
+
return { error: errorMessage };
|
|
7317
|
+
}
|
|
7318
|
+
return { data: await response.json() };
|
|
7319
|
+
}
|
|
7320
|
+
function validateOptions(options) {
|
|
7321
|
+
if (!options?.processorId) {
|
|
7322
|
+
return { processor_id: "Processor ID is required" };
|
|
7323
|
+
}
|
|
7324
|
+
return null;
|
|
7325
|
+
}
|
|
7326
|
+
function getMockScenarioStr(mockScenario) {
|
|
7327
|
+
return mockScenario && mockScenario !== "none" /* None */ ? mockScenario : void 0;
|
|
7328
|
+
}
|
|
7329
|
+
async function callStripeStartEndpoint(apiBaseUrl, secureToken, options, mockScenarioStr, checkoutRequestId) {
|
|
7330
|
+
return apiCall(
|
|
7331
|
+
`${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/start`,
|
|
7332
|
+
{
|
|
7333
|
+
method: "POST",
|
|
7334
|
+
headers: { "Content-Type": "application/json" },
|
|
7335
|
+
body: JSON.stringify({
|
|
7336
|
+
processor_id: options.processorId,
|
|
7337
|
+
customer_info: options.customerInfo,
|
|
7338
|
+
fraud_metadata: collectFraudMetadata(),
|
|
7339
|
+
mock_scenario: mockScenarioStr
|
|
7340
|
+
})
|
|
7341
|
+
},
|
|
7342
|
+
checkoutRequestId
|
|
7343
|
+
);
|
|
7344
|
+
}
|
|
7345
|
+
function initializeStripeAdapter(stripePk, mockScenario) {
|
|
7346
|
+
const adapter = new StripeApplePayAdapter(mockScenario);
|
|
7347
|
+
if (!adapter.initialize(stripePk)) {
|
|
7348
|
+
return { error: 'Stripe.js not loaded. Add <script src="https://js.stripe.com/v3/"><\/script> to your page.' };
|
|
7349
|
+
}
|
|
7350
|
+
return { adapter };
|
|
7351
|
+
}
|
|
7352
|
+
async function callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId, mockScenarioStr, checkoutRequestId, payerEmail) {
|
|
7353
|
+
const result = await apiCall(
|
|
7354
|
+
`${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/confirm`,
|
|
7355
|
+
{
|
|
7356
|
+
method: "POST",
|
|
7357
|
+
headers: { "Content-Type": "application/json" },
|
|
7358
|
+
body: JSON.stringify({
|
|
7359
|
+
payment_method_id: paymentMethodId,
|
|
7360
|
+
payer_email: payerEmail,
|
|
7361
|
+
mock_scenario: mockScenarioStr
|
|
7362
|
+
})
|
|
7363
|
+
},
|
|
7364
|
+
checkoutRequestId
|
|
7365
|
+
);
|
|
7366
|
+
if (result.error || !result.data) {
|
|
7367
|
+
return { errors: { apple_pay: result.error || "Failed to confirm payment" } };
|
|
7368
|
+
}
|
|
7369
|
+
const confirmData = result.data;
|
|
7370
|
+
if (confirmData.charge_status === "success") {
|
|
7371
|
+
return {
|
|
7372
|
+
data: {
|
|
7373
|
+
id: confirmData.transaction_id,
|
|
7374
|
+
checkoutAttemptId: confirmData.checkout_attempt_id,
|
|
7375
|
+
checkoutSessionId: confirmData.checkout_session_id ?? secureToken,
|
|
7376
|
+
state: "checkout_succeeded",
|
|
7377
|
+
paymentIntentId: confirmData.payment_intent_id,
|
|
7378
|
+
customerId: confirmData.customer_id,
|
|
7379
|
+
paymentMethodId: confirmData.payment_method_id,
|
|
7380
|
+
processorUsed: confirmData.processor_used,
|
|
7381
|
+
subscriptionId: confirmData.subscription_id,
|
|
7382
|
+
invoiceId: confirmData.invoice_id,
|
|
7383
|
+
invoiceNumber: confirmData.invoice_number,
|
|
7384
|
+
cardBrand: confirmData.card_brand,
|
|
7385
|
+
cardLast4: confirmData.card_last4,
|
|
7386
|
+
cardExpMonth: confirmData.card_exp_month,
|
|
7387
|
+
cardExpYear: confirmData.card_exp_year,
|
|
7388
|
+
errorCode: confirmData.error_code,
|
|
7389
|
+
errorMessageForCustomer: confirmData.error_message_for_customer,
|
|
7390
|
+
errorMessageForDebug: confirmData.error_message_for_debug,
|
|
7391
|
+
nextAction: confirmData.next_action
|
|
7392
|
+
}
|
|
7393
|
+
};
|
|
7394
|
+
}
|
|
7395
|
+
return {
|
|
7396
|
+
errors: {
|
|
7397
|
+
apple_pay: confirmData.error_message_for_customer || confirmData.error_message_for_debug || "Payment failed"
|
|
7398
|
+
}
|
|
7399
|
+
};
|
|
7400
|
+
}
|
|
7401
|
+
async function prepareApplePay(apiBaseUrl, secureToken, options, environment) {
|
|
7402
|
+
console.log("[ApplePay] prepareApplePay called");
|
|
7403
|
+
preparedStripeState = null;
|
|
7404
|
+
const mockScenarioStr = getMockScenarioStr(options.mockScenario);
|
|
7405
|
+
const checkoutRequestId = getOrCreateCheckoutRequestId(environment);
|
|
7406
|
+
console.log(`[ApplePay] Using checkout_request_id: ${checkoutRequestId}`);
|
|
7407
|
+
if (options.processorType === "airwallex") {
|
|
7408
|
+
console.log("[ApplePay] Airwallex processor - will use native ApplePaySession on submit");
|
|
7409
|
+
return { success: true, applePay: true };
|
|
7410
|
+
}
|
|
7411
|
+
const startResult = await callStripeStartEndpoint(
|
|
7412
|
+
apiBaseUrl,
|
|
7413
|
+
secureToken,
|
|
7414
|
+
options,
|
|
7415
|
+
mockScenarioStr,
|
|
7416
|
+
checkoutRequestId
|
|
7417
|
+
);
|
|
7418
|
+
if (startResult.error || !startResult.data) {
|
|
7419
|
+
return { success: false, error: startResult.error || "Failed to start Apple Pay" };
|
|
7420
|
+
}
|
|
7421
|
+
const startData = startResult.data;
|
|
7422
|
+
if (!startData.stripe_pk) {
|
|
7423
|
+
return { success: false, error: "Stripe publishable key not provided" };
|
|
7424
|
+
}
|
|
7425
|
+
const { adapter, error: adapterError } = initializeStripeAdapter(startData.stripe_pk, options.mockScenario);
|
|
7426
|
+
if (!adapter) {
|
|
7427
|
+
return { success: false, error: adapterError };
|
|
7428
|
+
}
|
|
7429
|
+
const prepareResult = await adapter.preparePaymentRequest({
|
|
7430
|
+
country: startData.country,
|
|
7431
|
+
currency: startData.currency.toLowerCase(),
|
|
7432
|
+
total: {
|
|
7433
|
+
label: "Total",
|
|
7434
|
+
amount: startData.amount
|
|
7435
|
+
}
|
|
7436
|
+
});
|
|
7437
|
+
if (!prepareResult.success) {
|
|
7438
|
+
return {
|
|
7439
|
+
success: false,
|
|
7440
|
+
error: prepareResult.error || "Failed to prepare payment request",
|
|
7441
|
+
applePay: prepareResult.applePay
|
|
7442
|
+
};
|
|
7443
|
+
}
|
|
7444
|
+
if (!prepareResult.applePay) {
|
|
7445
|
+
return {
|
|
7446
|
+
success: false,
|
|
7447
|
+
error: "Apple Pay is not available on this device or Stripe account",
|
|
7448
|
+
applePay: false
|
|
7449
|
+
};
|
|
7450
|
+
}
|
|
7451
|
+
preparedStripeState = {
|
|
7452
|
+
processor: "stripe",
|
|
7453
|
+
adapter,
|
|
7454
|
+
startData,
|
|
7455
|
+
mockScenarioStr,
|
|
7456
|
+
checkoutRequestId
|
|
7457
|
+
};
|
|
7458
|
+
console.log("[ApplePay] prepareApplePay success (Stripe), ready for click");
|
|
7459
|
+
return { success: true, applePay: true };
|
|
7460
|
+
}
|
|
7461
|
+
function clearPreparedApplePay() {
|
|
7462
|
+
if (preparedStripeState) {
|
|
7463
|
+
preparedStripeState.adapter.clearPrepared();
|
|
7464
|
+
}
|
|
7465
|
+
preparedStripeState = null;
|
|
7466
|
+
}
|
|
7467
|
+
async function callAirwallexStartEndpoint(apiBaseUrl, secureToken, options, validationUrl, initiativeContext, mockScenarioStr, checkoutRequestId) {
|
|
7468
|
+
return apiCall(
|
|
7469
|
+
`${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/start`,
|
|
7470
|
+
{
|
|
7471
|
+
method: "POST",
|
|
7472
|
+
headers: { "Content-Type": "application/json" },
|
|
7473
|
+
body: JSON.stringify({
|
|
7474
|
+
processor_id: options.processorId,
|
|
7475
|
+
customer_info: options.customerInfo,
|
|
7476
|
+
fraud_metadata: collectFraudMetadata(),
|
|
7477
|
+
validation_url: validationUrl,
|
|
7478
|
+
initiative_context: initiativeContext,
|
|
7479
|
+
mock_scenario: mockScenarioStr
|
|
7480
|
+
})
|
|
7481
|
+
},
|
|
7482
|
+
checkoutRequestId
|
|
7483
|
+
);
|
|
7484
|
+
}
|
|
7485
|
+
async function callAirwallexConfirmEndpoint(apiBaseUrl, secureToken, applePayToken, mockScenarioStr, checkoutRequestId, payerEmail) {
|
|
7486
|
+
const result = await apiCall(
|
|
7487
|
+
`${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/confirm`,
|
|
7488
|
+
{
|
|
7489
|
+
method: "POST",
|
|
7490
|
+
headers: { "Content-Type": "application/json" },
|
|
7491
|
+
body: JSON.stringify({
|
|
7492
|
+
apple_pay_token: applePayToken,
|
|
7493
|
+
payer_email: payerEmail,
|
|
7494
|
+
mock_scenario: mockScenarioStr
|
|
7495
|
+
})
|
|
7496
|
+
},
|
|
7497
|
+
checkoutRequestId
|
|
7498
|
+
);
|
|
7499
|
+
if (result.error || !result.data) {
|
|
7500
|
+
return {
|
|
7501
|
+
charge_status: "fail",
|
|
7502
|
+
error_message_for_debug: result.error || "Failed to confirm payment",
|
|
7503
|
+
checkout_attempt_id: ""
|
|
7504
|
+
};
|
|
7505
|
+
}
|
|
7506
|
+
return result.data;
|
|
7507
|
+
}
|
|
7508
|
+
async function callAirwallexVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId) {
|
|
7509
|
+
const result = await apiCall(
|
|
7510
|
+
`${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/verify`,
|
|
7511
|
+
{
|
|
7512
|
+
method: "POST",
|
|
7513
|
+
headers: { "Content-Type": "application/json" }
|
|
7514
|
+
},
|
|
7515
|
+
checkoutRequestId
|
|
7516
|
+
);
|
|
7517
|
+
if (result.error || !result.data) {
|
|
7518
|
+
return {
|
|
7519
|
+
charge_status: "fail",
|
|
7520
|
+
error_message_for_debug: result.error || "Failed to verify payment",
|
|
7521
|
+
checkout_attempt_id: ""
|
|
6741
7522
|
};
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
7523
|
+
}
|
|
7524
|
+
return result.data;
|
|
7525
|
+
}
|
|
7526
|
+
function toApplePayResult(response, secureToken) {
|
|
7527
|
+
if (response.charge_status === "success") {
|
|
7528
|
+
return {
|
|
7529
|
+
data: {
|
|
7530
|
+
id: response.transaction_id,
|
|
7531
|
+
checkoutAttemptId: response.checkout_attempt_id,
|
|
7532
|
+
checkoutSessionId: response.checkout_session_id ?? secureToken,
|
|
7533
|
+
state: "checkout_succeeded",
|
|
7534
|
+
paymentIntentId: response.payment_intent_id,
|
|
7535
|
+
customerId: response.customer_id,
|
|
7536
|
+
paymentMethodId: response.payment_method_id,
|
|
7537
|
+
processorUsed: response.processor_used,
|
|
7538
|
+
subscriptionId: response.subscription_id,
|
|
7539
|
+
invoiceId: response.invoice_id,
|
|
7540
|
+
invoiceNumber: response.invoice_number,
|
|
7541
|
+
cardBrand: response.card_brand,
|
|
7542
|
+
cardLast4: response.card_last4,
|
|
7543
|
+
cardExpMonth: response.card_exp_month,
|
|
7544
|
+
cardExpYear: response.card_exp_year,
|
|
7545
|
+
errorCode: response.error_code,
|
|
7546
|
+
errorMessageForCustomer: response.error_message_for_customer,
|
|
7547
|
+
errorMessageForDebug: response.error_message_for_debug,
|
|
7548
|
+
nextAction: response.next_action
|
|
6749
7549
|
}
|
|
6750
7550
|
};
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
// src/payment-methods/next-action-handlers.ts
|
|
6756
|
-
var sleep = (ms2) => new Promise((resolve) => setTimeout(resolve, ms2));
|
|
6757
|
-
var isStripeJsPresent = () => "Stripe" in window;
|
|
6758
|
-
var getLoadedStripe = async (publishableKey) => {
|
|
6759
|
-
for (let i2 = 0; i2 < 10; i2++) {
|
|
6760
|
-
if (isStripeJsPresent()) {
|
|
6761
|
-
break;
|
|
7551
|
+
}
|
|
7552
|
+
return {
|
|
7553
|
+
errors: {
|
|
7554
|
+
apple_pay: response.error_message_for_customer || response.error_message_for_debug || "Payment failed"
|
|
6762
7555
|
}
|
|
6763
|
-
|
|
7556
|
+
};
|
|
7557
|
+
}
|
|
7558
|
+
var MAX_USER_ACTIONS = 5;
|
|
7559
|
+
async function runAirwallexFlow(apiBaseUrl, secureToken, options, mockScenarioStr, checkoutRequestId) {
|
|
7560
|
+
let airwallexMockScenario = "none" /* None */;
|
|
7561
|
+
if (options.mockScenario === "success" /* Success */) {
|
|
7562
|
+
airwallexMockScenario = "success" /* Success */;
|
|
7563
|
+
} else if (options.mockScenario === "cancelled" /* Cancelled */) {
|
|
7564
|
+
airwallexMockScenario = "cancelled" /* Cancelled */;
|
|
6764
7565
|
}
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
7566
|
+
const adapter = new AirwallexApplePayAdapter(airwallexMockScenario);
|
|
7567
|
+
const config = {
|
|
7568
|
+
amount: options.amount || 0,
|
|
7569
|
+
currency: (options.currency || "USD").toUpperCase(),
|
|
7570
|
+
country: options.country.toUpperCase(),
|
|
7571
|
+
merchantName: options.merchantName || "Total"
|
|
7572
|
+
};
|
|
7573
|
+
if (!adapter.initialize(config)) {
|
|
7574
|
+
return { errors: { apple_pay: "Apple Pay not available on this device (requires Safari)" } };
|
|
7575
|
+
}
|
|
7576
|
+
const canPay = await adapter.canMakePayment();
|
|
7577
|
+
if (!canPay) {
|
|
7578
|
+
return { errors: { apple_pay: "Apple Pay not available on this device" } };
|
|
7579
|
+
}
|
|
7580
|
+
const initiativeContext = typeof window !== "undefined" ? window.location.hostname : "";
|
|
7581
|
+
if (airwallexMockScenario !== "none" /* None */) {
|
|
7582
|
+
const startResult = await callAirwallexStartEndpoint(
|
|
7583
|
+
apiBaseUrl,
|
|
7584
|
+
secureToken,
|
|
7585
|
+
options,
|
|
7586
|
+
"https://mock-apple-pay-gateway.example.com/paymentservices/startSession",
|
|
7587
|
+
initiativeContext,
|
|
7588
|
+
mockScenarioStr,
|
|
7589
|
+
checkoutRequestId
|
|
6768
7590
|
);
|
|
7591
|
+
if (startResult.error || !startResult.data) {
|
|
7592
|
+
return { errors: { apple_pay: startResult.error || "Failed to start mock checkout" } };
|
|
7593
|
+
}
|
|
7594
|
+
}
|
|
7595
|
+
const paymentResult = await adapter.showPaymentSheet(async (validationUrl) => {
|
|
7596
|
+
const startResult = await callAirwallexStartEndpoint(
|
|
7597
|
+
apiBaseUrl,
|
|
7598
|
+
secureToken,
|
|
7599
|
+
options,
|
|
7600
|
+
validationUrl,
|
|
7601
|
+
initiativeContext,
|
|
7602
|
+
mockScenarioStr,
|
|
7603
|
+
checkoutRequestId
|
|
7604
|
+
);
|
|
7605
|
+
if (startResult.error || !startResult.data) {
|
|
7606
|
+
return { error: startResult.error || "Merchant validation failed" };
|
|
7607
|
+
}
|
|
7608
|
+
if (!startResult.data.merchant_session) {
|
|
7609
|
+
return { error: "No merchant session returned from server" };
|
|
7610
|
+
}
|
|
7611
|
+
return { merchantSession: startResult.data.merchant_session };
|
|
7612
|
+
});
|
|
7613
|
+
if (!paymentResult.success) {
|
|
7614
|
+
if ("cancelled" in paymentResult && paymentResult.cancelled) {
|
|
7615
|
+
return { errors: { apple_pay: "Apple Pay cancelled by user" } };
|
|
7616
|
+
}
|
|
7617
|
+
return { errors: { apple_pay: paymentResult.error || "Apple Pay failed" } };
|
|
6769
7618
|
}
|
|
6770
|
-
const
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
7619
|
+
const { token, complete, payerEmail } = paymentResult;
|
|
7620
|
+
let response = await callAirwallexConfirmEndpoint(
|
|
7621
|
+
apiBaseUrl,
|
|
7622
|
+
secureToken,
|
|
7623
|
+
token,
|
|
7624
|
+
mockScenarioStr,
|
|
7625
|
+
checkoutRequestId,
|
|
7626
|
+
payerEmail
|
|
7627
|
+
);
|
|
7628
|
+
let userActionCount = 0;
|
|
7629
|
+
while (response.charge_status === "pending" && response.next_action && userActionCount < MAX_USER_ACTIONS) {
|
|
7630
|
+
userActionCount++;
|
|
7631
|
+
const nextAction = response.next_action;
|
|
7632
|
+
const actionResult = await handleNextAction({ type: nextAction.type, url: nextAction.url });
|
|
7633
|
+
const verifyResponse = await callAirwallexVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId);
|
|
7634
|
+
if (verifyResponse.charge_status === "pending" && verifyResponse.next_action) {
|
|
7635
|
+
if (!actionResult.success) {
|
|
7636
|
+
console.log("[ApplePay:Airwallex] 3DS failed but retry available, continuing loop...");
|
|
7637
|
+
}
|
|
7638
|
+
response = verifyResponse;
|
|
7639
|
+
continue;
|
|
7640
|
+
}
|
|
7641
|
+
if (!actionResult.success) {
|
|
7642
|
+
complete("fail");
|
|
7643
|
+
return {
|
|
7644
|
+
errors: {
|
|
7645
|
+
apple_pay: verifyResponse.error_message_for_customer || verifyResponse.error_message_for_debug || actionResult.error || "3DS authentication failed"
|
|
7646
|
+
}
|
|
7647
|
+
};
|
|
7648
|
+
}
|
|
7649
|
+
complete(verifyResponse.charge_status === "success" ? "success" : "fail");
|
|
7650
|
+
return toApplePayResult(verifyResponse, secureToken);
|
|
6780
7651
|
}
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
7652
|
+
if (userActionCount >= MAX_USER_ACTIONS) {
|
|
7653
|
+
complete("fail");
|
|
7654
|
+
return { errors: { apple_pay: "Too many authentication attempts. Please try again." } };
|
|
7655
|
+
}
|
|
7656
|
+
complete(response.charge_status === "success" ? "success" : "fail");
|
|
7657
|
+
return toApplePayResult(response, secureToken);
|
|
7658
|
+
}
|
|
7659
|
+
var defSubmitPayment = (states) => {
|
|
7660
|
+
const submitPayment = async (_fields, options) => {
|
|
7661
|
+
const { apiBaseUrl, secureToken, environment } = states;
|
|
7662
|
+
const applePayOptions = options;
|
|
7663
|
+
const validationError = validateOptions(applePayOptions);
|
|
7664
|
+
if (validationError) {
|
|
7665
|
+
return { errors: validationError };
|
|
7666
|
+
}
|
|
7667
|
+
try {
|
|
7668
|
+
const mockScenarioStr = getMockScenarioStr(applePayOptions.mockScenario);
|
|
7669
|
+
const checkoutRequestId = getOrCreateCheckoutRequestId(environment);
|
|
7670
|
+
console.log(`[ApplePay] Using checkout_request_id: ${checkoutRequestId}`);
|
|
7671
|
+
if (preparedStripeState?.adapter.isPrepared()) {
|
|
7672
|
+
console.log("[ApplePay] Using prepared Stripe state for immediate sheet display");
|
|
7673
|
+
const paymentResultPromise = preparedStripeState.adapter.showPreparedPaymentSheet();
|
|
7674
|
+
const paymentResult2 = await paymentResultPromise;
|
|
7675
|
+
if (!paymentResult2.success) {
|
|
7676
|
+
clearPreparedApplePay();
|
|
7677
|
+
if ("cancelled" in paymentResult2 && paymentResult2.cancelled) {
|
|
7678
|
+
return { errors: { apple_pay: "Apple Pay cancelled by user" } };
|
|
7679
|
+
}
|
|
7680
|
+
const errorMessage = "error" in paymentResult2 ? paymentResult2.error : "Unknown error";
|
|
7681
|
+
return { errors: { apple_pay: errorMessage } };
|
|
7682
|
+
}
|
|
7683
|
+
const { paymentMethodId: paymentMethodId2, paymentMethodEvent: paymentMethodEvent2, billingDetails: billingDetails2 } = paymentResult2;
|
|
7684
|
+
const confirmResult2 = await callStripeConfirmEndpoint(
|
|
7685
|
+
apiBaseUrl,
|
|
7686
|
+
secureToken,
|
|
7687
|
+
paymentMethodId2,
|
|
7688
|
+
mockScenarioStr,
|
|
7689
|
+
preparedStripeState.checkoutRequestId,
|
|
7690
|
+
billingDetails2?.email
|
|
7691
|
+
);
|
|
7692
|
+
if (confirmResult2.data) {
|
|
7693
|
+
paymentMethodEvent2.complete("success");
|
|
7694
|
+
clearPreparedApplePay();
|
|
7695
|
+
return confirmResult2;
|
|
7696
|
+
} else {
|
|
7697
|
+
paymentMethodEvent2.complete("fail");
|
|
7698
|
+
clearPreparedApplePay();
|
|
7699
|
+
return confirmResult2;
|
|
7700
|
+
}
|
|
6790
7701
|
}
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
return
|
|
7702
|
+
if (applePayOptions.processorType === "airwallex") {
|
|
7703
|
+
console.log("[ApplePay] Running Airwallex flow (processorType=airwallex)");
|
|
7704
|
+
return await runAirwallexFlow(apiBaseUrl, secureToken, applePayOptions, mockScenarioStr, checkoutRequestId);
|
|
7705
|
+
}
|
|
7706
|
+
const startResult = await callStripeStartEndpoint(
|
|
7707
|
+
apiBaseUrl,
|
|
7708
|
+
secureToken,
|
|
7709
|
+
applePayOptions,
|
|
7710
|
+
mockScenarioStr,
|
|
7711
|
+
checkoutRequestId
|
|
7712
|
+
);
|
|
7713
|
+
if (startResult.error || !startResult.data) {
|
|
7714
|
+
return { errors: { apple_pay: startResult.error || "Failed to start Apple Pay" } };
|
|
7715
|
+
}
|
|
7716
|
+
const startData = startResult.data;
|
|
7717
|
+
console.warn("[ApplePay] Stripe flow without prepared state - may fail due to user gesture requirements");
|
|
7718
|
+
if (!startData.stripe_pk) {
|
|
7719
|
+
return { errors: { apple_pay: "Stripe publishable key not provided" } };
|
|
7720
|
+
}
|
|
7721
|
+
const { adapter, error: adapterError } = initializeStripeAdapter(
|
|
7722
|
+
startData.stripe_pk,
|
|
7723
|
+
applePayOptions.mockScenario
|
|
7724
|
+
);
|
|
7725
|
+
if (!adapter) {
|
|
7726
|
+
return { errors: { apple_pay: adapterError || "Failed to initialize Stripe adapter" } };
|
|
7727
|
+
}
|
|
7728
|
+
const prepareResult = await adapter.preparePaymentRequest({
|
|
7729
|
+
country: startData.country,
|
|
7730
|
+
currency: startData.currency.toLowerCase(),
|
|
7731
|
+
total: { label: "Total", amount: startData.amount }
|
|
7732
|
+
});
|
|
7733
|
+
if (!prepareResult.success || !prepareResult.applePay) {
|
|
7734
|
+
return { errors: { apple_pay: prepareResult.error || "Apple Pay not available" } };
|
|
7735
|
+
}
|
|
7736
|
+
const paymentResult = await adapter.showPreparedPaymentSheet();
|
|
7737
|
+
if (!paymentResult.success) {
|
|
7738
|
+
if ("cancelled" in paymentResult && paymentResult.cancelled) {
|
|
7739
|
+
return { errors: { apple_pay: "Apple Pay cancelled by user" } };
|
|
7740
|
+
}
|
|
7741
|
+
const errorMessage = "error" in paymentResult ? paymentResult.error : "Unknown error";
|
|
7742
|
+
return { errors: { apple_pay: errorMessage } };
|
|
7743
|
+
}
|
|
7744
|
+
const { paymentMethodId, paymentMethodEvent, billingDetails } = paymentResult;
|
|
7745
|
+
const confirmResult = await callStripeConfirmEndpoint(
|
|
7746
|
+
apiBaseUrl,
|
|
7747
|
+
secureToken,
|
|
7748
|
+
paymentMethodId,
|
|
7749
|
+
mockScenarioStr,
|
|
7750
|
+
checkoutRequestId,
|
|
7751
|
+
billingDetails?.email
|
|
7752
|
+
);
|
|
7753
|
+
if (confirmResult.data) {
|
|
7754
|
+
paymentMethodEvent.complete("success");
|
|
7755
|
+
return confirmResult;
|
|
6794
7756
|
} else {
|
|
6795
|
-
|
|
6796
|
-
return
|
|
6797
|
-
handled: true,
|
|
6798
|
-
result: { success: false, error: error || "3DS authentication failed" }
|
|
6799
|
-
};
|
|
7757
|
+
paymentMethodEvent.complete("fail");
|
|
7758
|
+
return confirmResult;
|
|
6800
7759
|
}
|
|
7760
|
+
} catch (error) {
|
|
7761
|
+
clearPreparedApplePay();
|
|
7762
|
+
return { errors: { apple_pay: `Apple Pay error: ${error}` } };
|
|
6801
7763
|
}
|
|
6802
|
-
}
|
|
7764
|
+
};
|
|
7765
|
+
return submitPayment;
|
|
6803
7766
|
};
|
|
6804
|
-
var
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
7767
|
+
var ApplePayPaymentMethod = definePaymentMethod((paymentKitStates) => {
|
|
7768
|
+
return {
|
|
7769
|
+
name: "apple_pay",
|
|
7770
|
+
externalFuncs: {
|
|
7771
|
+
prepareApplePay: (options) => prepareApplePay(
|
|
7772
|
+
paymentKitStates.apiBaseUrl,
|
|
7773
|
+
paymentKitStates.secureToken,
|
|
7774
|
+
options,
|
|
7775
|
+
paymentKitStates.environment
|
|
7776
|
+
)
|
|
7777
|
+
},
|
|
7778
|
+
internalFuncs: {
|
|
7779
|
+
submitPayment: defSubmitPayment(paymentKitStates),
|
|
7780
|
+
cleanup: () => {
|
|
7781
|
+
clearPreparedApplePay();
|
|
7782
|
+
}
|
|
7783
|
+
}
|
|
7784
|
+
};
|
|
7785
|
+
});
|
|
7786
|
+
var apple_pay_default = ApplePayPaymentMethod;
|
|
7787
|
+
|
|
7788
|
+
// src/penpal/connect-card.ts
|
|
7789
|
+
var connectToCardIframe = (iframe, methods) => {
|
|
7790
|
+
return connectToWindow({ window: iframe.contentWindow, methods });
|
|
6813
7791
|
};
|
|
6814
7792
|
|
|
6815
7793
|
// src/payment-methods/vgs-collect-loader.ts
|
|
@@ -7082,9 +8060,15 @@ var PaymentKit = (() => {
|
|
|
7082
8060
|
}
|
|
7083
8061
|
cleanupVgs = () => {
|
|
7084
8062
|
if (type === "card_pan" && states.vgsForm) {
|
|
7085
|
-
|
|
8063
|
+
try {
|
|
8064
|
+
states.vgsFieldsCleanup?.();
|
|
8065
|
+
} catch {
|
|
8066
|
+
}
|
|
7086
8067
|
states.vgsFieldsCleanup = void 0;
|
|
7087
|
-
|
|
8068
|
+
try {
|
|
8069
|
+
states.vgsForm.unmount();
|
|
8070
|
+
} catch {
|
|
8071
|
+
}
|
|
7088
8072
|
states.vgsForm = void 0;
|
|
7089
8073
|
}
|
|
7090
8074
|
};
|
|
@@ -7118,7 +8102,10 @@ var PaymentKit = (() => {
|
|
|
7118
8102
|
cleanupDirect = () => {
|
|
7119
8103
|
const connection = cardInputConnections[type];
|
|
7120
8104
|
connection?.destroy();
|
|
7121
|
-
|
|
8105
|
+
try {
|
|
8106
|
+
parent.removeChild(iframe);
|
|
8107
|
+
} catch {
|
|
8108
|
+
}
|
|
7122
8109
|
states.cardInputConnections[type] = void 0;
|
|
7123
8110
|
};
|
|
7124
8111
|
parent.appendChild(iframe);
|
|
@@ -7151,7 +8138,7 @@ var PaymentKit = (() => {
|
|
|
7151
8138
|
return { mount: mountIFrame };
|
|
7152
8139
|
};
|
|
7153
8140
|
};
|
|
7154
|
-
var
|
|
8141
|
+
var defSubmitPayment2 = (states) => {
|
|
7155
8142
|
const submitPayment = async (fields, options) => {
|
|
7156
8143
|
if (states._sessionConfigReady) await states._sessionConfigReady;
|
|
7157
8144
|
const isVgsMode = states.cardTokenizationMode === "vgs";
|
|
@@ -7181,7 +8168,8 @@ var PaymentKit = (() => {
|
|
|
7181
8168
|
console.log("[PaymentKit] Submitting card via VGS CMP...");
|
|
7182
8169
|
const vgsSubmitResult = await submitVgsCardFields(states, tunnelX);
|
|
7183
8170
|
if (!vgsSubmitResult.isSuccess) {
|
|
7184
|
-
|
|
8171
|
+
const errorDetail = Object.entries(vgsSubmitResult.errors).map(([k2, v2]) => `${k2}: ${v2}`).join(", ");
|
|
8172
|
+
timingTracker.trackFail(null, "card_submit_error", errorDetail || "VGS card submission failed");
|
|
7185
8173
|
return { errors: vgsSubmitResult.errors };
|
|
7186
8174
|
}
|
|
7187
8175
|
} else {
|
|
@@ -7217,11 +8205,11 @@ var PaymentKit = (() => {
|
|
|
7217
8205
|
requestOptions
|
|
7218
8206
|
);
|
|
7219
8207
|
console.log("Card checkout result:", currentResult);
|
|
7220
|
-
const
|
|
8208
|
+
const MAX_USER_ACTIONS3 = 5;
|
|
7221
8209
|
let userActionCount = 0;
|
|
7222
|
-
while (currentResult.nextAction && userActionCount <
|
|
8210
|
+
while (currentResult.nextAction && userActionCount < MAX_USER_ACTIONS3) {
|
|
7223
8211
|
userActionCount++;
|
|
7224
|
-
console.log(`Handling user action ${userActionCount}/${
|
|
8212
|
+
console.log(`Handling user action ${userActionCount}/${MAX_USER_ACTIONS3}...`);
|
|
7225
8213
|
const actionResult = await handleNextAction(currentResult.nextAction);
|
|
7226
8214
|
console.log("User action completed, verifying checkout...");
|
|
7227
8215
|
const verifyResult = await tunnelX.publicEndpoints.cardCheckoutVerify(
|
|
@@ -7257,7 +8245,7 @@ var PaymentKit = (() => {
|
|
|
7257
8245
|
timingTracker.trackSuccess(verifyResult.checkoutAttemptId || "unknown");
|
|
7258
8246
|
return { data: verifyResult };
|
|
7259
8247
|
}
|
|
7260
|
-
if (userActionCount >=
|
|
8248
|
+
if (userActionCount >= MAX_USER_ACTIONS3) {
|
|
7261
8249
|
console.error("Max user actions exceeded");
|
|
7262
8250
|
timingTracker.trackFail(null, "max_actions_exceeded", "Too many authentication attempts");
|
|
7263
8251
|
return { errors: { root: "Too many authentication attempts. Please try again." } };
|
|
@@ -7293,8 +8281,27 @@ var PaymentKit = (() => {
|
|
|
7293
8281
|
const data = await resp.json();
|
|
7294
8282
|
return data.access_token;
|
|
7295
8283
|
};
|
|
8284
|
+
var VGS_FIELD_MAP = {
|
|
8285
|
+
// Actual VGS CMP error keys (verified empirically)
|
|
8286
|
+
pan: "card_pan",
|
|
8287
|
+
cvc: "card_cvc",
|
|
8288
|
+
"exp-date": "card_exp",
|
|
8289
|
+
// Alternative key formats (VGS documentation references)
|
|
8290
|
+
"card-number": "card_pan",
|
|
8291
|
+
"card-security-code": "card_cvc",
|
|
8292
|
+
"card-expiration-date": "card_exp"
|
|
8293
|
+
};
|
|
8294
|
+
var stringifyError = (err) => {
|
|
8295
|
+
if (err instanceof Error) return err.message;
|
|
8296
|
+
try {
|
|
8297
|
+
return JSON.stringify(err);
|
|
8298
|
+
} catch {
|
|
8299
|
+
return String(err);
|
|
8300
|
+
}
|
|
8301
|
+
};
|
|
7296
8302
|
var submitVgsCardFields = async (states, tunnelX) => {
|
|
7297
|
-
const { vgsForm, cardSetupIntentId, secureToken, apiBaseUrl } = states;
|
|
8303
|
+
const { vgsForm, cardSetupIntentId, secureToken, apiBaseUrl, checkoutRequestId } = states;
|
|
8304
|
+
const logPrefix = `[PaymentKit] [${checkoutRequestId}]`;
|
|
7298
8305
|
const errors = {};
|
|
7299
8306
|
if (!vgsForm) {
|
|
7300
8307
|
errors.card_pan = "required";
|
|
@@ -7304,11 +8311,19 @@ var PaymentKit = (() => {
|
|
|
7304
8311
|
errors.root = "Card setup intent not created";
|
|
7305
8312
|
return { errors, isSuccess: false };
|
|
7306
8313
|
}
|
|
8314
|
+
let accessToken;
|
|
8315
|
+
try {
|
|
8316
|
+
accessToken = await fetchCollectToken(apiBaseUrl, secureToken);
|
|
8317
|
+
} catch (err) {
|
|
8318
|
+
console.error(`${logPrefix} VGS auth token fetch failed:`, stringifyError(err));
|
|
8319
|
+
errors.root = "Card authentication failed \u2014 please try again";
|
|
8320
|
+
return { errors, isSuccess: false };
|
|
8321
|
+
}
|
|
8322
|
+
let cardResult;
|
|
8323
|
+
const VGS_CREATE_CARD_TIMEOUT_MS = 3e4;
|
|
7307
8324
|
try {
|
|
7308
|
-
const accessToken = await fetchCollectToken(apiBaseUrl, secureToken);
|
|
7309
|
-
const VGS_CREATE_CARD_TIMEOUT_MS = 3e4;
|
|
7310
8325
|
let createCardTimeoutId;
|
|
7311
|
-
|
|
8326
|
+
cardResult = await Promise.race([
|
|
7312
8327
|
new Promise((resolve, reject) => {
|
|
7313
8328
|
vgsForm.createCard(
|
|
7314
8329
|
{
|
|
@@ -7320,34 +8335,76 @@ var PaymentKit = (() => {
|
|
|
7320
8335
|
);
|
|
7321
8336
|
}),
|
|
7322
8337
|
new Promise((_2, reject) => {
|
|
7323
|
-
createCardTimeoutId = setTimeout(
|
|
7324
|
-
() => reject(new Error("VGS createCard timed out")),
|
|
7325
|
-
VGS_CREATE_CARD_TIMEOUT_MS
|
|
7326
|
-
);
|
|
8338
|
+
createCardTimeoutId = setTimeout(() => reject(new Error("VGS_TIMEOUT")), VGS_CREATE_CARD_TIMEOUT_MS);
|
|
7327
8339
|
})
|
|
7328
8340
|
]).finally(() => clearTimeout(createCardTimeoutId));
|
|
7329
|
-
|
|
7330
|
-
|
|
8341
|
+
} catch (err) {
|
|
8342
|
+
const errStr = stringifyError(err);
|
|
8343
|
+
console.error(`${logPrefix} VGS createCard failed:`, errStr);
|
|
8344
|
+
if (err instanceof Error && err.message === "VGS_TIMEOUT") {
|
|
8345
|
+
errors.root = "Card processing timed out \u2014 please try again";
|
|
8346
|
+
return { errors, isSuccess: false };
|
|
8347
|
+
}
|
|
8348
|
+
if (err && typeof err === "object" && !(err instanceof Error)) {
|
|
8349
|
+
const vgsErrors = err;
|
|
8350
|
+
for (const [vgsKey, fieldKey] of Object.entries(VGS_FIELD_MAP)) {
|
|
8351
|
+
if (vgsKey in vgsErrors) {
|
|
8352
|
+
const fieldErr = vgsErrors[vgsKey];
|
|
8353
|
+
const messages = fieldErr?.errorMessages;
|
|
8354
|
+
errors[fieldKey] = Array.isArray(messages) ? messages[0] : "invalid";
|
|
8355
|
+
}
|
|
8356
|
+
}
|
|
8357
|
+
if (Object.keys(errors).length > 0) {
|
|
8358
|
+
return { errors, isSuccess: false };
|
|
8359
|
+
}
|
|
7331
8360
|
}
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
8361
|
+
errors.root = "Card validation failed \u2014 please check your card details and try again";
|
|
8362
|
+
return { errors, isSuccess: false };
|
|
8363
|
+
}
|
|
8364
|
+
if (!cardResult?.data?.attributes) {
|
|
8365
|
+
console.error(`${logPrefix} VGS createCard returned invalid response:`, stringifyError(cardResult));
|
|
8366
|
+
errors.root = "Card processing returned an invalid response \u2014 please try again";
|
|
8367
|
+
return { errors, isSuccess: false };
|
|
8368
|
+
}
|
|
8369
|
+
const { pan_alias, cvc_alias, exp_month, exp_year } = cardResult.data.attributes;
|
|
8370
|
+
const fullYear = exp_year < 100 ? 2e3 + exp_year : exp_year;
|
|
8371
|
+
const formattedExp = `${String(exp_month).padStart(2, "0")}/${fullYear}`;
|
|
8372
|
+
const cmpCardId = cardResult.data.id;
|
|
8373
|
+
try {
|
|
8374
|
+
const updateIntentCall = tunnelX.publicEndpoints.updateCardSetupIntent({
|
|
7336
8375
|
checkoutToken: secureToken,
|
|
7337
8376
|
cardSetupIntentId,
|
|
7338
8377
|
updateCardSetupIntentReq: {
|
|
7339
8378
|
cardPan: pan_alias,
|
|
7340
8379
|
cardExp: formattedExp,
|
|
7341
8380
|
cardCvc: cvc_alias,
|
|
8381
|
+
cmpCardId,
|
|
7342
8382
|
fraudMetadata: collectFraudMetadata()
|
|
7343
8383
|
}
|
|
7344
8384
|
});
|
|
7345
|
-
|
|
8385
|
+
const proxyCvcCall = new Promise((resolve, reject) => {
|
|
8386
|
+
if (!vgsForm.submit) {
|
|
8387
|
+
reject(new Error("VGS form.submit not available"));
|
|
8388
|
+
return;
|
|
8389
|
+
}
|
|
8390
|
+
vgsForm.submit(
|
|
8391
|
+
`/api/card-setup-intents/${secureToken}/${cardSetupIntentId}`,
|
|
8392
|
+
{
|
|
8393
|
+
method: "post",
|
|
8394
|
+
headers: { "Content-Type": "application/json" },
|
|
8395
|
+
data: (fields) => ({ card_cvc: fields.cvc })
|
|
8396
|
+
},
|
|
8397
|
+
(_status) => resolve(),
|
|
8398
|
+
(err) => reject(err)
|
|
8399
|
+
);
|
|
8400
|
+
});
|
|
8401
|
+
await Promise.all([updateIntentCall, proxyCvcCall]);
|
|
7346
8402
|
} catch (err) {
|
|
7347
|
-
console.error(
|
|
7348
|
-
errors.root = "
|
|
8403
|
+
console.error(`${logPrefix} updateCardSetupIntent failed:`, stringifyError(err));
|
|
8404
|
+
errors.root = "Failed to save card details \u2014 please try again";
|
|
7349
8405
|
return { errors, isSuccess: false };
|
|
7350
8406
|
}
|
|
8407
|
+
return { errors: {}, isSuccess: true };
|
|
7351
8408
|
};
|
|
7352
8409
|
var submitCardFields = async (states) => {
|
|
7353
8410
|
const errors = {};
|
|
@@ -7396,7 +8453,7 @@ var PaymentKit = (() => {
|
|
|
7396
8453
|
createElement: defCreateElement(localStates)
|
|
7397
8454
|
},
|
|
7398
8455
|
internalFuncs: {
|
|
7399
|
-
submitPayment:
|
|
8456
|
+
submitPayment: defSubmitPayment2(localStates),
|
|
7400
8457
|
cleanup: () => {
|
|
7401
8458
|
if (localStates.vgsForm) {
|
|
7402
8459
|
localStates.vgsFieldsCleanup?.();
|
|
@@ -7506,7 +8563,7 @@ var PaymentKit = (() => {
|
|
|
7506
8563
|
},
|
|
7507
8564
|
signedMessage: "MOCK_SIGNED_MESSAGE"
|
|
7508
8565
|
};
|
|
7509
|
-
return { success: true, token: mockToken };
|
|
8566
|
+
return { success: true, token: mockToken, payerEmail: "mock@example.com" };
|
|
7510
8567
|
}
|
|
7511
8568
|
if (this.mockScenario === "cancelled" /* Cancelled */) {
|
|
7512
8569
|
console.log("[MockGooglePay:Airwallex] showPaymentSheet: returning mock cancelled");
|
|
@@ -7532,12 +8589,13 @@ var PaymentKit = (() => {
|
|
|
7532
8589
|
totalPrice,
|
|
7533
8590
|
currencyCode: this.config.currency.toUpperCase(),
|
|
7534
8591
|
countryCode: this.config.country.toUpperCase()
|
|
7535
|
-
}
|
|
8592
|
+
},
|
|
8593
|
+
emailRequired: true
|
|
7536
8594
|
};
|
|
7537
8595
|
const paymentData = await this.client.loadPaymentData(request);
|
|
7538
8596
|
const tokenString = paymentData.paymentMethodData.tokenizationData.token;
|
|
7539
8597
|
const token = JSON.parse(tokenString);
|
|
7540
|
-
return { success: true, token };
|
|
8598
|
+
return { success: true, token, payerEmail: paymentData.email };
|
|
7541
8599
|
} catch (error) {
|
|
7542
8600
|
if (error instanceof Error && error.message?.includes("CANCELED")) {
|
|
7543
8601
|
return { success: false, cancelled: true };
|
|
@@ -7632,11 +8690,13 @@ var PaymentKit = (() => {
|
|
|
7632
8690
|
return new Promise((resolve) => {
|
|
7633
8691
|
this.paymentRequest.on("paymentmethod", (event) => {
|
|
7634
8692
|
console.log("[GooglePay] showPaymentSheet: paymentmethod event", {
|
|
7635
|
-
paymentMethodId: event.paymentMethod.id
|
|
8693
|
+
paymentMethodId: event.paymentMethod.id,
|
|
8694
|
+
payerEmail: event.payerEmail
|
|
7636
8695
|
});
|
|
7637
8696
|
resolve({
|
|
7638
8697
|
success: true,
|
|
7639
8698
|
paymentMethodId: event.paymentMethod.id,
|
|
8699
|
+
payerEmail: event.payerEmail ?? void 0,
|
|
7640
8700
|
complete: (status) => {
|
|
7641
8701
|
console.log("[GooglePay] complete called:", status);
|
|
7642
8702
|
event.complete(status);
|
|
@@ -7657,6 +8717,7 @@ var PaymentKit = (() => {
|
|
|
7657
8717
|
return {
|
|
7658
8718
|
success: true,
|
|
7659
8719
|
paymentMethodId: "pm_mock_123456789",
|
|
8720
|
+
payerEmail: "mock@example.com",
|
|
7660
8721
|
complete: (status) => console.log(`[MockGooglePay] complete: ${status}`)
|
|
7661
8722
|
};
|
|
7662
8723
|
}
|
|
@@ -7700,7 +8761,7 @@ var PaymentKit = (() => {
|
|
|
7700
8761
|
};
|
|
7701
8762
|
|
|
7702
8763
|
// src/payment-methods/google-pay.ts
|
|
7703
|
-
async function
|
|
8764
|
+
async function apiCall2(url, options, checkoutRequestId) {
|
|
7704
8765
|
const headers = new Headers(options.headers);
|
|
7705
8766
|
if (checkoutRequestId) {
|
|
7706
8767
|
headers.set("x-request-id", checkoutRequestId);
|
|
@@ -7718,17 +8779,17 @@ var PaymentKit = (() => {
|
|
|
7718
8779
|
}
|
|
7719
8780
|
return { data: await response.json() };
|
|
7720
8781
|
}
|
|
7721
|
-
function
|
|
8782
|
+
function validateOptions2(options) {
|
|
7722
8783
|
if (!options?.processorId) {
|
|
7723
8784
|
return { processor_id: "Processor ID is required" };
|
|
7724
8785
|
}
|
|
7725
8786
|
return null;
|
|
7726
8787
|
}
|
|
7727
|
-
function
|
|
8788
|
+
function getMockScenarioStr2(mockScenario) {
|
|
7728
8789
|
return mockScenario && mockScenario !== "none" /* None */ ? mockScenario : void 0;
|
|
7729
8790
|
}
|
|
7730
8791
|
async function callStartEndpoint(apiBaseUrl, secureToken, options, mockScenarioStr, checkoutRequestId) {
|
|
7731
|
-
return
|
|
8792
|
+
return apiCall2(
|
|
7732
8793
|
`${apiBaseUrl}/api/checkout/${secureToken}/google-pay/start`,
|
|
7733
8794
|
{
|
|
7734
8795
|
method: "POST",
|
|
@@ -7743,7 +8804,7 @@ var PaymentKit = (() => {
|
|
|
7743
8804
|
checkoutRequestId
|
|
7744
8805
|
);
|
|
7745
8806
|
}
|
|
7746
|
-
function
|
|
8807
|
+
function initializeStripeAdapter2(stripePk, startData, mockScenario) {
|
|
7747
8808
|
const adapter = new StripeGooglePayAdapter(mockScenario);
|
|
7748
8809
|
if (!adapter.initialize(stripePk)) {
|
|
7749
8810
|
return { error: 'Stripe.js not loaded. Add <script src="https://js.stripe.com/v3/"><\/script> to your page.' };
|
|
@@ -7762,7 +8823,7 @@ var PaymentKit = (() => {
|
|
|
7762
8823
|
if (!startData.stripe_pk || !startData.client_secret) {
|
|
7763
8824
|
return { success: false, error: "Stripe credentials not provided" };
|
|
7764
8825
|
}
|
|
7765
|
-
const { adapter, error: adapterError } =
|
|
8826
|
+
const { adapter, error: adapterError } = initializeStripeAdapter2(startData.stripe_pk, startData, mockScenario);
|
|
7766
8827
|
if (!adapter) {
|
|
7767
8828
|
return { success: false, error: adapterError };
|
|
7768
8829
|
}
|
|
@@ -7784,7 +8845,7 @@ var PaymentKit = (() => {
|
|
|
7784
8845
|
return { success: false, error: "error" in confirmResult ? confirmResult.error : "Card setup failed" };
|
|
7785
8846
|
}
|
|
7786
8847
|
paymentResult.complete("success");
|
|
7787
|
-
return { success: true };
|
|
8848
|
+
return { success: true, payerEmail: paymentResult.payerEmail };
|
|
7788
8849
|
}
|
|
7789
8850
|
function initializeAirwallexAdapter(startData, mockScenario) {
|
|
7790
8851
|
if (!startData.merchant_name || !startData.airwallex_account_id) {
|
|
@@ -7813,7 +8874,7 @@ var PaymentKit = (() => {
|
|
|
7813
8874
|
}
|
|
7814
8875
|
return { adapter };
|
|
7815
8876
|
}
|
|
7816
|
-
async function
|
|
8877
|
+
async function runAirwallexFlow2(startData, mockScenario) {
|
|
7817
8878
|
const { adapter, error: adapterError } = initializeAirwallexAdapter(startData, mockScenario);
|
|
7818
8879
|
if (!adapter) {
|
|
7819
8880
|
return { success: false, error: adapterError };
|
|
@@ -7830,16 +8891,19 @@ var PaymentKit = (() => {
|
|
|
7830
8891
|
const errorMessage = "error" in paymentResult ? paymentResult.error : "Unknown error";
|
|
7831
8892
|
return { success: false, error: errorMessage };
|
|
7832
8893
|
}
|
|
7833
|
-
return { success: true, token: paymentResult.token };
|
|
8894
|
+
return { success: true, token: paymentResult.token, payerEmail: paymentResult.payerEmail };
|
|
7834
8895
|
}
|
|
7835
|
-
async function callConfirmEndpoint(apiBaseUrl, secureToken, googlePayToken, mockScenarioStr, checkoutRequestId) {
|
|
8896
|
+
async function callConfirmEndpoint(apiBaseUrl, secureToken, googlePayToken, mockScenarioStr, checkoutRequestId, payerEmail) {
|
|
7836
8897
|
const requestBody = {
|
|
7837
8898
|
mock_scenario: mockScenarioStr
|
|
7838
8899
|
};
|
|
7839
8900
|
if (googlePayToken) {
|
|
7840
8901
|
requestBody.google_pay_token = googlePayToken;
|
|
7841
8902
|
}
|
|
7842
|
-
|
|
8903
|
+
if (payerEmail) {
|
|
8904
|
+
requestBody.payer_email = payerEmail;
|
|
8905
|
+
}
|
|
8906
|
+
const result = await apiCall2(
|
|
7843
8907
|
`${apiBaseUrl}/api/checkout/${secureToken}/google-pay/confirm`,
|
|
7844
8908
|
{
|
|
7845
8909
|
method: "POST",
|
|
@@ -7858,7 +8922,7 @@ var PaymentKit = (() => {
|
|
|
7858
8922
|
return result.data;
|
|
7859
8923
|
}
|
|
7860
8924
|
async function callVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId) {
|
|
7861
|
-
const result = await
|
|
8925
|
+
const result = await apiCall2(
|
|
7862
8926
|
`${apiBaseUrl}/api/checkout/${secureToken}/google-pay/verify`,
|
|
7863
8927
|
{
|
|
7864
8928
|
method: "POST",
|
|
@@ -7881,22 +8945,55 @@ var PaymentKit = (() => {
|
|
|
7881
8945
|
data: {
|
|
7882
8946
|
id: response.transaction_id,
|
|
7883
8947
|
checkoutAttemptId: response.checkout_attempt_id,
|
|
7884
|
-
checkoutSessionId: secureToken,
|
|
7885
|
-
state: "checkout_succeeded"
|
|
8948
|
+
checkoutSessionId: response.checkout_session_id ?? secureToken,
|
|
8949
|
+
state: "checkout_succeeded",
|
|
8950
|
+
paymentIntentId: response.payment_intent_id,
|
|
8951
|
+
customerId: response.customer_id,
|
|
8952
|
+
paymentMethodId: response.payment_method_id,
|
|
8953
|
+
processorUsed: response.processor_used,
|
|
8954
|
+
subscriptionId: response.subscription_id,
|
|
8955
|
+
invoiceId: response.invoice_id,
|
|
8956
|
+
invoiceNumber: response.invoice_number,
|
|
8957
|
+
cardBrand: response.card_brand,
|
|
8958
|
+
cardLast4: response.card_last4,
|
|
8959
|
+
cardExpMonth: response.card_exp_month,
|
|
8960
|
+
cardExpYear: response.card_exp_year,
|
|
8961
|
+
errorCode: response.error_code,
|
|
8962
|
+
errorMessageForCustomer: response.error_message_for_customer,
|
|
8963
|
+
errorMessageForDebug: response.error_message_for_debug,
|
|
8964
|
+
nextAction: response.next_action
|
|
7886
8965
|
}
|
|
7887
8966
|
};
|
|
7888
8967
|
}
|
|
7889
|
-
return {
|
|
8968
|
+
return {
|
|
8969
|
+
errors: {
|
|
8970
|
+
google_pay: response.error_message_for_customer || response.error_message_for_debug || response.error_message || "Payment failed"
|
|
8971
|
+
}
|
|
8972
|
+
};
|
|
7890
8973
|
}
|
|
7891
|
-
async function confirmStripeGooglePay(apiBaseUrl, secureToken, mockScenarioStr, checkoutRequestId) {
|
|
7892
|
-
const response = await callConfirmEndpoint(
|
|
8974
|
+
async function confirmStripeGooglePay(apiBaseUrl, secureToken, mockScenarioStr, checkoutRequestId, payerEmail) {
|
|
8975
|
+
const response = await callConfirmEndpoint(
|
|
8976
|
+
apiBaseUrl,
|
|
8977
|
+
secureToken,
|
|
8978
|
+
void 0,
|
|
8979
|
+
mockScenarioStr,
|
|
8980
|
+
checkoutRequestId,
|
|
8981
|
+
payerEmail
|
|
8982
|
+
);
|
|
7893
8983
|
return toGooglePayResult(response, secureToken);
|
|
7894
8984
|
}
|
|
7895
|
-
var
|
|
7896
|
-
async function confirmAirwallexGooglePay(apiBaseUrl, secureToken, googlePayToken, mockScenarioStr, checkoutRequestId) {
|
|
8985
|
+
var MAX_USER_ACTIONS2 = 5;
|
|
8986
|
+
async function confirmAirwallexGooglePay(apiBaseUrl, secureToken, googlePayToken, mockScenarioStr, checkoutRequestId, payerEmail) {
|
|
7897
8987
|
let userActionCount = 0;
|
|
7898
|
-
let response = await callConfirmEndpoint(
|
|
7899
|
-
|
|
8988
|
+
let response = await callConfirmEndpoint(
|
|
8989
|
+
apiBaseUrl,
|
|
8990
|
+
secureToken,
|
|
8991
|
+
googlePayToken,
|
|
8992
|
+
mockScenarioStr,
|
|
8993
|
+
checkoutRequestId,
|
|
8994
|
+
payerEmail
|
|
8995
|
+
);
|
|
8996
|
+
while (response.charge_status === "pending" && response.next_action && userActionCount < MAX_USER_ACTIONS2) {
|
|
7900
8997
|
userActionCount++;
|
|
7901
8998
|
const actionResult = await handleNextAction(response.next_action);
|
|
7902
8999
|
const verifyResponse = await callVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId);
|
|
@@ -7916,21 +9013,21 @@ var PaymentKit = (() => {
|
|
|
7916
9013
|
}
|
|
7917
9014
|
return toGooglePayResult(verifyResponse, secureToken);
|
|
7918
9015
|
}
|
|
7919
|
-
if (userActionCount >=
|
|
9016
|
+
if (userActionCount >= MAX_USER_ACTIONS2) {
|
|
7920
9017
|
return { errors: { google_pay: "Too many authentication attempts. Please try again." } };
|
|
7921
9018
|
}
|
|
7922
9019
|
return toGooglePayResult(response, secureToken);
|
|
7923
9020
|
}
|
|
7924
|
-
var
|
|
9021
|
+
var defSubmitPayment3 = (states) => {
|
|
7925
9022
|
const submitPayment = async (_fields, options) => {
|
|
7926
9023
|
const { apiBaseUrl, secureToken, environment } = states;
|
|
7927
9024
|
const gpayOptions = options;
|
|
7928
|
-
const validationError =
|
|
9025
|
+
const validationError = validateOptions2(gpayOptions);
|
|
7929
9026
|
if (validationError) {
|
|
7930
9027
|
return { errors: validationError };
|
|
7931
9028
|
}
|
|
7932
9029
|
try {
|
|
7933
|
-
const mockScenarioStr =
|
|
9030
|
+
const mockScenarioStr = getMockScenarioStr2(gpayOptions.mockScenario);
|
|
7934
9031
|
const checkoutRequestId = getOrCreateCheckoutRequestId(environment);
|
|
7935
9032
|
console.log(`[GooglePay] Using checkout_request_id: ${checkoutRequestId}`);
|
|
7936
9033
|
const startResult = await callStartEndpoint(
|
|
@@ -7949,10 +9046,16 @@ var PaymentKit = (() => {
|
|
|
7949
9046
|
if (!stripeResult.success) {
|
|
7950
9047
|
return { errors: { google_pay: stripeResult.error } };
|
|
7951
9048
|
}
|
|
7952
|
-
return await confirmStripeGooglePay(
|
|
9049
|
+
return await confirmStripeGooglePay(
|
|
9050
|
+
apiBaseUrl,
|
|
9051
|
+
secureToken,
|
|
9052
|
+
mockScenarioStr,
|
|
9053
|
+
checkoutRequestId,
|
|
9054
|
+
stripeResult.payerEmail
|
|
9055
|
+
);
|
|
7953
9056
|
}
|
|
7954
9057
|
if (startData.processor === "airwallex") {
|
|
7955
|
-
const airwallexResult = await
|
|
9058
|
+
const airwallexResult = await runAirwallexFlow2(startData, gpayOptions.mockScenario);
|
|
7956
9059
|
if (!airwallexResult.success) {
|
|
7957
9060
|
return { errors: { google_pay: airwallexResult.error } };
|
|
7958
9061
|
}
|
|
@@ -7964,7 +9067,8 @@ var PaymentKit = (() => {
|
|
|
7964
9067
|
secureToken,
|
|
7965
9068
|
airwallexResult.token,
|
|
7966
9069
|
mockScenarioStr,
|
|
7967
|
-
checkoutRequestId
|
|
9070
|
+
checkoutRequestId,
|
|
9071
|
+
airwallexResult.payerEmail
|
|
7968
9072
|
);
|
|
7969
9073
|
}
|
|
7970
9074
|
return { errors: { google_pay: `Unsupported processor: ${startData.processor}` } };
|
|
@@ -7979,7 +9083,7 @@ var PaymentKit = (() => {
|
|
|
7979
9083
|
name: "google_pay",
|
|
7980
9084
|
externalFuncs: {},
|
|
7981
9085
|
internalFuncs: {
|
|
7982
|
-
submitPayment:
|
|
9086
|
+
submitPayment: defSubmitPayment3(paymentKitStates),
|
|
7983
9087
|
cleanup: () => {
|
|
7984
9088
|
}
|
|
7985
9089
|
}
|
|
@@ -7988,7 +9092,7 @@ var PaymentKit = (() => {
|
|
|
7988
9092
|
var google_pay_default = GooglePayPaymentMethod;
|
|
7989
9093
|
|
|
7990
9094
|
// src/payment-methods/paypal.ts
|
|
7991
|
-
var
|
|
9095
|
+
var defSubmitPayment4 = (states) => {
|
|
7992
9096
|
const submitPayment = async (_fields, options) => {
|
|
7993
9097
|
const { apiBaseUrl, secureToken, environment } = states;
|
|
7994
9098
|
const paypalOptions = options;
|
|
@@ -8117,7 +9221,7 @@ var PaymentKit = (() => {
|
|
|
8117
9221
|
// PayPal doesn't need createElement like card iframes
|
|
8118
9222
|
},
|
|
8119
9223
|
internalFuncs: {
|
|
8120
|
-
submitPayment:
|
|
9224
|
+
submitPayment: defSubmitPayment4(localStates),
|
|
8121
9225
|
cleanup: () => {
|
|
8122
9226
|
if (localStates.pollInterval) {
|
|
8123
9227
|
clearInterval(localStates.pollInterval);
|
|
@@ -8134,6 +9238,7 @@ var PaymentKit = (() => {
|
|
|
8134
9238
|
// src/cdn.ts
|
|
8135
9239
|
var cdn_default = index_default;
|
|
8136
9240
|
var PaymentMethods = {
|
|
9241
|
+
applePay: apple_pay_default,
|
|
8137
9242
|
card: card_default,
|
|
8138
9243
|
googlePay: google_pay_default,
|
|
8139
9244
|
paypal: paypal_default
|