User-to-User Purchase
Another version of this information is available
If you're new to Tilia services, a newer version of this information is available in the Transaction Tutorials section of these docs, which might be an easier place to start.
A typical purchase transaction consists of collecting payment information, creating an invoice, and submitting the invoice for processing. This example explains how to create a transaction for a purchase between two Tilia users.
Prerequisites
To complete this example, you'll need the following:
-
An Access Token with the requisite scopes:
read_payment_methods
,write_user_tokens
andwrite_invoices
- An account ID for the buyer. Refer to Registering Users for information on creating user accounts.
- An account ID for the seller.
- A web page containing the Tilia widget script. Refer to Widget Integration for instructions on setting this up.
- A payment method. Refer to Test Payments for payment methods you can use in testing.
The process of creating a transaction involves the following steps:
Step 1: Retrieve seller wallet details
Step 2: Create a secure redirect URL for the buyer
Step 3: Call the payment selection flow to obtain payment details
Step 4: Set up the purchase transaction
Step 5: POST the invoice for processing
Step 6: Handle the completion event
Step 1: Retrieve seller wallet details
Sellers receive payments in their Tilia wallets. Each wallet has a unique ID that can be used in building transactions.
To retrieve the seller's wallet ID, submit a GET request with the seller's' account_id
to the /payment_methods
endpoint.
curl --location --request GET https://payments.tilia-inc.com/v1/{account_id}/payment_methods \
--header 'Authorization: Bearer <Access_Token>' \
--header 'Content-Type: application/json' \
This returns all of the payment methods associated with the seller's account, including purchase-only payment methods such as credit cards. To locate the wallet, look for the payment method in which provider
has a value of wallet
, and the currency matches that of the transaction you are creating.
In this example, we are creating a USD transaction, so will be using the seller's USD wallet.
{
"status": "Success",
"message": [],
"codes": [],
"payload": [
{
"id": "fce464b4-cf9f-49c2-bdb1-2db3275d6284",
"account_id": "7f938c50-0225-4fbe-b465-81d70934064a",
"method_class": "registration",
"display_string": "USD Wallet",
"provider": "wallet",
"psp_reference": "a900281d-5d01-4784-a412-f447389929f8",
"psp_hash_code": "",
"processing_currency": "USD",
"pm_state": "ACTIVE",
"integrator": "acme",
"created": "2020-08-14 10:59:59",
"updated": "2020-08-14 10:59:59",
"wallet_balance": "2457",
"payment_method_id": "",
"provider_data": {
"wallet_id": "a900281d-5d01-4784-a412-f447389929f8",
"wallet_balance": "2457"
}
}
]
}
The wallet_id
is used in setting up the purchase transaction in step 4.
Step 2: Create a secure redirect URL
To complete a purchase, you'll need to obtain the buyer's payment information. To start, you'll pass the buyer's account ID to create a redirect URL. This URL creates a secure user session, forming the basis for calling the Tilia Purchase flow.
curl --location --request POST https://auth.tilia-inc.com/authorize/user \
--header 'Authorization: Bearer <Access_Token>' \
--header 'Content-Type: application/json' \
Request Body
{
"account_id": "string"
}
Sample response
{
"status": "Success",
"message": [],
"codes": [],
"payload": {
"redirect": "https://web.tilia-inc.com/ui/appauth/19a4a2b0-364c-4cad-a895-14c57bcd4e7c"
}
}
Step 3: Call the payment-selection flow to obtain payment details
The Payment Selection flow is a web UI that allows the purchasing user to choose a payment method. If the user does not have a stored payment method, they will be able to add one. Upon completion of the flow, an array of IDs for the user's payment method(s) is passed back to you for use in creating the transaction.
Users must have a signed copy of the most recent Tilia Terms of Service (TOS) on file. If the user has not accepted the TOS, or if there is an updated version available, they are presented with a TOS screen which must be accepted before they can select a payment method.
From the widget page, call the following JavaScript to execute the purchase flow.
window.Tilia.execute({
rootId: "< YOUR-ELEMENT-ID >",
flow: "payment-selection",
flowConfig: {
// Optionally include transactionDetails to allow the user the key functionality
// of choosing their remaining wallet balance before a second payment method.
transactionDetails: {
transaction_amount: "< TRANSACTION-AMOUNT >",
currency: "USD"
}
},
redirect: "< WIDGET-REDIRECT-URL >",
onComplete: handleComplete,
onError: handleError,
});
The widget invokes the handleComplete
callback with the result of the flow.
If the user cancels anywhere in the flow:
{
"source": “tilia”,
"event": “tilia.payment-selection.complete”,
"state": “cancel”,
}
If the user completes the flow:
{
"source": "tilia",
"event": "tilia.payment-selection.complete",
"state": "complete"
"paymentMethods": [
{
"payment_method_id": "a787923c-4b82-4400-81e4-34f7baa849b3",
"amount": 5000
},
{
"payment_method_id": "5ee85a7a-8319-4a53-837c-5d909d184442",
"amount": 0
}
]
}
You will be able to pass in the paymentMethods
array into the next step.
Step 4: Set up the purchase transaction
Once you have the user's payment method(s), you are ready to set up your purchase transaction, in the form of an invoice. Tilia uses the concept of invoices to describe the detailed information required in order to process a transaction.
For a user-to-user purchase, the value for transaction_type
must be user_to_user
.
For this transaction type, you need to provide the following values:
-
account_id
- the buyer's account ID -
payment_method_id(s)
- theid(s)
returned by the payment selection flow. You can pass the array returned by this flow into the invoice. When using multiple payment methods, provide an amount for each payment method. A value of “0” indicates the remaining value of the transaction will be charged to that payment method. One of the payment methods must have a value of "0". -
currency
- the currency for the purchase. -
amount
- the amount of the purchase -
source_wallet_id
- your publisher wallet to be used in processing the transfer of funds. Leave this value blank to use the default (appropriate in most cases). -
destination_wallet_id
- the seller's wallet ID (retrieved in step 1).
Additionally, you will want to provide details about the item(s) being purchased, including the seller's product description, SKU, and other transaction information.
The following example is for a simple invoice with a single item. More complex invoices, including multi-seller invoices, can be built using various properties found in our invoicing API. Refer to the API reference for details.
attention
This example is in USD. Therefore, all amounts are in cents. Refer to Working with Currencies for information on how currencies are used.
The example below requires an API token with the scope write_invoices
.
curl --location --request POST https://invoicing.tilia-inc.com/v2/invoice \
--header 'Authorization: Bearer <Access_Token>' \
--header 'Content-Type: application/json' \
Request Body
{
"account_id": "<buyer_account_id>",
"reference_type": "product_purchase_id",
"reference_id": "purchase_id123",
"description": "A description of the product",
"payment_methods": [
{"payment_method_id": "<id_from_payment_flow>"}
],
"line_items": [
{
"amount": 500,
"currency": "USD",
"transaction_type": "user_to_user",
"product_sku": "12345",
"reference_type": "seller_listing_id",
"reference_id": "listing123",
"recipients": [
{
"amount": 500,
"currency": "USD",
"source_wallet_id": "<your_merchant_wallet_id>",
"destination_wallet_id": "<seller_wallet_id>"
}
]
}
]
}
Create invoice sample response
A successful request returns the HTTP 201 Created
status code along with a JSON response body containing the invoice details. You will use the invoice_id
field value in the next step.
View Response
{
"status": "Success",
"message": [],
"codes": [],
"payload": {
"invoice_id": "7f31235d-93da-4f1f-80dd-8db34cc1cc6e",
"account_id": "793fab8e-6da5-4b26-b7f9-aab9cf809f91",
"reference_type": "product_purchase_id",
"reference_id": "purchase_id123",
"state": "open",
"description": "A description of the product",
"metadata": null,
"summary": {
"total_amount": 500,
"currency": "USD",
"display_amount": "USD 5.00"
},
"created": "2020-05-11T15:54:12Z",
"updated": "2020-05-11T15:54:12Z",
"payment_methods": {},
"line_items": {
"ac43aed7-b2ae-4e76-990d-25aea6832489": {
"line_item_id": "ac43aed7-b2ae-4e76-990d-25aea6832489",
"product_sku": "12345",
"amount": 500,
"currency": "USD",
"display_amount": "USD 5.00",
"reference_type": "seller_listing_id",
"reference_id": "listing123",
"transaction_type": "user_to_user",
"description": "",
"metadata": null,
"subitems": {
"6ba69fcb-0793-4798-9466-34e189445d8f": {
"subitem_id": "6ba69fcb-0793-4798-9466-34e189445d8f",
"amount": 500,
"currency": "USD",
"display_amount": "USD 5.00",
"reference_type": "invoicing.invoice_line_item_v2.line_item_id",
"reference_id": "ac43aed7-b2ae-4e76-990d-25aea6832489",
"subitem_type": "user_recipient",
"description": "",
"metadata": null,
"source_account_id": "793fab8e-6da5-4b26-b7f9-aab9cf809f91",
"source_payment_method_id": "950606a3-3b89-4589-9b53-f7d39a5f96ce",
"source_wallet_id": "26ac23a6-7457-48f4-9e97-faee2ce37664",
"destination_account_id": "7f938c50-0225-4fbe-b465-81d70934064a",
"destination_payment_method_id": "fce464b4-cf9f-49c2-bdb1-2db3275d6284",
"destination_wallet_id": "a900281d-5d01-4784-a412-f447389929f8"
}
}
}
},
"subitems": {
"6ba69fcb-0793-4798-9466-34e189445d8f": {
"subitem_id": "6ba69fcb-0793-4798-9466-34e189445d8f",
"amount": 500,
"currency": "USD",
"display_amount": "USD 5.00",
"reference_type": "invoicing.invoice_line_item_v2.line_item_id",
"reference_id": "ac43aed7-b2ae-4e76-990d-25aea6832489",
"subitem_type": "user_recipient",
"description": "",
"metadata": null,
"source_account_id": "793fab8e-6da5-4b26-b7f9-aab9cf809f91",
"source_payment_method_id": "950606a3-3b89-4589-9b53-f7d39a5f96ce",
"source_wallet_id": "26ac23a6-7457-48f4-9e97-faee2ce37664",
"destination_account_id": "7f938c50-0225-4fbe-b465-81d70934064a",
"destination_payment_method_id": "fce464b4-cf9f-49c2-bdb1-2db3275d6284",
"destination_wallet_id": "a900281d-5d01-4784-a412-f447389929f8"
}
}
}
}
Step 5: Post the invoice for processing
In the previous step, we created the invoice. Next, it needs to be submitted for processing and payment.
To submit the invoice for processing, POST the invoice_id
to the /pay
endpoint.
curl --location --request POST https://invoicing.tilia-inc.com/v2/invoice/{invoice_id}/pay \
--header 'Authorization: Bearer <Access_Token>' \
--header 'Content-Type: application/json' \
Pay invoice sample response
A successful request returns the HTTP 200 OK
status code along with a JSON response body containing the invoice details. Note that the value for state
has updated from open
to processing
.
View Response
{
"status": "Success",
"message": [],
"codes": [],
"payload": {
"invoice_id": "7f31235d-93da-4f1f-80dd-8db34cc1cc6e",
"account_id": "793fab8e-6da5-4b26-b7f9-aab9cf809f91",
"reference_type": "product_purchase_id",
"reference_id": "purchase_id123",
"state": "processing",
"description": "A description of the product",
"metadata": null,
"summary": {
"total_amount": 500,
"currency": "USD",
"display_amount": "USD 5.00"
},
"created": "2020-05-11T15:54:12Z",
"updated": "2020-05-11T15:54:12Z",
"payment_methods": {},
"line_items": {
"ac43aed7-b2ae-4e76-990d-25aea6832489": {
"line_item_id": "ac43aed7-b2ae-4e76-990d-25aea6832489",
"product_sku": "12345",
"amount": 500,
"currency": "USD",
"display_amount": "USD 5.00",
"reference_type": "seller_listing_id",
"reference_id": "listing123",
"transaction_type": "user_to_user",
"description": "",
"metadata": null,
"subitems": {
"6ba69fcb-0793-4798-9466-34e189445d8f": {
"subitem_id": "6ba69fcb-0793-4798-9466-34e189445d8f",
"amount": 500,
"currency": "USD",
"display_amount": "USD 5.00",
"reference_type": "invoicing.invoice_line_item_v2.line_item_id",
"reference_id": "ac43aed7-b2ae-4e76-990d-25aea6832489",
"subitem_type": "user_recipient",
"description": "",
"metadata": null,
"source_account_id": "793fab8e-6da5-4b26-b7f9-aab9cf809f91",
"source_payment_method_id": "950606a3-3b89-4589-9b53-f7d39a5f96ce",
"source_wallet_id": "26ac23a6-7457-48f4-9e97-faee2ce37664",
"destination_account_id": "09c9e3ee-8af5-4206-aaa4-1a913ea855d2",
"destination_payment_method_id": "76691843-ac5c-4b4b-a5c6-7fd3a558f23f",
"destination_wallet_id": "5d3d5e51-e622-4d0f-a3c2-e6dc99e3c487"
}
}
}
},
"subitems": {
"6ba69fcb-0793-4798-9466-34e189445d8f": {
"subitem_id": "6ba69fcb-0793-4798-9466-34e189445d8f",
"amount": 500,
"currency": "USD",
"display_amount": "USD 5.00",
"reference_type": "invoicing.invoice_line_item_v2.line_item_id",
"reference_id": "ac43aed7-b2ae-4e76-990d-25aea6832489",
"subitem_type": "user_recipient",
"description": "",
"metadata": null,
"source_account_id": "793fab8e-6da5-4b26-b7f9-aab9cf809f91",
"source_payment_method_id": "950606a3-3b89-4589-9b53-f7d39a5f96ce",
"source_wallet_id": "26ac23a6-7457-48f4-9e97-faee2ce37664",
"destination_account_id": "09c9e3ee-8af5-4206-aaa4-1a913ea855d2",
"destination_payment_method_id": "76691843-ac5c-4b4b-a5c6-7fd3a558f23f",
"destination_wallet_id": "5d3d5e51-e622-4d0f-a3c2-e6dc99e3c487"
}
}
}
}
The value for state
will be processing
until the invoice is processed, at which time the state will update to either:
-
success
, indicating the invoice has been successfully paid. -
failed
, indicating the invoice could not be paid. In this case, thefailure_reason
field returns additional information describing the failure.
You can check the status of an invoice by calling GET https://invoicing.tilia-inc.com/v2/invoice/{invoice_id}
.
Step 6: Handle the completion event
Although this step is not mandatory, we recommend implementing a webhook to notify you about changes to the transaction's status.
The webhook request body will be the same as the response body from create or pay invoice, but with a state of success
or failed
. See the Invoice Completion webhook documentation for complete details.
For more information about developing and registering webhook handlers, visit Webhooks.