Integration flow for Payment Intents
Fintoc uses the Payment Intent object to represent a bank transfer.
To make a transfer, you must follow some steps:
Create a Payment lntent
From your backend, create a Payment Intent with the amount, currency and recipient of the payment. Always create the Payment Intent from your backend, or a malicious user could alter any of those fields.
Here's an example:
curl --request POST "https://api.fintoc.com/v1/payment_intents" \
-- header 'Authorization: sk_live_0000000000000000' \
-- header 'Content-Type: application/json' \
--data-raw '{
"amount": 1000,
"currency": "CLP",
"recipient_account": {
"holder_id": "111111111",
"number": "123123123",
"type": "checking_account",
"institution_id": "cl_banco_de_chile"
}
}'
const fetch = require('node-fetch');
const payment_intent = {
amount: 1000,
currency: 'clp',
recipient_account: {
holder_id: "111111111",
number: "123123123",
type: "checking_account",
institution_id: "cl_banco_de_chile"
},
}
fetch('https://api.fintoc.com/v1/payment_intents', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'sk_live_000000000000'
},
body: JSON.stringify(payment_intent),
},
)
import requests
payment_intent = {
'amount': 1000,
'currency': 'clp',
'recipient_account': {
'holder_id': '111111111',
'number': '123123123',
'type': 'checking_account',
'institution_id': 'cl_banco_de_chile'
}
}
headers = {
'Accept': 'application/json', 'Authorization': 'sk_live_000000000000'
}
r = requests.post(
'https://api.fintoc.com/v1/payment_intents',
json=payment_intent,
headers=headers
)
require 'net/http'
require 'uri'
require 'json'
payment_intent = {
amount: 1000,
currency: 'clp',
recipient_account: {
holder_id: '111111111',
number: '123123123',
type: 'checking_account',
institution_id: 'cl_banco_de_chile'
}
}
header = {
Accept: 'application/json', Authorization: 'sk_live_000000000000'
}
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, header)
request.body = payment_intent.to_json
response = http.request(request)
The response should look like this:
{
"id": "pi_BO381oEATXonG6bj",
"object": "payment_intent",
"amount": 1000,
"currency": "CLP",
"widget_token": "pi_BO381oEATXonG6bj_sec_a4xK32BanKWYn",
"status": "created",
"metadata": {},
"reference_id": null,
"recipient_account": {
"holder_id": "183917137",
"number": "123456",
"type": "checking_account",
"institution_id": "cl_banco_de_chile"
},
"sender_account": null,
"created_at": "2021-10-15T15:23:11.474Z",
}
When creating a Payment Intent, a widget_token
will be created too (unique for that transfer). You need to use that token to complete the payment process through the widget. The next section contains more details about this.
Open the widget for Payment Intents
Once the Payment Intent is created, you must send its widget_token
to your frontend. Use that widget_token
to configure the widget and the workflow that the user must follow.
Here's an example of the widget configured with the widget_token
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fintoc Demo</title>
<script src="https://js.fintoc.com/v1/"></script>
</head>
<body>
<script>
window.onload(() => {
const widget = Fintoc.create({
holderType: 'individual',
widgetToken: 'pi_XXXXXXXX_sec_YYYYYYYY',
product: 'payments',
publicKey: 'pk_live_0000000000',
onSuccess: () => {},
});
widget.open();
});
</script>
</body>
</html>
Widget Token
When using the
widget_token
, Fintoc configures every internal data relevant for the payment: amount, currency and recipient.The
widget_token
is temporary and will expire 10 minutes after its creation.
To read more about the widget and its configuration, head over to the widget section.
Finish the transfer
Once the transfer is completed, we will send you an event with payment_intent
as its type using a webhook.
To subscribe to the event, you must first have created a Webhook Endpoint using Fintoc and assign to it the events that you want to receive.
It is very important that you subscribe to these events, as you can use them to identify successful transfers from failed ones.
Remember that with the Payment Intent object we can send you 3 different events using webhooks:
Event | Description |
---|---|
payment_intent.succeeded | Event that triggers when a transfer is validated as successful. |
payment_intent.failed | Event that triggers when a transfer fails due to a problem with the bank or with Fintoc. |
payment_intent.rejected | Event that triggers when a transfer is rejected by the user. This may happen when the user rejects the MFA or if it is entered incorrectly. |
Backend's webhook vs widget's onSuccess
It is very important that you wait for the webhook to mark a payment as finished either as succesful or failed. You should never finish the flow solely based on the
onSuccess
function from the widget, because your users may close the widget just before theonSuccess
callback gets executed.
A Payment Intent may fail when the transfer takes more than usual to execute or if the user closes the widget ahead of time.
Once again, we urge you to wait for the webhook to hit your backend before making any post-payment actions like sending confirmation emails to your users, entering the sale on your database or starting the shipping process of some product.
To subscribe to the webhook with the corresponding event, you can read the Webhooks section of our documentation. Remember that these events all start with payment_intent
.
Updated 4 months ago