Payment intents

Learn how to collect immediate payments using Pluto.

Payment intent lifecycle

All payment intents start as requires_confirmation. They can be updated to succeeded, failed, or canceled.

  • requires_confirmation: Pluto is waiting for a transaction associated with the payment intent to be finalized on-chain.
  • succeeded: The payment intent has succeeded and the transaction has been finalized on-chain.
  • failed: The payment intent has failed. Payment failures can result from events such as on-chain transaction failures or malicious payment attempts.
  • canceled: The payment intent has been canceled.
247

In this diagram, a payment intent is created via the Pluto API. Once the payment intent is retrieved on the frontend, the user is prompted to confirm the transaction from their wallet. The transaction is sent to Pluto's smart contract, which splits the payment among the specified wallets.

Typically, the payment will be split between two wallets: your account's payout wallet and Pluto's payout wallet (used for collecting a transaction fee). However, payments can be split between an unlimited number of wallets. This can be useful for an online marketplace, for example. Whenever a product is sold, the revenue is split between the merchant and the marketplace. Pluto's multiparty payments features allow you to easily build this functionality.

Finally, Pluto listens for the transaction to be finalized on-chain. After performing validation, it either fails or succeeds the payment intent. Additionally, Pluto handles transactions that are dropped and replaced.

You can execute logic determined by the outcome of the payment intent by setting up a webhook and listening for the payment_intent.succeeded and payment_intent.failed events.

Create a payment intent

Creating a payment intent can be done by passing any of the following combinations:

  • An invoice
  • A price and customer
  • An amount, currency, chain, and customer

If you pass an invoice, Pluto can determine the rest of the relevant information from the invoice, such as the amount to charge. This can be useful in integrations such as a custom invoice payment page.

const { Pluto } = require('@plutohq/pluto-node');
const pluto = new Pluto(process.env.PLUTO_SECRET_KEY);

await pluto.paymentIntents.create({ invoice: '{{INVOICE_ID}}' });

Passing a price allows you to easily create payment intents with the same amount. Additionally, this allows you to charge the same fiat amount (e.g. $30 in ETH) if the price has a base_price property.

📘

Payment intents with adjustable pricing

If you use an adjustable price, you will need to specify an amount when creating the payment intent.

const { Pluto } = require('@plutohq/pluto-node');
const pluto = new Pluto(process.env.PLUTO_SECRET_KEY);

await pluto.paymentIntents.create({
  price: '{{PRICE_ID}}',
  customer: '{{CUSTOMER_ID}}',
});

You can also specify an amount manually when creating a payment intent.

const { Pluto } = require('@plutohq/pluto-node');
const pluto = new Pluto(process.env.PLUTO_SECRET_KEY);

const paymentIntent = await pluto.paymentIntents.create({
  amount: 0.5,
  currency: 'eth',
  chain: 'eth',
  customer: '{{CUSTOMER_ID}}',
});

Add line items to a payment intent

If line items are added, the total amount to be charged will be calculated by summing each line item and an amount, if it exists. This can be useful for separating a base charge for an item from an initial fee. You can add as many line items as needed.

const { Pluto } = require('@plutohq/pluto-node');
const pluto = new Pluto(process.env.PLUTO_SECRET_KEY);

await pluto.paymentIntents.create({
  price: '{{PRICE_ID}}',
  customer: '{{CUSTOMER_ID}}',
  line_items: [
    { price_data: { amount: 0.25 } },
  ],
});

Pay a payment intent

Use one of our client-side libraries to pay a payment intent. This will prompt the user to confirm the transaction from their wallet.

const transaction = await plutoJS.confirmPayment('{{PAYMENT_INTENT_ID}}');

Cancel a payment intent

Payment intents can be canceled at any time. However, if a payment intent has an associated transaction processing on-chain, cancelling the payment intent will not automatically refund the transaction.

const { Pluto } = require('@plutohq/pluto-node');
const pluto = new Pluto(process.env.PLUTO_SECRET_KEY);

await pluto.paymentIntents.cancel('{{PAYMENT_INTENT_ID}}');