How 3D Secure works on PayMe

Prerequisites

3D Secure (3DS) asks the card issuer to confirm that the buyer is the cardholder before the card is charged. PayMe runs 3D Secure 2 (version 2.2.0). The issuer either approves without asking the buyer anything (frictionless), or shows a challenge, such as a one-time code.

This page explains when PayMe runs 3D Secure, what each integration has to do, how to test it, and how to read the result. The step-by-step pages it links to have the full request and response fields.

When 3D Secure runs

A card payment gets 3D Secure when all three conditions hold. Google Pay has its own rule, described below.

  1. The seller's account has the 3D Secure service. PayMe enables it. An account that has never had it gets no 3D Secure.
  2. The card brand is supported. PayMe's 3D Secure provider doesn't support Discover, JCB or Isracard cards, so those cards are charged without 3D Secure.
  3. A rule selects the payment. Any one of these is enough:
    • PayMe's system rules: a card issued in a country other than the seller's registered country; 3 or more installments; or an amount of at least the account's 3D Secure threshold. The amount rule compares sale_price in minor units with the threshold, without converting currencies, so the same number applies to every currency.
    • Rules of your own, which PayMe sets on the account. Ask your onboarding manager before you go live.
    • The per-sale setting described below.

3D Secure applies to card payments: credit-card, a card the buyer chose on a multi page, and Google Pay cards saved in the buyer's Google account (see Google Pay). It runs on authorize sales as well as on ordinary sales.

These payments never go through 3D Secure:

Turn it on or off for one sale

Send services with the 3DSecure service when you create the sale with Create a sale with 3D Secure:

{
  "services": [{"name": "3DSecure", "settings": {"active": true}}]
}

What each integration does

Integration Who collects the browser data How the challenge reaches the buyer Details
Hosted payment page (sale_url) PayMe's page PayMe's page shows it Below
Hosted Fields PayMe.clientData() in your page, sent as meta_data_jwt pay-sale returns status_code: 5 and redirect_url 3DS with Hosted Fields
Direct API (pay-sale with card fields) You, sent as meta_data_jwt status_code: 5 and redirect_url Below
Google Pay (googleSale()) PayMe's library paymentCompleted gets status_code: 5 and redirect_url Accept Google Pay
Standalone 3D Secure PayMe's JS library status_code: 5 and redirect_url Standalone 3D Secure

Hosted payment page

There's nothing extra to build. When a rule selects the payment, PayMe's page collects the browser data and shows the challenge. 3D Secure also works when you show sale_url in an iframe, but some issuing banks block their own challenge screen inside an iframe, so keep a fallback that opens the page in a full window. See Hosted Payment Page options.

A failed attempt doesn't close the sale: sale_url stays payable until the sale is paid, or until sale_expiry_seconds passes if you set it. See Understand the sale lifecycle.

Hosted Fields

Follow 3DS with Hosted Fields. In short:

  1. Tokenize the card with Hosted Fields.
  2. In the same page, call PayMe.clientData(testMode) and send the hash it returns to your server.
  3. Create the sale with generate-sale without a buyer_key, and set sale_callback_url and sale_return_url there.
  4. Call pay-sale with the payme_sale_id, the token as buyer_key, and the hash as meta_data_jwt.
  5. Handle the result: status_code 5 means send the buyer's browser to redirect_url; 0 paid; 1 declined.

Always send meta_data_jwt. Without it, pay-sale charges the token without 3D Secure, and nothing in the response tells you so.

Direct API (pay-sale)

The Direct API (PCI DSS Level 1 partners only) sends the card fields to pay-sale. PayMe runs 3D Secure inside the same call when a rule selects the payment:

Google Pay

Whether 3D Secure runs on a Google Pay payment depends on the card, not on the rules or the device:

With the googleSale() button, a payment that needs a challenge calls paymentCompleted(null, sale) with sale.status_code 5 and sale.redirect_url. The sale isn't paid yet: send the buyer to redirect_url. See Accept Google Pay.

Standalone 3D Secure

Use it to authenticate a card without charging it: when another gateway processes the payment, or when you authenticate now and charge later. The flow is on Standalone 3D Secure: process flow, and the background on 3D Secure as a service:

  1. Collect the browser data with PayMe's JS library and create a card sale.
  2. From the browser, call Start 3D Secure authentication. A frictionless approval returns hash_3dsecure; a challenge returns status_code 5 and redirect_url.
  3. From your server, call Resolve a 3D Secure hash to get eci, cavv and xid for your gateway. If authentication failed, the result has a non-null status and no cavv.

The seller needs the 3D Secure service (otherwise error 720), and the call needs the browser data (otherwise error 670).

Test it in the sandbox

The sandbox applies the same rules as production, so a rule must select the sale. 4918914107195005 is issued abroad, so the foreign-card rule selects it at any amount. For the other two cards, make sure a rule selects the sale, for example by forcing 3D Secure with services ("active": true). All three cards use expiry 07/28 and CVV 123.

Card What happens What you see
4918914107195005 Challenge. Enter 555 to pass; any other code (for example 111) fails. Pass: completed, sale_3ds 1. Fail: failed, error 21017
4907639999909022 Frictionless approval, no challenge completed, sale_3ds 1
5283901906612672 Frictionless decline, no challenge failed, error 21017

The full sandbox list is on Test Cards and Payment Methods.

Read the result

Where Field Meaning
Sale callback sale_3ds 1 when the payment went through 3D Secure
pay-sale response sale_3ds true when the payment passed 3D Secure
get-sales and get-transactions sale_is_3ds true if the payment used 3D Secure. Also a filter: "sale_is_3ds": true returns only those payments
Standalone: Resolve a 3D Secure hash eci, cavv, xid The values to send to your gateway

Before you fulfil an order, confirm the sale with the callback or with get-sales, as described on Callbacks.

Failures and error codes

What happened What you get
The buyer failed the challenge The sale becomes failed. sale-failure with status_error_code 21017 ("Verification failed, please try again"). The return-URL redirect carries payme_status=error
The issuer declined without a challenge pay-sale returns HTTP 200 with status_code 1 and status_error_code 21017. The sale becomes failed, and PayMe sends sale-failure
The card or its issuer can't run 3D Secure By default PayMe charges the card without 3D Secure, and sale_3ds is 0. If PayMe has set your account to refuse such payments, or for a Google Pay PAN_ONLY card, the payment fails with 21017
No browser data on pay-sale No error: the card is charged without 3D Secure
3D Secure is required, but no terminal on the account can run it Error 420 with 3DS in status_additional_info. Contact PayMe support
Standalone: the seller has no 3D Secure service Error 720
Standalone: the browser data is missing or unreadable Error 670

A failed 3D Secure attempt is an ordinary failed attempt: the buyer can try again on the same sale. Error codes and the HTTP status of each are on Errors.