card.wallet tells it apart.
Payra enables wallets per workspace. They work through Payra Elements on your own page and on the
hosted checkout. The first part of this page applies to both wallets. Google Pay
and Apple Pay cover what is specific to each.
Before you start
- Keep a card form on the page. Elements draws a wallet’s button only where the device can pay with it. A
device that cannot pay with one wallet may pay with the other, so offer both and show what comes back
available, as the hosted checkout does. - A wallet already holds the customer’s saved cards. Apple Pay and Google Pay keep them on the customer’s
device and account, so a returning customer pays by tapping the button again. A wallet card pays once: the
charge refuses
save_payment_method, andPOST /payment-methodsrefusesusage: "saved". To save a card, collect it with a card session. - The amount is fixed when the session is created. The sheet (the wallet’s own payment screen) shows it, the customer confirms it, and the charge must be for exactly that amount and currency.
Accept a wallet payment
1
Create a session for each wallet
One session collects one wallet and carries the amount its sheet shows, in the smallest unit of
currency
(USD when omitted, or CAD). To show both buttons, create two sessions.Response (abbreviated)
apple_pay works the same way. Three things are refused before any page opens: a session without amount
(400 parameter_invalid on amount), a currency other than USD or CAD (400 parameter_invalid on
currency), and a wallet your workspace does not offer (400 payment_provider_not_configured on
payment_method_types). Hand the page each session’s client_secret and nothing more.2
Mount the buttons
Each wallet gets its own There is no form to submit. The customer confirms in the sheet, which shows the amount and your business name.
Elements then confirms the session with the wallet’s token and fires
elements() call, with its own session.confirmed, the moment to charge. After a
decline the page swaps the spent session for a new one, since a session pays once.3
Charge on your server
Send the session as The payment answers
payment_method_session, with its amount.Response (abbreviated)
succeeded, a decline, or requires_action, as a typed card does. An amount or currency
other than the session’s is 400 parameter_invalid on amount, and nothing reaches the processor.A session has two 30-minute windows. The customer has 30 minutes from its creation to pay in the sheet, and
you have 30 minutes from confirmed to charge it. A later charge answers payment_method_session_inactive. A
session pays once, approved or declined, and a second charge answers payment_method_session_used.requires_action means the card’s bank wants to verify the customer. Send return_url on every wallet charge:
on a workspace that offers wallets it always takes effect, and without it the customer cannot be sent to the
bank. handleNextAction follows the payment’s redirect, and the customer comes back to your return_url.
The rest of 3-D Secure applies.The button
Each wallet draws its own button with Google’s and Apple’s own libraries, so it always matches their brand rules.
The button fills the width of the container you mount into, so size the container. For anything the theme does
not cover, the container has the classes
PayraElement and PayraElement--wallet, and the button has
PayraElement-wallet-button plus PayraElement-wallet-button--google_pay or --apple_pay. Place the buttons
where the customer expects an express option, above or beside the card fields, and follow
Apple’s and
Google’s guidelines for the space around
them.
Events and errors
payra.confirmPaymentMethodSession(elements) is not needed with a wallet. On a wallet element it submits nothing,
and answers the session confirmed carried, or wallet_not_authorized before the customer pays.
Apple Pay adds three codes of its own. Errors from the charge are under
Payments.
What you read back
The payment, the payment method it made and everypayment.* webhook carry the card as the wallet
disclosed it:
exp_month and exp_year are always null on a wallet card. brand and last4 are null only when the wallet
did not disclose them. billing_details.name is null, since a wallet does not hand over the name. Read wallet as
an open string, since the list may grow. Refund a wallet payment as any card payment.
On the hosted checkout
When your workspace offers wallets and a checkout session offerscard, the page shows the
wallet buttons above the payment form, Apple Pay first, and only those the customer’s device can pay with. There
is nothing to send. payment_method_types never lists wallets, and a checkout without card shows none.
The customer taps, confirms on the device, and the page charges and finishes as with a card. The customer lands
on success_url with ?checkout_session=cs_…, the session’s payment carries card.wallet, and
checkout_session.completed and payment.succeeded are sent. A refused wallet payment shows its reason under
the buttons, and the customer can tap again or pay with the form.
Testing
In sandbox the sheets are real and no money moves. Test Google Pay and Test Apple Pay say how to pay in each wallet’s test environment. Check the payment forcard.wallet, and that payment.succeeded reached you. A wallet never asks for a name, so the name-on-card
refusals on Testing do not apply. Try your decline path with a typed card.
Content Security Policy
If your page sets one, addhttps://pay.google.com (Google Pay) and https://applepay.cdn-apple.com (Apple Pay)
to script-src, on top of what Elements needs. Then try one payment with
each wallet under your policy. A blocked host shows in the browser console as a Content Security Policy
violation.