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 Developers → API 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 ​