# Handling SDK Events ## Overview The embedded SDK emits several **events** that you can listen to in order to handle various stages of the payment process. This can be done by using the `Ryft.addEventHandler` method to intercept any events triggered by the form so you can process the payment accordingly. The following is a list of events that can be listened for: - **walletPaymentSessionResult**: Fired when a wallet payment (Apple Pay or Google Pay) finishes. - **cardValidationChanged**: Fired whenever card input details change. - **paymentMethodSelectionChanged**: Fired when a stored payment method is selected or deselected. - **billingAddressValidationChanged**: Fired when the billing address changes. - **walletButtonsReady**: Fired when Apple Pay / Google Pay buttons are ready. ## Events and Actions Below are examples of how to use each event: walletPaymentSessionResult **What it does** Triggered when a wallet payment session finishes. **When to use** Required for Apple Pay and Google Pay payments. **Why it matters** Lets you check whether the wallet payment was successful, needs further action, or failed. **Event shape** ```javascript walletPaymentSessionResult - Event Shape { eventName: 'walletPaymentSessionResult', paymentSession: PaymentSession, } ``` **PaymentSession shape** ```javascript PaymentSession - Object Shape { id: string; amount: number; currency: string; status: 'PendingPayment' | 'PendingAction' | 'Approved' | 'Captured'; returnUrl: string; createdTimestamp: number; lastUpdatedTimestamp: number; customerEmail?: string; requiredAction?: { type: 'Redirect'; url: string }; lastError?: string; } ``` **Example usage** ```javascript Handling walletPaymentSessionResult Event Ryft.addEventHandler("walletPaymentSessionResult", (e) => { const session = e.paymentSession; if (session.status === "Approved" || session.status === "Captured") { // Payment successful – show success page return; } if (session.lastError) { const userFacingError = Ryft.getUserFacingErrorMessage(session.lastError); // Show user-facing error } }); ``` cardValidationChanged **What it does** Fired whenever card details are updated. **When to use** Strongly recommended for card payments. **Why it matters** Keeps your UI in sync with validation results (e.g. enable/disable pay button). **Event shape** ```javascript cardValidationChanged - Event Shape { eventName: 'cardValidationChanged', isValid: boolean, cardNumberValid: boolean, expirationValid: boolean, cvcValid: boolean, nameOnCardValid: boolean, } ``` **Example usage** ```javascript Handling cardValidationChanged Event Ryft.addEventHandler("cardValidationChanged", (e) => { const payButton = document.getElementById("pay-btn"); payButton.disabled = !e.isValid; }); ``` paymentMethodSelectionChanged **What it does** Triggered when a stored payment method is selected or deselected. **When to use** Strongly recommended if supporting stored payment methods. **Why it matters** Lets you enable/disable the pay button depending on whether a valid payment method is active. **Event shape** ```javascript paymentMethodSelectionChanged - Event Shape { eventName: 'paymentMethodSelectionChanged', paymentMethod: PaymentMethod | null, validation: { expirationValid: boolean } } ``` **Example usage** ```javascript Handling paymentMethodSelectionChanged Event Ryft.addEventHandler("paymentMethodSelectionChanged", (e) => { const payButton = document.getElementById("pay-btn"); payButton.disabled = !e.paymentMethod; }); ``` billingAddressValidationChanged **What it does** Triggered when the billing address form is updated. **When to use** Strongly recommended if you collect billing addresses. **Why it matters** Ensures you don’t enable the pay button until both card details and billing address are valid. **Event shape** ```javascript billingAddressValidationChanged - Event Shape { eventName: 'billingAddressValidationChanged', isValid: boolean } ``` **Example usage** ```javascript Handling billingAddressValidationChanged Event Ryft.addEventHandler("billingAddressValidationChanged", (e) => { const payButton = document.getElementById("pay-btn"); billingAddressValid = e.isValid; payButton.disabled = !billingAddressValid || !cardInvalid; }); ``` walletButtonsReady **What it does** Fired when Apple Pay and/or Google Pay buttons are ready to use. **When to use** Optional, but useful for wallet payments. **Why it matters** Helps you manage the UI state of wallet buttons, such as for error handling, or for showing/hiding a spinner or progress bar while the buttons are loading. **Event shape** ```javascript walletButtonsReady - Event Shape { eventName: 'walletButtonsReady', applePay: { status: 'skipped' | 'ok' | 'error' }, googlePay: { status: 'skipped' | 'ok' | 'error' } } ``` **Note**: A status of `skipped` means that no wallet config was provided during initialisation. **Example usage** ```javascript Handling walletButtonsReady Event Ryft.addEventHandler("walletButtonsReady", (e) => { if (e.applePay.status === "ok") { // Apple Pay is ready } if (e.googlePay.status === "ok") { // Google Pay is ready } }); ``` ## Putting It All Together Here's a complete example that improves the code from the [Initial Setup](/documentation/get_started/process_payments/embedded_sdk/initial_setup#putting-it-all-together) section by adding **event handlers** that enable and disable the P*AY button based on form validation. It also includes a spinner that shows while the payment is being processed. ```html Complete Basic Payment Form Example
``` ## Next Steps You should now have a basic payment form set up and be able to process card payments using the embedded SDK, with improved user experience through event handling. Next steps include handling SDK errors to provide more detailed feedback to users. For more information, refer to the [SDK Errors](/documentation/get_started/process_payments/sdk_errors) page.