Furlpay Docs
Open App

Integrations

Stripe Crypto & Stablecoin

Accept stablecoin payments (settling as fiat USD) and pay out merchant balances using Stripe Crypto — powered by the Bridge stablecoin orchestration infrastructure. In Furlpay this is wired through lib/payments/stripe.ts and two API routes.

1. Stablecoin checkout (PaymentIntents)

Create a PaymentIntent on the server. With dynamic payment methods, enable Crypto under Dashboard → Payments → Payment methods; Stripe then handles network selection (Ethereum, Base, Solana, Polygon) and asset support (USDC, USDP) behind the scenes.

typescript
// lib/payments/stripe.ts (server)
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function createCryptoPaymentIntent(amountInCents: number) {
  const paymentIntent = await stripe.paymentIntents.create({
    amount: amountInCents,
    currency: 'usd',
    automatic_payment_methods: { enabled: true }, // card + crypto
    metadata: { integration: 'furlpay_connect_stablecoin' },
  });
  return { clientSecret: paymentIntent.client_secret };
}

Furlpay exposes this at POST /api/payments/stripe/intent, which returns the client secret consumed by Stripe Elements.

Render Stripe Elements (frontend)

Elements renders the wallet connection interface (Phantom, MetaMask, Coinbase Wallet) and handles signing via crypto.stripe.com. See components/StripeCryptoCheckout.tsx.

tsx
'use client';
import { loadStripe } from '@stripe/stripe-js';
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);

function CheckoutForm() {
  const stripe = useStripe();
  const elements = useElements();
  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!stripe || !elements) return;
    const { error } = await stripe.confirmPayment({
      elements,
      confirmParams: { return_url: 'https://furlpay.app/dashboard' },
    });
    if (error) console.error(error.message);
  };
  return (
    <form onSubmit={onSubmit}>
      <PaymentElement />
      <button disabled={!stripe}>Pay with Stablecoin</button>
    </form>
  );
}

2. B2B payouts & transfers

Send stablecoins to external vendor wallets or pay out merchant balances via the Transfers API.

typescript
export async function transferToMerchantWallet(destination: string, amount: number) {
  return stripe.transfers.create({
    amount,               // amount in cents
    currency: 'usd',
    destination,
    description: 'Furlpay stablecoin settlement payout via Bridge rails',
  });
}

3. Security best practices

Cryptographic webhook verification

Never trust events over HTTP without verifying the signature. Stripe signs webhooks with HMAC-SHA256; constructEvent validates the stripe-signature header against your endpoint secret and rejects tampered or replayed payloads.

typescript
// app/api/webhooks/stripe/route.ts
export async function POST(request: Request) {
  const payload = await request.text();          // raw body is required
  const sig = request.headers.get('stripe-signature')!;
  try {
    const event = stripe.webhooks.constructEvent(payload, sig, endpointSecret);
    if (event.type === 'payment_intent.succeeded') {
      // credit the Furlpay Safe balance / trigger local bank routing
    }
    return Response.json({ received: true });
  } catch (err) {
    return Response.json({ error: 'Signature verification failed' }, { status: 400 });
  }
}

Tokenized compliance (PCI / KYC offloading)

  • Zero card custody: with Elements, your servers never touch card details or wallet private keys — keeping Furlpay in the lowest PCI bracket (SAQ-A).
  • Travel Rule: for transactions over $1,000, Stripe/Bridge injects sender/receiver identity metadata to satisfy global AML requirements.

Network failover & slippage

  • If an Ethereum transaction fails on a gas spike, dynamic routing falls back to high-speed L2s (Base or Solana).
  • Slippage limits are set to <0.1% during stablecoin-to-fiat conversion to protect margins.

Idempotency

Stripe delivers events at least once. Furlpay dedupes by event.id so a redeliveredpayment_intent.succeeded never double-credits a balance.