The Khipu API for creating and receiving payments enables collectors (individuals or organizations) with an active Khipu collection account to generate charges. The process of creation, payment, and validation is as follows:
- The collector generates a charge using the API and displays a button for purchase.
- The payer clicks the payment button on the website or a payment link in an email or another medium and pays using Khipu.
- The payer is redirected to the return page defined by the collector where it must be indicated that the payment is under verification (or to the failure page if the payment could not be made).
- Moments later, Khipu verifies the transaction and notifies the payer by email. Additionally, the merchant is notified by email and/or by invoking a web service.
- The collector validates the payment notification and delivers the transacted good to the payer (or discards the notification if it is invalid).
¡Important!
In the third step, the payer is redirected to a return page (3a) or to a possible abandonment of payment (3b). Success means that the transfer is in the verification process, but this does not mean that it has been successfully completed yet. It is essential to complete the verification in step 5 before delivering the product or service. The same applies to rejection; the user still has instances to resume the payment and complete it.
When a person creates a user account on Khipu, a "collection account" is automatically created for them. This collection account is where the payments received from other people will be associated.
To be able to collect payments, it is necessary to activate the collection account by associating it with a bank account. The bank account is where the daily collections are deposited on the next business day. This bank account can be changed later and will affect all payments that have not yet been reconciled.
Initially, a collection account does not have a bank account associated with it. To associate a bank account, you must go to your Khipu account and try to create a payment request. The system will ask you to complete a payment using that bank account to ensure that you have access to it. The payment amount will be refunded on the next business day.
Importante
If the new collection account is associated with a natural person, the account will have a maximum amount of $50,000 per payment (in Chile). To increase this amount, you must contact us at support@khipu.com.
A user account in Khipu can create (or have access to) multiple collection accounts. This serves, for example, to have different businesses, each with its own collection account. Each collection account must have its bank account configured, but several collection accounts can share the data of the same bank account where the money will be deposited.
Every collection account has credentials that allow using the REST API. These credentials are generated at the time of creating the collection account.
The credentials have two parameters:
receiver id: It is the unique identifier of this collection account and cannot be changed. secret: It is a secret and unique key of the collection account.
The most important part of the credentials is the Secret. This key is used to sign API requests and should not be shared with anyone. Khipu support may eventually request the ID for tracking purposes, but will never ask for your «secret». You can always create a new key that will invalidate the old one if you want to change it.
Two different security mechanisms are used in the creation and validation of a payment. On one hand, Khipu uses an extended validation certificate that allows the collector to always know that they are effectively communicating with Khipu's official servers. Additionally, the merchant must sign all API calls using the unique credentials of their account.
To understand the signing process in detail, review the documentation on signing.
In this section, we show you the necessary steps to start integrating Khipu into your site. The most important thing to note is that, during the development and testing process, you should use development collection account credentials. Only when your site is ready and the integration is prepared to make real payments should you change the credentials to those of a production collection account.
Khipu does not have a separate testing version from the production version like other platforms. Instead, the API and servers of the main platform are used. To carry out development tests, a "developer collection account" is used. These collection accounts are identical to regular ones but have some differences:
- The associated current accounts are not real because no real money is settled.
- They are created only for testing purposes.
- Charges generated with them can only be paid using test banks.
To create a development account, you must follow these steps:
- Register as a user here: https://khipu.com/user/register
- Go to your user profile in Khipu
- In "Developer Options" activate developer mode.
- Then go to configure and choose "Collection Accounts"
- Now a button "Create account in developer mode" will appear
Now that you have a development account, all you need from it are the account credentials. These are obtained in the "Account Options" under the "To integrate Khipu into your website" option.
Development collection accounts can only receive payments from test banks. These banks are banks created by Khipu for testing purposes.
The test bank allows you to test that the payment process is complete, including going to the bank and depositing to Khipu or using simplified transfer. Since these banks do not operate with real money, you can make as many transfers as you want because the balance never runs out.
Additionally, these banks have on-screen instructions for logging in, filling in passwords, and making transfers.
We have generated libraries for the most popular programming languages. The following code shows how to install these libraries.
In PHP, for libraries and dependencies, we use “composer“. We must add Khipu to the dependencies of the "composer.json" file.
{
"require": {
"khipu/khipu-api-client": "2.9.1"
}
}
And then run:
$ composer install
Installing dependencies (including require-dev)
- Installing khipu/khipu-api-client (2.9.1)
Downloading: 100%
Writing lock file
Generating autoload files
Then, in our php files we must add the following line to have the library available:
require __DIR__ . '/vendor/autoload.php';
In Java, using Maven to resolve dependencies, we need to add the following lines to our pom.xml
file.
<dependency>
<groupId>com.khipu</groupId>
<artifactId>khipu-api-client</artifactId>
<version>2.9.0</version>
</dependency>
The Khipu library is intended to be used with a Java Virtual Machine 1.7 or higher. However, it is still possible to use it with Java 1.6. For this, it is necessary to add the following changes.
First, it is necessary to add a more recent cryptographic provider. To do this, you need to add this new dependency:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
Luego, para que este proveedor criptográfico esté disponible es necesario agregarlo a los disponibles de la máquina virtual. En el código fuente de la aplicación es necesario agregar las siguientes líneas:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
It is also possible to leave this provider integrated into the virtual machine. This way, we avoid including the lines of code, and the provider remains available for other applications. To do this, you need to follow the instructions available on the page http://www.bouncycastle.org.
In Ruby, we have prepared a gem. To install the gem, we must use the "gem" command:
$ gem install khipu-api-client
Then in your script you must add this line to have the client available:
require 'khipu-api-client'
###.NET
For .NET we have available a library packaged in a NuGet that is installed using the Package Manager Console
PM> Install-Package KhipuApiClient
To access the Khipu REST API, it is necessary to have an internet connection. This is required to create and modify payments.
Every time Khipu receives a payment, the merchant is notified so that they can deliver the product or service to the customer. This notification can be via email or using the instant notification API. The recommended mechanism is instant notification as it does not require human intervention once it is properly configured. These notifications are invocations that Khipu must make to a web service on the merchant's website, which is why this web service must be visible from the Internet.
Let's analyze the most common use case of the REST API, which is making a payment on a web store to obtain a product. The most common flow has the following steps:
To access the Khipu REST API, an internet connection is required. This is necessary for creating and modifying payments. Let's analyze the most common use case of the REST API, which is making a payment on a web store to obtain a product. The most common flow has the following steps:
- The customer selects their products and chooses to pay.
- The merchant creates a payment using the REST API.
- The merchant directs the customer to pay via Khipu.
- The customer makes the payment.
- The customer is redirected to the merchant's website and waits for a moment while Khipu verifies the payment.
- The payment is verified, and the merchant is notified via web service.
- The merchant delivers the product or service.
- Now let's look at the steps where integration with Khipu is necessary:
Let's now see the steps where integration with Khipu is necessary:
After the customer selects their products and opts to pay, the payment process begins. Most e-commerce software operates in a similar manner. They all have some type of object that represents the purchase order. What we need to do is associate this purchase order with a payment in Khipu.
Let's look at the following code:
<?php
// We must know $receiverId and $secretKey beforehand
$receiverId = your-receiver-id;
$secretKey = 'your-secret';
require __DIR__ . '/vendor/autoload.php';
$configuration = new KhipuConfiguration();
$configuration->setReceiverId($receiverId);
$configuration->setSecret($secretKey);
// $configuration->setDebug(true);
$client = new KhipuApiClient($configuration);
$payments = new KhipuClientPaymentsApi($client);
try {
$opts = array(
"transaction_id" => "MTI-100",
"return_url" => "https://mi-ecomerce.com/backend/return",
"cancel_url" => "https://mi-ecomerce.com/backend/cancel",
"picture_url" => "https://mi-ecomerce.com/pictures/foto-producto.jpg",
"notify_url" => "https://mi-ecomerce.com/backend/notify",
"notify_api_version" => "1.3"
);
$response = $payments->paymentsPost(
"Sample payment",
"CLP",
100.0,
$opts
);
print_r($response);
} catch (KhipuApiException $e) {
echo print_r($e->getResponseBody(), TRUE);
}
int receiverId = your-receiver-id;
String secretKey = 'your-secret';
ApiClient apiClient = new ApiClient();
apiClient.setKhipuCredentials(receiverId, secretKey);
apiClient.setPlatform("demo-client", "2.0");
// apiClient.setDebugging(true);
PaymentsApi paymentsApi = new PaymentsApi();
paymentsApi.setApiClient(apiClient);
Map<String, Object> options = new HashMap<>();
options.put("transactionId", "MTI-100");
options.put("returnUrl", "https://mi-ecomerce.com/backend/return");
options.put("cancelUrl", "https://mi-ecomerce.com/backend/cancel");
options.put("pictureUrl", "https://mi-ecomerce.com/pictures/foto-producto.jpg");
options.put("notifyUrl", "https://mi-ecomerce.com/backend/notify");
options.put("notifyApiVersion", "1.3");
PaymentsCreateResponse response = paymentsApi.paymentsPost("Sample payment"
, "CLP"
, 100.0
, options
);
System.out.println(response);
require 'khipu-api-client'
receiver_id = your-receiver-id
secret_key = 'your-secret'
Khipu.configure do |c|
c.secret = secret_key
c.receiver_id = receiver_id
c.platform = 'demo-client'
c.platform_version = '2.0'
# c.debugging = true
end
client = Khipu::PaymentsApi.new
response = client.payments_post('Sample payment', 'CLP', 120000, {
transaction_id: 'FACT2001',
expires_date: DateTime.new(2016, 4, 4),
body: 'A simple description',
picture_url: 'https://mi-ecomerce.com/pictures/some-picture.jpg',
return_url: 'https://mi-ecomerce.com/backend/return',
cancel_url: 'https://mi-ecomerce.com/backend/cancel',
notify_url: 'https://mi-ecomerce.com/backend/notify',
notify_api_version: '1.3'
})
Configuration.ReceiverId = your-receiver-id;
Configuration.Secret = "your-secret";
PaymentsApi a = new PaymentsApi();
try
{
DateTime dt = DateTime.Now;
dt = dt.AddDays(5);
PaymentsCreateResponse response = a.PaymentsPost(
"Some description",
"CLP",
100.0,
transactionId: "FACT2001",
expiresDate: dt,
body: "Some description",
pictureUrl: "https://mi-ecomerce.com/pictures/some-picture.jpg",
returnUrl: "https://mi-ecomerce.com/backend/return",
cancelUrl: "https://mi-ecomerce.com/backend/cancel",
notifyUrl: "https://mi-ecomerce.com/backend/notify",
notifyApiVersion: "1.3"
);
System.Console.WriteLine(response);
}
catch (ApiException e)
{
Console.WriteLine(e);
}
In the first step, we obtain the purchase order object. This can be created at the moment or retrieved using an id
. In the next step, a payment is created in Khipu using the associated library.
If you look closely, the transaction_id
parameter in the call sends the identifier of the purchase order. This is necessary so that at the time of reconciliation, we can retrieve the purchase order and mark it as paid.
The response of the call will be an object with information about the created payment. The payment_id
field contains the identifier of our payment and the URL to which we must direct the user to make the payment.
This step is optional but can be useful for some merchants. In the previous call to create payments, you can see the parameter "Bank ID to pay". This ID is used to create a payment with a preselected bank (only from the banks supported by Khipu). To obtain this ID, you can use the banksGet call, which provides a list of the banks supported by Khipu, their names, their IDs, and other information.
Let's look at the following example:
<?php
// We must know $receiverId and $secretKey beforehand
$receiverId = your-receiver-id;
$secretKey = 'your-secret';
require __DIR__ . '/vendor/autoload.php';
$configuration = new KhipuConfiguration();
$configuration->setReceiverId($receiverId);
$configuration->setSecret($secretKey);
// $configuration->setDebug(true);
$client = new KhipuApiClient($configuration);
$banksApi = new KhipuClientBanksApi($client);
try {
$response = $banksApi->banksGet();
print_r($response);
} catch (KhipuApiException $e) {
echo print_r($e->getResponseBody(), TRUE);
}
int receiverId = your-receiver-id;
String secretKey = 'your-secret';
ApiClient apiClient = new ApiClient();
apiClient.setKhipuCredentials(receiverId, secretKey);
apiClient.setPlatform("demo-client", "2.0");
// apiClient.setDebugging(true);
BanksApi banksApi = new BanksApi();
banksApi.setApiClient(apiClient);
BanksResponse response = banksApi.banksGet();
System.out.println(response);
require 'khipu-api-client'
receiver_id = your-receiver-id
secret_key = 'your-secret'
Khipu.configure do |c|
c.secret = secret_key
c.receiver_id = receiver_id
c.platform = 'demo-client'
c.platform_version = '2.0'
# c.debugging = true
end
banks = Khipu::BanksApi.new
response = banks.banks_get()
print response
The result of the call contains the value banks
which is a list of banks. Each bank has a bank_id
with the value that we can use to create configured payments.
Once a payment is created, we need to begin the payment process. This can be done in two ways. The recommended way is to use our JavaScript library, which will handle starting the payment. You can find extensive documentation on the GitHub website. Additionally, you can use our library integration example that simulates a merchant using this library.
The other option to initiate the payment is simply to redirect the customer to the payment URL on Khipu. This URL corresponds to the payment_url
parameter returned by the payment creation call.
After the customer makes the payment on the Khipu portal, they will be redirected back to the merchant's website. The URL of the merchant to which the user is redirected must be configured for each payment in the return_url
field, although it could be the same for all payments.
It is very important to note that when the user returns to the merchant's page, this does not mean that the payment is verified. On this page, the merchant should indicate that the payment is in the process of verification and that the user should wait for a moment.
The merchant must implement on the payment return page a way to check the status of the payment and inform the user when the payment has been confirmed.
For this, there are 3 strategies, with the most common ones being:
- WebSockets: The merchant's server informs the client's browser that the payment is confirmed so that it can display it. It is the most efficient way but the most complex to implement. For more information, visit https://en.wikipedia.org/wiki/WebSocket.
- AJAX Calls: The page checks via an AJAX call to the merchant's server about the status of the order. When the response is positive, the page notifies the user that the payment has been completed.
- Periodically Reloading the Page: It is the simplest mechanism and involves using a timer to reload the page periodically, for example, every 10 seconds. Each time the page loads, it checks if the order is complete. If it is, the user is redirected to the success page. If not, it informs the user that they need to continue waiting and starts a new timer.
If you have configured a URL to receive a notification, then Khipu will invoke it immediately after reconciling the payment. This notification is received through Khipu's instant notification API. The version of this API defines how Khipu notifies the merchant.
There are several versions of the API, but we will focus on the latest one, version 1.3. In this version of the API, two parameters will arrive via POST: one with the API version, api_version
which is used to verify that it is the correct version, and the second parameter is notification_token
. Using the notification_token
, we can obtain the information of the collection to mark the product as paid.
Important
Khipu waits for 30 seconds to receive a response to the notification. If no response is obtained after 30 seconds, Khipu will attempt to notify again later. Therefore, if the process of receiving the notification takes more than 30 seconds, it needs to be performed in the background, and an immediate response should be sent.
Let's look at the following code:
<?php
require __DIR__ . '/vendor/autoload.php';
// We must know $receiverId and $secretKey beforehand
$receiverId = your-receiver-id;
$secretKey = 'your-secret';
$api_version = 'get-from-parameters'; api_version
$notification_token = 'get-from-parameters';
$amount = original-amount;
try {
if ($api_version == '1.3') {
$configuration = new KhipuConfiguration();
$configuration->setSecret($secret);
$configuration->setReceiverId($receiver_id);
// $configuration->setDebug(true);
$client = new KhipuApiClient($configuration);
$payments = new KhipuClientPaymentsApi($client);
$response = $payments->paymentsGet($notification_token);
if ($response->getReceiverId() == $receiver_id) {
if ($response->getStatus() == 'done' && $response->getAmount() == $amount) {
// mark the payment as complete and deliver the good or service
}
} else {
// receiver_id does not match
}
} else {
// Use previous version of the notification API
}
} catch (KhipuApiException $exception) {
print_r($exception->getResponseObject());
}
int receiverId = your-receiver-id;
String secretKey = 'your-secret';
String apiVersion = "get-from-parameters";
String notificationToken = "get-from-parameters";
double amount = monto-original-del-cobro;
if (apiVersion.equals("1.3")) {
ApiClient apiClient = new ApiClient();
apiClient.setKhipuCredentials(receiverId, secret);
apiClient.setPlatform("demo-client", "2.0");
// apiClient.setDebugging(true);
PaymentsApi paymentsApi = new PaymentsApi();
paymentsApi.setApiClient(apiClient);
PaymentResponse response = paymentsApi.paymentsGet(notificationToken);
if (response.getReceiverId().longValue() == receiverId) {
if (response.getStatus().equals("done") && response.getAmount() == amount) {
// mark the payment as complete and deliver the good or service
}
} else {
// receiver_id does not match
}
} else {
// Use previous version of the notification API
}
require 'khipu-api-client'
receiver_id = your-receiver-id
secret_key = 'your-secret'
api_version = 'get-from-parameters'
notification_token = 'get-from-parameters'
amount = original-amount
if api_version == '1.3'
Khipu.configure do |c|
c.receiver_id = receiver_id
c.secret = secret
c.platform = 'demo-client'
c.platform_version = '2.0'
# c.debugging = true
end
client = Khipu::PaymentsApi.new
response = client.payments_get(notification_token)
if response.receiver_id == receiver_id
if response.status == 'done' && response.amount == amount
# mark the payment as complete and deliver the good or service
end
else
# receiver_id does not match
end
else
# Use previous version of the notification API
end
Configuration.ReceiverId = your-receiver-id;
Configuration.Secret = "your-secret";
string notificationToken = "get-from-parameters";
string apiVersion = "get-from-parameters";
double amount = original-amount;
if(apiVersion.Equals("1.3")) {
PaymentsApi a = new PaymentsApi();
try
{
PaymentsResponse response = a.PaymentsGet(notificationToken);
if(response.ReceiverId.Equals(Configuration.ReceiverId)
&& response.Status.Equals("done") && response.Amount == amount)
{
# mark the payment as complete and deliver the good or service
}
else
{
# ignore
}
}
catch (ApiException e)
{
Console.WriteLine(e);
}
}