React Integration - Basic Setup
Learn how to integrate Bloque Payments into your React application using the BloqueCheckout component.
Installation
Install the React components package:
npm install @bloque/payments-react
# or
yarn add @bloque/payments-react
# or
pnpm add @bloque/payments-react
# or
bun add @bloque/payments-react
SDK Initialization
Before using the BloqueCheckout component, you need to initialize the SDK with your Public API Key:
import { init } from '@bloque/payments-react';
// Initialize once at the start of your application (e.g., in main.tsx or App.tsx)
init({
publicApiKey: 'pk_live_...',
mode: 'sandbox', // or 'production'
});
Public API Key
Use your Public API Key to initialize the SDK in the frontend. This key is safe to expose in client-side code. Your Secret API Key should only be used on the backend.
Basic Component Usage
The simplest way to add payments to your React app. The component processes payments directly with the Bloque API:
import { init, BloqueCheckout } from '@bloque/payments-react';
// Initialize once at the start of your application
init({
publicApiKey: 'pk_live_...',
mode: 'production',
});
function CheckoutPage() {
return (
<BloqueCheckout
config={{
payment_methods: ['card', 'pse', 'cash'],
amount: 2999,
currency: 'USD',
}}
onSuccess={(response) => {
console.log('Payment successful!', response.id);
window.location.href = '/success';
}}
onError={(error) => {
console.error('Payment failed:', error.message);
alert(`Payment failed: ${error.message}`);
}}
/>
);
}
export default CheckoutPage;
Usage with Custom Backend
If you prefer to process payments through your own backend, use the onSubmit prop:
import { BloqueCheckout } from '@bloque/payments-react';
function CheckoutPage() {
const handleSubmit = async (payload) => {
const response = await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error('Payment failed');
}
return response.json();
};
return (
<BloqueCheckout
config={{
payment_methods: ['card', 'pse', 'cash'],
amount: 2999,
currency: 'USD',
}}
onSubmit={handleSubmit}
onSuccess={(response) => {
console.log('Payment successful!', response.id);
window.location.href = '/success';
}}
onError={(error) => {
console.error('Payment failed:', error.message);
alert(`Payment failed: ${error.message}`);
}}
/>
);
}
export default CheckoutPage;
Component Props
Optional Props
onSubmit
Function called when the user submits the payment form. If not provided, the component processes the payment directly with the Bloque API.
onSubmit?: (payload: PaymentSubmitPayload) => Promise<PaymentResponse | undefined>;
Example:
const handleSubmit = async (payload) => {
const response = await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error('Payment failed');
}
return response.json();
};
<BloqueCheckout onSubmit={handleSubmit} />
Optional Props
config
Configuration object for the checkout experience:
interface CheckoutConfig {
payment_methods?: PaymentMethodType[]; // ['card', 'pse', 'cash']
amount?: number; // Amount in smallest currency unit
currency?: string; // Currency code (e.g., 'USD')
labels?: CheckoutLabels; // Custom text labels
}
Example:
<BloqueCheckout
config={{
payment_methods: ['card', 'pse'],
amount: 2999,
currency: 'USD',
}}
onSubmit={handleSubmit}
/>
config.labels
Customize the payment form text labels:
interface CheckoutLabels {
card?: CardFormLabels;
pse?: PSEFormLabels;
cash?: CashFormLabels;
}
interface CardFormLabels {
cardNumber?: string;
cardNumberPlaceholder?: string;
cardholderName?: string;
cardholderNamePlaceholder?: string;
expiryDate?: string;
expiryDatePlaceholder?: string;
cvv?: string;
cvvPlaceholder?: string;
email?: string;
emailPlaceholder?: string;
submitButton?: string;
}
Example with custom labels:
<BloqueCheckout
config={{
payment_methods: ['card', 'pse'],
amount: 4999,
currency: 'USD',
labels: {
card: {
cardNumber: 'Card Number',
cardNumberPlaceholder: '1234 5678 9012 3456',
cardholderName: 'Cardholder Name',
cardholderNamePlaceholder: 'JOHN DOE',
expiryDate: 'Expiry Date',
expiryDatePlaceholder: 'MM/YY',
cvv: 'CVV',
cvvPlaceholder: '123',
email: 'Email',
emailPlaceholder: 'example@email.com',
submitButton: 'Pay $49.99',
},
},
}}
onSubmit={handleSubmit}
/>
appearance
Customize the visual appearance:
interface AppearanceConfig {
primaryColor?: string; // Brand color
borderRadius?: string; // Border radius for inputs
fontFamily?: string; // Font family
}
Example:
<BloqueCheckout
config={config}
appearance={{
primaryColor: '#10b981',
borderRadius: '12px',
fontFamily: 'Inter, system-ui, sans-serif',
}}
onSubmit={handleSubmit}
/>
amount
Alternative way to set the amount (instead of using config.amount):
<BloqueCheckout
amount={2999}
config={{
payment_methods: ['card'],
currency: 'USD',
}}
onSubmit={handleSubmit}
/>
availableMethods
Array of payment methods to show (alternative to config.payment_methods):
<BloqueCheckout
availableMethods={['card', 'pse']}
onSubmit={handleSubmit}
/>
requireEmail
Whether email is required for card payments (default: true):
<BloqueCheckout
requireEmail={true}
config={{ payment_methods: ['card'] }}
onSubmit={handleSubmit}
/>
showMethodSelector
Show/hide the payment method selector (default: true):
<BloqueCheckout
showMethodSelector={true}
config={{ payment_methods: ['card', 'pse'] }}
onSubmit={handleSubmit}
/>
onSuccess
Callback fired when payment succeeds:
<BloqueCheckout
config={config}
onSubmit={handleSubmit}
onSuccess={(response) => {
console.log('Payment successful!');
console.log('Payment ID:', response.id);
console.log('Status:', response.status);
window.location.href = '/success';
}}
/>
onError
Callback fired when payment fails:
<BloqueCheckout
config={config}
onSubmit={handleSubmit}
onError={(error) => {
console.error('Payment failed:', error.message);
alert(`Payment failed: ${error.message}`);
}}
/>
className and style
Standard React props for styling:
<BloqueCheckout
config={config}
onSubmit={handleSubmit}
className="my-checkout"
style={{ maxWidth: '600px', margin: '0 auto' }}
/>
Complete Example
Here's a complete example with all common options:
import { BloqueCheckout } from '@bloque/payments-react';
import type {
CheckoutConfig,
AppearanceConfig,
PaymentResponse,
} from '@bloque/payments-react';
function CheckoutPage() {
// Configuration
const config: CheckoutConfig = {
payment_methods: ['card', 'pse', 'cash'],
amount: 2999,
currency: 'USD',
};
// Appearance
const appearance: AppearanceConfig = {
primaryColor: '#10b981',
borderRadius: '12px',
fontFamily: 'Inter, system-ui, sans-serif',
};
// Submit handler
const handleSubmit = async (payload) => {
try {
const response = await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Payment failed');
}
return response.json();
} catch (error) {
console.error('Payment error:', error);
throw error;
}
};
// Success handler
const handleSuccess = (response: PaymentResponse) => {
console.log('Payment successful!');
console.log('Payment ID:', response.id);
console.log('Status:', response.status);
window.location.href = `/success?payment=${response.id}`;
};
// Error handler
const handleError = (error: { message: string }) => {
console.error('Payment failed:', error.message);
alert(`Payment failed: ${error.message}`);
};
return (
<div className="checkout-container">
<h1>Checkout</h1>
<BloqueCheckout
config={config}
appearance={appearance}
onSubmit={handleSubmit}
onSuccess={handleSuccess}
onError={handleError}
className="checkout-form"
style={{ maxWidth: '600px' }}
/>
</div>
);
}
export default CheckoutPage;
TypeScript Support
The package includes full TypeScript definitions:
import type {
BloqueCheckoutProps,
CheckoutConfig,
AppearanceConfig,
PaymentResponse,
PaymentSubmitPayload,
PaymentMethodType,
} from '@bloque/payments-react';
// Type-safe configuration
const config: CheckoutConfig = {
payment_methods: ['card', 'pse'],
amount: 2999,
currency: 'USD',
};
// Type-safe handlers
const handleSuccess = (response: PaymentResponse) => {
console.log('Payment ID:', response.id);
};
Framework-Specific Examples
Next.js App Router
'use client';
import { BloqueCheckout } from '@bloque/payments-react';
export default function CheckoutPage() {
const handleSubmit = async (payload) => {
const response = await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
return response.json();
};
return (
<BloqueCheckout
config={{
payment_methods: ['card', 'pse'],
amount: 2999,
currency: 'USD',
}}
onSubmit={handleSubmit}
/>
);
}
Next.js Pages Router
import { BloqueCheckout } from '@bloque/payments-react';
export default function Checkout() {
const handleSubmit = async (payload) => {
const response = await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
return response.json();
};
return (
<BloqueCheckout
config={{
payment_methods: ['card'],
amount: 2999,
currency: 'USD',
}}
onSubmit={handleSubmit}
/>
);
}
Vite + React
import { BloqueCheckout } from '@bloque/payments-react';
function App() {
const handleSubmit = async (payload) => {
const response = await fetch('http://localhost:3000/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
return response.json();
};
return (
<BloqueCheckout
config={{
payment_methods: ['card', 'pse', 'cash'],
amount: 2999,
currency: 'USD',
}}
onSubmit={handleSubmit}
/>
);
}
export default App;
Next Steps