Apple Pay
Tilled allows Partners to accept Apple Pay payments, which Customers can use to make payments if they are using a compatible device and browser.
Tilled supports Apple Pay through the Tilled.js PaymentRequest
object.
Requirements
Before you begin, you will need to:
- Create a domain that meets the following requirements:
- Create an Apple Developer Account (this will be used when testing Apple Pay on your Website)
These requirements apply to both Sandbox and Production environments. For Sandbox testing, to get started, you can use a service like ngrok or Netlify.
Apple Pay Domain Verification
Verifying your Domain for Apple Pay
You must register and verify all top-level domains and subdomains where you will display the Apple Pay button. For example, if you were to host a Payment Form that displays the Apple Pay button on https://pay.example.com/
and https://example.com/
, you will need to complete Domain Verification for both.
In the Sandbox Environment, Domain Verification is not needed, but you will still need to follow the domain requirements here
In the Production environment, to receive your Domain Verification files for Apple Pay, you will need to reach out to the Onboarding Team at [email protected] and provide the following information:
On how many domains do you plan to host the Apple Pay button? - If each Merchant will be using a different domain or subdomain, you will need to include that in your answer if the Merchant will be hosting the Apple Pay button. - You will need to register and verify all top-level domains and subdomains where you will display the Apple Pay button. For example, if you were to host a payment form that displayed the Apple Pay button on
https://pay.example.com/
andhttps://example.com/
, you would need to complete domain verification for both.How many merchants are you planning to enable Apple Pay for?
Will you be using your own payment/checkout page (using Tilled.js) or Tilled’s Checkout Sessions?
Once this information is received by our Onboarding Team, we provide you with the files and instructions on hosting them to ensure successful Domain Verification, so that are able to start accepting Payments on your site.
Including Tilled.js
To accept Apple Pay payments through Tilled, you will need to include Tilled.js on your page. Add the following HTML snippet to your web page, preferably in the <head>
tag of your web page:
1<script src="https://js.tilled.com/v2"></script>
Initializing Tilled.js
Instantiate an instance of Tilled
by providing it with your publishable API key and the Tilled account id of the merchant account to perform the action on behalf of.
1const tilled = new Tilled('pk_…', 'acct_…');
Use new Tilled(publishableKey, tilledAccount, options?)
to create an instance of the Tilled
object. The Tilled
object provides access to the rest of the Tilled.js SDK. Your Tilled publishable API key is required when calling this function, replace the sample API key above with your actual API key. You can retrieve your API key by accessing https://app.tilled.com/api-keys.
Creating the PaymentRequest
In this example, we will be using the div container <div id="native-payment-element">
to inject the PaymentRequest Button (Apple Pay button) if the paymentRequest.canMakePayment(): Promise<boolean>
returns as true
.
PaymentRequest
instances emit several different types of events, we will use tilled.paymentRequest
to create a PaymentRequest
object.
In Safari, tilled.paymentRequest
uses Apple Pay.
PaymentRequest Example
1const paymentRequest = tilled.paymentRequest({
2 total: {
3 label: "Tilled tee",
4 amount: paymentIntent.amount,
5 },
6 style: {
7 type: "donate",
8 theme: "black",
9 },
10 requestPayerName: true,
11 requestPayerEmail: true,
12});
When creating a PaymentRequest for Apple Pay, we highly recommend you collect the name as this also results in the collection of the billing address for Apple Pay, which can be used to perform address verification. A customer name can be collected by setting the requestPayerName
option to true
.
To view all PaymentRequest options
properties, you can read more here.
card
.
Displaying The Apple Pay Button
To ensure that only customers who have an Apple Pay Wallet with an active card attached see the Apple Pay button, you will utilize paymentRequest.canMakePayment(): Promise<boolean>
. This returns a Promise
that resolves true
if an enabled wallet is ready to pay. If no wallet is available, it resolves with false
;
The example below injects paymentRequestButton (Apple Pay button) to the div container <div id="native-payment-element">
if paymentRequest.canMakePayment(): Promise<boolean>
resolves true
.
1var prButton = form.createField('paymentRequestButton', {
2 paymentRequest: paymentRequest,
3});
4
5paymentRequest.canMakePayment().then((result) => {
6 if (result) {
7 // Inject paymentRequestButton Form Field to the DOM
8 prButton.inject('#native-payment-element');
9 }
10});
PaymentMethod Creation
Tilled.js automatically creates a payment method after the customer is done interacting with the browser’s payment interface. To access the created payment method, listen for this event by utilizing paymentRequest.on('paymentmethod', handler): void
Payment methods created through Apple Pay will have a "type"
of "card"
and a validity period of 5 minutes.
For further details on PaymentMethod Creation, please refer to the Tilled.js documentation here.
Creating and Confirming The PaymentIntent
Before displaying your checkout form and confirming the payment, your backend server will need to make an API call to Tilled to create a Payment Intent
with the payment amount. You will pass the intent’s client_secret
to your front end. Use the tilled.confirmPayment(client_secret, { payment_method })
method to process the payment with the newly created Payment Method
.
tilled.confirmPayment(clientSecret: string, params): Promise<PaymentIntent>
confirms a Payment Intent
and, optionally, creates a Payment Method
from the Form Field
s in the DOM.
This method returns a Promise
which will resolve with a Payment Intent
object.
1paymentRequest.on('paymentmethod', (ev) => {
2 let paymentMethod = ev.paymentMethod;
3 tilled
4 .confirmPayment(paymentIntentClientSecret, {
5 payment_method: paymentMethod.id,
6 })
7 .then(
8 (paymentIntent) => {
9 // The payment intent confirmation occurred, but the
10 // actual charge may still have failed. Check
11 if (
12 paymentIntent.status === 'succeeded' ||
13 paymentIntent.status === 'processing'
14 ) {
15 ev.complete('success');
16 alert('Successful payment');
17 } else {
18 ev.complete('fail');
19 const errMsg = paymentIntent.last_payment_error?.message;
20 alert('Payment failed: ' + errMsg);
21 }
22 },
23 (err) => {
24 ev.complete('fail');
25 },
26 );
27});
Testing your Apple Pay integration
Apple allows developers to test Apple Pay before or after implementation by using their Apple Developer Account to create a Sandbox Tester Account. To start testing your Apple Pay Integration you will need to do the following:
-
Make sure that your domain:
-
Enroll in the Apple Developer Program if you haven't already.
-
Sign in to your Sandbox Tester Account on a Compatible Device you would like to test out your integration on.
- Once you are signed in, you will add a Test Card Number to your Apple Pay Wallet using one of the Test Cards provided by Apple.
Examples
See our Apple Pay Examples below:
- Apple Pay Example | Netlify
- Apple Pay Example | ngrok
- Apple Pay Example | React Typescript | ngrok
- Apple Pay Example | React Typescript | Netlify
Apple Pay | PaymentRequest Example
1/**
2 * Example assumptions:
3 * The paymentRequestButton field has a div defined in the DOM
4 * <div id="native-payment-element"></div>
5 *
6 */
7const form = tilled.form({
8 payment_method_type: 'card',
9});
10
11const paymentRequest = tilled.paymentRequest({
12 total: {
13 label: 'Tilled tee',
14 amount: secretData.amount,
15 },
16});
17
18const prButton = form.createField('paymentRequestButton', {
19 paymentRequest: paymentRequest,
20});
21
22paymentRequest.canMakePayment().then((result) => {
23 if (result) {
24 prButton.inject('#native-payment-element');
25 } else {
26 document.getElementById('native-payment-element').style.display =
27 'none';
28 }
29});
30
31paymentRequest.on('paymentmethod', (ev) => {
32 let paymentMethod = ev.paymentMethod;
33 tilled
34 .confirmPayment(paymentIntentClientSecret, {
35 payment_method: paymentMethod.id,
36 })
37 .then(
38 (paymentIntent) => {
39 // The payment intent confirmation occurred, but the
40 // actual charge may still have failed. Check
41 if (
42 paymentIntent.status === 'succeeded' ||
43 paymentIntent.status === 'processing'
44 ) {
45 ev.complete('success');
46 alert('Successful payment');
47 } else {
48 ev.complete('fail');
49 const errMsg = paymentIntent.last_payment_error?.message;
50 alert('Payment failed: ' + errMsg);
51 }
52 },
53 (err) => {
54 ev.complete('fail');
55 },
56 );
57});