Receive payments with authorization and capture

With the authorization and capture service, you can create a charge now and capture the funds in the future. Review this article to know how this process works.

Web
iOS
Android
This functionality is available for the following models:

☑ Acquirer
☐ Aggregator

Receiving one-time card payments under the authorization and capture scheme guarantees the availability of the amount on the customer’s card for a maximum of 7 days for debit and 28 days for credit cards. If the payment is not captured within that time, the funds retained will be released by the issuing bank back to the cardholder.

An example of what you will integrate is as follows:

Flow

The flow you will integrate will be as follows:

Payment flow with authorization and capture for Colombia

1. Obtain the single-use payment token

The responsibility of the front end is to securely collect the user’s card information, tokenize that information through Kushki’s servers, and then send that information to the back-end to initiate the authorization process.

You have three options for integrations: kajita, Kushki.js and Kushki.js Hosted Fields.

Kajita

Kushki has ready to use payment forms to securely collect card information. You can use any of our versions:

  • Cajita: the first version of the payment form. It is not customizable.
  • Kajita: the second version. It allows you to customize your payment forms from your Admin Console and even have multiple Kajita versions, for example, one for each payment method.

Create and customize your Kajitas

With Kushki, you can create your Kajitas from the Admin Console. Click here to learn how to do it.

Set up Kajita

Include the kushki-checkout.js on your page by adding it to the <head> of your HTML file. Always load kushki-checkout directly from cdn.kushkipagos.com. __Do not include the script in a bundle or package or host a copy of it.

<head>
<title>Checkout</title>
<script src="https://cdn.kushkipagos.com/kushki-checkout.js"> </script>
</head>

Add Kajita to your site

Kajita needs space within your page. Enter the following code in the <body> of your site where you want the payment form to be displayed.

For Kajita (v.2)

<form id="my-form"" action="/confirm" method="post">
<input type="hidden" name="cart_id" value="123">
</form>

For Kajita (v.1)

<form id="payment-form" action="/confirm" method="post">
<input type="hidden" name="cart_id" value="123">
</form>

Remember to configure the form action according to the corresponding endpoint in your back-end to obtain the token.

Next, add the script tag.

For the Kajita (v.2) you can obtain this script from your Admin Console as explained in the Payment Kajitas article.

<script type="text/javascript">
var kushki = new KushkiCheckout({
kformId: "HmJXukKb5",
form: "my-form",
publicMerchantId: "${publicCfredentialId}",// Replace this with your public credential
amount: {
subtotalIva: 0,
iva: 0,
subtotalIva0: 50000,
}
});
</script>

For V.1 (Cajita), add the following script, making sure the form has loaded:

<script type="text/javascript">
var kushki = new KushkiCheckout({
form: "payment-form",
merchant_id: "8291028192001", // Reemplaza esto por tu public merchant id
amount: "50000",
currency: "COP",
payment_methods:["credit-card"], // Podrás habilitar más medios de pago.
inTestEnvironment: true, // Configurado en modo prueba
});
</script>

This will create a predefined form on your page to accept payments.

Kushki.js

Use kushki.js if you need greater control over the “look & feel” or appearance of your payment form.

Set up Kushki.js

option 1 -CDN

Use the following script tag at the end of the <body> on your payment page.

<script src="https://cdn.kushkipagos.com/kushki.min.js"></script>
Option 2 - NPM

Install the package from npm.

npm install --save @kushki/js

Then import it into your code.

import { Kushki } from “@kushki/js”;
Configure the Kushki object

Add the following code to your application

const kushki = new Kushki({
merchantId: 'public-merchant-id', // Your public merchant id
inTestEnvironment: true,
});

Collect user information and send it to your back-end

First, add the form to your payment page with the required fields. You can design it any way you like.

For example:

<form id="payment-form">
<input placeholder="Card Number" type="text" name="number">
<input placeholder="Full Name" type="text" name="name">
<input placeholder="MM" type="text" name="expiry_month">
<input placeholder="YY" type="text" name="expiry_uear">
<input placeholder="CVV" type="text" name="cvv">
<button id="submit">Pagar $50000</button>
</form>

Then, when the user submits the form, request the token and send it to your back-end.

kushki.requestToken({
amount: '50000',
currency: "COP",
card: {
name: form.name,
number: form.number,
cvv: form.cvv,
expiryMonth: form.expiry_month,
expiryYear: form.expiry_year,
},
}, (response) => {
if(response.code){
console.log(response);
// Submit your code to your back-end
} else {
console.error('Error: ',response.error, 'Code: ', response.code, 'Message: ',response.message);
}
});

Kushki.js Hosted Fields

With Hosted Fields, included in Kushki.js, you can securely collect customer payment information through fields stored on Kushki infrastructure. Returns a token which allows the payment flow to continue from the back-end.

Import Kushki.js Hosted Fields into your app

Option 1 - CDN

Import the Kushki.js Hosted Fields library into your application via a <script> tag inside the <body> tag. Once imported, you will be able to access the resources described below to create a payment flow with Kushki.

It is necessary to import the libraries kushki.min.js (which brings the necessary code to store your merchant’s credentials) and card.min.js (the module that brings the necessary functionalities for the flow with card payments).

<script src="https://cdn.kushkipagos.com/js/latest/kushki.min.js"></script>
<script src="https://cdn.kushkipagos.com/js/latest/card.min.js"></script>
Option 2 - NPM

Install the Kushki.js Hosted Fields library as an npm package inside your application with the following code:

npm install --save @kushki/js-sdk
Option 3 - YARN

Install the Kushki.js Hosted Fields library as a yarn package inside your application with the following code:

yarn install @kushki/js-sdk
Create an instance of KushkiOptions

To use the Kushki.js Hosted Fields library, it is necessary to create an instance of KushkiOptions which allows you to set the public key of the work environment (test or production) through the init() method.

Add the following code to your application:

import { IKushki, init, KushkiError } from "@kushki/js-sdk";
const kushkiOptions : KushkiOptions = {
publicCredentialId: '<public-credential-id>', // This corresponds to the public credential of the merchant
inTest: true
};
const buildKushkiInstance = async () => {
try {
const kushkiInstance : Ikushki = await init(kushkiOptions);
} catch (e: KushkiError) {
console.error(e.message);
}
}

Check the reference for more information about the KushkiOptions instance.

Initialize the form on the front-end

Follow the steps below to render the hosted fields. This way, your clients will be able to enter the necessary data to carry out transactions.

Step 1. Define containers for hosted fields.

Before calling the initCardToken() method, it is required to place the necessary elements to be able to render each hosted field.

<!DOCTYPE html>
<html lang="en">
<body>
...
<form>
<div id="cardholderName_id"></div>
<div id="cardNumber_id"></div>
<div id="cvv_id"></div>
<div id="expirationDate_id"></div>
<div id="deferred_id"></div> //optional
</form>
...
</body>
</html>
Step 2. Create an instance of CardOptions

Create an instance of CardOptions with the transaction information, such as the amount, currency, among other parameters.

import { IKushki, init, KushkiError } from "@kushki/js-sdk";
import {
CardOptions,
ICard,
initCardToken
} from "@kushki/js-sdk/Card";
const options : CardOptions = {
amount: {
iva: 1,
subtotalIva: 10,
subtotalIva0: 10
},
currency: "USD",
fields: {
cardholderName: {
selector: "cardholderName_id"
},
cardNumber: {
selector: "cardNumber_id"
},
cvv: {
selector: "cvv_id"
},
expirationDate: {
selector: "expirationDate_id"
}
}
}
Step 3. Render hosted fields with the initCardToken() method

After creating an instance of CardOptions, you need to call the initCardToken() function to initialize an instance of ICard.

const buildCardInstance = async () => {
try {
// kushkiInstance must be previously initialized
const cardInstance: ICard = await initCardToken(kushkiInstance, options)
} catch (e: KushkiError) {
console.error(e.message);
}
}

Check the reference for more information on form initialization.

Request a token to continue the payment flow

Request a card payment token that you can later use to charge a customer with the endpoint to make a one-time payment or to create a recurring charge.

To obtain a card payment token, it is necessary to call the requestToken() method on the previously initialized card instance. This method performs 3DS, OTP and Sift Science validations automatically. Also, validate that all the fields are correct; otherwise it will throw an exception.

// If deferred data is generated, you can use this data in the charge of the payment
try {
const tokenResponse: TokenResponse = await cardInstance.requestToken();
// Code to send the obtained token to your back-end
// On Success, if deferred data exist can get deferred options
// For Ecuador, Mexico ex. {token: "a2b74b7e3cf24e368a20380f16844d16", deferred: {creditType: "03", graceMonths: 2, months: 12}}
// For Chile, Colombia, Peru ex. {token: "a2b74b7e3cf24e368a20380f16844d16", deferred: {months: 12}}
if(tokenResponse.deferred)
console.log("This is a deferred options", tokenResponse.deferred)
} catch (error: any) {
// On Error, catch response
console.error("Catch error on request card Token", error.code, error.message);
}

Once the token is obtained, send it to your back-end to continue the payment flow.

To perform validations using OTP, check out OTP validation.

See the reference for more information about the token request.

2. Perform the authorization

The responsibility of the back-end is to use the collected token to make an authorization request. If approved, perform a capture or void, depending on the case

When the user submits the form, your front-end transfers a token to an endpoint you have specified. With this token, you should make a call to our authorization endpoint to initiate the authorization of funds.

  • Javascript
  • Python
  • PHP
import request from 'request';
const options = {
method: 'POST',
url: 'https://api-uat.kushkipagos.com/card/v1/preAuthorization',
headers: {
'content-type': 'application/json'
},
body: {
token: 'QZPnSP1000000b3MG3062555GhIrcYt5', // Replace it with the obtained token
amount: {
subtotalIva: 0,
subtotalIva0: 50000,
ice: 0,
iva: 0,
currency: 'COP'
},
orderDetails: {
siteDomain: 'tuebook.com',
shippingDetails: {
name: 'John Doe',
phone: +573988734644,
address: '13th street, 39 avenue 40',
city: 'Bogotá',
region: 'Bogotá DC',
country: 'Colombia',
zipCode: 170402
},
billingDetails: {
name: 'John Doe',
phone: +573988734644,
address: '13th street, 39 avenue 40',
city: 'Bogotá',
region: 'Bogotá DC',
country: 'Colombia',
zipCode: 170402
}
},
fullResponse: v2
},
json: true
};
request(options, (error, response, body) => {
if (error) throw new Error(error);
console.log(body);
});
import requests
url = "https://api-uat.kushkipagos.com/card/v1/preAuthorization"
payload = "{\"token\":\"QZPnSP1000000b3MG3062555GhIrcYt5\",\"amount\":{\"subtotalIva\":0,\"subtotalIva0\":50000,\"ice\":0,\"iva\":0,\"currency\":\"COP\" },\"orderDetails\":{\"siteDomain\":\"tuebook.com\",\"shippingDetails\":{\"name\": \"John Doe\",\"phone\":\"+573988734644\",\"address\":\"13th street, 39 avenue 40\",\"city\":\Bogotá\",\"region\":\"Bogota DC\",\"country\":\"Colombia\",\"zipCode\":\"170402\"},\"billingDetails\":{\"name\":\"John Doe\",\"phone\":\"+573988734644\",\"address\":\"13th street, 39 avenue 40\",\"city\":\Bogotá\",\"region\": \"Bogotá DC\",\"country\": \"Colombia\",\"zipCode\": \"170402\"}},\"fullResponse\":v2}
headers = {'content-type': 'application/json'}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
$client = new http\Client;
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->append('{"token":"QZPnSP1000000b3MG3062555GhIrcYt5","amount":{"subtotalIva":0,"subtotalIva0":50000,"ice":0,"iva":0,"currency":"COP"},"orderDetails": {"siteDomain":"tuebook.com","shippingDetails":{"name":"John Doe","phone":"+573988734644","address":"13th street, 39 avenue 40","city": "Bogotá","region":"BogotáDC","country":"Colombia","zipCode":"170402"},"billingDetails":{"name": "John Doe","phone":"+573988734644","address":"13th street, 39 avenue 40","city": "Bogotá","region":"BogotáDC","country":"Colombia","zipCode": "170402"}},"fullResponse":v2}');
$request->setRequestUrl('https://api-uat.kushkipagos.com/card/v1/preAuthorization');
$request->setRequestMethod('POST');
$request->setBody($body);
$request->setHeaders(array(
'content-type' => 'application/json'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();

3. Kushki verifies authorization

Kushki will validate the availability of funds with the card-issuing entity. Once you receive a response from Kushki, save the ticketNumber, as this will be the identifier for the reauthorization, capture or cancellation.

4. Reauthorize the charge (optional)

Extend the validity or amount of the authorization before capturing your funds by calling our reauthorization endpoint.

  • Javascript
  • Python
  • PHP
var request = require("request");
var options = {
method: 'POST',
url: 'https://api-uat.kushkipagos.com/card/v1/reauthorization',
headers: {'content-type': 'application/json' , 'Private-Merchant-Id': '13dc47c55c714839800a22824d56126c'
},
body: {
ticketNumber: '319228478889680318',
amount: {currency: 'COP', subtotalIva: 0, iva: 0, subtotalIva0: 50000},
fullResponse: v2
},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
import requests
url = "https://api-uat.kushkipagos.com/card/v1/reauthorization"
payload = {
"ticketNumber": "319228478889680319",
"amount": {
"currency": "COP",
"subtotalIva": 0,
"iva": 0,
"subtotalIva0": 50000,
"ice": 0
},
"fullResponse": "v2"
}
headers = {
"Content-Type": "application/json",
"Private-Merchant-Id": "13dc47c55c714839800a22824d56126c"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
$client = new http\Client;
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->append('{"ticketNumber":"319228478889680318","amount":{"currency":"COP","subtotalIva":0,"iva":0,"subtotalIva0":50000,"ice":0},"fullResponse":v2}');
$request->setRequestUrl('https://api-uat.kushkipagos.com/card/v1/reauthorization');
$request->setRequestMethod('POST');
$request->setBody($body);
$request->setHeaders(array(
'content-type' => 'application/json'
' Private-Merchant-Id ' => '13dc47c55c714839800a22824d56126c'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();

5. Capture or release the funds

5.1 Perform the capture (optional)

Capture the amount you define according to the authorized by calling our capture endpoint, using the ticketNumber obtained in the authorization.

  • Javascript
  • Python
  • PHP
var request = require("request");
var options = {
method: 'POST',
url: 'https://api-uat.kushkipagos.com/card/v1/capture',
headers: {'content-type': 'application/json'},
body: {
ticketNumber: '319228478889680318',
amount: {currency: 'COP', subtotalIva: 0, iva: 0, subtotalIva0: 50000},
fullResponse: v2
},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
import http.client
conn = http.client.HTTPSConnection("api-uat.kushkipagos.com")
payload = "{\"ticketNumber\":\"319228478889680318\",\"amount\":{\"currency\":\"COP\",\"subtotalIva\":0,\"iva\":0,\"subtotalIva0\":50000,\"ice\":0},\"fullResponse\":v2}"
headers = { 'content-type': "application/json" }
conn.request("POST", "/card/v1/capture", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
$client = new http\Client;
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->append('{"ticketNumber":"319228478889680318","amount":{"currency":"COP","subtotalIva":0,"iva":0,"subtotalIva0":50000,"ice":0},"fullResponse":v2}');
$request->setRequestUrl('https://api-uat.kushkipagos.com/card/v1/capture');
$request->setRequestMethod('POST');
$request->setBody($body);
$request->setHeaders(array(
'content-type' => 'application/json'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();

5.2 Authorization void (optional)

If you need to void an authorization to release the funds to the cardholder, you can do so by calling charge void endpoint, using the ticketNumber obtained in the authorization.

  • Javascript
  • Python
  • PHP
var request = require("request");
var options = {
method: 'DELETE',
url: 'https://api-uat.kushkipagos.com/v1/charges/1528188291221',
headers: {'content-type': 'application/json'},
body: {
fullResponse: v2,
amount: {subtotalIva: 0, subtotalIva0: 50000, ice: 0, iva: 0, currency: 'COP'}
},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
import http.client
conn = http.client.HTTPSConnection("api-uat.kushkipagos.com")
payload = "{\"fullResponse\":v2,\"amount\":{\"subtotalIva\":0,\"subtotalIva0\":50000,\"ice\":0,\"iva\":0,\"currency\":\"COP\"}}"
headers = { 'content-type': "application/json" }
conn.request("DELETE", "/v1/charges/1528188291221", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
$client = new http\Client;
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->append('{"fullResponse":v2,"amount":{"subtotalIva":0,"subtotalIva0":50000,"ice":0,"iva":0,"currency":"COP"}}');
$request->setRequestUrl('https://api-uat.kushkipagos.com/v1/charges/1528188291221');
$request->setRequestMethod('DELETE');
$request->setBody($body);
$request->setHeaders(array(
'content-type' => 'application/json'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();

Test your integration

There are test cards that you can use in the UAT environment to ensure that your integration is ready. Use them with any CVV, zip code and future expirationdate.

  • Approve transaction: 5451951574925480.
  • Transaction declined at token request(front-end): 4574441215190335.
  • Trabsaction declined at authorization: 4349003000047015.
  • Transaction declined at captur: 4547004841271012.

Prepare your certification

Consider the following guidelines to pass the technical certification (required to obtain production credentials):

  • Tax calculations are correct.
  • Do not store sensitive card data in your database (full card number, CVV, etc).
  • On screen messages according to Kushki responses.
  • Save and record all Kushki responses (required in case support is needed).
  • Make sure to send all the required data specified in the API reference,such as product details (productDetails), as well as your customer-payer contact information (contactDetails), along with billing information ( "orderDetails"."billingDetails") and shipping informations (if your business model requires it: "orderDetails"."shippingDetails"), within the request to make the change.
  • The Kushki logo must be visible to the customer. You can find our logo in various formats here.

If you are using Kushki.js, also consider the consider the following:

  • The cardholder name is required.
  • The card number field is required.
  • The card number field accepts only numbers.
  • The card number field has a maximum of 16 digits (it can be less).
  • The CVV field is required.
  • The CVV field accepts only numbers.
  • The CVV fields must be of password type.
  • The CVV field allows a maximum of 4 digits and a minimum of 3
  • The expiration date is required.
  • The expiration date must accept only future dates.
  • The payment button is disabled after the first click.
  • If your have enabled the option of email notification to your customers about the outcome of transactions from Kushky, the emailparameter of the object contactDetails is required.
  • The Kushki logo must be visible to the customer. You can find our logo in various formats here.