Boleto is a payment method regulated by the Central Bank of Brazil, which utilizes vouchers for payment transactions. Rather than making direct online payments for goods or services, the customers have the option to generate a Boleto and pay with either cash or, for enhanced security, a card. They can save or print the voucher and take it to an authorized payment location, such as a bank or lottery agency, to make the payment. At the payment location, your customers can scan the barcode or enter the voucher number to process the payment. Once the payment is processed, Chargebee will receive a confirmation from the gateway.
- Currently, Boleto payments are supported via the Stripe gateway.
- This feature is a Private Beta Release. Contact Chargebee support to enable Boleto via Stripe for your Test and Live site.
Gateway Prerequisites
The following are the prerequisites for setting up the integration:
Enable Boleto via Stripe.
Configure Smart routing to select offline payments for the Brazilian Real(BRL) currencies:
Set up Chargebee.js
Include the Chargebee.js script on your page and initialize a Chargebee instance before you start. For the script tag, the Chargebee.init options, and the tearDown() caveat, see Set up Chargebee.js.
Create a Payment Intent
You should create a payment intent before submitting the form to authorize the payments.
payment_intent performs the essential function of tracking different events involved in a transaction. This includes:
Automatically changing its status based on the outcome of authorization and capture events.
Automatically refunding in case of an error post-payment.
A payment_intent can be created at your server-side using create a payment intent API and returned to the client side. The payment method handler uses the created payment_intent internally to perform authorization.
Here's the sample code to create a payment_intent.
This must be done from your backend to avoid exposing sensitive data.
Example:
curl https://{site-name}.chargebee.com/api/v2/payment_intents \
-u {fullaccess_api_key}: \
-d amount=500 \
-d currency_code="BRL" \
-d payment_method_type="boleto"
Initiate the above step as request from your frontend.
Frontend code:
function createPaymentIntent() {
return fetch('/payment-intents', {
method: 'POST',
body: JSON.stringify({
amount: 500,
currency_code: 'BRL',
payment_method_type: 'boleto'
})
}).then(function(response) {
return response.json();
}).then(function(responseJson) {
return responseJson.payment_intent;
});
}
Authorize Payment Intent
Ensure smooth payment processing by authorizing the payment intent created above.
Follow these steps to integrate Boleto into your website and authorize the payment intent.
Set up Boleto
a. Load Boleto integration.
loadBoletointegration usingcbInstance.load("boleto").b. Set payment intent. Pass the
payment_intentobject toboletoHandler.setPaymentIntent(payment_intent).Handle Payment
UseboletoandpaymentInfoas the input parameter toboletoHandler.handlePaymentfunction, as this enables the function to handle Boleto payments.
When the payment intent has no reference_id, pass customer (firstName, lastName, email), billingAddress, and taxId in paymentInfo. For the complete paymentInfo reference, see Boleto handlePayment().
Sample Code
cbInstance.load("boleto").then(boletoHandler => {
createPaymentIntent().then((intent) => {
boletoHandler.setPaymentIntent(intent);
const paymentInfo = {
"customer": {
"firstName": "assa",
"lastName": "ssa",
"email": "a@a.com",
"phone": "+12332434343"
},
"billingAddress": {
"firstName": "assa",
"lastName": "ssa",
"addressLine1": "No 4 metro street",
"addressLine2": "rio street",
"city": "rio",
"state": "ap",
"countryCode": "BR",
"zip": "76787678"
},
"taxId": "00000000000000"
}
boletoHandler.handlePayment(paymentInfo).then(intent => {
// SUCCESS!!! payment_intent is authorized.
var response = fetch('/subscriptions', {
method: 'POST',
body: JSON.stringify({
paymentIntentId: intent.id,
plan_id: 'pro_plan',
plan_quantity: 1,
billingAddress: {
...
}, // provide billing address
customer: {
...
} // provide customer details if the subscription is to be created for an existing <code>customer</code> in Chargebee.
})
}).then(function(response) {
return response.json();
});
}).catch(err => {
// OOPS!!! payment_intent is not authorized.
});
});
});
If the payment intent is consumed after authorization, the details sent during payment intent confirmation will be stored in Chargebee. Only the last four digits of the tax ID will be retained.
Examples of Promises and Callbacks
Use webhooks for production use, instead of making the subscription creation request from the frontend, it's more secure and reliable to respond to webhooks from Chargebee on the backend. Listen to the payment_intent_updated event via webhooks and create the subscription when the payment_intent.status is authorized.
const paymentInfo = {
"customer": {
"firstName": "assa",
"lastName": "ssa",
"email": "a@a.com",
"phone": "+12332434343"
},
"billingAddress": {
"firstName": "assa",
"lastName": "ssa",
"addressLine1": "No 4 metro street",
"addressLine2": "rio street",
"city": "rio",
"state": "ap",
"countryCode": "BR",
"zip": "76787678"
},
"taxId": "00000000000000"
}
boletoHandler.handlePayment(paymentInfo).then(intent => {
// SUCCESS!!! payment_intent is authorized.
var response = fetch('/subscriptions', {
method: 'POST',
body: JSON.stringify({
paymentIntentId: intent.id,
plan_id: 'pro_plan',
plan_quantity: 1,
billingAddress: {
...
}, // provide billing address
customer: {
...
} // provide customer details if the subscription is to be created for an existing <code>customer</code> in Chargebee.
})
}).then(function(response) {
return response.json();
});
}).catch(err => {
// OOPS!!! payment_intent is not authorized.
});
const paymentInfo = {
"customer": {
"firstName": "assa",
"lastName": "ssa",
"email": "a@a.com",
"phone": "+12332434343"
},
"billingAddress": {
"firstName": "assa",
"lastName": "ssa",
"addressLine1": "No 4 metro street",
"addressLine2": "rio street",
"city": "rio",
"state": "ap",
"countryCode": "BR",
"zip": "76787678"
},
"taxId": "00000000000000"
}
const callbacks = {
success: (intent) => {
// SUCCESS!!! payment_intent is authorized.
var response = fetch('/subscriptions', {
method: 'POST',
body: JSON.stringify({
paymentIntentId: intent.id,
plan_id: 'pro_plan',
plan_quantity: 1,
billingAddress: {
...
}, // provide billing address
customer: {
...
} // provide customer details if the subscription is to be created for an existing <code>customer</code> in Chargebee.
})
}).then(function(response) {
return response.json();
});
},
error: (err) => {
// OOPS!!! payment_intent is not authorized.
}
}
boletoHandler.handlePayment(
paymentInfo, callbacks
)
Once the authorization is successful, the payment_intent transitions to the authorized state. After creating a subscription, you can utilize the Chargebee APIs to showcase the vouchers.
Learn more about the additional functions supported for Boleto.
Create a Subscription
Pass the ID of the successfully authorized payment_intent to Chargebee's to create a subscription API.
Sample Request
curl https://{site}.chargebee.com/api/v2/customers/__test__8asz8Ru9WhHOJO/subscription_for_items \
-X POST \
-u {site_api_key}: \
-d payment_intent[id]="<Id of authorized payment_intent recieved in last step.>" \
-d subscription_items[item_price_id][0]="basic-BRL" \
-d subscription_items[billing_cycles][0]=2 \
-d subscription_items[quantity][0]=1 \
-d subscription_items[item_price_id][1]="day-pass-BRL" \
-d subscription_items[unit_price][1]=100 \
-d offline_payment_method=boleto \
-d auto_collection=off
auto_collection needs to be off and the payment_intent[payment_method_type] needs to be selected as boleto at the subscription level.
If a subscription is created and an immediate charge is required, a voucher will be generated to cover the corresponding invoice. Here's how you can determine whether a voucher has been generated and present it to the customer.
Sample response when an invoice is created
{
"subscription": {
"id": "1mGnq7ZThst6vQ9tl",
"billing_period": 1,
"billing_period_unit": "month",
"auto_collection": "off",
"customer_id": "1mGnq7ZThsuObLCKj",
"status": "active",
"current_term_start": 1687411907,
"current_term_end": 1690003907,
"next_billing_at": 1690003907,
"created_at": 1687411907,
"started_at": 1687411907,
"activated_at": 1687411907,
"created_from_ip": "44.196.151.224",
"updated_at": 1687411908,
"has_scheduled_changes": false,
"offline_payment_method": "boleto",
"channel": "web",
"resource_version": 1687411908997,
"deleted": false,
"object": "subscription",
"db_id": "subscription_1774696",
"currency_code": "BRL",
"subscription_items": [
{
"item_price_id": "5_plan-BRL-Monthly",
"item_type": "plan",
"quantity": 1,
"unit_price": 1000,
"amount": 1000,
"free_quantity": 0,
"object": "subscription_item"
}
],
"shipping_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AR",
"state": "Arunachal Pradesh",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "shipping_address"
},
"due_invoices_count": 1,
"due_since": 1687411907,
"total_dues": 1000,
"mrr": 0,
"has_scheduled_advance_invoices": false,
"payment_mandates": []
},
"customer": {
"id": "1mGnq7ZThsuObLCKj",
"email": "brl@a.com",
"auto_collection": "on",
"net_term_days": 0,
"allow_direct_debit": false,
"created_at": 1687411906,
"created_from_ip": "44.196.151.224",
"taxability": "taxable",
"updated_at": 1687411909,
"pii_cleared": "active",
"channel": "web",
"resource_version": 1687411909018,
"deleted": false,
"object": "customer",
"db_id": "customer_2365861",
"billing_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AR",
"state": "Arunachal Pradesh",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "billing_address",
"db_id": "billing_address_433374"
},
"card_status": "no_card",
"promotional_credits": 0,
"refundable_credits": 0,
"excess_payments": 0,
"unbilled_charges": 0,
"preferred_currency_code": "BRL",
"tax_providers_fields": []
},
"invoice": {
"id": "452",
"customer_id": "1mGnq7ZThsuObLCKj",
"subscription_id": "1mGnq7ZThst6vQ9tl",
"recurring": true,
"status": "payment_due",
"price_type": "tax_exclusive",
"date": 1687411907,
"due_date": 1687411907,
"net_term_days": 0,
"exchange_rate": 4.7638,
"total": 1000,
"amount_paid": 0,
"amount_adjusted": 0,
"write_off_amount": 0,
"credits_applied": 0,
"amount_due": 1000,
"updated_at": 1687411908,
"resource_version": 1687411908949,
"deleted": false,
"object": "invoice",
"db_id": "invoice_7126832",
"first_invoice": true,
"amount_to_collect": 1000,
"round_off_amount": 0,
"new_sales_amount": 1000,
"has_advance_charges": false,
"currency_code": "BRL",
"base_currency_code": "USD",
"generated_at": 1687411907,
"is_gifted": false,
"term_finalized": true,
"channel": "web",
"tax": 0,
"line_items": [
{
"id": "li_1mGnq7ZThsuOnGCKq",
"date_from": 1687411907,
"date_to": 1690003907,
"unit_amount": 1000,
"quantity": 1,
"amount": 1000,
"pricing_model": "flat_fee",
"is_taxed": false,
"tax_amount": 0,
"object": "line_item",
"db_id": "line_item_10672563",
"subscription_id": "1mGnq7ZThst6vQ9tl",
"customer_id": "1mGnq7ZThsuObLCKj",
"description": "5_plan",
"entity_type": "plan_item_price",
"entity_id": "5_plan-BRL-Monthly",
"tax_exempt_reason": "tax_not_configured",
"discount_amount": 0,
"item_level_discount_amount": 0
}
],
"sub_total": 1000,
"linked_payments": [],
"applied_credits": [],
"adjustment_credit_notes": [],
"issued_credit_notes": [],
"linked_orders": [],
"dunning_attempts": [],
"billing_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AR",
"state": "Arunachal Pradesh",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "billing_address",
"db_id": "billing_address_null"
},
"shipping_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AR",
"state": "Arunachal Pradesh",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "shipping_address"
}
},
"meta_version": 2,
"version": "V2",
"build_version": 100390,
"supported_versions": [
"V1",
"V2"
],
"extra_info": {}
}
Sample response when an invoice has not been created
{
"subscription": {
"id": "1mGnq7ZThsvnfvENP",
"billing_period": 1,
"billing_period_unit": "week",
"auto_collection": "off",
"customer_id": "1mGnq7ZThsw5MnEqU",
"status": "active",
"current_term_start": 1687412311,
"current_term_end": 1688017111,
"next_billing_at": 1688017111,
"created_at": 1687412311,
"started_at": 1687412311,
"activated_at": 1687412311,
"created_from_ip": "44.196.151.224",
"updated_at": 1687412312,
"has_scheduled_changes": false,
"offline_payment_method": "boleto",
"channel": "web",
"resource_version": 1687412312642,
"deleted": false,
"object": "subscription",
"db_id": "subscription_1774845",
"currency_code": "BRL",
"subscription_items": [
{
"item_price_id": "5_plan-BRL-Weekly",
"item_type": "plan",
"quantity": 1,
"unit_price": 0,
"amount": 0,
"free_quantity": 0,
"object": "subscription_item"
}
],
"shipping_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AS",
"state": "Assam",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "shipping_address"
},
"due_invoices_count": 0,
"mrr": 0,
"has_scheduled_advance_invoices": false,
"payment_mandates": []
},
"customer": {
"id": "1mGnq7ZThsw5MnEqU",
"email": "brl1@a.com",
"auto_collection": "on",
"net_term_days": 0,
"allow_direct_debit": false,
"created_at": 1687412309,
"created_from_ip": "44.196.151.224",
"taxability": "taxable",
"updated_at": 1687412312,
"pii_cleared": "active",
"channel": "web",
"resource_version": 1687412312673,
"deleted": false,
"object": "customer",
"db_id": "customer_2366001",
"billing_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AS",
"state": "Assam",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "billing_address",
"db_id": "billing_address_433422"
},
"card_status": "no_card",
"promotional_credits": 0,
"refundable_credits": 0,
"excess_payments": 0,
"unbilled_charges": 0,
"preferred_currency_code": "BRL",
"tax_providers_fields": []
},
"invoice": {
"id": "453",
"customer_id": "1mGnq7ZThsw5MnEqU",
"subscription_id": "1mGnq7ZThsvnfvENP",
"recurring": true,
"status": "paid",
"price_type": "tax_exclusive",
"date": 1687412311,
"due_date": 1687412311,
"net_term_days": 0,
"exchange_rate": 4.7638,
"total": 0,
"amount_paid": 0,
"amount_adjusted": 0,
"write_off_amount": 0,
"credits_applied": 0,
"amount_due": 0,
"paid_at": 1687412311,
"updated_at": 1687412312,
"resource_version": 1687412312619,
"deleted": false,
"object": "invoice",
"db_id": "invoice_7127256",
"first_invoice": true,
"amount_to_collect": 0,
"round_off_amount": 0,
"new_sales_amount": 0,
"has_advance_charges": false,
"currency_code": "BRL",
"base_currency_code": "USD",
"generated_at": 1687412311,
"is_gifted": false,
"term_finalized": true,
"channel": "web",
"tax": 0,
"line_items": [
{
"id": "li_1mGnq7ZThsw5xvEqs",
"date_from": 1687412311,
"date_to": 1688017111,
"unit_amount": 0,
"quantity": 1,
"amount": 0,
"pricing_model": "flat_fee",
"is_taxed": false,
"tax_amount": 0,
"object": "line_item",
"db_id": "line_item_10673161",
"subscription_id": "1mGnq7ZThsvnfvENP",
"customer_id": "1mGnq7ZThsw5MnEqU",
"description": "5_plan",
"entity_type": "plan_item_price",
"entity_id": "5_plan-BRL-Weekly",
"tax_exempt_reason": "tax_not_configured",
"discount_amount": 0,
"item_level_discount_amount": 0
}
],
"sub_total": 0,
"linked_payments": [],
"applied_credits": [],
"adjustment_credit_notes": [],
"issued_credit_notes": [],
"linked_orders": [],
"dunning_attempts": [],
"billing_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AS",
"state": "Assam",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "billing_address",
"db_id": "billing_address_null"
},
"shipping_address": {
"first_name": "a2",
"last_name": "a2",
"email": "a2@a.com",
"phone": "+1765432",
"line1": "hhh",
"line2": "aaa",
"city": "hhhh",
"state_code": "AS",
"state": "Assam",
"country": "IN",
"zip": "203098",
"validation_status": "not_validated",
"object": "shipping_address"
}
},
"meta_version": 2,
"version": "V2",
"build_version": 100390,
"supported_versions": [
"V1",
"V2"
],
"extra_info": {}
}
If payment_intent is created for zero Brazilian Real or no immediate charges are applied, then invoice will not be created.
Display Boleto Voucher to Customer
In situations where a payment is required, such as for regular pricing plans or discounted plans with a non-zero amount, an invoice is generated. Once a voucher for an invoice is generated, you can display the voucher details to the customer so that they can make payments for the voucher. Follow these steps:
Use the List vouchers for an invoice API to retrieve vouchers for an invoice in reverse chronological order.
Use the Create a hosted page to view Boleto vouchers API to create a voucher detail hosted page and email customers a link to it. Customers can review the voucher details on that page.
Sample Response
{"list": [
{"payment_voucher": {
"id": "pv_1mG11S1TcNL0SP9Vd",
"id_at_gateway": "pi_3N0V7aK7ilSfRo7v1pfbc2NI",
"payment_voucher_type": "boleto",
"expires_at": 1682364922,
"status": "active",
"amount": 18900,
"gateway_account_id": "gw_161my9TXG5oNYwgv",
"payment_source_id": "pm_1mG11S1TcNKrvR9Up",
"gateway": "stripe",
"payload": "{\"url\":\"https://payments.stripe.com/boleto/voucher/test_YWNjdF8xTHZnMFRLN2lsU2ZSbzd2LF9ObTNFc3MzMDlsbU1qamg1Q2ROdDNzOWNYUk81bkhp0100p0cMVCz3\",\"voucher_number\":\"01010101010101010101010101010101010101010101010\",\"expiry\":\"1682364922\"}",
"url": "http://john.chargebee.com/pages/v3/__dev__w5aPBsoEK5z6kIEt2mrEIH9GWLliHXrN/view_voucher",
"date": 1682364742,
"updated_at": 1682364742,
"resource_version": 1682364742832,
"object": "payment_voucher",
"linked_invoices": [
{
"invoice_id": "60",
"date": 1682364741,
"total": 18900,
"status": "payment_due"
},
{..}
],
"currency_code": "BRL",
"customer_id": "test_d23ed22ew"
}},
{..}
]}
We're always happy to help you with any questions you might have! Click here to reach out to us.