Skip to main content
Version: v0.10.13

Payment Rails

PEAC receipts can carry payment evidence from any supported rail. Each rail adapter extracts settlement references from the payment processor and produces a standardized PaymentEvidence object that you attach to a receipt at issuance time.

Supported rails

RailPackageEvidence sourceStatus
x402 (Coinbase)@peac/rails-x402x402 payment headersStable
Stripe@peac/rails-stripePaymentIntent, CryptoPaymentIntentStable
Razorpay@peac/rails-razorpayUPI, cards, netbanking, walletsStable
Card networks@peac/rails-cardVisa, Mastercard, AmexStable

x402 (Coinbase)

The x402 adapter extracts payment evidence from Coinbase's HTTP 402 payment headers. It supports USDC and other stablecoins on Base, Ethereum, and other EVM chains.

Terminal
pnpm add @peac/rails-x402
x402-evidence.ts
import { fromX402Payment } from '@peac/rails-x402';

const evidence = fromX402Payment({
paymentHeader: req.headers['x-402-payment'],
amount: '0.001',
currency: 'USDC',
network: 'base',
});

Stripe

The Stripe adapter supports both traditional fiat payments via PaymentIntent and crypto payments via CryptoPaymentIntent.

Terminal
pnpm add @peac/rails-stripe

From PaymentIntent

Use fromStripePaymentIntent for standard card and bank-based Stripe payments.

stripe-fiat.ts
import { fromStripePaymentIntent } from '@peac/rails-stripe';

// Pass the Stripe PaymentIntent object directly
const evidence = fromStripePaymentIntent(paymentIntent);

From CryptoPaymentIntent

Use fromCryptoPaymentIntent for Stripe's crypto payment flow. Added in v0.10.11.

stripe-crypto.ts
import { fromCryptoPaymentIntent } from '@peac/rails-stripe';

// Pass the Stripe CryptoPaymentIntent object directly
const evidence = fromCryptoPaymentIntent(cryptoPaymentIntent);

Razorpay

The Razorpay adapter supports UPI, cards, netbanking, and wallet payments across the Indian payment ecosystem.

Terminal
pnpm add @peac/rails-razorpay
razorpay-evidence.ts
import { fromRazorpayPayment } from '@peac/rails-razorpay';

const evidence = fromRazorpayPayment({
paymentId: 'pay_abc123',
orderId: 'order_xyz789',
method: 'upi',
amount: 1000,
currency: 'INR',
});

Card networks

The card adapter works with raw authorization data from Visa, Mastercard, and Amex.

Terminal
pnpm add @peac/rails-card
card-evidence.ts
import { fromCardPayment } from '@peac/rails-card';

const evidence = fromCardPayment({
network: 'visa',
authorizationCode: 'AUTH123',
last4: '4242',
amount: 1999,
currency: 'USD',
});

PaymentEvidence interface

All rail adapters produce a standardized PaymentEvidence object. This is the common type that gets attached to a receipt regardless of which rail generated it.

PaymentEvidence
interface PaymentEvidence {
rail: string; // 'x402' | 'stripe' | 'razorpay' | 'card'
amount: string; // Amount as string (avoids floating-point)
currency: string; // ISO 4217 or token symbol (e.g., 'USD', 'USDC')
settlement_ref?: string; // Rail-specific settlement reference
evidence: Record<string, unknown>; // Rail-specific details
}

Attaching payment evidence to a receipt

Once you have a PaymentEvidence object from any rail adapter, attach it to a receipt during issuance.

issue-payment-receipt.ts
import { issueReceipt } from '@peac/protocol';
import { fromStripePaymentIntent } from '@peac/rails-stripe';

const paymentEvidence = fromStripePaymentIntent(paymentIntent);

const receipt = await issueReceipt({
privateKey: process.env.PEAC_PRIVATE_KEY,
kid: 'peac-2026-02',
claims: {
iss: 'https://api.example.com',
sub: 'user:customer-456',
peac: {
type: 'payment',
attestation_type: 'payment',
status: 'executed',
payment: paymentEvidence,
},
},
});
tip

The status field tracks the payment lifecycle. Use proposed for pending payments, executed for completed payments, and denied for rejected payments.