SDK Integration Guide
Overview
This guide walks through integrating Paze Button within your checkout experience using a Review and Pay flow. This flow allows customers to review their order details on the merchant site before completing payment through the Paze wallet. Watch the video below to understand the interactions between your Customer, Your Server, the Paze JS SDK, the Paze Server, and the Payment Processor.
At a high level, the sequence covers:
- Initializing the SDK
- Integrating the Paze Button
- Launching the Paze Checkout Flow on button click
- Handling requests and responses
- Completing the transaction
Sequence Diagram
The following sequence diagram illustrates how the merchant site, Paze SDK, and Paze Experience interact during this process. It’s meant as a quick reference to understand the end-to-end flow before a deep dive into the sequence diagram and detailed integration steps.
Integration Steps
There are five basic steps to integrate the Button and Review and Pay flow from the Paze SDK with your application:
Each step includes what is happening, why it matters, when to implement, and best practices.
1. Load: Include the Paze SDK using the script tag
<!-- Paze SDK (choose environment) -->
<!-- 0. Sandbox -->
<script src="https://checkout.wallet.cat.earlywarning.io/web/resources/js/digitalwallet-sdk.js"></script>
<!-- 1. Production -->
<!-- <script src="https://checkout.paze.com/web/resources/js/digitalwallet-sdk.js"></script> -->
WHAT: Load the Paze SDK. It attaches a global object to the window named
DIGITAL_WALLET_SDK. The merchant later reads from that global in the JavaScript code. (in Part 2)WHY: You need the SDK available before you can
initialize(), call functions, or launch the Paze Checkout Experience.WHEN: Add the
<script>tag once per page where the button would be rendered, usually the checkout pages.BEST PRACTICES: Include exactly one environment (sandbox or prod) on your checkout pages with the Paze Button.
2. Initialize: Configure the Paze SDK using initialize()
const paze = window.DIGITAL_WALLET_SDK;
await paze.initialize({
client: {
// Required
id: "YOUR_CLIENT_ID", // Required: assigned by Paze Distributor
profileId: "YOUR_PROFILE_ID", // Required: assigned by Paze Distributor
name: "YOUR_MERCHANT_DISPLAY_NAME", // Recommended: customer-friendly name associated with merchant site the customer is shopping on
},
});
WHAT: You create a configured SDK instance tied to your merchant identifier. After the await resolves, the SDK is ready. The
client.idis the merchant’s assigned identifier at onboarding. Theclient.profileIdis also assigned during onboarding. Both of these values are issued by Paze.WHY:
initialize()authenticates and scopes all subsequent calls to your merchant profile.WHEN: This should be called once on page load to avoid customer experience delays.
BEST PRACTICES: On Error, fail gracefully; do not block the native checkout flow on fail.
client.nameis rendered if available, else the default used is “merchant.” In this example “Bexleigh” is theclient.name. This should be a consumer-friendly name associated with the merchant site they are shopping on.
3. Render button: Display the Paze Button adhering to brand guidelines
Merchants render the Paze button according to the Paze Checkout User Interface Standards guide. The required .SVG logo files and usage instructions are provided to merchants during onboarding. Use one of the approved colorways such as the preferred Paze Blue (#F042F8) or variants approved for monochromatic sites. Maintain clear space at least one-third of the logo’s height and display the button as a rectangular or pill-shaped button as outlined in the standards guide. It should load immediately with other wallet options, not hidden in menus, and match their visual prominence.
<!-- Paze option in your "Wallets" group -->
<button id="pazeBtn" type="button" class="paze-btn">
<img src="/assets/paze-logo.svg" alt="Paze" class="paze-logo" />
</button>
.paze-btn {
padding: 7px 60px;
background-color: #0f42f8;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
Rendered Code Example
Note: For approved variants, consult the Paze User Interface standards.
WHAT: Render the branded Paze button on your checkout pages. This button allows customers to initiate the Paze checkout experience by clicking. Make sure to adhere to the Paze Button Guide to ensure compliance. There are a few approved variants so you can align with your site’s design while staying compliant with brand guidelines.
WHY: The button offers a customer-driven entry point into the Paze experience.
WHEN: Render the button whenever you surface payment options in your checkout experiences. The Paze Button should always be rendered after the initialization step to ensure a smooth launch experience.
BEST PRACTICES: Follow brand guidelines in the Paze Button Guide. It should only be used after
initialize()has been called so thecheckout()call can be successfully called.
4. Checkout: Launch the Paze Wallet on button click using checkout()
// on click event for the paze button
pazeBtn.addEventListener("click", async () => {
const checkoutResponse = await paze.checkout({
// Identity and session
emailAddress: "[email protected]", // Optional: Used to prefill customer info for seamless login
mobileNumber: "CUSTOMER_MOBILE_NUMBER", // Optional: Used to prefill customer info if available
sessionId: "YOUR_SESSION_ID", // Recommended: same value per session that is used to link the transaction in your system
// Flow control (this is for modifying how the Paze Experience works)
actionCode: "START_FLOW", // Optional: START_FLOW (default and option required for Review and Pay Flow)
intent: "REVIEW_AND_PAY", // Required: REVIEW_AND_PAY required for this flow.
// Amount to display
transactionValue: {
// Recommended: as it renders subtotal in Paze Experience
transactionCurrencyCode: "USD", // Conditional with transactionValue
transactionAmount: "149.99", // Conditional with transactionValue
},
// Address and card controls
shippingPreference: "ALL", // Optional: ALL (default) | NONE
billingPreference: "ALL", // Optional: ALL (default)
});
// checkoutResponse → { result: "COMPLETE" | "INCOMPLETE", checkoutResponse?: "<JWS>" }
});
WHAT:
checkout()results in the launching of the Paze UI conditionally. This checkout() call only occurs when the Paze button is clicked. Paze then passes identity, session data, and controls that tune the flow: intent, card/address preferences, accepted networks, etc. Within the UI, the buyer authenticates and selects the payment method. The call resolves with a result ofCOMPLETEorINCOMPLETEand a <JWS> on success.WHY: This is the actual customer interaction where they authenticate and select payment method inside the wallet.
WHEN: On button click. This should only be called after
initialize().BEST PRACTICES: You should reuse the same
sessionIdthroughout checkout. Keep the flow as minimal as possible and only pass the options that you need. Handle theINCOMPLETEresponse by falling back to the normal merchant checkout flow. Restore focus to your checkout form to return to your native flow to avoid customer dead-ends. Storing the last four digits returned for future reference on the payment confirmation and email pages is also recommended.
Response to checkout() Call
checkout() returns a result of COMPLETE or INCOMPLETE and if complete the response contains a JSON Web Signature (JWS) called checkoutResponse. The checkoutResponse object contains information that can be used to pre-populate a merchant’s review and pay page. This checkoutResponse JWS can be decoded with a Base64 decoder.
Checkout Response
{
"result": "COMPLETE", // Required: String (Enum: COMPLETE | INCOMPLETE)
"checkoutResponse": "eyJhbGciOi..." // Conditional: only when result === COMPLETE String (JWS<CheckoutResponse>)
}
Decoded \JWS<CheckoutResponse>
{
"sessionId": "abc123", // Optional: String (echoed if provided)
"consumer": {
// Required: Object (Consumer)
"firstName": "Jane", // Optional: String
"lastName": "Doe", // Optional: String
"fullName": "Jane Doe", // Required: String
"emailAddress": "[email protected]", // Required: String (RFC 5322)
"mobileNumber": {
// Optional: Object (PhoneNumber)
"countryCode": "1", // Required: String (ISD code)
"phoneNumber": "5551234567" // Required: String
}
},
"maskedCard": {
// Required: Object (MaskedCard)
"digitalCardId": "uuid-1234-5678", // Required: String (UUID)
"panLastFour": "4242", // Required: String (last 4 digits)
"paymentAccountReference": "PAR1234567890", // Required: String (PAR)
"panExpirationMonth": "12", // Conditional: String (MM)
"panExpirationYear": "2028", // Conditional: String (YYYY)
"paymentCardDescriptor": "Rewards Plus", // Required: String
"paymentCardType": "CREDIT", // Required: Enum (CREDIT | DEBIT)
"paymentCardBrand": "VISA", // Required: Enum (VISA | MASTERCARD)
"paymentCardNetwork": "VISA", // Required: Enum (network)
"digitalCardData": {
// Required: Object (Digital Card Data)
"artUri": "https://cdn.paze.com/cardart/visa.png", // Required: URL
"artHeight": 48, // Required: Number (px)
"artWidth": 76 // Required: Number (px)
},
"billingAddress": {
// Conditional: Object (Address)
"line1": "123 Main St", // Required: String
"city": "Phoenix", // Required: String
"state": "AZ", // Required: String
"zip": "85001", // Required: String
"countryCode": "US" // Required: String (ISO 3166-1 alpha-2)
}
},
"shippingAddress": {
// Conditional: Object (ShippingAddress)
"name": "Jane Doe", // Required: String
"line1": "123 Main St", // Required: String
"city": "Phoenix", // Required: String
"state": "AZ", // Required: String
"zip": "85001", // Required: String
"countryCode": "US", // Required: String (ISO 3166-1 alpha-2)
"deliveryContactDetails": {
// Optional: Object
"contactPhoneNumber": {
// Optional: Object (PhoneNumber)
"countryCode": "1", // Required: String
"phoneNumber": "5551234567" // Required: String
},
"contactFullName": "Jane Doe" // Optional: String
}
}
}
5. Complete: Finalize the transaction using complete()
const completeResponse = await paze.complete({
// Transaction semantics
transactionType: "PURCHASE", // Required: "PURCHASE" | "CARD_ON_FILE" (store/manage for later use) | "BOTH" (CARD_ON_FILE + PURCHASE)
sessionId: "YOUR_SESSION_ID", // Recommended: same value per session
transactionValue: {
// Conditional: **Required if** transactionType=PURCHASE or BOTH
transactionCurrencyCode: "USD", // Required with transactionValue
transactionAmount: "149.99", // Required with transactionValue
},
// Output behavior
transactionOptions: {
// Optional
payloadTypeIndicator: "PAYMENT", // Optional: "ID" (ID only) | "PAYMENT" (return JWE now)
billingPreference: "ALL", // Optional: ALL | NONE
},
// Additional metadata (if used by your risk/processor flows)
enhancedTransactionData: {
// Optional
// Example placeholders:
// orderId: "ORDER-12345",
// riskScore: 42,
// channel: "ECOMMERCE"
// (Replace with your real ecom data fields)
},
});
// completeResponse → { completeResponse: "<JWS containing payloadId[, securedPayload]>" }
WHAT: You ask the SDK to finalize and return the payment payload that your payment processor needs. Your promise resolves with a
completeResponse: <JWS> that contains thesecuredPayload.WHY:
complete()gives you the tokenized, signed result that is needed for your payment processor.WHEN: Immediately after
checkout()is submitted and confirmed on the merchant review page and you are ready to submit the order.BEST PRACTICES: Idempotency: include/track so retries do not double-charge. Retries should not use the same cryptogram from Paze. Include any
enhancedTransactionDatathat your risk or processor flows use. On Error, fallback to your standard payment methods to avoid customer drop-off.
Response to complete() Call
complete() response contains a JSON Web Signature completeResponse which can be verified with Paze public key for authenticity, then decoded with a Base64 decoder. This contains the sessionId which matches the other calls in this session. The securedPayload is a JSON Web Encryption (JWE) that is encrypted and must be decrypted with the merchant's private key associated with the certificate provided by the merchant during onboarding. This object contains the data needed for your payment services provider to process the transaction. The dynamic data cryptogram is sent by the merchant to the payment processor and is valid for 24 hours.
Complete() Response
completeResponse is a JWS (JSON Web Signature) containing the signed response payload.
{
"completeResponse": "eyJhbGciOi..." // Required: String (JWS<CompleteResponse>)
}
BEST PRACTICES: We strongly recommend that you send the contents of the
completeResponseto your server for decoding and decryption.
Decoded completeResponse
After receiving the completeResponse JWS, first decode it to extract the JSON payload containing payloadId, sessionId, and optionally securedPayload.
{
"payloadId": "txn-7890-1234", // Required: String (≤ 50 chars)
"sessionId": "YOUR_SESSION_ID", // Optional: String (echoed if provided)
"securedPayload": "eyJhbGciOi..." // Conditional: String (JWE<JWS<Payload>>)
}
Decrypted securePayload
Decrypt the securePayload using your merchant's private key. The decrypted payload contains sensitive information necessary for you to process the transaction.
{
"clientId": "merchant-12345", // Required: String
"profileId": "profile-6789", // Required: String
"eci": "05", // Optional: String (ECI code)
"consumer": {
// Required: Object (Consumer)
"fullName": "Jane Doe", // Required: String
"emailAddress": "[email protected]" // Required: String (RFC 5322)
},
"billingAddress": {
// Conditional: Object (Address)
"line1": "123 Main St", // Required: String
"city": "Phoenix", // Required: String
"state": "AZ", // Required: String
"zip": "85001", // Required: String
"countryCode": "US" // Required: String (ISO 3166-1 alpha-2)
},
"token": {
// Required: Object (Token)
"paymentToken": "[Removed]", // Required: String (network token)
"tokenExpirationMonth": "12", // Required: String (MM)
"tokenExpirationYear": "2028", // Required: String (YYYY)
"paymentAccountReference": "PAR1234567890" // Required: String (PAR)
},
"paymentCardNetwork": "VISA", // Required: Enum (VISA | MASTERCARD | DISCOVER)
"dynamicData": [
// Required: Array<DynamicData>
{
"dynamicDataType": "PURCHASE", // Required: Enum (PURCHASE | CARD_ON_FILE)
"dynamicData": "CiAgICAg...", // Required: String (cryptogram) This is sent to the payment processor as is and is not decrypted by the merchant. The cryptogram is valid for 24 hours.
"dynamicDataExpiration": "2025-12-31T23:59:59Z" // Optional: String (ISO 8601)
}
]
}
Testing and Error Handling
Environments
- Sandbox (Test) – full wallet flows for integration/QA
- Use Paze-provided test-accounts (emails / mobile numbers) that simulate various customer states
- Test Data Includes:
- Wallet present (active, suspended, no card)
- Different card networks (Visa, Mastercard, Discover)
- Production – live environment, only after certification and approval.
Testing Recommendations
- Initialize once and reuse the same sessionId across checkout and complete.
- Session timeout: Wallet warns after 6 min, expires after 8 min. Require new session.
- Positive test cases:
- Eligible wallet launches immediately and completes checkout
- Multiple cards: verify card selection
- Multiple addresses: verify shipping selection
- Button click calls checkout() and launches the Paze Experience
- Action codes for checkout():
- START_FLOW: launch Paze Experience
- CHANGE_CARD (if used): render card selection screen
- CHANGE_SHIPPING_ADDRESS (if used): render address selection screen
Error Handling
- Initialization errors: continue normal merchant checkout.
- Ineligible consumer: no popup; continue standard checkout.
- Customer cancel / INCOMPLETE: No popup shown or dismissed; continue checkout.
- Timeout: wallet closes; require customer to retry with a new session.
- Complete() errors: allow retry with new idempotency key.
Paze SDK Error Response Object
The error response object contains both a reason and a message. The reason is intended for merchant logic to process and handle the issue while the message is intended for human readability and manual debugging or logging. There is an optional array of objects called details that adds specificity to the issue if needed. This details array contains an XPath pointer to the source of the error with a human-readable error message
{
"reason": "ERROR_CODE", // Required: String for merchant error handling mechanics
"message": "This describes the error", // Required: String for readable description of the error.
"details": [ // Optional: Object Array of data validation errors
{
"location": "Failure pointer", // Required: String XPath pointer to failure
"message": "Specific error for field" // Required: String specific error for field
}
]
} For more information on the Error Response Object, see Errors.
Updated 3 days ago