Two Payment Integration
Two is a Buy Now, Pay Later payment solution for businesses. Once a purchase is made via Two, the invoice is sent directly to the selected organization’s accounting system using EHF. Two is currently available in the United Kingdom and Norway, with plans to launch in Sweden soon.
To get started, you will need to create a Two account. After signing up, you will receive an email containing the test credentials. Alternatively, you can also find the credentials under the “Developer tools” section in the dashboard. As soon as you are ready to go into production, you can contact Two to receive the production keys instantly.
Using the Two Search API, the user can enter their company details. Two checks whether an invoice can be offered to the company.
- The next step is verifying the user’s identity. If the user is based in Norway, this is done via Vipps.
- Lastly, when the order is accepted, the user receives an invoice made out to their company that can be paid as per convenience.
The first step is the user searching for their company so Two can check whether sending an invoice is an option or not. This is done via their Search API. The API is location specific, so you need to specify the country code as follows:
Norway
https://no.search.two.inc/
UK
https://gb.search.two.inc/
It takes three required parameters:
- limit: total number of companies you’d like to be returned
- offset: starting index of results in an array of matches
- q: the query string
A request to the Search API would then look like the code snippet below:
const query = new URLSearchParams({
limit: 'string',
offset: 'string',
q: 'string'
}).toString();
const resp = await fetch(
`https://no.search.two.inc/search?${query}`,
{method: 'GET'}
);
const data = await resp.text();
After the company verification, a user is then redirected to pay via invoice at Two. To create an order there, you will need to send a POST request to the /order endpoint with all the order-related information:
const resp = await fetch(
`https://sandbox.api.two.inc/v1/order`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'string'
},
body: JSON.stringify({
currency: 'GBP',
invoice_type: 'DIRECT_INVOICE',
gross_amount: '400',
net_amount: '360',
discount_amount: '0.0',
discount_rate: '0.00',
tax_amount: '40',
tax_rate: '0.01',
buyer: {
representative: {
first_name: 'John',
last_name: 'Doe',
phone_number: '12345678',
email: 'example@example.inc'
},
company: {
country_prefix: 'GB',
organization_number: '13078389',
company_name: 'TWO B2B LTD'
}
},
line_items: [
{
type: 'PHYSICAL',
name: 'Aluminium Plant',
description: 'This is a plant',
discount_amount: '0.00',
gross_amount: '200.00',
net_amount: '180.00',
quantity: 5,
unit_price: '0.00',
tax_amount: '20',
tax_rate: '0.1',
tax_class_name: 'VAT 25%',
quantity_unit: 'pcs',
image_url: 'https://www.exampleobjects.com/product-image-1200x1200.jpg',
product_page_url: 'https://www.example.com/products/f2a8d7e34',
details: {
brand: 'testbrand',
categories: ['cat1', 'testcategory'],
barcodes: [
{
value: '1234',
type: 'testbarcode'
}
],
part_number: 'testnumber'
},
prototype_id: 'bd06d90d-fdef-4d6b-9438-11f160f219ac'
},
{
type: 'PHYSICAL',
name: 'Aluminium Plant',
description: 'This is a plant',
discount_amount: '0.00',
gross_amount: '200.00',
net_amount: '180.00',
quantity: 5,
unit_price: '0.00',
tax_amount: '20',
tax_rate: '0.1',
tax_class_name: 'VAT 25%',
quantity_unit: 'pcs',
image_url: 'https://www.exampleobjects.com/product-image-1200x1200.jpg',
product_page_url: 'https://www.example.com/products/f2a8d7e34',
details: {
brand: 'testbrand',
categories: ['cat1', 'testcategory'],
barcodes: [
{
value: '1234',
type: 'testbarcode'
}
],
part_number: 'testnumber'
},
prototype_id: 'bd06d90d-fdef-4d6b-9438-11f160f219ac'
},
{
type: 'PHYSICAL',
name: 'Aluminium Plant',
description: 'This is a plant',
discount_amount: '0.00',
gross_amount: '200.00',
net_amount: '180.00',
quantity: 5,
unit_price: '0.00',
tax_amount: '20',
tax_rate: '0.1',
tax_class_name: 'VAT 25%',
quantity_unit: 'pcs',
image_url: 'https://www.exampleobjects.com/product-image-1200x1200.jpg',
product_page_url: 'https://www.example.com/products/f2a8d7e34',
details: {
brand: 'testbrand',
categories: ['cat1', 'testcategory'],
barcodes: [
{
value: '1234',
type: 'testbarcode'
}
],
part_number: 'testnumber'
},
prototype_id: 'bd06d90d-fdef-4d6b-9438-11f160f219ac'
}
],
merchant_order_id: '1232',
merchant_urls: {
merchant_confirmation_url: 'http://localhost:6000/confirmation'
},
billing_address: {
organization_name: 'Test',
street_address: 'test2',
postal_code: '1237',
city: 'Oslo',
region: 'test',
country: 'NO'
},
shipping_address: {
organization_name: 'Test',
street_address: 'test2',
postal_code: '1237',
city: 'Oslo',
region: 'test',
country: 'NO'
}
})
}
);
const data = await resp.json();
Some of these fields are required, while some aren’t. To get a more comprehensive idea regarding the fields, head over to Two’s official documentation. (access required)
After the purchase has been confirmed, the user will be redirected back to the shop for a confirmation message. This redirect URL can be specified in the POST request made to the order endpoint. The endpoint to confirm the order takes in the order ID as a parameter. If the returned result says confirmed, this is also where you would ideally create an order in Crystallize.
const id = 'YOUR_id_PARAMETER';
const resp = await fetch(
`https://sandbox.api.two.inc/v1/order/${id}/confirm`,
{
method: 'POST',
headers: {'X-API-Key': 'string'}
}
);
const data = await resp.text();