Embedded Checkout
Drop-In
A modal overlay that appears when the customer clicks the pay button. The payment form appears centered on the screen with a backdrop overlay.
Live Demo
See the Drop-In modal in action at embedcheckout.payonify.com.
Complete Integration
HTML Structure
Code<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Checkout - Drop-In Modal</title> <link rel="stylesheet" href="styles.css"> </head> <body> <!-- Your product/cart content --> <div class="product-page"> <h1>Premium Subscription</h1> <p class="price">$15.00</p> <button id="pay-button" class="pay-btn">Pay Now</button> </div> <!-- Modal overlay --> <div id="checkout-modal" class="modal-overlay hidden"> <div class="modal-backdrop"></div> <div class="modal-content"> <button id="close-modal" class="close-btn">×</button> <div id="checkout-container"></div> </div> </div> <script src="https://js.payonify.com/payonify.umd.js"></script> <script src="checkout.js"></script> </body> </html>
CSS Styles
Code/* Modal overlay - covers entire screen */ .modal-overlay { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; } .modal-overlay.hidden { display: none; } /* Semi-transparent backdrop */ .modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); } /* Modal content container */ .modal-content { position: relative; background: white; border-radius: 16px; padding: 2rem; max-width: 450px; width: 90%; max-height: 90vh; overflow-y: auto; box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25); animation: modal-appear 0.3s ease-out; } @keyframes modal-appear { from { opacity: 0; transform: scale(0.95) translateY(10px); } to { opacity: 1; transform: scale(1) translateY(0); } } /* Close button */ .close-btn { position: absolute; top: 1rem; right: 1rem; background: none; border: none; font-size: 1.5rem; color: #6b7280; cursor: pointer; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background 0.2s; } .close-btn:hover { background: #f3f4f6; color: #1f2937; } /* Checkout container */ #checkout-container { min-height: 300px; }
JavaScript
Production Note
Remove all console.log and console.error statements before deploying to production.
Code// Configuration const PUBLISHABLE_KEY = 'pk_test_abc123...'; // Your publishable key // DOM elements const payButton = document.getElementById('pay-button'); const modal = document.getElementById('checkout-modal'); const closeButton = document.getElementById('close-modal'); const backdrop = document.querySelector('.modal-backdrop'); const container = document.getElementById('checkout-container'); let payonify = null; // Initialize Payonify SDK function initPayonify() { payonify = new Payonify({ publishableKey: PUBLISHABLE_KEY }); // Event handlers payonify.onSuccess = (data) => { console.log('Payment successful!', data); // Remove in production closeModal(); window.location.href = '/success?session_id=' + data.session_id; }; payonify.onError = (error) => { console.error('Payment error:', error); // Remove in production alert('Payment failed: ' + error.message); }; payonify.onClose = () => { console.log('Payment form closed'); // Remove in production }; } // Create checkout session (call your backend) async function createCheckoutSession() { const response = await fetch('/api/create-checkout-session', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ line_items: [ { unit_amount: 1500, name: 'Premium Subscription', quantity: 1 } ], currency: 'usd' }) }); if (!response.ok) { throw new Error('Failed to create checkout session'); } return response.json(); } // Open modal and mount payment form async function openModal() { modal.classList.remove('hidden'); container.innerHTML = '<div class="loading"><p>Loading...</p></div>'; try { const session = await createCheckoutSession(); container.innerHTML = ''; payonify.mount({ container: container, clientSecret: session.client_secret }); } catch (error) { console.error('Error:', error); // Remove in production container.innerHTML = '<p style="color: red;">Failed to load. Please try again.</p>'; } } // Close modal and cleanup function closeModal() { modal.classList.add('hidden'); if (payonify) { payonify.unmount(); } } // Event listeners payButton.addEventListener('click', openModal); closeButton.addEventListener('click', closeModal); backdrop.addEventListener('click', closeModal); document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !modal.classList.contains('hidden')) { closeModal(); } }); // Initialize on page load initPayonify();
Backend API Example
Code
const express = require('express');
const app = express();
app.use(express.json());
app.post('/api/create-checkout-session', async (req, res) => {
const response = await fetch('https://api.payonify.com/v1/checkout/sessions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic ' + Buffer.from(process.env.PAYONIFY_PUBLISHABLE_KEY + ':' + process.env.PAYONIFY_SECRET_KEY).toString('base64')
},
body: JSON.stringify({
line_items: req.body.line_items,
mode: 'payment',
currency: 'usd',
success_url: 'https://yoursite.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'https://yoursite.com/cancel'
})
});
const session = await response.json();
res.json({ client_secret: session.client_secret });
});
app.listen(3000);Next Steps
- Sidebar Integration - Payment form next to your product
- Slide-In Integration - Slide-in panel from the right
- Webhooks Guide - Handle payment events server-side
Last modified on