Starting a transaction to reserve funds for a user purchase
In the Bango Platform, transactions are two-step: in the first step your store authorizes payment, and in the second step your store captures payment. To authorize payment, you create a transaction by making a POST
request to the Bango Payment API.
As part of the API request, you supply:
(You might want to check payment methods before creating the transaction.)
The API response is a structure that contains:
A payment might not be authorized if, for example, the user has exceeded a spending limit, or is barred, or has spent too much money in a short time.
function get_transaction_id () {
// *Always* use this endpoint prefix for the Bango Payment API.
const base_url = "https://api.bango.net/v5/";
// This is what we're trying to find.
let transaction_id = null;
const request_body_params = {
// The user's identity.
// In production you would probably pass this as an argument
// to the function.
bangoUserId: "123456789",
// An array of strings, one for each supported payment method
// you would like the Bango Platform to consider.
// For example:
paymentMethods: [
"OPERATORBILLING", // Direct Carrier Billing payment
"INTERNET", // Internet-based payment
],
// The item to be purchased.
// (Always use an array of one item: multiple items might
// be supported at a later date.)
// In production you would probably pass this as an argument
// to the function.
paymentItems: [
{
itemName: "My item",
itemDescription: "My item description",
priceList: [
{
grossAmount: "0.99",
currencyIso3: "USD",
financialBreakdown: {
taxAmount: "0.00"
}
},
{
grossAmount: "0.89",
currencyIso3: "EUR",
financialBreakdown: {
taxAmount: "0.00"
}
},
{
grossAmount: "0.79",
currencyIso3: "GBP",
financialBreakdown: {
taxAmount: "0.00"
}
}
]
}
],
// Store's custom transaction id for correlation/idempotency, if necessary
externalTransactionId: "my-unique-tx-id-12345678",
// Store's custom URL: the Bango Platform POSTs asynchronously
// to this URL on authorization, if the response can't be
// returned synchronously due to REDIRECT action
extensionData: {
notificationUrl: "https://example.com/my-store/tx-create?my_param=abcd1234"
}
};
try {
// POST UTF-8 JSON to the Bango Payment API and parse the JSON response
let response = rest_client_call({
method: "POST",
url: base_url + "transaction/",
headers: {
"Authorization": get_authorization_header(),
"Content-Type": "application/json",
},
body: make_json_string(request_body_params),
}).from_json();
// The responseCode tells us the result.
switch (response.responseCode) {
// Success: payment is authorized, transaction created
case "OK":
transaction_id = response.transactionId;
break;
// More to do: The store must take action
case "CLIENT_ACTION_REQUIRED":
// This response parameter tells us what we need to do.
switch (response.parameters.action) {
case "REDIRECT":
// Send the user to a particular web page.
// request_body_params must include either
// notificationUrl or callbackUrl to ensure
// the store receives the result asynchronously
redirect_device_to({
url: response.parameters.url,
});
break;
default:
// Unrecognized action.
// Check the documentation again.
throw "Unrecognized client action";
}
break;
// Failure: unable to proceed with purchase
case "NOT_AVAILABLE": // None of the requested methods is available
case "PRICE_NOT_SUPPORTED": // Payment methods don't support supplied prices
case "USER_EXCEEDED_LIMIT": // User cannot spend more money
case "DECLINED": // Payment provider declined authorization
case "SPEED_LIMIT": // Request too soon after previous payment
case "USER_BARRED": // User not allowed to use payment method
case "USER_INSUFFICIENT_CREDIT": // User cannot afford purchase
case "USER_NOT_ENABLED": // Payment provider not enabled user
case "USER_SPEND_LIMIT": // User reached limit imposed by provider
case "USER_SUSPENDED": // User temporarily barred from payment method
throw "Unable to purchase item";
// Merchant problems
// These indicate issues in your code, not the Bango Platform.
case "BAD_REQUEST": // Invalid request
case "INVALID_BANGOUSERID": // Bango ID not recognized
case "UNAUTHORIZED": // Check your credentials
throw "Merchant implementation error";
// Bango Platform issues
// These likely indicate transient problems.
// In production code, you might want to try the request again
// after a delay, ultimately falling back to an error state.
case "INTERNAL_ERROR":
case "CONNECT_ERROR":
case "FAILURE":
case "SERVICE_UNAVAILABLE":
case "CONNECT_TIMEOUT":
throw "Bango Platform unavailable"
// This might indicate Bango has added a new response code.
// Check the documentation again.
default:
throw "Unrecognized response code";
}
} catch (exception) {
// Production code might want to notify the merchant in some way,
// and/or log full details of the exception for later analysis,
// and degrade gracefully for the user.
output("An error occurred!");
output(exception);
}
// null if payment not authorized or user redirected.
// In the redirect case, a transaction ID might be set asynchronously
// through the notificationUrl or callbackUrl parameter.
return transaction_id;
}