Wallet Use Cases

Transfer Funds Between Wallets

Prerequisites

  • Valid JWT with access to the source wallet
  • Sufficient funds available in the source wallet.
  • Sender Wallet ID and Receiver Wallet ID. A Wallet ID can be found by using the Customer ID and API GET/eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/wallets

Wallet to Wallet Transfer

Perform the wallet to wallet transfer

POST  /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/transfers
{
  amount: 100,
  description: "Test transfer",
  externalId: "67174956-0343-42ba-bc39-d056dab119d7",
  externalUniqueId: "387c6075-5b7c-4737-8d4b-b3d42a8efe2f",
  fromWalletId: 29124,
  ignoreLimits: false,
  sessionId: "",
  toWalletId: 30341
}

Due to Eclipse abstracting the underlying store of value and providing a consistent wallet API, it often needs to transfer between wallets which are on a different platform. E.g. a transfer from a digital wallet to a prepaid card wallet. Due to the nature of the SoV APIs, transfers cannot always be done in an ACID (https://en.wikipedia.org/wiki/ACID) transaction. This is due to the fact that the debit leg and credit leg are on different isolated systems which do not support a 2-phase-commit protocol. To overcome this, Eclipse utilises the following approaches for transfers between different stores of value:

Transfer from Eclipse SoV to Non-Eclipse Sov

    1. A transaction is started
    1. The Eclipse wallet is debited
    1. The non-Eclipse wallet is retrieved and verified it is in a state to accept a credit
    1. A retry-able task is added into the Eclipse database to credit the Non-Eclipse wallet
    1. The transaction is committed
    1. A post-commit hook kicks off a process to try and retry the credit leg until it succeeds so that eventual consistency is achieved.

Typically eventual consistency is achieved within 1-2s depending on the latency of the destination SoV. If something goes wrong in the destination SoV between steps 3 and 6 then it will retry with a back-off algorithm forever until the destination is credited.

Transfer from Non-Eclipse SoV to Eclipse Sov

    1. A transaction is started
    1. The non-Eclipse wallet is debited
    1. A post-rollback hook is enlisted to undo the debit (with a compensating credit) if the transaction is rolled back
    1. The Eclipse wallet is credited
    1. The transaction is committed

As can be seen in the above flows when debiting Eclipse and crediting a non-Eclipse SoV, it is possible that the transfer is done and will be eventually consistent and yet if one checks the balance of the destination wallet immediately after the transfer, it may not show the new balance. This can be confusing for end users if a UI wants to show the new balance immediately after a transfer returns. To aid in this, the transfer API has a field called “replyPolicy” which can be used to make Eclipse only reply to the transfer after it was seen that eventual consistency has been achieved. This alleviates the need for a front end to possibly poll and waits for the destination wallet to show the new balance.

The Policy Field has 2 Options:
WHEN_GUARANTEED: Eclipse should reply when the result is guaranteed to happen and will eventually happen. I.e. Eclipse will reply after the transaction commit has happened.

WHEN_COMPLETE: Eclipse should only reply when the source and destination are fully consistent. I.e. after step 6 is successful in the scenario “Transfer from Eclipse SoV to Non-Eclipse Sov”'

In all normal situations and by default, WHEN_GUARANTEED should be used. For most wallet transfers between wallets in the same store of value, WHEN_GUARANTEED and WHEN_COMPLETE are identical. WHEN_COMPLETE is only useful when transferring from a digital wallet within Eclipse to a store of value like a card wallet that sits outside of Eclipse.

NB: If the destination wallet is not consistent within 5 seconds then Eclipse will reply as if WHEN_GUARANTEED was passed in, In order to prevent timeouts on the client. This is not considered a failure and the transfer API will still return HTTP 204 as the status code as the transfer is guaranteed to happen but has just not happened yet.

Bulk Transfers

Eclipse supports bulk transfers between closed loop digital wallets - this can be used for efficient disbursement of funds within a tenant.

Two modes of operation are supported when doing bulk transfers:

  1. Atomic - for atomic bulk transfers all transfers are processed synchronously and if there are any failures all transfers within the batch fail.
  2. Non-atomic - for non atomic bulk transfers the transfers are executed one by one in the background and some may fail and some may succeed. The results for non atomic transfers are sent by email to the caller.

The atomic query parameter determines the mode of operation. Typically atomic transfers are for a smaller number of transfers (less than 500 in a batch). Non atomic transfers can handle batch sizes up to 500,000. For atomic transfers the response is either 200 (all successful) or failure. For non-atomic transfers the response provides details on the transfer including a bulkTransferId that can be queried for progress details.

Bulk transfer from a specific wallet

To do a bulk transfer to a number of wallets from a single source wallet the wallet bulk transfer endpoint is used.

Prerequisites

  • Valid JWT with access to the source wallet
  • Sufficient funds available in the source wallet
POST /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/bulk-transfers?atomic=false
[
  {amount: "100", description: "test1", toWalletId: "192875", externalUniqueId: "2.8934345"},
  {amount: "100", description: "test2", toWalletId: "192876", externalUniqueId: "2.5534345"}
]
{
    "bulkTransferId": "81d64651-a05f-48c4-b7fe-d62f8074472c",
    "inProgress": true,
    "transfersTotal": 2,
    "transfersDone": 0,
    "transfersFailed": 0,
    "transfersSucceeded": 0,
    "transfersPerSecond": 0,
    "percentageComplete": 0
}

📘

Note

The get bulk transfer by bulkTransferId endpoint can be used to retrieve progress information for a non-atomic transfer.

Bulk transfer from multiple source wallets

To do a bulk transfer to a number of wallets from a number of source wallet the bulk transfer endpoint is used. This API works identically to the one described above except that in the request the fromWalletId is included for each transfer object.

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/bulk-transfers?atomic=false
[
  {amount: "100", description: "test1", fromWalletId: "123", toWalletId: "192875", externalUniqueId: "2.8934345"},
  {amount: "100", description: "test2", fromWalletId: "567", toWalletId: "192876", externalUniqueId: "2.5534345"}
]

Cross Tenant Transfers

Tenants can transfer from their customer wallets to other tenant customer wallets so long as:

  1. They have a wallet set up for outbound transfers to flow through. This is set as config value xTenantOutboundWalletId
  2. The destination tenant wallet has the same currency as the source tenant wallet, as well as config value xTenantInboundWalletId.

The flow is as follows:

624

Cross Tenant Transfers

Get Wallet Balance

A customer or tenant may request a wallet balance, subject to the program access rules. Note that a customer may have multiple wallets.

Prerequisites

  • Valid JWT with access to read the wallet
  • wallet ID

Wallet Request
The below API will provide the details of a specific wallet:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}
{
  "walletId": 29124,
  "customerId": 29520,
  "name": "Test Digital Wallet",
  "currentBalance": 5352.1,
  "availableBalance": 5335.1,
  "reservations": 17,
  "status": "ACTIVE",
  "created": "2022-10-12T09:15:11.000Z",
  "walletTypeId": 1395,
  "externalUniqueId": "1c4fb345-5",
  "currency": "ZAR",
  "friendlyId": "H6NJPS4C",
  "configuration": []
}

One can also get all the customer's wallets by calling the wallets endpoint on the customer entity:

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/customers/{customerId}/wallets
[
  {
    "walletId": 29124,
    "customerId": 29520,
    "name": "Digital Wallet",
    "currentBalance": 5352.1,
    "availableBalance": 5335.1,
    "reservations": 17,
    "status": "ACTIVE",
    "created": "2022-10-12T09:15:11.000Z",
    "walletTypeId": 1395,
    "externalUniqueId": "1c4fb345-5",
    "currency": "ZAR",
    "friendlyId": "H6NJPS4C",
    "configuration": []
  },
  {
    "walletId": 29142,
    "customerId": 29520,
    "name": "Card Wallet",
    "currentBalance": 1485,
    "availableBalance": 1485,
    "reservations": 0,
    "status": "ACTIVE",
    "created": "2022-10-12T10:40:57.000Z",
    "walletTypeId": 1394,
    "externalUniqueId": "79cdec64-1",
    "currency": "ZAR",
    "friendlyId": "JWZ2Y2A7",
    "configuration": []
  },
]

Get Wallet Limits

Eclipse has extensive limit configurations that can be applied to a wallet type or individual wallet instances - refer to Limit Specific Wallet Type Configuration Parameters for full details on these limits.

A customer can request the limits that are applied to a particular wallet - all the associated wallet limits will be returned as well the remainingOverallCredit and remainingOverallDebit for that particular wallet.

Prerequisites

  • Valid JWT with access to read the wallet
  • wallet ID

Wallet Request
The below API call will provide limits associated with a wallet:

GET eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/limits
{
  "remainingDailyDebitLimitAtWalletLevel": 3000,
  "remainingMonthlyDebitLimitAtWalletLevel": 25000,
  "remainingOverallCredit": -1,
  "remainingOverallDebit": 77.672246772
}

Refer to the Wallet Limit API documentation for full details.

Get Wallet Transaction History (Statement)

A customer, organisation and Tenant may request a wallet balance history, subject to the program access rules. Note that a customer may have multiple wallets.

To retrieve the full set of transaction history you need to:

  1. Retrieve all completed transactions on the wallet
  2. Retrieve all reservations on the wallet
  3. Optionally enrich the completed transactions with payments, withdrawals and remittances information

Prerequisites

  • Valid JWT with access to read the wallet
  • WalletId

1. Retrieve all completed transactions

Any change in ledger on the wallet is recorded as a transaction on a wallet. These transactions could be transfers, payments, withdrawals and remittances. A list of all completed transactions can be retrieved as follows:

GET  /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/transactions?dateFromIncl=2023-01-26T00:00:00.000&dateToExcl=2023-02-12T00:00:00.000
{
    "transactionId": "79812",
    "walletId": 29124,
    "type": "tfr.debit.fee.pay.za_masterpass_in.card.server",
    "date": "2022-11-10T15:16:30.000Z",
    "amount": -0.4,
    "currency": "ZAR",
    "balance": 668.1,
    "description": "Incoming CARD fee",
    "externalId": "35064",
    "externalUniqueId": "DB-Payment-35064-Fee",
    "otherWalletId": 29118,
    "location": "unknown",
    "info": []
 }

The results can be filtered with query parameters include to date (dateToIncl) and from date (dateFromIncl). Note that card statements can return a maximum of 40 transactions

2. Retrieve all reservations

The above will only return completed transactions. Any transactions that have not yet completed can be retrieved as follows:

GET  /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/reservations
[
  {
    "reservationId": 10769,
    "walletId": 29124,
    "sessionId": "18460a63-027b-4ce9-b953-07fd80b43364",
    "description": "test",
    "amount": 17,
    "created": "2022-11-09T20:33:14.000Z",
    "expires": "2032-11-06T20:33:14.000Z"
  }
]

3. Optionally enrich the completed transactions

Payments, withdrawals and remittances are special types of transactions. They will appear in the list of transactions but there is additional information stored specific to the payments, withdrawals and remittances . This information can be retrieved by calling the GET payments, withdrawals and remittances endpoints but can also be added to the transaction history by passing in query parameters fields=payments,withdrawals,remittances (comma separated list that currently only supports payments,withdrawals,remittances) when calling the transactions endpoint:

GET  /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/transactions?fields=payments,withdrawals

The transactions are enriched with additional payment, withdrawal and remittances information if that transaction is a payment, withdrawal or remittances:

[
  {
    "transactionId": "79812",
    "walletId": 29124,
    "type": "tfr.debit.fee.pay.za_masterpass_in.card.server",
    "date": "2022-11-10T15:16:30.000Z",
    "amount": -0.4,
    "currency": "ZAR",
    "balance": 668.1,
    "description": "Incoming CARD fee",
    "externalId": "35064",
    "externalUniqueId": "DB-Payment-35064-Fee",
    "otherWalletId": 29118,
    "payment": {
      "paymentId": 35064,
      "externalUniqueId": "MP-IN-1554553-SUCCESS",
      "status": "SUCCESSFUL",
      "amount": 40,
      "description": "Paid: Topup Wallet",
      "merchantName": "Topup Wallet",
      "currency": "ZAR",
      "additionalFields": [],
      "acceptedCardSchemes": [],
      "cardPhone": "27723898365",
      "acceptedPaymentMechanisms": [],
      "paymentType": "CARD",
      "authCode": " DEBUG",
      "retrievalReferenceNumber": 656375,
      "created": "2022-11-10T15:16:30.000Z",
      "paymentData": "7213752999",
      "paymentInstrumentInfo": {
        "cardBin": "424242",
        "cardType": "CREDIT",
        "cardLast4": "4242",
        "cardName": "RA GOOD"
      },
      "fee": 0.4,
      "paymentReference": "71a7060e-c835-4e1f-b417-ef8cec1a2165",
      "walletId": 29124,
      "customerId": 29520,
      "associatedPaymentId": 35063,
      "gatewayTransactionId": "MP-IN-1554553-SUCCESS"
    },
    "location": "unknown",
    "info": []
  },
  {
    "transactionId": "7366",
    "walletId": 508,
    "type": "tfr.credit.remittance.wallet",
    "date": "2022-10-10T08:00:59.000Z",
    "amount": 13,
    "currency": "ZAR",
    "balance": 13709.272173903,
    "description": "Send money to MM Zimbabwe",
    "externalId": "1442",
    "externalUniqueId": "CR-Remittance-1442",
    "otherWalletId": 2053,
    "location": "172.31.45.119",
    "info": [],
    "remittance": {
      "additionalFields": [
        {
          "id": "serviceId",
          "value": "clicksendnow_zw"
        },
        {
          "id": "purposeOfTransaction",
          "value": "Gift"
        },
        {
          "id": "sourceOfFunds",
          "value": "Gift"
        },
        {
          "id": "senderReportingCategory",
          "value": "401"
        },
        {
          "id": "providde_beneficiary_id",
          "value": "003b9015-f7a8-4af4-bed0-c4ee8b28b2ee"
        }
      ],
      "remittanceId": 1442,
      "status": "SUCCESSFUL",
      "created": "2022-10-10T08:00:15.000Z",
      "destinationAmount": 0.68,
      "fee": 0,
      "amount": 13,
      "currency": "ZAR",
      "destinationCurrency": "USD",
      "exchangeRate": 18.1366,
      "quoteExpires": "2022-10-10T08:20:15.000Z",
      "externalUniqueId": "cc9fe449-53de-4ed9-bc00-fa9787a83991",
      "walletId": 2053,
      "extraInfo": "{\"voucherCode\":\"43197999\",\"status\":\"COMPLETED\"}",
      "description": "Send money to MM Zimbabwe",
      "destinationCountry": "ZW"
    }
  }
]

Create a QR Code linked to a Wallet

It is possible to create a QR Code for acquiring purposes, if enabled for the wallet type.

Prerequisites

  • Pre-created Wallet
  • walletId
  • Valid JWT

Step 1 – Create QR Code linked to the wallet
Create a QR Code which is linked to the wallet.

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}/qr-codes

Pull QR Code Details

It receive QR Code and wallet details

Prerequisites

  • QR Code
  • Valid JWT

Step 1 – Get QR Code details

GET /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/qr-codes/{code}

Cancel Digital Wallet

This can only be done if the wallet has no card, transactions, QRCodes or any other activity. If a wallet has any cards etc then do a PUT and set the status of the wallet to CANCELLED.

Prerequisites

  • The wallet's available balance should be zero.
  • Valid JWT

Step 1 – Delete the Wallet

DELETE /eclipse-conductor/rest/v1/tenants/{tenantId}/wallets/{walletId}

Scan to Pay Voucher Wallets

With Eclipse wallet capabilities a wide range of closed loop and filtered loop voucher use cases are possible. Scan to Pay vouchers is one such use case that combines the reach of Scan To Pay with the flexibility of Eclipse, currently available in South Africa. Tenants can create voucher programmes and disburse vouchers through a self service voucher portal. Voucher recipients receive the vouchers in their Scan to Pay app or Scan to Pay White Label app if applicable, and the vouchers can be used at any of the 600,000 Scan to Pay merchant locations in South Africa.

Scan To Pay Voucher portal

Scan To Pay Voucher portal

Once added as a voucher admin tenants can:

  • View their disbursement wallet balance and request topups
  • View transaction history on their disbursement wallet
  • Create new voucher programmes including setting the programme name, icon and SMS/push notification content and disbursing vouchers
  • View and manage voucher programmes
  • Manage their team - and add new voucher admins

For more information please contact your account manager.

Provision vouchers by API

While tenants can use the voucher admin portal to create voucher programmes and provision vouchers they can also call a simple API to provision vouchers. This covers the common use case where tenants want to sell vouchers directly from their own platforms.

Prerequisites

  • Tenants needs to be onboarded as a Scan To Pay voucher partner and be added as an admin user to the Scan To Pay Voucher portal - contact your account manager for more details.
  • JWT issued using the Scan To Pay Voucher portal admin user credentials.
  • The following tenant configs must be set:
    • allowVoucherWallet - must be set to true
    • source.wallet.config.STP_VOUCHER.{orgId} - must be set to the wallet ID of the wallet from which voucher funds will be disbursed.
    • oltio.config.{OrgId}.username - must be set the oltio config for the specific organization if not specified then it will pick tenant level config.
    • oltio.config.{OrgId}.password- must be set the oltio config for the specific organization if not specified then it will pick tenant level config.
    • mustache.app.notification.body.{OrgId}.program.{programId}- Required to send the notification and it will be configured on tenant level.
    • mustache.app.notification.title.{OrgId}.program.{programId}-Required to send the notification and it will be configured on tenant level.
    • mustache.sms.{OrgId}.program.{programId}-Required to send the notification and it will be configured on tenant level.

To provision a voucher, tenants just need to call the POST wallets endpoint for wallet type STP_VOUCHER and pass in the following additional information:

FieldDescription
tenantIdScan To Pay Vouchers sandbox tenantId=11131, Scan To Pay Vouchers production tenantId=13561
organisationIdThe ID assigned to your voucher organisation. Request this from [email protected] or your account manager
voucherProgrammethis is the ID assigned to your voucher programme. Request this from [email protected] or your account manager
voucherValueThe value of the voucher to provision, e.g. R100
voucherPhoneNumberThe phone number to provision the voucher against
walletTypeIdsandbox STP_VOUCHER walletTypeId=7264, production STP_VOUCHER walletTypeId=208

Example request:

POST /eclipse-conductor/rest/v1/tenants/{tenantId}/organisations/{organisactionId}/wallets
{
  "configuration": [
    {
      "att": "voucherProgramme",
      "val": "123445343"
    },
    {
      "att": "voucherValue",
      "val": "10"
    },
    {
      "att": "voucherPhoneNumber",
      "val": "27727863453"
    },
    {
   	 "att": "programId",
		  "val": "{programId}"
    }
  ],
  "description": "STP Voucher Wallet 1",
  "externalUniqueId": "123456789013543533534534",
  "name": "STP Voucher Wallet 1",
  "status": "ACTIVE",
  "walletTypeId": 7264
}