Working With Apple Pay
Note: Primarily purpose of this article is to put all the contents in one place . Majority of the contents were taken from WWDC. All code follows
iOS 11
Api’s
Merchant
A merchant is a company or individual who sells a service or goods. Like If you are using Uber app , then Uber company is the merchant
What is Apple Pay
Apple pay is an easy, private and secure way to pay within application as well as contactlessly and it allows for one touch payments and you can use it for physical goods and services
How excited people when apple first introduced apple pay in 2014. Here is the link
Benefits
- Easy to use (user don’t need to re enter payment , contact, billing and shipping information )
- Secure (pay using touch ID / FaceID)
- Private (Card number not exposed Instead you sending a device number along with the unique token that valid only for that purchase)
- It’s so easy that you don’t need to onboard your users
- Merchant see higher checkout conversion rates and faster checkouts after integrating Apple Pay
Difference between Apple pay and InApp Purchase
- Apple pay used for physical goods and services mean like gym membership , ride sharing , grocery delivery and buying stuff from store
- Where inApp purchases used for in app content and functionality , In app currency and digital subscription
Availability
Apple pay is available on all devices that has a secure element chip. So secure elements is this hardware chip that dedicated to securely storing your card information and is available on iPhone 6, 6plus and future devices
Apple pay Architecture
- The first thing you need to create a Merchant Identifier , They require this and it uniquely identifies you as a merchant , Now you can set your merchant identifier up on the developer portal or through the Xcode capability window and it’s backed by the private key in a certificate . They used this certificate to securely encrypt the payment information that we generate so it’s unique to you as a merchant , No body else can decrypt the payment information . It’s just another great security benefit of apple pay . use reverse DNS format. EXAMPLE:
merchant.com.wwdc.emporium.
Apps that use Apple Pay need to enable the Apple Pay capabilities in Xcode. You also register a merchant ID and create a Payment Processing certificate, which is a cryptographic key that is used to securely send payment data to your server. - Display Apple pay button in app
- Your app then receive a payment token in response (Now a payment token contains all the information you need to charge the payment , It’s encrypted using your merchant identifier certificate, so unique to you only you as the developer can decrypt it )
- Send this token to your processor and display a success sheet in your app
Payment Flow :
- First app will show/ display the your checkout flow
- Then you can ask iOS whether the user has any Apple Pay cards available because if the users doesn’t have any apple pay cards available or the device doesn’t support it, you want take them to traditional payment flow
- Now if they do , then we will present the apple pay sheet, iOS will check wether the touch Id / face ID is valid. If it is valid , apple will actually pass this information down to the dedicated secure element, which is gonna securely wrap all of this payment information in your up, this includes the cryptogram which is an encrypted piece of data required to make the payment , It’s then going to send it to apple servers. Now on apple servers it just get rewrapped using your merchant identifier , so that’s all apple are doing . This is because Apple don’t want to ship your certificate in the app right . So their server re routes the payment and encrypts it uniquely to you and its passed back up through the system where you can then send it for processing , Now assuming the processing is successful you can dismiss the payment sheet and display you own confirmation screen
How Do I process the Payment / How You Get Money (Payment Processing)
So there is two way you can process your apple pay token
- To use a payment platform , The payment platform can handle this decryption and the understanding of the cryptogram on your behalf, When you sign up, you provider them with your merchant identifier and Certificate , and they decrypt it for you and you simply send them the payment token and some payment platform actually provide native iOS development kits Swift/Objc. (Recommended)
- To process the payment your self , Now apple recommend this if you are experienced working with payments and you have some existing payment infrastructure and if you do this you are gonna decrypt it the payment token on your server and then you gonna send this to the underlying cryptogram that the secure element generated to your Merchant Acquirers , your acquiring bank and do a transaction
Merchant ID vs Payment Processing certificate
A merchant ID identifies you to Apple Pay as being able to accept payments. This identifier you register with Apple that uniquely identifies your business as a merchant able to accept payments. This ID never expires, and can be used in multiple websites and iOS apps.
A Payment Processing certificate that is associated with your merchant ID is used to encrypt/decrypt payment information. Apple Pay servers use the certificate’s public key to encrypt payment data. You (or your payment service provider) use the private key to decrypt the data to process payments
Getting Started
STEP 1 → Register a Merchant ID
- In Member Center, select Certificates, Identifiers & Profiles.
- Under Identifiers, select Merchant IDs.
- Click the Add button (+) in the upper-right corner.
- Enter a description and identifier, and click Continue.
- Review the settings, and click Register.
- Click Done.
STEP 2 → Create a Payment Processing certificate
- In Member Center, select Certificates, Identifiers & Profiles.
- Under Identifiers, select Merchant IDs.
- Select the merchant ID from the list, and click Edit.
- In the Payment Processing Certificates section, click Create Certificate. Follow the instructions to obtain or generate your certificate signing request (CSR), and click Continue.
- Click Choose File, select your CSR, and click Generate.
- Download the certificate by clicking Download, and click Done.
STEP 3 → Enable Apply Pay On App
To enable Apple Pay for your app in Xcode, open the Capabilities pane. Select the switch in the Apple Pay row, and then select the merchant IDs you want the app to use as shown in Figure 2
If you want to see Step 1 to 3 through video, here is the link
STEP 4 → Device Availability
As shown in Figure 3 , we Determined whether this device can process payment requests of not in our case true we can pass first check
canMakePayments() → Determine whether this device can process payment requests. YES if the device is generally capable of making in-app payments. NO if the device cannot make in-app payments or if the user is restricted/locked from authorizing payments.
Restricted Account
Many Apple Pay Cash users can’t tell the difference between a locked and restricted account. If you can still transfer the balance from your account to your bank or make payments in stores, within apps, and on the internet, that means that your account is just restricted. Apple has the right to restrict your account if its security system spots any suspicious activity on it.
Locked Account
On the other hand, if your account is locked, you will no longer be able to make purchases via Apple Pay Cash, or send and receive money. That also means that you won’t be able to transfer your balance to your bank account. Just like with a restricted account, Apple may lock your account if it discovers an activity that is considered suspicious on your account.
STEP 5 → Payment Network Support
Payment Network → When you go to the grocery store and swipe your card, the terminal transmits your account information to a third-party company. That company then sends the request to your financial institution, which approves or denies it based on your balance or credit limit. The third-party company then sends that information back to the merchant terminal, which approves or denies the purchase. The third-party company involved in all of this is known as a payment network. Common payment networks today include
Visa
,MasterCard
, andMaestro
.
As shown in Figure 4 we Determined whether this device can process payment requests using specific payment network brands YES if the user can authorize payments on this device using one of the payment networks supported // by the merchant // NO if the user cannot authorize payments on these networks or if the user is restricted from authorising payments.
Note: If you implement step 5 you don’t need to do step 4. User may not be able to make payments for a variety of reasons. For example, this functionality may not be supported by their hardware, or it may be restricted by parental controls. On devices that support making payments but don’t have any payment cards configured, the
canMakePayments()
method returnstrue
because the hardware and parental controls allow making payments, but thecanMakePayments(usingNetworks:)
method returnsfalse
regardless of network.
As shown in Figure 5 in my real device I have only master card , it return false,
STEP 6 → Design Apple Pay Button
The system provides several Apple Pay button types and styles you can use in your app. Don’t create your own Apple Pay button design or attempt to mimic the system-provided button designs . For System provided button use PKPaymentButtonType (iOS). For more details please have a look
When you use the system-provided APIs, you get: Apple-approved configuration , localization , maintain ideal proportions as you change its size
Guidlines:
- Make the Apple Pay button no smaller than other payment buttons, and avoid making people scroll to see it.
- In a side-by-side layout, place the Apple Pay button to the right of an Add to Cart button.
- In a stacked layout, place the Apple Pay button above an Add to Cart button.
- By default, an Apple Pay button has rounded corners. You can change the corner radius to produce a button with square corners or a pill-shaped button
As shown in Figure 6 we setup Apple Pay button
STEP 7 → Creating a Payment Request
Encapsulates a request for payment, including information about payment processing capabilities, the payment amount, and shipping information.
As shown in Figure 7 we created a payment request object. Few things to note
supportedNetworks →
First we provide some supported networks which is array of string (The payment networks supported by the merchant) since our application supports Visa and master card we provide this only. This affects which of your user’s cards show up in the Apple Pay sheet.merchantIdentifier →
Provided the merchantIdentifier Identifies the merchant, as previously agreed with Apple. Must match one of the merchant identifiers in the application’s entitlement. This also helps us how to encrypt your payment correctly Now you already set this up on the developer portalcountryCode →
You pass then country code (ISO
country code, it should be the country code where your payment processor is in , the country in which you’ll making the charge, so it’s not the country that the user is in ). In short is the 2-character country code where your transaction takes place.currencyCode →
Set this property to the three-letter ISO 4217 code for the currency used by this payment request. Apple Pay interprets the amounts provided in the summary items of this request as amounts in this currency. The currency code is validated.merchantCapabilities →
Merchant capabilities so in turns out there two different ways of generating payment data one of them is called3DS
and the other is calledEMV.
Now you don’t need to know how these works . Most of you use 3DS ,and you should check with your payment processor or you're acquiring bank as to the right setting for you . So agin majority of you will be 3DS but the payment platform or processor can give you the exact advice that you need herepaymentSummaryItems →
Finally what we actually chargePKPaymentSummary
piece of information you like to charge it has amount and a label , amount is the classNSDecimalNumber
, precisely represents number in base 10 which is very important when you are working on in finance and with currency
As show in Figure 8 This code creates a simple PKPaymentRequest
object that represents a single Apple Pay payment, as well as the creation of a PKPaymentAuthorizationViewController
constructed with the PKPaymentRequest
instance responsible for displaying the Apple Pay payment sheet. Finally, the ViewController
presents the PKPaymentAuthorizationViewController
.
Recommendation
new in iOS 15, if you are in Xcode and see this error
Payment request is invalid: Error Domain=PKPassKitErrorDomain Code=1 “Invalid in-app payment request” UserInfo={NSLocalizedDescription=Invalid in-app payment request, NSUnderlyingError=0x11204dbe0 {Error Domain=PKPassKitErrorDomain Code=1 “PKPaymentRequest must contain an NSArray property ‘paymentSummaryItems’ of valid objects of class PKPaymentSummaryItem” UserInfo={NSLocalizedDescription=PKPaymentRequest must contain an NSArray property ‘paymentSummaryItems’ of valid objects of class PKPaymentSummaryItem, NSUnderlyingError=0x11204cc00 {Error Domain=PKPassKitErrorDomain Code=1 “PKPaymentSummaryItem has an invalid label or amount property” UserInfo={NSLocalizedDescription=PKPaymentSummaryItem has an invalid label or amount property, NSUnderlyingError=0x11204ca00 {Error Domain=PKPassKitErrorDomain Code=1 “Amount is not valid for specified currency. Amount: 11.397, Currency: SAR” UserInfo=0x11204cbd0 (not displayed)}}}}}}
While creating payment summary object make sure price digits should follow https://en.wikipedia.org/wiki/ISO_4217 as per country wise , we faced problem our coutry is Saudia which has 2 digit standard and we passed apple pay amount 11.397 which is three digit . In this case apple pay sheet will not open, Imagine in your production some people are saying the are unable to use or see apple pay sheet at all and you are tesing in your end with 11.39 two digit cases and you say it is working fine, It tool us 2 days to reproduce the issue
PKPaymentAuthorizationViewController(paymentRequest: paymentRequest)
will return nil , And sorry no documentation for that thing
Recommendation
- Use line items to explain additional charges, discounts, pending costs, and add-on donations. A line item includes a label and cost. Don’t use line items to show an itemized list of products that make up the purchase. I saw apple reject application with this “3.1.6 Apple Pay: Apps using Apple Pay must provide all material purchase information to the user prior to sale of any good or service and must use Apple Pay branding and user interface elements correctly, as described in the Apple Pay Identity Guidelines and Human Interface Guidelines. Apps using Apple Pay to offer recurring payments must, at a minimum, disclose the following information:”
- Provide a business name after the word PAY on the same line as the total. Use the same business name people will see when they look for the charge on their bank or credit card statement. This provides reassurance that payment is going to the right place. For example: PAY [BUSINESS_NAME].
- paymentSummaryItems the last index apple automatically male it as Bold, it expect last item in this array will be total so it makes it bigger
As shown in Figure 9 there is another way to present Apple Pay payment sheet using PKPaymentAuthorizationController
PKPaymentAuthorizationController vs PKPaymentAuthorizationViewController
The PKPaymentAuthorizationController
class performs the same role as the PKPaymentAuthorizationViewController
class, but it does not depend on the UIKit framework. This means that the authorization controller can be used in places where a view controller cannot (for example, in watchOS apps or in SiriKit extensions). So PKPaymentAuthorizationViewController
we can present on our view and PKPaymentAuthorizationController
do all things itself. In short we have two ways to open apple pay sheet. We will use PKPaymentAuthorizationViewController
in this tutorial
STEP 8 → Implement Delegate
As shown in Figure 10 we implemented two important delegates method
1. paymentAuthorizationViewController:didAuthorizePayment:
- Tells the delegate that the user has authorized the payment request and asks for a result. This method gives you
PKPayment
object and you need to returnPKPaymentAuthorizationResult
PKPayment
object holds the Apple Pay authorization token, you send this token to your own server or third party processor , which do actual transaction. You wait for the processor to signal weather transaction is failed or not usingPKPaymentAuthorizationResult.
In our case we assume transaction is successful.- If you return
PKPaymentAuthorizationResult
success case iOS display a nice check mark on the sheet as shown in Figure 10 , if something goes wrong in which case we tell the user what happened you in red message - Ideally you shouldn’t dismiss the view controller in this delegate
2. paymentAuthorizationViewControllerDidFinish:
- Sent to the delegate when payment authorization is finished. This may occur when, the user
cancels
the request, or after thePKPaymentAuthorizationStatus
parameter of thepaymentAuthorizationViewController:didAuthorizePayment:completion:
has been shown to the user. The delegate is responsible for dismissing the view controller in this method.
We will explore these method , in later section . This is the only simple example
Can we test Apple pay in simulator:
Yes. You can test apple pay using iOS 9 simulator. So you don’t need to add any testing sheet instead PKPaymentAuthorizationViewController
. It’s working on iOS 9 simulator. Make sure your app run on iPhone 6, iPhone 6 plus or latest version of simulator. But you can only test frontend part , means you can’t test with your backend because The simulator Apple Pay flow won’t return a valid payment token (payment.token.paymentData is empty (payment.token.paymentData.llength == 0
), which could cause some people to trip up!. In addition to this It provides simulated cards for all the supported payment networks and returns dummy payment data in plain text. On a device, this data is encrypted with your merchant identifier and must be decrypted either on your server or by your payment processor. In previous examples I used fake merchantIdentifier
and it is working fine . .
Use the Apple Pay Sandbox environment to test your app on a device with test cards.
Create a Sandbox Tester Account
To test Apple Pay on your sandbox site, you’ll need to use the Apple Pay Sandbox. Getting it setup takes just a few minutes and below are the steps you have to follow:
- If you don’t have one already, create an Apple Developer account.
- Log into iTunes Connect.
- Select Users and Roles, then select the Sandbox Testers link at the top of the page.
- Next to “Testers”, click ⊕ to create a new test user. Fill out the page, taking note of the email and password you used, and click Save on the upper right.
Important: If you mistakenly use a sandbox tester account to sign in to a production environment, like iTunes, on your test device instead of your test environment, the sandbox account becomes invalid and can’t be used again. If this happens, create a new sandbox tester account with a new email address.
Adding a Test Card Number on Real Device(iOS 13 devices)
- Sign out of iTunes & App Store on your device
- Sign out of iCloud
- Run app on device, and tap on Apple pay Button
- When prompted for an ID/Password, enter the Sandbox Tester credentials.
- It took entering the credentials a couple of times, but now you Setting → Tap on iTunes you will see SandBox Environment
- Go to Wallet and tap Add Credit or Debit Card.
- Tap Add Credit or Debit Card, then when prompted to photograph your card tap Enter Card Details Manually.
- Enter 4761 1200 1000 0492, expiration 11/2022, CVV 533 (this is a test Visa card; for more test cards see the Apple Pay Sandbox Guide).
Note: To provision test cards on your device and use the sandbox, you will need to make sure that your device’s region is set to a country or region that supports Apple Pay. Means as shown in Figure 11 we used Visa test card your device region should match or your region should have availability of VISA
Real Device With Wrong Merchant Identifier
If you run the application with wrong merchant identifier , it will not present the payment authentication sheet , and log in the error on the console
Failed to present in-app payment interface: Error Domain=PKPassKitErrorDomain Code=4 “No entitlement for merchant identifier: merchant.com.ali.com” UserInfo={NSLocalizedDescription=No entitlement for merchant identifier: merchant.com.ali.com}
As show in Figure 12 , you get the payment token on sandbox environment on real device. Note this token will use to test our backend integration, like certificate is working fine . It replicated what we get in production.
On Figure 13 , token we get the simulated and can’t be used to test backend integration
Request Billing Information
A billing address is the address connected to a specific form of payment, which is typically a credit or debit card. Companies use the billing address to verify the authorized use of such a card. It is also where companies send paper bills and bank statements. Billing addresses must match what the card issuing bank has on file, or the attempted purchase may not go through. When the cardholder moves, the billing address must change to match the holder’s current address. This can be accomplished by contacting the card issuing bank.
requiredBillingContactFields →
The fields of billing information that you require from the user to process the transaction.Use requiredBillingContactFields
to request the user's billing address that is associated with their payment method
As shown in Figure 14 , we added requiredBillingContactFields
while creating our PKPaymentRequest object
As show in Figure 15 , we didn’t provide billing address , so it ask us to give in the sheet . Tap on ! mark and you can search already exists or enter manually
As shown in Figure 16, we get extracted billing address , Apple are hopping that you don’t need the billing information just for verification purpose , But it is available if your system still requires it.
As shown in Figure 17 we validate address locally and send specific error to user instead of telling generic error like Invalid Billing address
It will make the error field red so user can , easily update it’s billing information
Request Shipping Information
requiredShippingContactFields →
The fields of shipping information that you require from the user to fulfill the order. Use requiredShippingContactFields
to request the user's address and other contact information that you require to fulfill the order. You will receive the customer’s name when you request postalAddress
. If you don't need the customer's address, you can request the name
contact field directly.
As shown in Figure 19 , we requested apple pay to give user shipping address, if you selling physical products and you need to send it someone you’ll want a shipping address as well , It’s very easy for customer to change the shipping information. Since phone number is not provided it gives the error
As shown inn Figure 20 , we display error on payment sheet after validating shipping address and same as billing address user can look what actual failed , in this case invalid zip code.
PKPayment →
Represents the result of authorizing a payment request and contains payment information, encrypted in the payment token.
PKPaymentToken →
Contains the user’s payment credentials. The information used to process a payment has a nested data structure. A payment token is an instance of the PKPaymentToken
class. The value of its paymentData
property is a JSON dictionary, which has a header with information used for validation, and encrypted payment data. The encrypted data includes information such as the amount and cardholder name and other information used for the specific payment processing protocol.
Flow After You Send Payment Token to Server / Payment processing platform
- First you Send the payment information to your server, along with other information needed to process the order on
paymentAuthorizationViewController: didAuthorizePayment
delegate method - Server Verifying the hashes and signature of the payment data, using certificate we uploaded to their portal
- Decrypting the encrypted payment data with same certificate we uploaded to their portal
- Submitting payment data to the payment processing network (Actual Acquiring Bank)
- Return response weather success or fail, rememberer you are waiting in your delegate until the server response