Honor Cross-border Payments

Learn how to honor cross-border payments in PIPE

1. Overview

In the Send Cross-Border Payments tutorial, you learned how you, the Payment Gateway, can acknowledge fund deposits for cross-border payments on behalf of your users.

End users in other financial institutions may wish to send funds that terminate in your financial institution. It is your job, as the financial institution, to honor those payment requests.

You do that by checking all pending cross-border payments that terminate into your financial institution. The relevant APIs are found below. Once you’ve found pending payment requests, you process them within your own backend.

NB: Cross-border terminating requests DO NOT get pushed to you, the integrator. You will have to continuously POLL the payments endpoint to find new payment requests for you to process.

Your bank will either be classified as a liquidity gateway or a non-liquidity gateway.

1.1 Liquidity Gateways.

Liquidity gateways hold funds on behalf of liquidity providers and can transact directly with the cross-border payment engine.

If the terminating receiver account is found in the Liquidity Gateway’s systems, the flow is as follows:

PIPEChain -> Liquidity Gateway -> RECEIVER

The liquidity gateway is expected to update the cross-border payment status to processed on PIPEChain after the receiver receives funds.

1.2 Non-Liquidity Gateways.

Non-liquidity gateways cannot query for pending transactions to process directly from PIPEChain.

Liquidity Gateways will detect that the terminating receiving account is meant for the Non-Liquidity Gateway and perform a local payment using pre-approved means from the Liquidity Gateway to the Non-Liquidity Gateway.

If the receiver is not found in the Liquidity Gateway’s accounts, the flow is as follows:

PIPEChain -> Liquidity Gateway -> Non-Liquidity Gateway -> RECEIVER

The liquidity gateway (not the non-liquidity gateway) is expected to update the cross-border payment status to processed on PIPEChain after the receiver receives funds.

1.3 Gateway Payment Statuses

Possible values are:

  • pending

  • processed

  • error

  • reverted

Endpoints



3. API Calls

3.1 Get pending payments


GET /v2/payments/receiverLiquidityGatewayId=string&receiverGatewayStatus=pending

Gets the list of all pending payment requests on the receiving gateway.

receiverLiquidityGatewayId=string: filter only payments for this receiving payment gateway

receiverGatewayStatus=pending: return only pending payments on the receiving end

3.2 Confirm processed payment

Updates the status of the payment transaction

PUT /v2/payments/{paymentId}

{

"receiverGatewayTransactionId": //“[string] Core banking transaction id after the receiving payment gateway has processed the payment.”,

"receiverGatewayStatus": //“[string] New status of the payment after the receiving payment gateway has processed the payment.”

}

4. Try it out:

You will need to obtain the value for the X_INTERSTELLAR_ERM_API_KEY header required below. Please contact the product owner to get or generate this api key for you. See the section on API Keys for more details.

For this demo, use the following:

export X_INTERSTELLAR_ERM_API_KEY=ocQPTBQUdhpCOeBznkJc8sM2rVu4iTFg

Let's get a list of pending payment requests and confirm one payment.

4.1 Tools you might need

These are the tools you might need to follow along with this tutorial.

  • linux or mac: Many of the command line examples have been customized for UNIX-like operating systems.

  • curl: To perform API calls.

    • mac: brew install curl
    • ubuntu/debian:.sudo apt-get install curl
  • jq: To process JSON on the command line.

    • mac: brew install jq
    • ubuntu/debian:.sudo apt-get install jq
  • jo: To create JSON on the command line.

    • mac: brew install jo
    • ubuntu/debian:.sudo apt-get install jo
  • openssl: To perform cryptographic operations on the command line.

    • mac: brew install openssl
    • ubuntu/debian:.sudo apt-get install openssl

4.2 Get Token

export TOKEN_ENDPOINT=https://id.pipechain-testnet.stargate.is/realms/interswitch-dev/protocol/openid-connect/token\;

export TOKEN_CLIENT_ID=interswitch-dev-api;

export API_ENDPOINT=https://dev-api-pipechain.qa.interswitchng.com
export MY_USERNAME="ng.bank.tutorialsv2.ngn.api";
export MY_PASSWORD="abc";
export MY_TOKENS=`curl -s --request POST \
--url "$TOKEN_ENDPOINT" \
--data-urlencode grant_type='password' \
--data-urlencode username="$MY_USERNAME" \
--data-urlencode password="$MY_PASSWORD" \
--data-urlencode client_id="$TOKEN_CLIENT_ID"`
echo $MY_TOKENS
export MY_ACCESS_TOKEN=`echo $MY_TOKENS | jq -r ".access_token"`
echo $MY_ACCESS_TOKEN

4.3 Get payments to honor


curl --request GET \
  --url "$API_ENDPOINT/v2/payments?receiverProcessingGatewayId=gh.bank.demo.ghs&receiverGatewayStatus=pending" \
--header "X_INTERSTELLAR_ERM_API_KEY: $X_INTERSTELLAR_ERM_API_KEY" \
--header "Authorization: Bearer $MY_ACCESS_TOKEN" 

Sample Response

[
  {
    "id": "ae5894c2c97738b01b5865a3b357bb8bab4b5535d649bdca6f055a122c4598b9",
    "createdAt": "2021-10-11T13:26:50.962Z",
    "updatedAt": "2021-10-11T13:26:50.962Z",
    "pagingToken": "1633958810962-2395471023",
    "senderGatewayId": "gh.wallet.expresspay.ghs",
    "senderAmount": "780",
    "senderCurrency": "GHS",
    "senderAccount": "233243722297",
    "senderName": "Isa Frimpong",
    "receiverGatewayId": "cm.wallet.interstellar-demo.xaf",
    "receiverProcessingGatewayId": "cm.wallet.interstellar-demo.xaf",
    "receiverAmount": "1200",
    "receiverCurrency": "XAF",
    "receiverAccount": "225345654334",
    "receiverName": "Interstellar XAF 12345",
    "senderGatewayStatus": "processed",
    "receiverGatewayStatus": "pending",
    "senderGatewayTransactionId": "test_trf_00001",
    "receiverGatewayTransactionId": "",
    "senderGatewayPublicKey": "",
    "receiverGatewayPublicKey": "",
    "blockchainTransactionId": "1592160e86810cd8b7caca774c2cb016c8009ee3031e68321018afd5c1277c69",
    "receivingGatewayFee": "100",
    "memo": "",
    "creationRequestUrl": "/payments",
    "creationRequestBody": "{\"senderGatewayId\":\"gh.wallet.expresspay.ghs\",\"senderAmount\":\"780\",\"senderCurrency\":\"GHS\",\"senderAccount\":\"233243722297\",\"senderName\":\"Isa Frimpong\",\"receiverGatewayId\":\"cm.wallet.interstellar-demo.xaf\",\"receiverAmount\":\"1200\",\"receiverCurrency\":\"XAF\",\"receiverAccount\":\"225345654334\",\"receiverName\":\"Interstellar XAF 12345\",\"receivingGatewayFee\":\"100\",\"extras\":null,\"senderGatewayTransactionId\":\"test_trf_00001\"}",
    "creationRequestPublicKeyBase64": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFybWxvbktlS0U3bmY2L2FYS2lRNQpDVFErdlgzWWE4b2FWbDdqN3I4Wld2QjR2K0dsU3ZpOG96ZFVKeGZtVFdROUN1dUNwT2p3SnBmRmk5YWVBRm5pClFJdlhXK1pqdjBqcjVncmEwSUt3SnNjVnNod3N6TGlnQVUyQVprcXV0Q2NVdFFnajgzWDNLNnhHaHpaSXRvYWIKYjVQRXhBQlFuQzNJUFBKRno3ZW8zRlRCM2wyQ2FjZkJ6MkNOOFM4S251VVhiR0VwODdMbmlPaUlWalVzdStsNQpxZWIzUjhjeWhSVHd2R203YzdGNklqaEF6SXRPSWtZdHlDbm1lQ3pNMjRJamZKZG5KZ2JETERoeitrR0Z0OGo2Ck01Vml0RHpiOWtDT2h3UDNYSklJTUdSNFFSQU93Z3AvRXhkZmhZaERwNDJoYjZESitWUzR6ZGIwTS9hVnl5c1UKYndJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==",
    "creationRequestSignatureBase64": "lLmSi2NDXNS1M22K1/cBVxY2+Xo9UtpVA0xasQNP60T8ll8JY6VWnp0n8suyvyH7qplJOToD3/hr/INbgWzoXk9JxI1hIjQDh9hNvu/ACDrZsLKv7yM1E4iHPfxXVPNEnZlRtYuDmW8BPN0goY2td+k+WnGT05dZUkhqXHVjumgykWoT5ZBNMHiZ1G8mdmSz6H6W6v6OAtP6RXvZPv8f/kTIr9+DRvqgonxYwBwlgJM3rM2LSF6z781jMUP3PNFNlaaic1IbzqUY9WJI8HF8w3rEvMdTTw1KmjGGwAhp8TeCCCVR/TSoR/hwqXg2nNIrhNSlJeKwyeIZnt8mJwWRwg==",
    "extras": null
  }

]

NB: The field receiverGatewayId will help you decide if the payment is for a customer in your bank, or the payment is for a customer in another bank. If the terminating receiver is a customer in another bank, you have to use whatever pre-approved local payment means to honor the cross-border payment.

4.4 Confirm processed payment on the receiver gateway

Let's confirm the previous payment ID has been processed on the receiving gateway.

export PAYMENT_ID=ae5894c2c97738b01b5865a3b357bb8bab4b5535d649bdca6f055a122c4598b9
curl --request PUT \
  --url $API_ENDPOINT/v2/payments/$PAYMENT_ID \
  --header "Authorization: Bearer $MY_ACCESS_TOKEN" \
  --header "X_INTERSTELLAR_ERM_API_KEY: $X_INTERSTELLAR_ERM_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "receiverGatewayTransactionId": "'$(date +%s)'",
  "receiverGatewayStatus": "processed"
}'

5. Data Models

5.1 Payment

fieldtypedescription
senderGatewayIdstringPayment Gateway ID of the sender
senderCurrencystringCurrency used by the sender
senderAccountstringSender account
receiverGatewayIdstringPayment Gateway ID of the receiver
receiverAccountstringReceiver account
receiverCurrencystringCurrency used by the receiver
receiverAmountstringAmount in the receiver's currency that the destination will receive
memostringmemo associated with the payment
senderAmountstringAmount the sender has to pay, excluding sender fees
senderNamestringName of the sender
receiverNamestringName of the receiver
receivingGatewayFeestringAmount in the receiver currency charged by the receiving gateway
senderGatewayTransactionIdstringTransaction id generated by the sending gateway when sending a payment
receiverGatewayTransactionIdstringThe transaction ID generated by the receiving gateway when honoring a payment
senderGatewayStatusstringStatus of the payment according to the sending gateway
receiverGatewayStatusstringStatus of the payment according to the receiving gateway
blockchainTransactionIdstringBlockchain transaction ID of the payment