Card payments

Accept credit and debit cards with secure, PCI-compliant input elements.

View as Markdown

PaymentKit.js renders card inputs inside isolated iframes, ensuring sensitive card data never touches your servers.

Setup

1<script src="https://unpkg.com/@payment-kit-js/vanilla/dist/cdn/paymentkit.min.js"></script>
2<script>
3 const paymentKit = PaymentKit.default({
4 environment: 'sandbox',
5 secureToken: 'aBcDeFgHiJkLmNoPqRsTuVwXyZ123456', // From your backend
6 paymentMethods: [PaymentKit.PaymentMethods.card]
7 });
8</script>

Create and mount card elements

1// Create elements
2const cardNumber = paymentKit.card.createElement('card_pan');
3const cardExpiry = paymentKit.card.createElement('card_exp');
4const cardCvc = paymentKit.card.createElement('card_cvc');
5
6// Mount to DOM containers
7cardNumber.mount('#card-number');
8cardExpiry.mount('#card-expiry');
9cardCvc.mount('#card-cvc');
ElementTypeDescription
Card numbercard_panCard number (13-19 digits)
Expirationcard_expMM / YY expiration date
Security codecard_cvc3 or 4-digit CVC/CVV

Element options

Pass options to createElement to customize appearance and behavior:

1const cardNumber = paymentKit.card.createElement('card_pan', {
2 style: {
3 fontSize: '16px',
4 fontFamily: 'Inter, system-ui, sans-serif',
5 color: '#1f2937'
6 },
7 placeholder: '1234 1234 1234 1234',
8 onLoaded: () => console.log('Ready'),
9 onFocusChange: (isFocused) => console.log('Focus:', isFocused)
10});
OptionTypeDescription
styleRecord<string, string>CSS properties applied to the input inside the iframe
placeholderstringPlaceholder text for the input field
onLoaded() => voidCalled when the input element is ready
onFocusChange(isFocused: boolean) => voidCalled when the input gains or loses focus

Styling

The style object applies CSS properties directly to the input element inside the iframe. For layout properties like height, border, and background, style the parent container in your HTML instead:

1<div id="card-number" style="height: 44px; padding: 12px; border: 1px solid #e5e7eb; border-radius: 8px; background-color: #ffffff;"></div>

PaymentKit.js automatically reads your container’s padding and applies it to the input inside the iframe, so text alignment and vertical centering match your container’s styling.

Submit payment

1paymentKit.submit({
2 fields: {
3 customer_name: 'Jane Smith',
4 customer_email: 'jane@example.com',
5 customer_country: 'US',
6 customer_zip_code: '94102'
7 },
8 paymentMethod: 'card',
9 onSuccess: (result) => {
10 console.log('Payment ID:', result.paymentIntentId);
11 window.location.href = '/success';
12 },
13 onError: (errors) => {
14 // Card errors: errors.card_pan, errors.card_exp, errors.card_cvc
15 // Form errors: errors.customer_name, errors.customer_email, etc.
16 // General error: errors.root
17 console.error(errors);
18 }
19});

3D Secure

3D Secure (3DS) authentication is handled automatically by PaymentKit.js when required by the card issuer or payment processor.

When 3DS is required, PaymentKit.js displays a Stripe.js authentication modal. The customer completes authentication (entering a code or biometric), and PaymentKit.js verifies the result and completes the payment. No additional code is required in your submit() call.

For 3DS to work, include Stripe.js in your page: <script src="https://js.stripe.com/v3/"></script>

Error codes

Error codeFieldDescription
requiredAllField is empty
invalidAllBasic validation failed
unknown_errorAllUnexpected error during card processing
penpal_not_connectedAllCard input iframe failed to connect
missing_checkout_tokenAllCheckout token missing from request