Implement callbacks to customise your Paze payment flow for Web.
Components emit events based on user interaction or validation. You can use these to implement callback functions, which allow you to inject your own business logic and user experience customisations into the payment flow at critical moments. They ensure that while the SDK handles the complex technical aspects of payment processing, you retain full control over the customer experience and can seamlessly integrate payments into your broader business workflows and systems.
Callbacks enable you to:
- Validate business rules before payments proceed.
- Display custom error, failure, or success messages.
- Tailor user interfaces to match your brand's look and feel.
- Integrate with your own systems for fraud detection or customer management.
- Control exactly how your customers experience both successful and failed transactions.
- Handle Paze specific popup and decryption flow requirements.
Configure these callbacks on PxpCheckout.initialize(), not on the paze-button component. They supply shopper and shipping data when the SDK builds the Unity transaction request after decryption.
onGetShopper(recommended): Called during authorisation to retrieve shopper data for the transaction payload.onGetShippingAddress(optional): Called during authorisation when you need shipping address data included in the transaction.
These callbacks ensure the Paze component always uses the latest customer data from your application state, forms, or APIs when submitting payments.
This callback is recommended for most integrations. The SDK calls it optionally when building the transaction request, after decryption and before Unity authorisation.
You can use it to:
- Provide a stable shopper ID for your customer account or guest session.
- Return the latest name, email, and contact details from your application.
- Associate the Paze network-token transaction with your customer records.
Set onGetShopper on PxpCheckout.initialize():
const pxpSdk = PxpCheckout.initialize({
environment: 'test',
session: { /* ... */ },
transactionData: { /* ... */ },
onGetShopper: async () => ({
id: 'shopper-123',
email: 'customer@example.com',
firstName: 'John',
lastName: 'Doe'
})
});This callback receives no parameters. It must return a Promise<Shopper>.
| Property | Description |
|---|---|
idstring | A unique shopper identifier. Use your customer account ID for logged-in users or a persistent session ID for guest checkout so transactions can be linked to your records. |
firstNamestring | The shopper's given name, included in the transaction shopper profile sent to Unity. |
lastNamestring | The shopper's family name, included in the transaction shopper profile sent to Unity. |
emailstring | The shopper's email address for transaction records and customer correspondence. |
phoneNumberstring | A contact phone number for the shopper profile in the transaction request. |
dateOfBirthstring | The shopper's date of birth, when required by your integration or risk screening rules. |
houseNumberOrNamestring | The first line of the shopper's address, such as a house number or building name, for profile data in the transaction. |
streetstring | The street name or remaining address line for the shopper's profile data. |
citystring | The city or locality associated with the shopper's address. |
postalCodestring | The postal or ZIP code for the shopper's address. |
countryCodestring | A two-letter ISO 3166-1 alpha-2 country code for the shopper's address (for example, "US"). |
statestring | The state, province, or region for the shopper's address. |
productsobject | A key-value metadata object describing products in the order, forwarded with the transaction shopper data. |
orderDescriptionstring | A human-readable description of the order included in the transaction shopper data. |
All properties are optional in the type, but you should always return an id so transactions can be linked to your customer records.
onGetShopper: async () => {
const customer = await getCurrentCustomer();
if (customer) {
return {
id: customer.id,
email: customer.email,
firstName: customer.firstName,
lastName: customer.lastName,
phoneNumber: customer.phone
};
}
return {
id: getOrCreateGuestShopperId()
};
}Paze wallet identity (emailAddress / phoneNumber on the component) is separate from onGetShopper. Component identity controls Paze presentment and checkout. onGetShopper supplies the shopper object sent to Unity during authorisation. When both emailAddress and phoneNumber are set on the component, only phoneNumber is sent to Paze checkout() (both are still used for dynamic canCheckout()).
This callback is optional. When configured, the SDK calls it during authorisation and includes the returned address in the transaction request.
You can use it to:
- Include shipping address data for physical goods.
- Pass fulfilment address details required by your backend or risk screening.
Set onGetShippingAddress on PxpCheckout.initialize() alongside onGetShopper:
const pxpSdk = PxpCheckout.initialize({
// ... session and transactionData
onGetShopper: async () => ({ id: 'shopper-123' }),
onGetShippingAddress: async () => ({
address: '123 Main St',
city: 'New York',
state: 'NY',
postalCode: '10001',
countryCode: 'US'
})
});This callback receives no parameters. It must return a Promise<ShippingAddress>.
| Property | Description |
|---|---|
addressstring | The primary shipping street address. The SDK maps this value to addressLine1 in the transaction request. |
addressLine2string | An additional shipping address detail, such as an apartment, suite, or unit number. |
citystring | The city or locality where the order will be delivered. |
statestring | The state, province, or region for the shipping destination. |
countystring | The county or district for the shipping destination, when applicable. |
postalCodestring | The postal or ZIP code for the shipping destination. |
countryCodestring | A two-letter ISO 3166-1 alpha-2 country code for the shipping destination (for example, "US"). |
onGetShippingAddress: async () => {
const shipping = await getSelectedShippingAddress();
return {
address: shipping.line1,
addressLine2: shipping.line2,
city: shipping.city,
state: shipping.state,
postalCode: shipping.postalCode,
countryCode: shipping.countryCode
};
}Configure these callbacks on pxpSdk.create('paze-button', { ... }). All Paze-specific events are optional and can be mixed and matched based on your business needs.
For a successful payment, callbacks fire in this order:
onInit: after the Paze SDK initialises (before presentment resolves in dynamic mode).onPresentmentResolved: after the button visibility is determined.onCustomValidation→onPazeButtonClicked: when the customer clicks the button.onCheckoutCompleteoronCheckoutIncomplete: after the Pazecheckout()popup closes.onComplete: after Pazecomplete()returns and the response is decoded.onPreDecryption→onPostDecryption(if SDK decryption proceeds): decrypt secured payload.onPreAuthorisation→ Unity authorisation (the SDK callsonGetShopperandonGetShippingAddresshere) →onPostAuthorisation(if configured).
onError handles init, load, checkout, complete, and decryption errors. onSubmitError handles authorisation submission failures.
SDK initialisation callbacks (onGetShopper, onGetShippingAddress) are configured on PxpCheckout.initialize(). Paze component callbacks handle wallet popup interactions, decryption, and authorisation events.
This callback is triggered after the Paze SDK initialises for this component, before presentment resolves in dynamic mode.
You can use it to:
- Log that Paze has successfully initialised.
- Enable UI elements that depend on Paze being ready.
- Track SDK initialisation in your analytics.
This callback receives no parameters.
onInit: () => {
console.log('Paze component initialised successfully');
// Enable the Paze button in UI
enablePaymentButton('paze');
// Track initialisation in analytics
trackEvent('paze-initialised', {
timestamp: new Date().toISOString()
});
}This callback is triggered after presentment resolves, indicating whether the Paze button is visible or hidden based on eligibility checks.
You can use it to:
- Show or hide alternative payment methods based on Paze availability.
- Track how often Paze is presented to customers.
- Adjust page layout when Paze is not available.
| Parameter | Description |
|---|---|
isVisibleboolean | Indicates whether the Paze button is visible to the customer. |
onPresentmentResolved: (isVisible) => {
console.log('Paze button visible:', isVisible);
// Track presentment result
trackEvent('paze-presentment-resolved', {
isVisible: isVisible,
timestamp: new Date().toISOString()
});
if (!isVisible) {
// Show alternative payment methods
showAlternativePaymentMethods();
console.log('Paze not available, showing alternatives');
} else {
// Optionally hide other less preferred methods
prioritisePazeButton();
}
}This callback is triggered when the customer clicks the Paze button, before the checkout popup opens. It runs before onPazeButtonClicked and before Paze's checkout() is called.
You can use it to:
- Validate cart state, inventory, or order totals before checkout starts.
- Enforce terms acceptance or other merchant business rules.
- Block checkout from opening when prerequisites are not met.
Return true to allow checkout to proceed, or false to prevent the Paze popup from opening.
This callback receives no parameters.
| Return value | Behaviour |
|---|---|
true | Checkout proceeds to onPazeButtonClicked and the Paze popup. |
false | Checkout is cancelled. The Paze popup does not open. |
onCustomValidation: async () => {
if (!cartHasItems()) {
showError('Your cart is empty.');
return false;
}
if (!termsAccepted()) {
showError('Please accept the terms and conditions.');
return false;
}
const inventoryAvailable = await checkInventoryAvailability();
if (!inventoryAvailable) {
showError('Some items are no longer available.');
return false;
}
return true;
}Use onCustomValidation for merchant-side checks that must pass before the Paze wallet opens. Use onCheckoutComplete to approve or reject checkout data after the shopper finishes in the Paze popup but before complete() runs.
This callback is triggered after onCustomValidation passes, before the Paze checkout() popup opens.
You can use it to:
- Clear UI state or error messages before starting checkout.
- Show loading indicators.
- Track button click events for analytics.
| Parameter | Description |
|---|---|
eventEvent | The native browser click event object. |
onPazeButtonClicked: async (event) => {
console.log('Paze button clicked');
// Show loading state
setLoading(true);
clearErrorMessages();
// Track click event
trackEvent('paze-button-clicked', {
timestamp: new Date().toISOString(),
cartValue: getCurrentCartValue()
});
}This callback is triggered after the Paze popup returns a COMPLETE status, before the SDK calls Paze complete().
You can use it to:
- Validate the checkout result on your backend.
- Perform business rule checks before proceeding.
- Confirm order details with the customer.
- Apply final price adjustments.
If you omit this callback, the SDK treats checkout as approved and proceeds to complete(), decryption, and authorisation.
Return true to allow the SDK to proceed with complete(), decryption, and transaction submission. Return false to cancel the flow; the SDK then calls onCheckoutIncomplete with reason "Merchant validation rejected completion.".
| Parameter | Description |
|---|---|
resultPazeCheckoutResult | Object containing checkout result data. |
result.resultstring | The checkout result status ("COMPLETE" or "INCOMPLETE"). |
result.checkoutResponsestring | Present when result is "COMPLETE". Encoded checkout response JWT. |
result.checkoutDecodedResponseobject | Present when result is "COMPLETE". Decoded checkout response containing consumer, session, and masked card data. |
result.reasonstring | Optional reason from Paze (may be present on "COMPLETE" or "INCOMPLETE"). |
onCheckoutComplete: async (result) => {
console.log('Paze checkout completed:', result);
try {
// Validate the checkout result on your backend
const isValid = await validateCheckoutResult({
sessionId: result.checkoutDecodedResponse.sessionId,
consumerEmail: result.checkoutDecodedResponse.consumer.emailAddress,
cardLast4: result.checkoutDecodedResponse.maskedCard.panLastFour
});
if (!isValid) {
showError('Unable to validate checkout. Please try again.');
return false;
}
// Check if customer is eligible for this payment method
const isEligible = await checkCustomerEligibility(
result.checkoutDecodedResponse.consumer.emailAddress
);
if (!isEligible) {
showError('This payment method is not available for your account.');
return false;
}
// Track successful checkout completion
trackEvent('paze-checkout-completed', {
sessionId: result.checkoutDecodedResponse.sessionId,
timestamp: new Date().toISOString()
});
// Proceed with decryption and submission
return true;
} catch (error) {
console.error('Checkout validation failed:', error);
showError('Unable to process payment. Please try again.');
return false;
}
}This callback is triggered when the Paze checkout ends without completion or when the popup is closed by the customer.
You can use it to:
- Track abandonment rates for conversion optimisation.
- Show helpful messages or alternative options.
- Save the customer's cart for later completion.
- Trigger email campaigns for abandoned checkouts.
| Parameter | Description |
|---|---|
resultPazeCheckoutResult | Object containing checkout result data. |
result.resultstring | The checkout result status ("INCOMPLETE"). |
result.reasonstring | The reason for the incomplete checkout. |
onCheckoutIncomplete: (result) => {
console.log('Paze checkout incomplete:', result);
// Track abandonment for analytics
trackEvent('paze-checkout-abandoned', {
reason: result.reason || 'unknown',
timestamp: new Date().toISOString(),
cartValue: getCurrentCartValue()
});
// Preserve cart for later
saveCartForLater();
// Show context-appropriate message
// reason values come from Paze or the SDK (e.g. "Merchant validation rejected completion.")
if (result.reason?.toLowerCase().includes('cancel')) {
showMessage('No worries! Your items are saved. You can complete your purchase anytime.', 'info');
} else {
showMessage('Checkout was not completed. Please try again or use a different payment method.', 'warning');
}
// Offer alternatives after a short delay
setTimeout(() => {
showAlternativePaymentOptions();
}, 2000);
// Remove loading state
setLoading(false);
}This callback is triggered when Paze complete() returns successfully and the response JWT is decoded. It runs before onPreDecryption and before any SDK decryption or authorisation.
You can use it to:
- Read
securedPayloadfrom the decoded complete response. - Update UI with completion status.
- Track that the Paze complete step succeeded in analytics.
If onPreDecryption returns false, handle decryption manually using result.completeDecodedResponse.securedPayload. See Backend decryption for the PXP decrypt-token API.
| Parameter | Description |
|---|---|
resultPazeCompleteResult | Object containing the complete response data. |
result.completeResponsestring | The encoded complete response JWT. |
result.completeDecodedResponseobject | The decoded response containing payloadId, sessionId, and securedPayload. |
result.completeDecodedResponse.securedPayloadstring | The JWE encrypted payload to be decrypted. |
onComplete: async (result) => {
console.log('Paze complete flow finished');
console.log('Payload ID:', result.completeDecodedResponse?.payloadId);
console.log('Session ID:', result.completeDecodedResponse?.sessionId);
// Track completion
trackEvent('paze-complete-flow-finished', {
payloadId: result.completeDecodedResponse?.payloadId,
sessionId: result.completeDecodedResponse?.sessionId,
timestamp: new Date().toISOString()
});
// If handling decryption manually (when onPreDecryption returns false)
// Use result.completeDecodedResponse?.securedPayload on your backend
}This callback is triggered after onComplete, before the SDK calls Unity to decrypt the secured payload.
You can use it to:
- Request merchant operator approval for high-value transactions.
- Perform additional security checks.
- Control whether decryption should proceed.
- Handle decryption manually on your backend.
Return true to allow the SDK to decrypt and continue the built-in flow. Return false to abort SDK decryption and handle it yourself.
This callback receives no parameters.
To allow SDK to handle decryption:
onPreDecryption: async () => {
console.log('Pre-decryption check');
// Optional: Check transaction amount or other criteria
const cartValue = getCurrentCartValue();
if (cartValue > 1000) {
// Request approval for high-value transactions
const approved = await requestManagerApproval({
amount: cartValue,
timestamp: new Date().toISOString()
});
if (!approved) {
showError('Transaction requires manager approval');
return false;
}
}
// Allow SDK to proceed with decryption
return true;
}To handle decryption manually:
onPreDecryption: async () => {
console.log('Preventing SDK decryption - will handle manually');
// Return false to prevent SDK from decrypting
// Handle decryption in onComplete callback instead
return false;
}This callback is triggered after Unity successfully decrypts the network token.
You can use it to:
- Log masked token details for debugging.
- Store card information for display purposes.
- Update UI with payment method details.
- Validate decrypted token before proceeding.
This callback is only triggered if onPreDecryption returns true (SDK-managed decryption).
| Parameter | Description |
|---|---|
decryptedPayloadPazeDecryptTokenResponse | The decrypted token response from Unity. |
decryptedPayload.shopperobject | Customer information (name, email, phone, country, language). |
decryptedPayload.billingAddressobject | Optional billing address (address line, city, state, country code, postal code). |
decryptedPayload.fundingDataobject | Network token data (token, expiry, account reference, card network, token usage type, dynamic data expiration). |
onPostDecryption: async (decryptedPayload) => {
console.log('Token decrypted successfully');
// Log masked token for debugging (first 6 and last 4 digits only)
const maskedToken = decryptedPayload.fundingData.networkToken.slice(0, 6) +
'...' +
decryptedPayload.fundingData.networkToken.slice(-4);
console.log('Masked network token:', maskedToken);
console.log('Card network:', decryptedPayload.fundingData.cardNetwork);
console.log('Expiry:', `${decryptedPayload.fundingData.expirationMonth}/${decryptedPayload.fundingData.expirationYear}`);
// Store masked card details for display
saveMaskedCardDetails({
network: decryptedPayload.fundingData.cardNetwork,
lastFour: decryptedPayload.fundingData.networkToken.slice(-4),
expiry: `${decryptedPayload.fundingData.expirationMonth}/${decryptedPayload.fundingData.expirationYear}`
});
// Update UI with shopper information
displayShopperInfo({
name: decryptedPayload.shopper.fullName,
email: decryptedPayload.shopper.emailAddress,
postalCode: decryptedPayload.billingAddress?.postalCode
});
// Track successful decryption
trackEvent('paze-decryption-completed', {
cardNetwork: decryptedPayload.fundingData.cardNetwork,
timestamp: new Date().toISOString()
});
}This callback is triggered before the transaction is submitted to Unity.
You can use it to:
- Integrate with Kount or other fraud detection services.
- Perform AVS (Address Verification System) checks.
- Apply business rules based on transaction amount or customer history.
- Include additional risk screening data.
- Abort the transaction if needed.
Return false to abort the transaction. Return true or null to proceed without extra data. Return a PazeTransactionInitData object with riskScreeningData to include fraud detection data in the transaction request.
This callback receives no parameters.
To proceed with basic authorisation:
onPreAuthorisation: async () => {
console.log('Pre-authorisation check');
// Perform basic checks
const isValid = await validateOrderDetails();
if (!isValid) {
showError('Order validation failed');
return false; // Abort transaction
}
// Proceed with authorisation
return true;
}To include risk screening data:
onPreAuthorisation: async () => {
console.log('Including risk screening data');
const customerData = await getCustomerData();
const orderItems = await getOrderItems();
const shippingAddress = await getShippingAddress();
return {
riskScreeningData: {
performRiskScreening: true,
userIp: await getUserIpAddress(),
account: {
id: customerData.id,
creationDateTime: customerData.createdAt
},
items: orderItems.map(item => ({
price: item.price,
quantity: item.quantity,
category: item.category,
sku: item.sku
})),
fulfillments: [{
type: "Shipped",
shipping: {
shippingMethod: "Standard"
},
recipientPerson: {
phoneNumber: customerData.phone,
email: customerData.email,
address: {
line1: shippingAddress.street,
city: shippingAddress.city,
region: shippingAddress.state,
countryCode: shippingAddress.countryCode,
postalCode: shippingAddress.postalCode
}
}
}],
transaction: {
subtotal: orderItems.reduce((sum, item) => sum + (item.price * item.quantity), 0)
}
}
};
}This callback is triggered after Unity returns a successful HTTP response for the transaction submission. Configure it on the component to receive transaction results; if omitted, the SDK does not call it.
The callback receives authorised, declined, and other non-failure states. HTTP or validation failures route to onSubmitError instead.
You can use it to:
- Retrieve full authorisation result from your backend using the transaction identifiers.
- Redirect customers to a success page with order confirmation.
- Update stock levels for purchased items.
- Send order confirmation emails to customers.
- Record successful transactions for business intelligence.
| Parameter | Description |
|---|---|
dataPazePostAuthorisationData | Object containing transaction result data. |
data.merchantTransactionIdstring | Your unique identifier for the transaction. |
data.systemTransactionIdstring | The Unity system transaction identifier. |
data.networkTokenstring | The network token used for the transaction. |
data.providerResponseCodestring | Optional provider response code. |
data.statestring | Optional transaction state (e.g. "Authorised", "Declined", "Error"). |
data.stateDataCodestring | Optional additional state information code. |
onPostAuthorisation: async (data) => {
console.log('Payment authorisation completed');
console.log('Merchant Transaction ID:', data.merchantTransactionId);
console.log('System Transaction ID:', data.systemTransactionId);
console.log('Transaction State:', data.state);
try {
// Retrieve full transaction details from your backend
const transactionResult = await getTransactionResult(
data.merchantTransactionId,
data.systemTransactionId
);
if (data.state === 'Authorised') {
// Update inventory
await updateInventory(data.merchantTransactionId);
// Send confirmation email
await sendOrderConfirmation({
transactionId: data.merchantTransactionId,
systemTransactionId: data.systemTransactionId,
amount: transactionResult.amount
});
// Track successful purchase
trackEvent('paze-purchase-completed', {
transactionId: data.merchantTransactionId,
amount: transactionResult.amount,
timestamp: new Date().toISOString()
});
// Redirect to success page
window.location.href = `/payment-success?txn=${data.merchantTransactionId}`;
} else if (data.state === 'Declined') {
console.error('Payment declined:', data.providerResponseCode);
showErrorMessage('Payment declined. Please try again or use a different payment method.');
setLoading(false);
} else {
console.error('Unexpected payment state:', data.state);
showErrorMessage('Payment processing error. Please contact support if charged.');
setLoading(false);
}
} catch (error) {
console.error('Failed to process post-authorisation:', error);
showErrorMessage('Unable to confirm payment status. Please contact support.');
setLoading(false);
}
}This callback is triggered when transaction submission or pre-submit validation fails.
You can use it to:
- Log errors for debugging and support.
- Display user-friendly error messages.
- Offer alternative payment methods.
- Report errors to your monitoring system.
The callback receives one of:
| Type | When | Key fields |
|---|---|---|
FailedSubmitResult | Risk screening validation fails before submit, or Unity returns an HTTP error response | errorCode, errorReason, correlationId, httpStatusCode, details |
PazeTransactionFailedException | Unity returns a failed transaction response | ErrorCode, message, submitResult (FailedSubmitResult) |
BaseSdkException | Other authorisation errors | ErrorCode, message, details |
onSubmitError: async (submitError) => {
console.error('Transaction submission failed:', submitError);
// PazeTransactionFailedException wraps FailedSubmitResult
if ('submitResult' in submitError) {
const failed = submitError.submitResult;
logErrorToMonitoring({
errorCode: failed.errorCode,
errorReason: failed.errorReason,
correlationId: failed.correlationId,
httpStatusCode: failed.httpStatusCode
});
showSupportInfo(`Reference: ${failed.correlationId}`);
showErrorMessage('Payment failed. Please try again.');
return;
}
// FailedSubmitResult (e.g. risk screening validation)
if ('errorCode' in submitError && 'errorReason' in submitError) {
showErrorMessage(submitError.errorReason);
return;
}
// BaseSdkException
showErrorMessage(submitError.message);
logErrorToMonitoring({
errorCode: submitError.ErrorCode,
message: submitError.message
});
setLoading(false);
}This callback is triggered when SDK, presentment, checkout, complete, or decryption errors occur (initialisation, script load, popup failures, and similar).
You can use it to:
- Log errors for debugging and monitoring.
- Display user-friendly error messages.
- Offer alternative payment methods.
- Report critical errors to support.
| Parameter | Description |
|---|---|
errorBaseSdkException | The error object containing details. |
error.ErrorCodestring | The SDK error code. |
error.messagestring | Human-readable error description. |
error.detailsany | Additional error details (optional). |
onError: (error) => {
console.error('Paze SDK error:', error);
// Log error for debugging
logError('paze-sdk-error', {
errorCode: error.ErrorCode,
message: error.message,
details: error.details,
timestamp: new Date().toISOString()
});
// Handle different error types
let userMessage = 'Payment setup failed. Please try again.';
if (error.message.includes('initialization') || error.message.includes('initialisation')) {
userMessage = 'Unable to initialise payment method. Please refresh the page.';
notifySupport('Paze initialization failed', error);
} else if (error.message.includes('Network') || error.message.includes('timeout')) {
userMessage = 'Network error. Please check your connection and try again.';
} else if (error.message.includes('popup') || error.message.includes('blocked')) {
userMessage = 'Popup was blocked. Please allow popups for this site and try again.';
} else if (error.message.includes('configuration')) {
userMessage = 'Payment system configuration error. Please contact support.';
notifySupport('Paze configuration error', error);
}
showErrorMessage(userMessage);
// Track error in analytics
trackEvent('paze-error', {
errorCode: error.ErrorCode,
errorType: error.message,
timestamp: new Date().toISOString()
});
// Show alternative payment options
showAlternativePaymentMethods();
}The object returned by onGetShopper:
interface Shopper {
id?: string;
firstName?: string;
lastName?: string;
dateOfBirth?: string;
email?: string;
phoneNumber?: string;
houseNumberOrName?: string;
street?: string;
city?: string;
postalCode?: string;
countryCode?: string;
state?: string;
products?: Record<string, string>;
orderDescription?: string;
}The object returned by onGetShippingAddress:
interface ShippingAddress {
countryCode?: string;
postalCode?: string;
address?: string;
addressLine2?: string;
city?: string;
county?: string;
state?: string;
}The checkout result object passed to onCheckoutComplete and onCheckoutIncomplete:
interface PazeCheckoutResult {
result: "COMPLETE" | "INCOMPLETE";
checkoutResponse?: string;
reason?: string;
checkoutDecodedResponse?: {
sessionId?: string;
consumer: {
fullName: string;
firstName: string;
lastName: string;
emailAddress: string;
mobileNumber: PazePhoneNumber | null;
countryCode: string;
languageCode: string;
};
maskedCard: {
digitalCardId: string;
panLastFour: string;
paymentAccountReference: string;
panExpirationMonth: string;
panExpirationYear: string;
paymentCardDescriptor: string;
paymentCardType: string;
paymentCardBrand: string;
paymentCardNetwork: string;
digitalCardData: PazeDigitalCardData;
billingAddress: PazeCheckoutAddress;
};
};
}checkoutDecodedResponse is only populated when result is "COMPLETE".
The complete result object passed to onComplete:
interface PazeCompleteResult {
completeResponse: string;
completeDecodedResponse?: {
payloadId: string;
sessionId?: string;
securedPayload?: string;
};
}decryptedPayload is not populated on onComplete. Decrypted token data is passed to onPostDecryption when SDK decryption proceeds.
The decrypted token response passed to onPostDecryption:
interface PazeDecryptTokenResponse {
shopper: {
firstName?: string;
lastName?: string;
fullName: string;
emailAddress: string;
phoneCountryCode?: string;
phoneNumber?: string;
countryCode?: string;
languageCode?: string;
};
billingAddress?: {
addressLine1: string;
city: string;
state: string;
countryCode: string;
postalCode: string;
};
fundingData: {
networkToken: string;
expirationMonth: string;
expirationYear: string;
accountReference?: string;
cardNetwork: string;
tokenUsageType?: string;
dynamicDataExpiration?: string;
};
}The authorisation data passed to onPostAuthorisation:
interface PazePostAuthorisationData {
merchantTransactionId: string;
systemTransactionId: string;
networkToken: string;
providerResponseCode?: string;
state?: string;
stateDataCode?: string;
}onSubmitError may receive FailedSubmitResult, PazeTransactionFailedException (with a submitResult property), or BaseSdkException. See the onSubmitError section above.
Used for HTTP submission failures and validation errors before submit:
interface FailedSubmitResult {
errorCode: string;
errorReason: string;
correlationId: string;
httpStatusCode: number;
details: any[];
}The error data passed to onError:
interface BaseSdkException {
ErrorCode: string;
message: string;
details?: any;
}Event callbacks should handle errors gracefully and provide appropriate feedback to customers:
const pazeConfig = {
onCheckoutComplete: async (result) => {
try {
// Validate checkout result
const isValid = await validateCheckout(result);
if (!isValid) {
showError('Checkout validation failed');
return false;
}
return true;
} catch (error) {
console.error('Checkout validation error:', error);
showError('Unable to validate checkout. Please try again.');
return false;
}
},
onPostAuthorisation: async (data) => {
try {
// Retrieve transaction details from backend
const result = await getTransactionResult(
data.merchantTransactionId,
data.systemTransactionId
);
if (data.state === 'Authorised') {
// Process successful payment
await processSuccessfulPayment(data);
window.location.href = `/payment-success?txn=${data.merchantTransactionId}`;
} else {
showErrorMessage('Payment was not authorised. Please try again.');
}
} catch (error) {
console.error('Failed to retrieve transaction result:', error);
showErrorMessage('Unable to confirm payment status. Please contact support.');
}
},
onSubmitError: async (submitError) => {
console.error('Transaction submission failed:', submitError);
if ('submitResult' in submitError) {
showErrorMessage(submitError.submitResult.errorReason);
} else if ('errorCode' in submitError) {
showErrorMessage(submitError.errorReason);
} else {
showErrorMessage(submitError.message);
}
setLoading(false);
},
onError: (error) => {
console.error('Paze SDK error:', error);
// Log for debugging
logError('paze-error', error);
// Show appropriate message
if (error.message.includes('popup')) {
showErrorMessage('Please allow popups for this site and try again.');
} else if (error.message.includes('initialization')) {
showErrorMessage('Unable to initialise payment method. Please refresh the page.');
} else {
showErrorMessage('Payment setup failed. Please try again or use a different payment method.');
}
}
};If you need to decrypt the secured payload on your own backend instead of using the SDK's built-in decryption, see Backend decryption for the PXP decrypt-token API.
const pazeConfig = {
// Prevent SDK from decrypting
onPreDecryption: async () => {
console.log('Handling decryption manually');
return false;
},
// Handle secured payload in onComplete
onComplete: async (result) => {
const securedPayload = result.completeDecodedResponse?.securedPayload;
try {
// Forward securedPayload to your backend (never decrypt in the browser)
const decryptedData = await fetch('/api/paze/decrypt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ securedPayload })
}).then(r => r.json());
// Use decrypted data to submit transaction
const transactionResult = await submitTransaction(decryptedData);
if (transactionResult.success) {
window.location.href = `/payment-success?txn=${transactionResult.transactionId}`;
} else {
showErrorMessage('Transaction failed. Please try again.');
}
} catch (error) {
console.error('Manual decryption failed:', error);
showErrorMessage('Payment processing failed. Please try again.');
}
}
};Integrate with fraud detection services in the onPreAuthorisation callback:
onPreAuthorisation: async () => {
console.log('Performing fraud checks');
try {
const customerData = await getCustomerData();
const orderData = await getOrderData();
const shippingAddress = await getShippingAddress();
// Optional merchant-side fraud check before submit
const fraudScore = await checkFraudScore({
customerId: customerData.id,
orderValue: orderData.total
});
if (fraudScore > 70) {
showErrorMessage('We were unable to process your payment. Please contact support.');
return false;
}
return {
riskScreeningData: {
performRiskScreening: true,
userIp: await getUserIpAddress(),
account: {
id: customerData.id,
creationDateTime: customerData.createdAt
},
items: orderData.items.map(item => ({
price: item.price,
quantity: item.quantity,
category: item.category,
sku: item.sku
})),
fulfillments: [{
type: 'Shipped',
shipping: {
shippingMethod: orderData.shippingMethod
},
recipientPerson: {
name: {
first: customerData.firstName,
family: customerData.lastName
},
email: customerData.email,
phoneNumber: customerData.phone,
address: {
line1: shippingAddress.street,
city: shippingAddress.city,
region: shippingAddress.state,
countryCode: shippingAddress.countryCode,
postalCode: shippingAddress.postalCode
}
}
}],
transaction: {
subtotal: orderData.subtotal
}
}
};
} catch (error) {
console.error('Fraud check failed:', error);
logError('fraud-check-failed', error);
return true;
}
}Track Paze events comprehensively for business intelligence:
const pazeConfig = {
onInit: () => {
trackEvent('paze_initialized', {
timestamp: new Date().toISOString()
});
},
onPresentmentResolved: (isVisible) => {
trackEvent('paze_presentment_resolved', {
is_visible: isVisible,
timestamp: new Date().toISOString()
});
},
onCustomValidation: async () => {
return cartHasItems() && termsAccepted();
},
onPazeButtonClicked: async (event) => {
trackEvent('paze_button_clicked', {
cart_value: getCurrentCartValue(),
cart_items: getCartItemCount(),
timestamp: new Date().toISOString()
});
},
onCheckoutComplete: async (result) => {
trackEvent('paze_checkout_completed', {
session_id: result.checkoutDecodedResponse.sessionId,
card_network: result.checkoutDecodedResponse.maskedCard.paymentCardNetwork,
timestamp: new Date().toISOString()
});
return true;
},
onCheckoutIncomplete: (result) => {
trackEvent('paze_checkout_abandoned', {
reason: result.reason,
cart_value: getCurrentCartValue(),
timestamp: new Date().toISOString()
});
},
onPostAuthorisation: async (data) => {
trackEvent('paze_payment_completed', {
merchant_transaction_id: data.merchantTransactionId,
system_transaction_id: data.systemTransactionId,
state: data.state,
timestamp: new Date().toISOString()
});
// Process payment...
},
onSubmitError: async (submitError) => {
const errorCode = 'submitResult' in submitError
? submitError.submitResult.errorCode
: 'errorCode' in submitError
? submitError.errorCode
: submitError.ErrorCode;
trackEvent('paze_payment_failed', {
error_code: errorCode,
timestamp: new Date().toISOString()
});
}
};