Skip to content

Stripe Integration

Bridge Payments provides seamless integration with Stripe, the world's leading payment processing platform.

Overview

Stripe integration supports:

  • Payment Intents - One-time payments with 3D Secure support
  • Payment Methods - Tokenized card storage (PCI compliant)
  • Subscriptions - Recurring billing with trials
  • Payment Elements - Modern, customizable payment UI
  • Webhooks - Real-time event notifications
  • 3D Secure - Strong Customer Authentication (SCA)
  • Apple Pay & Google Pay - Digital wallet support
  • Multi-Currency - 135+ currencies supported

Configuration

1. Get Stripe API Keys

  1. Sign up at stripe.com
  2. Navigate to DevelopersAPI Keys
  3. Copy your Publishable Key and Secret Key

2. Configure Bridge Payments

In your Bridge Payments instance (Pubflow dashboard):

bash
# Stripe API Keys
STRIPE_SECRET_KEY=sk_test_... # or sk_live_... for production
STRIPE_PUBLISHABLE_KEY=pk_test_... # or pk_live_... for production

# Webhook Secret (optional, for webhook verification)
STRIPE_WEBHOOK_SECRET=whsec_...

3. Configure Webhooks

Set up webhook endpoint in Stripe dashboard:

Webhook URL:

https://your-instance.pubflow.com/bridge-payment/webhooks/stripe

Events to Subscribe:

  • payment_intent.succeeded
  • payment_intent.failed
  • payment_intent.canceled
  • payment_method.attached
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.payment_succeeded
  • invoice.payment_failed

Payment Flows

One-Time Payment

Step 1: Create Payment Intent

bash
curl -X POST "https://your-instance.pubflow.com/bridge-payment/payments/intents" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: session_abc123" \
  -d '{
    "total_cents": 2000,
    "currency": "USD",
    "provider_id": "stripe",
    "concept": "Premium Plan"
  }'

Response:

json
{
  "id": "pay_123",
  "client_secret": "pi_123_secret_abc",
  "status": "requires_confirmation",
  "total_cents": 2000,
  "currency": "USD"
}

Step 2: Confirm Payment (Frontend)

javascript
import { loadStripe } from '@stripe/stripe-js';

const stripe = await loadStripe('pk_test_...');

const { error, paymentIntent } = await stripe.confirmCardPayment(
  clientSecret,
  {
    payment_method: {
      card: cardElement,
      billing_details: {
        name: 'John Doe',
        email: '[email protected]'
      }
    }
  }
);

if (error) {
  console.error('Payment failed:', error.message);
} else if (paymentIntent.status === 'succeeded') {
  console.log('Payment successful!');
}

Step 3: Sync Status (Backend)

bash
curl -X POST "https://your-instance.pubflow.com/bridge-payment/payments/intents/pay_123/sync" \
  -H "X-Session-ID: session_abc123"

Payment with Saved Method

Step 1: Create Payment Method

bash
curl -X POST "https://your-instance.pubflow.com/bridge-payment/payment-methods" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: session_abc123" \
  -d '{
    "provider_id": "stripe",
    "provider_payment_method_token": "pm_1234567890",
    "alias": "My Visa Card"
  }'

Step 2: Create Payment with Method

bash
curl -X POST "https://your-instance.pubflow.com/bridge-payment/payments/intents" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: session_abc123" \
  -d '{
    "total_cents": 2000,
    "currency": "USD",
    "provider_id": "stripe",
    "payment_method_id": "pm_123",
    "concept": "Monthly Subscription"
  }'

Step 3: Confirm Payment

bash
curl -X POST "https://your-instance.pubflow.com/bridge-payment/payments/intents/pay_123/confirm" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: session_abc123" \
  -d '{
    "payment_method_id": "pm_123"
  }'

Subscription

bash
curl -X POST "https://your-instance.pubflow.com/bridge-payment/subscriptions" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: session_abc123" \
  -d '{
    "customer_id": "cust_123",
    "payment_method_id": "pm_123",
    "provider_id": "stripe",
    "total_cents": 2000,
    "currency": "USD",
    "billing_interval": "monthly",
    "trial_days": 14,
    "concept": "Premium Monthly Plan"
  }'

Frontend Integration

React with Stripe Elements

jsx
import { useState, useEffect } from 'react';
import { loadStripe } from '@stripe/stripe-js';
import {
  Elements,
  PaymentElement,
  useStripe,
  useElements
} from '@stripe/react-stripe-js';

const stripePromise = loadStripe('pk_test_...');

function CheckoutForm({ paymentIntentId }) {
  const stripe = useStripe();
  const elements = useElements();
  const [error, setError] = useState(null);
  const [processing, setProcessing] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    if (!stripe || !elements) return;

    setProcessing(true);

    const { error, paymentIntent } = await stripe.confirmPayment({
      elements,
      confirmParams: {
        return_url: `${window.location.origin}/success`
      },
      redirect: 'if_required'
    });

    if (error) {
      setError(error.message);
      setProcessing(false);
    } else if (paymentIntent.status === 'succeeded') {
      // Sync with backend
      await fetch(`/bridge-payment/payments/intents/${paymentIntentId}/sync`, {
        method: 'POST',
        headers: {
          'X-Session-ID': sessionId
        }
      });
      
      // Redirect to success page
      window.location.href = '/success';
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      {error && <div className="error">{error}</div>}
      <button disabled={!stripe || processing}>
        {processing ? 'Processing...' : 'Pay Now'}
      </button>
    </form>
  );
}

function PaymentPage({ amount }) {
  const [clientSecret, setClientSecret] = useState('');
  const [paymentIntentId, setPaymentIntentId] = useState('');

  useEffect(() => {
    // Create payment intent
    fetch('/bridge-payment/payments/intents', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Session-ID': sessionId
      },
      body: JSON.stringify({
        total_cents: amount,
        currency: 'USD',
        provider_id: 'stripe'
      })
    })
      .then(res => res.json())
      .then(data => {
        setClientSecret(data.client_secret);
        setPaymentIntentId(data.id);
      });
  }, [amount]);

  return (
    <div>
      {clientSecret && (
        <Elements stripe={stripePromise} options={{ clientSecret }}>
          <CheckoutForm paymentIntentId={paymentIntentId} />
        </Elements>
      )}
    </div>
  );
}

export default PaymentPage;

React Native with Stripe

jsx
import { useStripe } from '@stripe/stripe-react-native';

function PaymentScreen() {
  const { confirmPayment } = useStripe();
  const [loading, setLoading] = useState(false);

  const handlePayment = async () => {
    setLoading(true);

    // Create payment intent
    const response = await fetch(
      'https://your-instance.pubflow.com/bridge-payment/payments/intents',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Session-ID': sessionId
        },
        body: JSON.stringify({
          total_cents: 2000,
          currency: 'USD',
          provider_id': 'stripe'
        })
      }
    );

    const { client_secret, id } = await response.json();

    // Confirm payment
    const { error, paymentIntent } = await confirmPayment(client_secret, {
      paymentMethodType: 'Card'
    });

    if (error) {
      Alert.alert('Error', error.message);
    } else if (paymentIntent.status === 'Succeeded') {
      // Sync with backend
      await fetch(
        `https://your-instance.pubflow.com/bridge-payment/payments/intents/${id}/sync`,
        {
          method: 'POST',
          headers: { 'X-Session-ID': sessionId }
        }
      );
      
      Alert.alert('Success', 'Payment completed!');
    }

    setLoading(false);
  };

  return (
    <View>
      <Button
        title={loading ? 'Processing...' : 'Pay $20.00'}
        onPress={handlePayment}
        disabled={loading}
      />
    </View>
  );
}

Features

3D Secure (SCA)

Stripe automatically handles 3D Secure authentication:

javascript
const { error, paymentIntent } = await stripe.confirmCardPayment(clientSecret);

if (error) {
  // Handle error
} else if (paymentIntent.status === 'requires_action') {
  // Stripe will automatically show 3D Secure modal
  const { error: actionError } = await stripe.handleCardAction(clientSecret);
  
  if (!actionError) {
    // Authentication successful
  }
}

Apple Pay & Google Pay

Enable digital wallets in Payment Element:

javascript
const elements = stripe.elements({
  clientSecret,
  appearance: { theme: 'stripe' }
});

const paymentElement = elements.create('payment', {
  wallets: {
    applePay: 'auto',
    googlePay: 'auto'
  }
});

Multi-Currency

Stripe supports 135+ currencies:

bash
curl -X POST "/bridge-payment/payments/intents" \
  -d '{
    "total_cents": 2000,
    "currency": "EUR",  # or GBP, JPY, CAD, etc.
    "provider_id": "stripe"
  }'

Testing

Test Cards

Card NumberDescription
4242424242424242Successful payment
4000002500003155Requires 3D Secure
4000000000009995Declined (insufficient funds)
4000000000000002Declined (generic)

Expiration: Any future date (e.g., 12/25)
CVC: Any 3 digits (e.g., 123)

Test Mode

Use test API keys for development:

bash
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...

Best Practices

  1. Use Payment Elements - Modern, customizable UI
  2. Enable Webhooks - Handle async events reliably
  3. Verify Signatures - Validate webhook authenticity
  4. Handle 3D Secure - Support SCA requirements
  5. Test Thoroughly - Use test cards before going live
  6. Monitor Dashboard - Track payments and disputes

Next Steps