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 two options for integrations: kajita and Kushki.js.

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);
}
});

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.