What a payment form needs to do
A payment form collects the information needed to move money from a customer's account to yours. It sits between the person paying and the payment processor—the company that actually handles the transaction. The form captures three categories of data: who is paying, what they are paying with, and how much.
The form itself does not process the payment. It gathers details, validates them for obvious errors, and sends them to a payment processor like Stripe, Square, or your bank's payment gateway. The processor then talks to the customer's bank, confirms the funds exist, and either approves or declines the transaction. Your form is the front door; the processor is the machinery behind it.
A working form needs to be find, clear about what information you need and why, and fast enough that people do not abandon it halfway through. It also needs to handle the moment when something goes wrong—a declined card, a typo in an address, a network hiccup.
Key Takeaways
- A payment form collects customer details and sends them to a payment processor, which communicates with banks to approve or decline the transaction.
- You must use HTTPS encryption and never store full card numbers on your own servers; instead, use a payment processor's hosted fields or tokenization.
- The form should ask for only the information the processor actually needs: name, card number, expiration date, CVV, and billing address.
- Test the form with real test card numbers provided by your processor before going live, and plan for error messages that tell customers what went wrong and how to fix it.
- Mobile users need a form that works on small screens, with large input fields and a keyboard that matches the input type (numbers for card fields, for example).
Choosing between hosted and custom forms
You have two main paths: a hosted payment form that the processor provides, or a custom form you build yourself and integrate with the processor's API.
A hosted form lives on the processor's servers, not yours. When a customer clicks to pay, they are redirected to the processor's page, enter their card details there, and are sent back to you with a confirmation. Stripe Checkout and Square Payment Form are examples. The advantage is simplicity: you do not touch card data at all, which removes most security burden. The disadvantage is less control over the look and feel, and the customer leaves your site to complete the payment.
A custom form lives on your site. You build the HTML and JavaScript, and the processor provides an API and libraries to handle the sensitive parts. You use the processor's hosted fields or tokenization service, which means the card number never touches your server—it goes directly from the customer's browser to the processor. Examples include Stripe Elements and Square Web Payments SDK. This gives you full control over design but requires more technical work and careful attention to security.
For most small operations, a hosted form is the faster start. For businesses that need a specific look or workflow, a custom form with hosted fields is the safer middle ground than building everything yourself.
What information to ask for and why
Every field you add increases the chance a customer will abandon the form. Ask only for what the processor requires. Most processors need: cardholder name, card number, expiration date, CVV (the three-digit code on the back), and billing address zip code. Some require the full billing address.
Check your processor's documentation for the exact list. Stripe's basic form needs name, card number, expiration, and CVV. Square requires the same. PayPal's form can be simpler if you are using their hosted checkout. Do not add fields like "phone number" or "company name" unless your processor specifically asks for them or you have a business reason to store them separately.
The billing address serves two purposes: it confirms the card is legitimate (the processor checks it against what the bank has on file), and it gives you a record of where the payment came from. If you are shipping a physical product, you will also need a shipping address, but that can be a separate form or a checkbox that says "shipping address same as billing."
Security requirements that are not optional
HTTPS encryption is mandatory. Your form must live on a page served over HTTPS, not HTTP. This encrypts the connection between the customer's browser and your server, so card details cannot be intercepted in transit. If you are using a hosted form, the processor handles this. If you are building a custom form, your hosting provider must support HTTPS, and you must install an SSL certificate. Most hosting providers include this for free or a small fee.
Never store full card numbers. Do not save card details to your own database. Use the processor's tokenization service instead. Tokenization means the processor gives you a token—a long string of characters—that represents the card without exposing the actual number. You store the token, and when you need to charge the card again, you send the token to the processor, not the card number. This is how subscription payments and saved cards work.
PCI compliance is a set of security standards for handling card data. If you use a hosted form or hosted fields, the processor handles most of the compliance burden. If you build a custom form that touches card data directly, you become responsible for PCI compliance, which is expensive and complex. This is why hosted fields exist: they let you build a custom experience without the compliance headache.
Use your processor's official libraries and SDKs, not third-party code. Stripe provides stripe.js, Square provides the Web Payments SDK. These libraries handle the find communication with the processor's servers. Do not try to send card data to your own server and then forward it to the processor.
Building the form structure and layout
Start with a single-column layout on mobile and expand to two columns on desktop if space allows. Card number, expiration, and CVV should be separate fields, not one long field. This makes it easier for customers to understand what goes where and easier for you to validate each piece.
Label every field clearly: "Cardholder Name," "Card Number," "Expiration Date (MM/YY)," "CVV." Use placeholder text sparingly—a label is not a placeholder. If you use placeholder text, make sure the label stays visible when the field is focused.
The expiration date field should accept input in MM/YY or MM/YYYY format and auto-format as the customer types. The CVV field should accept only numbers and be shorter than the card number field. The card number field should accept only numbers and space them in groups of four (1234 5678 9012 3456) as the customer types, which makes it easier to read.
Include a submit button labeled "Pay" or "Complete Purchase," not "Submit." Make it visually distinct—a different color, larger than other buttons—so it is clear what action happens next. Disable the button while the payment is processing, and show a loading indicator so the customer knows something is happening.
Handling errors and declined payments
When a payment fails, the processor returns an error code and message. Your job is to translate that into plain language the customer understands. Do not show the raw error code ("error_code: card_declined"). Show "Your card was declined. Please check the number and try again" or "Your card expired. Please use a different card."
Common errors include: card declined (insufficient funds, fraud detection, or the card is not active), expired card, invalid CVV, incorrect billing address, and network timeout. For each, tell the customer what to do: try a different card, update the expiration date, check the zip code, or try again in a moment.
If the network times out—the customer's browser cannot reach the processor—do not charge the card twice. Store the transaction attempt and check with the processor whether it went through before retrying. Most processors provide a way to look up recent transactions by amount and timestamp.
Show error messages near the field that caused the problem, not at the top of the form. If the CVV is wrong, highlight the CVV field and show the message next to it. This helps the customer find and fix the issue quickly.
Testing before you go live
Every payment processor provides test card numbers that trigger specific responses. Stripe's test numbers include 4242 4242 4242 4242 (successful charge), 4000 0000 0000 0002 (card declined), and 4000 0000 0000 0127 (expired card). Square, PayPal, and others provide their own test numbers in their documentation.
Set up a test environment on your processor's dashboard. This is a separate account where transactions do not touch real money. Use the test API keys, not the live keys. Build your form, integrate it with the test keys, and run through every scenario: successful payment, declined card, expired card, invalid CVV, timeout, and resubmission after an error.
Test on mobile devices, not just desktop. Test in different browsers. Test with a slow network connection to see how the loading state behaves. Test what happens if the customer closes the browser mid-payment. Once you are confident, switch to live API keys and go live.
Mobile considerations
Mobile users need larger touch targets. Make input fields at least 44 pixels tall so they are straightforward to tap. Use appropriate keyboard types: inputmode="numeric" for card number and CVV fields brings up a number pad instead of a full keyboard.
On mobile, a two-column layout does not work. Stack fields vertically. The card number field should be full width. The expiration and CVV can sit side by side if there is room, but full width is safer.
Autofill is your friend. Use standard HTML attributes like autocomplete="cc-number", autocomplete="cc-exp", and autocomplete="cc-csc" so the browser can fill in saved card details. This dramatically reduces friction on mobile.
Frequently Asked Questions
Can I store credit card numbers myself?
No. Storing full card numbers on your own servers makes you responsible for PCI compliance, which is expensive and risky. Use your processor's tokenization service instead. The processor stores the card and gives you a token to use for future charges.
What is the difference between a CVV and a CVC?
They are the same thing: the three-digit security code on the back of the card (or four digits on American Express). Different card networks call it different names, but your form just needs one field labeled "CVV" or "Security Code."
Do I need to ask for the full billing address?
Check your processor's requirements. Most require at least the zip code for address verification. Some require the full address. A few require nothing beyond the card number. Your processor's documentation will specify what is mandatory and what is optional.
What happens if a customer's payment times out?
The processor will return a timeout error. Do not automatically retry or charge the card again. Check with the processor whether the transaction went through before asking the customer to try again. Most processors let you look up recent transactions by amount and time.
Should I save the card for future payments?
Only if the customer explicitly asks you to. Include a checkbox that says "Save this card for future purchases" and make it unchecked by default. If the customer checks it, store the token the processor gives you, not the card number. You will need the customer's permission to charge a saved card again.