# 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