Instant Card Top-Ups

Introduction

This page contains step-by-step instructions on how to implement the Instant Card Top-Ups feature in your solution.

Product overview

The Instant Card Top-Ups via Acquirer feature allows your customers to instantly add funds to their account using a card (debit or credit) or a digital wallet (e.g., Google Pay or Apple Pay). In short, customers enter the desired amount to top up their account in your frontend, and then Solaris credits these funds to the customer's account.

Solaris offers this feature in cooperation with Stripe (referred to throughout this guide as the "Acquirer"). The Acquirer collects card details from the customer and processes the payment, while Solaris credits the Top-Up funds to the customer's account immediately after the payment is processed. To use this feature, you must integrate both the Solaris Top-Up APIs and the Acquirer's SDK.

Top-Up product flow

The sequence diagram below shows the process of collecting payment information from the customer in the frontend and how Solaris and the Acquirer process it on their respective backends.

To view a larger version, right-click the image and click "Open in a new tab."

Diagram: Top-Up product flow

User journey

The product flow consists of the following steps:

  1. Provide your customer a screen to request a Top-Up and specify the Top-Up amount.

    • Perform soft validation on the client side to ensure that the Top-Up amount fits within the minimum and maximum allowed amounts.
  2. Call the POST Create a Top-Up method to start the payment process.
  3. If all validation checks are successful (e.g., Top-Up limits), then the Solaris API will call the Acquirer's API to create a payment object on their backend. Otherwise, the API will return an error.
  4. Present your customer with a screen to collect their card details.

  5. The customer enters their card details, and then the Acquirer will initiate a 3DS challenge, which the customer must authorize. This step occurs in your frontend using the Acquirer's SDK.
  6. Once the Top-Up has been authorized and successfully processed, Solaris will trigger the clearing of the funds from its buffer account with the Acquirer.
  7. The funds will be credited instantly to the customer's account for the amount specified in step 1. Later, the Acquirer will settle the funds in the buffer account in a pre-defined settlement cycle, e.g., T+2.
note

You must cancel a Top-Up if a customer has dropped from the Top-Up session in your solution. If a created Top-Up's status is left as ACCEPTED and the customer never completes it, then it will count toward the monthly Top-Up limit set by Solaris until it is canceled.

Prerequisites

You can only implement this feature after you have onboarded your customers with bank accounts and cards. See the Get started guide for instructions on how to implement the customer onboarding process for Digital Banking & Cards.

1. Integrate Acquirer SDK

Before implementing Solaris' Top-Ups APIs, you must integrate the Acquirer's SDK in your solution to collect your customers' payment details.

Stripe PaymentIntents and PaymentSheets

Stripe's PaymentIntent object represents your intention to collect a payment from a customer. It tracks the state of a payment using a multi-step state machine. If the payment succeeds, then the final state of the PaymentIntent will be succeeded.

Stripe's Android and iOS SDKs include a PaymentSheet UI component. The PaymentSheet provides all of the necessary UI elements to collect payment data from your customer. The mobile SDKs tokenize sensitive payment details within a PaymentSheet, which allows you to accept different payment methods within a single integration.

See the documentation links below for more information:

Passing the customer's billing address to Stripe

You are required to use the customer's address information from their person resource as the billing address of the payment that will be processed by Stripe. Solaris recommends filling this information in on your frontend on behalf of the customer. Use the following properties from the address object on the customer's person resource:

  • line1
  • postal_code
  • city
  • country

Handling payment errors

Your solution may encounter errors when making requests to the Stripe API. Stripe's documentation provides general information on error handling as well as a list of all error codes that can occur.

Note that Stripe uses special codes for card declines.

Apple Pay integration

To offer Apple Pay as a payment method for Card Top Ups, you must follow the steps below:

  1. Register for an Apple Merchant ID. See the Stripe documentation for instructions.
  2. Configure the Apple Pay certificates for iOS and/or web. For this step, you must coordinate with your Account Manager or assigned TSE, as this is managed between Solaris' Stripe account configurations and your implementation.

Stripe SDK documentation

note

You may ignore all server-side implementation details in the following documentation resources, as Solaris provides all necessary credentials and endpoints.

Click the links below to learn how to integrate Stripe's web, iOS, and Android SDKs, depending on which platform(s) your solution runs on:

Stripe.js (web integration)

Android

iOS

(iOS only) A note about singletons

The Stripe iOS SDK makes use of the singleton, a common pattern in iOS development across Objective-C and Swift. The singleton pattern guarantees that only one instance of a class is instantiated and that your solution uses that instance to interact with the class. Singletons also provide global access to that instance, which eliminates the need to pass it around to different components.

Stripe's iOS SDK indicates singletons using the property names sharedInstance, shared(), and default(). Examples:

  • STPPaymentConfiguration.shared() (API keys and other configs)
  • STPAPIClient.shared() (make Stripe API calls)
  • STPTheme.default() (theming configuration for UI components)
  • STPPaymentHandler.shared() (for authenticating SCA payments)

If you create an API client class that interfaces with your own local or hosted web server, common practice indicates that you should create a singleton instance out of it, too. To do so, simply create a static property on the class as follows:

Copy
Copied
static let sharedInstance = API_Client()

You can read more about singletons here: What Is a Singleton and How To Create One In Swift

One common mistake that iOS developers make is to set their API keys on a new instance of STPPaymentConfiguration instead of on the singleton. Then, when they use the SDK, it returns the error of "no API keys," and the problem can be difficult to debug.

2. Subscribe to webhooks

Subscribe to the following webhook events to receive notifications on key events related to Top-Ups:

  • ACQUIRER_TOPUP_EXECUTED: Triggered when Solaris successfully processes a Top-Up via an Acquirer. The funds from the Top-Up are cleared to the customer's account, and the status of the Top Up changes to EXECUTED.
  • ACQUIRER_TOPUP_DECLINED: Triggered when a Top-Up transaction is declined by Solaris. The status of the Top-Up will change to DECLINED and any charge to the cardholder will be refunded.
  • ACQUIRER_TOPUP_PAYMENT_FAILED: Triggered when the payment processing for a Top-Up fails (e.g., if the card does not have sufficient funds to complete the transaction). The status of the Top-Up will remain ACCEPTED. You may prompt the customer to retry the Top-Up with the same payment method or with a different one.

3. Create and service Top-Ups

After completing the steps above, you are now ready to call the Solaris Top-Ups API endpoints.

Rules and validations

Please note that each created Top-Up must pass the following checks:

  • Maximum Top-Up amount: The maximum amount allowed for an individual Top-Up. The default maximum is 2000,00 EUR as per compliance requirements. Please double-check with your Partner Manager about the limit in place for your solution.
  • Monthly cumulative Top-Up amount: The maximum Top-Up amount allowed per customer per month. The Solaris Compliance team will define this limit.

POST Create a Top-Up

This method creates a Top-Up object, which begins the payment process with Solaris and its acquiring partner (e.g., Stripe).

The response to a successful request includes a client_secret ID that corresponds to the client_secret of the Payment object ("payment intent") of the Acquirer. You must provide this to the SDK to confirm the card payment with the Acquirer.

If the customer is using a previously saved card for the Top-Up, then you must provide the card's payment_method_id in the request body. See the payment methods section below for instructions on how to get a card's payment_method_id.

Request URL:

Copy
Copied
POST /v1/persons/{person_id}/accounts/{account_id}/topups

Request example:

Copy
Copied
{
  "amount": {
    "value": 10000,
    "currency": "EUR"
  },
  "payment_method_id": null
}

Response example:

Copy
Copied
{
  "id": "b76cdcc321d345618084feedc47bbb1d",
  "amount": {
    "value": 10000,
    "currency": "EUR"
  },
  "acquirer_error_code": null,
  "acquirer_decline_code": null,
  "cancellation_reason": "abandoned",
  "decline_reason": null,
  "client_secret": "pi_1DrPlP2eZvKYlo2CSBQ7uqFH_secret_o1A7UsYFLWeGISUD1QYNkT8IU",
  "status": "EXECUTED",
  "instruction_id": "3eba1ee2d8bc4d5883d350031a5fe9d8"
}

Click here to view the full API reference.

GET Index Top-Ups for a customer

This method returns a list of all Top-Ups for a given customer.

Request URL:

Copy
Copied
GET /v1/persons/{person_id}/accounts/{account_id}/topups

Response example:

Copy
Copied
[
  {
    "id": "b76cdcc321d345618084feedc47bbb1d",
    "amount": {
      "value": 10000,
      "currency": "EUR"
    },
    "acquirer_error_code": null,
    "acquirer_decline_code": null,
    "cancellation_reason": "abandoned",
    "decline_reason": null,
    "client_secret": "pi_1DrPlP2eZvKYlo2CSBQ7uqFH_secret_o1A7UsYFLWeGISUD1QYNkT8IU",
    "status": "EXECUTED",
    "instruction_id": "3eba1ee2d8bc4d5883d350031a5fe9d8"
  }
]

Click here to view the full API reference.

GET Retrieve a Top-Up

This method returns the details of a specific Top-Up.

Request URL:

Copy
Copied
GET /v1/persons/{person_id}/accounts/{account_id}/topups/{topup_id}

Response example:

Copy
Copied
{
  "id": "b76cdcc321d345618084feedc47bbb1d",
  "amount": {
    "value": 10000,
    "currency": "EUR"
  },
  "acquirer_error_code": null,
  "acquirer_decline_code": null,
  "cancellation_reason": "abandoned",
  "decline_reason": null,
  "client_secret": "pi_1DrPlP2eZvKYlo2CSBQ7uqFH_secret_o1A7UsYFLWeGISUD1QYNkT8IU",
  "status": "EXECUTED",
  "instruction_id": "3eba1ee2d8bc4d5883d350031a5fe9d8"
}

Click here to view the full API reference.

POST Cancel a Top-Up

This method cancels a requested Top-Up. You must provide the cancellation reason in the request body (in the cancellation_reason property).

note

You must cancel a Top-Up if a customer has dropped from the Top-Up session in your solution. If a created Top-Up's status is left as ACCEPTED and the customer never completes it, then it will count toward the monthly Top-Up limit set by Solaris until it is canceled.

Request URL:

Copy
Copied
POST /v1/persons/{person_id}/accounts/{account_id}/topups/{topup_id}/cancel

Request example:

Copy
Copied
{
  "cancellation_reason": "abandoned"
}

Response example:

Copy
Copied
{
  "id": "b76cdcc321d345618084feedc47bbb1d",
  "amount": {
    "value": 10000,
    "currency": "EUR"
  },
  "acquirer_error_code": null,
  "acquirer_decline_code": null,
  "cancellation_reason": "abandoned",
  "decline_reason": null,
  "client_secret": "pi_1DrPlP2eZvKYlo2CSBQ7uqFH_secret_o1A7UsYFLWeGISUD1QYNkT8IU",
  "status": "CANCELLED",
  "instruction_id": "3eba1ee2d8bc4d5883d350031a5fe9d8"
}

Click here to view the full API reference.

4. Payment method servicing

Implement the following API calls in your solution to interact with a customer's stored payment methods:

GET Index payment methods for a customer

This method returns all payment methods that a customer stored in your frontend. Solaris retrieves information about stored payment methods from the Acquirer SDK.

Request URL:

Copy
Copied
GET /v1/persons/{person_id}/topups/payment_methods

Response example:

Copy
Copied
[
  {
    "person_id": "18de883f507d49b8a074519c73cecper",
    "payment_method_id": "53165f2b3a8846bd9fd344342a6093d6",
    "card_last4": "7654",
    "card_brand": "mastercard"
  }
]

Click here to view the full API reference.

DELETE Remove a customer's payment method

This method removes a customer's stored payment method.

Request URL:

Copy
Copied
DELETE /v1/persons/{person_id}/topups/payment_methods/{payment_method_id}

Response example:

Copy
Copied
{
  "payment_method_id": "53165f2b3a8846bd9fd344342a6093d6"
}

Click here to view the full API reference.

5. Testing

Appendix I: Top-Up status values

The table below contains all possible status values for a Top-Up and descriptions of what each one means:

Status value Description
ACCEPTED The customer has requested the Top-Up and all checks have passed. Solaris will create a payment object with the Acquirer, pending authentication and authorization. If the Top-Up fails to execute (e.g., due to insufficient funds on the customer's card or failure to complete 3DS authentication), the Top-Up will retain this status value until the Top-Up is successfully executed (e.g., with another payment method).
CONFIRMED The customer has successfully authenticated the Top-Up (e.g., using 3DS) and the Acquirer has successfully processed the payment, but the funds have not yet been cleared to the customer's account.
EXECUTED The Top-Up funds have been cleared to the customer's account.
DECLINED The Top-Up was declined by Solaris due to an internal validation (e.g., the customer's account was blocked at the time of payment processing by the Acquirer). In such cases, the transaction will be refunded to the cardholder automatically.
CANCELLED The Top-Up was cancelled using POST Cancel a Top-Up. This usually occurs when a user drops out from the Top-Up session or if the customer does not confirm the Top-Up in a timely manner.