Solutions/Website payments

Website payments

Accept Bitcoin payments in your checkout, sell digital products, or let visitors pay for individual pieces of content. Your Phoenixd node handles Lightning invoices and payments; your application connects those payments to orders and access.

Build the checkout flow

  1. Create an order in your backend and calculate its price in satoshis.
  2. Request an invoice from your node, attaching an order reference with externalId.
  3. Save the invoice's payment hash against the order. Return the invoice to the browser so the customer can copy it or scan a QR code.
  4. Confirm payment on your backend before fulfilling the order or unlocking content.

Keep the node URL and password in your server configuration. The browser needs the invoice and order status, rather than direct access to the node.

Create an invoice

This server-side example creates an invoice for 1,000 sats with a ten-minute expiry. Set PHOENIXD_URL to your node's HTTPS endpoint and PHOENIXD_PASSWORD to the appropriate API password.

curl --fail-with-body "$PHOENIXD_URL/createinvoice" \
  --user ":$PHOENIXD_PASSWORD" \
  --data-urlencode "description=Order 1042" \
  --data-urlencode "amountSat=1000" \
  --data-urlencode "externalId=order-1042" \
  --data-urlencode "expirySeconds=600"

Persist the returned paymentHash and show the serialized invoice to the customer. Generate a unique reference for each checkout attempt so a replacement invoice can still be traced back to its order.

If you price in another currency, calculate the sats amount on your server and give the quote an expiry. Display that amount and expiry alongside the invoice.

Confirm and fulfil

Use authenticated payment notifications or query the node's incoming payment API to determine whether the invoice has been paid. Check the payment hash and amount against the saved order. A browser redirect or a customer's claim that they paid is insufficient confirmation.

Treat notifications as repeatable: update the order and record fulfilment atomically, so processing the same payment twice cannot ship two products or grant duplicate credit. Let the browser poll your application's order-status endpoint while the checkout is open.

Handle interrupted checkouts

  • Let customers resume an unpaid checkout while its invoice remains valid.
  • Create a replacement invoice when the previous one expires, retaining both payment hashes in your records.
  • Reconcile payments independently of whether the customer still has the page open.
  • Implement refunds as a separate outbound payment workflow with its own approval and audit trail.

For charging software clients to access an endpoint, see Paid APIs (L402). Consult the Phoenixd HTTP API for invoice and payment endpoints.

On this page