Skip to content
Last updated

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:

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

walletPaymentSessionResult - Event Shape
{
    eventName: 'walletPaymentSessionResult',
    paymentSession: PaymentSession,
}

PaymentSession shape

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

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
    }
});

Putting It All Together

Here's a complete example that improves the code from the Initial Setup 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.

Complete Basic Payment Form Example
<!DOCTYPE html>
<html lang="en">

<head>
    <script src="https://embedded.ryftpay.com/v2/ryft.min.js"></script>
    <style>
        .spinner {
            border: 4px solid rgba(0, 0, 0, 0.1);
            width: 36px;
            height: 36px;
            border-radius: 50%;
            border-left-color: #09f;
            animation: spin 1s ease infinite;
            display: none;
            /* Initially hidden */
            margin: 10px auto;
        }

        @keyframes spin {
            0% {
                transform: rotate(0deg);
            }

            100% {
                transform: rotate(360deg);
            }
        }
    </style>
</head>

<body>
    <div>
        <div class="Ryft--paysection">
            <form id="ryft-pay-form" class="Ryft--payform">
                <button id="pay-btn" disabled>PAY NOW</button>
                <div id="ryft-pay-error"></div>
                <div id="spinner-container" class="spinner"></div>
            </form>
        </div>
    </div>
</body>

<script type="text/javascript">
    const clientSecret = ""; // Returned when creating a Payment Session
    const publicKey = ""; // Available in the Ryft Portal
    const accountId = ""; // The unique identifier for the Sub-Account, if using Platform Fee model

    Ryft.init({
        publicKey,
        clientSecret,
        // accountId: accountId, // Uncomment if using Platform Fee model
    });

    // Get a reference to the pay button
    const payButton = document.getElementById("pay-btn");
    // Get a reference to the form
    const form = document.getElementById("ryft-pay-form");
    // Get a reference to the new spinner
    const spinner = document.getElementById("spinner-container");

    function handlePaymentResult(paymentSession) {
        // Hide the spinner
        spinner.style.display = "none";
        // Re-enable the button once the result is known
        payButton.disabled = false;

        if (
            paymentSession.status === "Approved" ||
            paymentSession.status === "Captured"
        ) {
            console.log("Payment Successful", paymentSession);
            document.getElementById("ryft-pay-error").innerHTML =
                "<p style='color: green;'>Payment Successful!</p>";
            return;
        }

        if (paymentSession.lastError) {
            const userFacingError = Ryft.getUserFacingErrorMessage(
                paymentSession.lastError
            );
            console.error("Payment Error", paymentSession.lastError, userFacingError);
            document.getElementById("ryft-pay-error").innerHTML = `<p style='color: red;'>${userFacingError}</p>`;
        }
    }

    Ryft.addEventHandler("cardValidationChanged", (e) => {
        payButton.disabled = !e.isValid;
    });

    Ryft.addEventHandler("paymentMethodSelectionChanged", (e) => {
        payButton.disabled = !e.paymentMethod;
    });

    Ryft.addEventHandler("walletPaymentSessionResult", (e) => {
        handlePaymentResult(e.paymentSession);
    });

    form.addEventListener("submit", async (e) => {
        e.preventDefault();
        document.getElementById("ryft-pay-error").innerHTML = ""; // Clear previous errors

        // Disable the button and show the spinner immediately when the payment attempt starts
        payButton.disabled = true;
        spinner.style.display = "block";

        try {
            const paymentSession = await Ryft.attemptPayment();
            handlePaymentResult(paymentSession);
        } catch (error) {
            // Hide the spinner and re-enable the button if an unexpected error occurs
            spinner.style.display = "none";
            payButton.disabled = false;

            // Show error to customer
            console.error("Payment Error", error);
            document.getElementById("ryft-pay-error").innerHTML =
                "<p style='color: red;'>An unexpected error occurred.</p>";
        }
    });
</script>

</html>

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 page.