Accept a card payment
Collect card details in your own checkout and send them to the Griner API from your server.
Your customers enter their card details in your own checkout form. Your server stores them in the Griner vault and starts the payment. Griner handles 3-D Secure. You control the full checkout experience, and your customers stay on your website until they authenticate with their bank.
PCI DSS compliance required
Card data passes through your systems, so you must be PCI DSS compliant to store, process or transmit it. Not compliant, or not sure? Use the hosted payment page instead.
How it works
A card payment takes three requests:
| Step | Request | Result |
|---|---|---|
| 1 | Create an order | An order with a transaction and a setup_token. |
| 2 | Store the card in the vault | The card details are stored in the vault. You get a vault_token. |
| 3 | Start authentication | A redirect_url for 3-D Secure authentication. |
After step 3, you redirect your customer to the redirect_url to authenticate with their bank. Your customer then returns to your return_url, and you confirm the result.
Before you begin
- Get the API key of your test project in the merchant portal at https://merchant.pay.griner.io, under Settings > Project. Only use it from your server.
- Make sure your PCI DSS compliance covers your checkout form and every system the card details pass through.
Create an order
When your customer submits your checkout form, create an order with one transaction for the credit-card payment method:
curl https://api.pay.griner.io/v1/orders/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"currency": "GBP",
"amount": 995,
"merchant_order_id": "EXAMPLE001",
"description": "Example card order",
"return_url": "https://www.example.com/order/EXAMPLE001",
"webhook_url": "https://www.example.com/webhook",
"transactions": [
{
"payment_method": "credit-card"
}
],
"customer": {
"merchant_customer_id": "123456789",
"email_address": "user@example.com",
"first_name": "John",
"last_name": "Smith",
"address_type": "billing",
"address": "100 Main Street",
"postal_code": "SW1A 1AA",
"city": "London",
"country": "GB",
"locale": "en-GB",
"phone_numbers": ["+441234566788"],
"ip_address": "192.0.2.1"
}
}'The response contains the order and its transaction. The response is shortened:
{
"id": "8078d78f-8700-4cfe-94b1-4a777d3400f2",
"amount": 995,
"currency": "GBP",
"merchant_order_id": "EXAMPLE001",
"status": "new",
"transactions": [
{
"id": "a5dac3de-d304-4570-922b-373d478b8b3a",
"amount": 995,
"currency": "GBP",
"payment_method": "credit-card",
"payment_method_details": {
"setup_token": "87f05a5d-1755-48c7-8161-f8a9544e56bf"
},
"status": "new"
}
]
}Save the order id, the transaction id and the setup_token. You need them in the next steps.
Store the card in the vault
Send the card details and the setup_token to the vault. The vault stores the card and returns a vault_token that represents it.
curl https://tokens.pay.griner.io/v1/cards/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"name": "John Smith",
"pan": "4111111111111111",
"expiry": "012030",
"setup_token": "87f05a5d-1755-48c7-8161-f8a9544e56bf"
}'{
"vault_token": "d972dc43-6a3d-4dcf-b54e-6e9a0fe325e3",
"truncated_pan": "4111********1111",
"brand": "visa",
"brands": ["visa"]
}The setup token expires quickly
A setup_token works only once, and only within 300 seconds after the order was created. Store the card right after your customer submits your checkout form.
Store the vault_token if you want to reuse the card later, for example for one-click payments.
Start authentication
Send the vault_token and the card's CVC to the transaction:
curl https://api.pay.griner.io/v1/orders/8078d78f-8700-4cfe-94b1-4a777d3400f2/transactions/a5dac3de-d304-4570-922b-373d478b8b3a/authenticate/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"vault_token": "d972dc43-6a3d-4dcf-b54e-6e9a0fe325e3",
"cvc": "123"
}'{
"redirect_url": "/pay/8078d78f-8700-4cfe-94b1-4a777d3400f2/a5dac3de-d304-4570-922b-373d478b8b3a/authenticate-3ds/"
}Redirect your customer to the redirect_url, on the https://api.pay.griner.io domain. Griner checks whether the card is enrolled for 3-D Secure and forwards your customer to their bank. The bank decides whether your customer needs to approve the payment. See 3-D Secure.
Already authenticated your customer with your own 3-D Secure provider? Send the authentication values in this request instead. See External 3-D Secure.
Your customer returns
After authentication, your customer is redirected back to your return_url. Show a page that tells your customer the payment is being checked, and confirm the result from your server before you show a confirmation.
Don't rely on the redirect alone
Your customer can close the browser before they're redirected, and anyone can open your return_url. Always retrieve the order from your server before you show a confirmation or deliver.
Confirm the payment
Griner sends a webhook to your webhook_url when the order status changes. Retrieve the order from the API and act on its status: the payment succeeded when the order status is completed and the transaction status is accepted. Stop checking when the status is final, such as error or expired.
See Confirm the payment for how to handle the webhook, and Order and transaction status for every status.
Test your integration
Use your test project and the test cards on Test data. Test at least these cases:
- Frictionless payment: an order of 3000 or less, for example with Visa
4635440000002207. The payment succeeds without a challenge. - 3-D Secure challenge: an order of more than 3000. Complete the challenge after the redirect.
- Abandoned payment: close the browser on the 3-D Secure page. Your checkout must not show a confirmation, and your order stays open until its status is final.
- Expired setup token: store a card more than 300 seconds after creating the order. Your checkout must create a new order.
Go live
- Replace the API key of your test project with the key of your live project.
- Check that your PCI DSS compliance covers your live checkout form and servers.
- Set the webhook URL in your live project, or send a
webhook_urlwith every order. - Make sure no card numbers or CVCs end up in your logs, also not in error logs.
Then work through the go-live checklist.
Fields
The steps above show the fields a card payment needs. The API reference describes all fields of each request:
- Create an order: the order with one
credit-cardtransaction, and thecustomer. Card schemes use the customer details for 3-D Secure risk assessment, so complete details lead to more frictionless payments. - Store a card: the card details. Never log or store them yourself unless your PCI DSS certification covers it.
- Authenticate a transaction: the
vault_tokenand thecvc.
E-wallet merchants
If you're an e-wallet merchant, add receiver_account_number and receiver_account_number_type to the payment_method_details of the transaction. See e-wallet merchants.
Beyond the basics
External 3-D Secure
Send the results of your own 3-D Secure provider.
Pre-authorize and capture
Reserve the amount now and capture it later.
One-click payments
Let returning customers pay with a stored card.
Recurring payments
Charge a stored card for subscriptions.
Apple Pay
Add the Apple Pay button to your checkout.
Google Pay
Add the Google Pay button to your checkout.
See Beyond the basics for everything you can add.