Streaming is available in most browsers,
and in the Developer app.
-
What’s new in Wallet and Apple Pay
Discover the latest updates to Wallet & Apple Pay. We'll show you how to support Orders in Wallet for your apps and websites and securely validate someone's age and identity with the Identity Verification API. We'll also explore PassKit support for SwiftUI, and discuss how you how you can improve your Apple Pay experience with Automatic Payments.
Resources
- Apple Pay
- Apple Pay Merchant Token Management API
- Apple Pay on the Web
- Apple Pay on the Web Interactive Demo
- ApplePayPaymentRequest
- Example Order Packages
- Human Interface Guidelines: Wallet
- PassKit (Apple Pay and Wallet)
- Requesting identity data from a Wallet pass
- Verifying Wallet identity requests
- Wallet Orders
Related Videos
WWDC23
-
Download
♪ Mellow instrumental hip-hop music ♪ ♪ Lais Minchillo: Hi, my name is Lais. David Silver: And I'm David. And we will be presenting this year's new features in Wallet and Apple Pay. We launched Apple Pay in 2014, setting a new benchmark for making fast, secure, and private payments in store, online and in-app. Since then, we've expanded Apple Pay across the globe. Apple Pay is now available in 72 countries and territories and handles more than a million transactions every day. Today we're introducing exciting new features and APIs into Wallet and Apple Pay. Lais will tell you more. Lais: Thank you, David! Let's take a look at the main agenda for today. First, we'll talk about some quick updates. We are adding support for payments to multiple merchants in a single transaction. We are also greatly improving support for automatic payments, including subscriptions, With order tracking, you can enhance the postpurchase experience for your customers. And finally, David will talk about identity verification with IDs in Wallet. We have a few exciting updates to share. Tap to Pay on iPhone was announced earlier this year and launched in iOS 15.4 in the US. Tap to Pay on iPhone provides a secure, private, and easy way to accept contactless payments. You can easily integrate this into your app to seamlessly and securely accept contactless payments. This includes Apple Pay, contactless credit and debit cards, and other digital wallets. The transaction is completed through a simple tap to the iPhone, removing the need for additional hardware or payment terminals. Meanwhile, in macOS 13, we redesigned the Apple Pay experience. The iOS payment sheet redesign last year was a great success and this year we're bringing a similar experience to macOS. We used SwiftUI to implement this, which helped us bring new features to macOS at the same time as iOS. All of the Apple Pay features we are introducing today are also supported on Mac. We're introducing new SwiftUI APIs. Integrating Add to Apple Wallet or Apple Pay buttons in your SwiftUI app will be much easier. These new APIs will significantly reduce the amount of code you need to write. Let's take a look at how you can add a button to prompt the user to add an airline pass. First, create the pass. You should handle the case where it wasn't successfully loaded. This could happen if the pass data is malformed or if it was not properly signed, for example. Next, call AddPassToWalletButton with an array of passes. In this example, we have an array with only one element, but you can have multiple passes on the same button. The result is passed in as a Bool, and you can save, log, or trigger other actions in your app based on whether the user has added a pass or not. In this example, I'm saving that to a state var. And that's it! You can also customize the button's size and style within a set of minimum values. This is the default size: width 250 and height 50. You could also make it wider...
...or taller.
This wraps up how you can add an Add to Apple Wallet button in SwiftUI. Now, let's see how you can add a Pay with Apple Pay button. First, create a payment request using the PKPaymentRequest class, setting your usual configuration on it. Then, create an authorizationChange method. Now that we have these two pieces ready, let's add code to show the button. Add a call to PayWithApplePayButton, passing in the label, the paymentRequest object, and the authorizationChange method. To handle cases where Apple Pay isn't supported by the current device, you can pass in a fallback view. Just like the Add Pass button, you can also customize its size and style. In total, there are 17 different labels, so you are able to customize the pay button to align with your use case. These are available on iOS, iPadOS, macOS, and watchOS. Now, let's take a look at multimerchant payments. In iOS 16, we're introducing the ability to request multiple payment tokens for different merchants in the same transaction. This is useful for things like online marketplaces, travel bookings, and ticketing services. Let's take a closer look at an example. Imagine Allison is planning a trip. She goes to a travel agency's website and they conveniently offer her all of the things she needs to book -- flight tickets, a hotel stay, and a car rental. Allison just needs to pay a total of $500 dollars. Allison provides the travel agency her full credit card information. Now, you might imagine that the travel agency will charge Allison's credit card $500 dollars, and then pay the other companies involved. But what typically happens is the travel agency simply passes along the credit card information to each company to make their individual charges. This works, but it's not great for Allison's privacy and security to have her credit card information shared around. Now, with the new multimerchant payment API, it's possible to request a payment token for each merchant involved in a transaction. Using these payment tokens, the multiple companies involved can each charge Allison for the relevant amount she authorized. Allison can now book and pay for her trip while taking advantage of the privacy and security benefits that Apple Pay offers. The payment sheet has been updated to show customers a breakdown of the submerchants involved in a transaction. Customers can tap on the total field to navigate to the payment summary. Here, the customer can see a breakdown of all the merchants involved in the transaction, along with the amount authorized for each one. Now, let's look at how you can add multimerchant payments to your app. First, create a payment request using the PKPaymentRequest class, setting your usual configuration on it. Then add summary items for your payment, including the total. Next, create a payment token context for each additional merchant involved in the transaction, using the new PKPaymentTokenContext class. Provide details for each merchant, as well as the amount to authorize for each. Finally, set the payment token contexts on the payment request. Keep in mind that the sum of the amounts for all of your payment token contexts must be less than or equal to the total amount of the payment request itself. Also, you should always use the same external identifier for the same merchant any time you request a payment token for that merchant in your app. For adopting multi-merchant payments with Apple Pay on the web, check out the Apple Pay JS API documentation. Now, let's take a look at our improvements to automatic payments. In iOS 16, we're introducing the ability for people to view and manage automatic payments they've set up with merchants, right from the Wallet app. In this release, we're supporting two types of automatic payments: recurring payments, which includes things like subscriptions, installments, or recurring billing; and automatic reload payments, such as store card balance top-ups. We're introducing new APIs to allow you to request to set up an automatic payment when you make a payment request. We're also introducing Apple Pay merchant tokens, a new kind of payment token tied to a customer's Apple ID, which can help you more reliably charge your customers on an ongoing basis. Let's take a closer look at Apple Pay merchant tokens to see how they can be useful. Imagine Julie is paying for a book club membership using Apple Pay on her iPhone. The book club makes a payment request, and when Julie authorizes the payment, the book club receives a payment token, and every month they can use that to charge Julie her membership fee. This payment token is linked to the device Julie used to authorize the payment. But what happens if Julie gets a new iPhone? With the new automatic payments feature, the book club will instead receive an Apple Pay merchant token, if Julie's payment network supports it. This payment token is tied to Julie's Apple ID, rather than to her iPhone, which provides better assurances for ongoing authorizations. This means that if Julie upgrades her iPhone, or resets her current phone, the book club can continue to reliably charge Julie her monthly membership fee. If you accept Apple Pay for these types of payments, it's a great idea to adopt automatic payments to ensure you can continue reliably charging your customers, as well as avoid any interruption to their services. The first type of automatic payment we're supporting in this release is recurring payments. Recurring payments have a fixed or variable amount that is charged on a regular schedule, such as weekly, monthly, or annually. These payments can end on a certain date or they can be ongoing until canceled. A trial or introductory period is also supported. Subscriptions, installment plans, and regular billing are perfect uses for this type of payment. Let's take a look at how you can set up a recurring payment in your app using automatic payments. Start by specifying the amount and duration of the recurring payment, using the PKRecurringPaymentSummaryItem class. For recurring payments, you can specify both a regular billing period as well as an introductory or trial period. You can use the startDate and endDate properties to indicate when the trial period ends and the regular billing period starts. Next, create a recurringPaymentRequest using the new PKRecurringPaymentRequest class. Provide a description of the payment, the regular billing period, as well as a managementURL to a web page where the customer can update or delete the payment method for the recurring payment. You can also optionally provide a trial billing period as well as billingAgreement text to help explain the terms of the payment to the customer. Finally, you can optionally provide a tokenNotificationURL where your server can receive life cycle notifications about the Apple Pay merchant token for the payment, if one was issued. For example, you can receive notifications if the card issuer or the user deletes the token. For more information about merchant token life cycle notifications, see the Apple Pay Merchant Token Management API documentation. Finally, set the recurringPaymentRequest on the paymentRequest object. A quick note on summary items, your recurring payment will not be added to the payment request's summary items automatically. So be sure to add items for it to the summary items array. The total for the payment request should be the first amount that the customer will be charged. So in this example, the total is set to display the trial period amount, as that's the first amount the customer will be charged. The payment sheet will show details of your recurring payment to customers, and they can tap on the Billing Details section to read further. Now, let's take a look at the second type of automatic payment we're supporting in this release: automatic reload payments. With this type of payment, a balance is automatically topped up with a fixed amount whenever the balance drops below a certain threshold amount. Automatic reload payments are perfect for things like store card top-ups and prepaid balances. To request to set up an automatic reload payment, start by specifying the reload and threshold amounts, using the new PKAutomatic ReloadPaymentSummaryItem class. Next, create an automaticReloadPaymentRequest using the new PKAutomatic ReloadPaymentRequest class, passing in a description of the payment, the billing, and a management URL, just like for recurring payments. You can also optionally provide billing agreement text and a token notification URL. Finally, set the automatic reload payment request on the payment request object. Again, be sure to include your automatic reload payment in the summary items and set the total of the paymentRequest appropriately. For adopting automatic payments with Apple Pay on the web, check out the Apple Pay JS API documentation. Here's how the automatic reload payment appears in the payment sheet for your customers. Finally, here's a few things to remember to help give your customers the best possible experience when you adopt automatic payments in your app. Remember to include summary items for your automatic payment as these are not added for you. The total amount of your payment request should be the first amount the customer will be charged. You should keep the billing agreement text short. The payment sheet will only show the first 500 characters. The billing agreement text is not intended to replace your normal billing and legal agreements. It's up to you to be compliant with your local recurring billing laws. If you have a legal agreement to show the customer, that might mean displaying it to the customer before you present the payment sheet. You can only request one type of automatic payment in a single transaction. Also, automatic payments cannot be used with multi-merchant payments. Finally, if you want to receive life cycle notifications for the Apple Pay merchant token issued for the payment, be sure to provide a token notification URL and adopt the Apple Pay Merchant Token Management API on your server. We think you'll love these new APIs and the benefits of Apple Pay merchant tokens. Here are just a few of our partners that will also be adopting support for automatic payments. Apple Pay merchant tokens will be supported by American Express, Discover, Mastercard, and Visa, with support for other payment networks in the future. We are excited to introduce Order Tracking to enhance the postpurchase experience. New in iOS 16, order tracking allows users to track orders placed with participating merchants. Wallet now provides an intuitive overview of active orders, recently completed orders, and past orders. I currently have a single active order for some bakery goods. My order is still in processing; I'll get back to that later. For now, I want to buy some toys and accessories for my cat from Pet Avenue. I choose to check out with Apple Pay. Shortly after I authorize the payment, I receive a notification to track my order in Wallet. Interacting with that notification takes me to the details of my order where I can check the current status. I can see the order status, including shipping and tracking information, and the list of line items I have ordered. Further below, I have multiple options to contact Pet Avenue, check the payment information, and go back to Pet Avenue's app. Now, imagine Pet Avenue is really fast in processing incoming orders and they just shipped my items. As soon as Pet Avenue shipped my order, they have updated the available information. I can see the status changed to "On the Way," with an estimated delivery date of June 10th. They also included a custom message and tracking information for the shipment. Oh, remember my baking goods? I just got a notification that they are ready for pickup. Let's check it out. I have ordered my bakery goods for pick up. They are ready for pick up, that's great! Bake My Breath Away has provided my pickup window, pickup instructions, and a barcode to present upon arrival. We've seen that order tracking works seamlessly with Apple Pay. Let's have a look at how you can integrate order tracking into your customer experience. To get started with order tracking, first, you must create an Order Type ID in your developer account. An Order Type ID identifies your organization as an entity that provides order information. You can register multiple Order Type IDs -- for example, to provide order information on behalf of multiple merchants. Also create an Order Type ID Certificate. You will use the certificate to build order packages and update orders. Orders are distributed as order packages. An order package includes all the metadata and information for an order. It can represent a wide range of scenarios, including shipping, pickup, and multifulfillment orders. An order package also includes images, like your logo and line item images. You can also add localizations to support your diverse range of customers. Every order package must be cryptographically signed to verify its origin. Once everything is in place, order packages are compressed for distribution. Check out the sample order packages attached to this session. And for more information on order packages, see the developer documentation. Adding an order to Wallet works seamlessly with Apple Pay. When your customer authorized a payment, your app or web page receives payment information, then sends it to your server for processing. If processing the payment information succeeds, your server creates an order and some metadata. Your server then returns details about that order to your app or web page to include in the result. The order details enable the device to asynchronously request the order from your server. Your server then returns the order package to the device. When your server creates an order, assign an Order ID that is unique within the namespace of your Order Type ID. Your server must also generate a secure authentication token. This is a shared secret that is part of the order details. The device will use the token to authenticate itself when it requests the order. Let's take a look at an example for returning a payment authorization result. When your customer authorized a payment, your app sends the payment information to your server and asks it to create an order. Check whether the server result indicates success and handle any error returned by your server. If the server result does indicate success, complete the payment with an appropriate authorization result. To return a payment authorization result with order details, first, extract them from the server result. Then create a PKPaymentOrderDetails object with the Order Ttype ID, Order ID, the URL to your server, and the authenticationToken. Assign the PKPaymentOrderDetails object to the new orderDetails property on PKPaymentAuthorizationResult. That's it! You can complete a payment with order details on the web too. As before, extract the order details from the server result. Then include the order details in the data you complete the payment with. To be able to update an order, create an order package that indicates support for automatic updates. When the order is added, the device will register for updates to it. Your server must store information about registrations. Later on, when your server updates the order, use the registration information to notify devices that registered for updates to it. When the device receives the push notification, it will again request the order from your server. Your server then returns the updated order package to the device. Only your customers and you should know what they have ordered. We designed order tracking with privacy in mind. Order information is exchanged directly between devices and your server. When orders are synchronized via iCloud, they are end-to-end encrypted. Follow these practices to provide the best customer experience possible. Associate your app with orders that you provide. If your app delivers notifications and is installed, you can disable order tracking notifications. This helps to prevent duplicate notifications. Use the knowledge you have about your customer preferences to provide relevant localizations only. Be mindful of the order package size. Try to keep the size small to reduce expensive networking cost. When you update an order, promptly notify devices that registered for updates to it. Orders in Wallet should match the actual state of the order. Make sure to also check out the HIG for order tracking. Platforms can make your integration of order tracking much simpler. We are happy to announce Shopify, Narvar, and Route will support order tracking by fall. Look out for more platforms supporting order tracking in the coming months. Order tracking is a great way to enhance the postpurchase experience for your customers. With automatic updates, your customers will always be up to date about the status of their orders. We believe your customers will love this experience and we look forward to ordering with you soon! Now, I'll pass over to David. David: Thanks, Lais! I'm super excited to talk about the new functionality we've added to IDs in Wallet in iOS 16. We launched IDs in Wallet earlier this year in iOS 15.4. It allows users in supported US states to add their driver's license or State ID to Wallet. IDs in Wallet are issued by the same issuing authorities as users' physical IDs. in the US, that's their State's Department of Motor Vehicles or equivalent organization. In iOS 16, we've added a new API that allows apps and App Clips to request information from IDs in Wallet in order to verify a user's age or identity. Your app will request the information, the user will review and approve the request, Then your app will send the response to your server for decryption and verification. You can request a number of data elements from the user's ID. These include their name, their address, their date of birth, their photo -- known as the portrait -- the issuing authority that issued their ID, the number and expiration date of their physical ID, and the driving privileges granted by their ID, if there are any. A very common use case for IDs is to verify someone's age. With a physical ID, that means looking at their date of birth. But the date of birth reveals far more information than is necessary just to verify age. If you're checking my age, you don't actually need to know the exact day or year I was born, or even how old I am. You just need to know if I'm old enough. With IDs in Wallet, you can ask that question directly. Your app can request a Boolean data element indicating whether the user is above a certain age, providing a more privacy-preserving way to do age verification than checking the full date of birth. When your app invokes the API, a sheet will show the user what information you're requesting. It will also show whether you intend to store that information, and for how long you intend to store it. This lets the user make an informed decision about whether to share the information with your app. No information is shared until they give their explicit approval using Face ID or Touch ID. The response you receive contains just the elements you requested. Other identity verification mechanisms, such as scanning a physical ID card, share everything that's on the ID. By limiting the sharing to just what you need, IDs in Wallet is more privacy-preserving for the user and reduces the amount of sensitive information you need to keep secure on your server. The response is signed by the ID's issuing authority, making it straightforward to verify that the information in the response is authentic. Note that the issuing authority creates the ID but is not involved at the time you invoke the API. They do not learn when users share their information or to whom they share it with. To use the API, you need to request an entitlement through your developer account. You'll then need to set up a merchant ID and encryption certificate. This process is very similar to setting up in-app payment with Apple Pay. We'll talk more about how to use the ID and certificate in a little bit. For now, let's talk about the verification flow. At a high level, it consists of four steps. First, your app will invoke the API in the PassKit framework and specify the information you're requesting. The system will then display a sheet prompting the user to approve the request. Once they do, your app will receive an encrypted response. Your app will then pass that response to your server for decryption and verification. First, let's talk about how to use the API in PassKit. If your app uses SwiftUI, you should use the VerifyIdentityWithWalletButton SwiftUI view. This displays a button that triggers the identity verification flow when pressed. Just like the Pay with Apple Pay and Add Pass to Wallet buttons, the Verify Identity with Wallet button provides a familiar, consistent experience across apps using the API. You can choose between four different labels to display a button that fits your use case. It automatically switches between single and multiline versions depending on the space available to it. When creating the button, you need to specify a PKIdentityRequest object, which describes the information you want to request and how it should be returned. Let's take a look at how to create it. You begin by creating a PKIdentityDrivers LicenseDescriptor, which describes the data elements that you're looking for. Use the addElements method to specify elements you want to request, along with whether you intend to store them. You can invoke the addElements method multiple times to specify different sets of elements with different intents to store. In this example, I'm calling it twice. First, I add an age(atLeast: element, which is not going to be stored. Then, I call the addElements method again to request the user's givenName, familyName, and portrait, all of which may be stored for up to 30 days. The descriptor then goes into a PKIdentityRequest. The next step is to specify a merchantIdentifier to use. The merchantIdentifier indicates the encryption certificate to which the API response will be encrypted. You'll configure both the merchantIdentifier and its encryption certificate through your developer account. Finally, you'll need to specify a nonce, which will be tied to the response you receive from the API. Its an important security feature used to prevent replays of a response and to bind it to a specific user session. Exactly how you manage the nonce is up to you, based on your own security requirements. Often, it comes from your server, because later on, your server will be responsible for enforcing that the nonce is valid. With all of those properties set, you have your PKIdentityRequest. Now, let's get back to the button. If identity verification is available, the button will be displayed in your app, and tapping it will start the identity verification flow with your request. If identity verification is not available, a fallback view you specify will be displayed instead. For example, this will happen if there isn't an ID in Wallet on this iPhone. You can use the fallback view to offer other ways to verify identity. Let's assume identity verification is available, and the user taps the button. The system will then show a sheet with your request, including the elements you requested and your intent to store them. The user can approve the request with Face ID or Touch ID, or close the sheet without approving. Your code will then receive a result object containing the outcome of the request. If the request was approved, you'll receive a success result. This comes with a PKIdentityDocument object containing the encrypted response, which your app will send to your server for decryption and verification. If the request was not successful, you'll receive a failure result. The most common cause of failure is that the request was not approved, in which case you'll receive a cancelled error. That was VerifyIdentityWithWalletButton, the SwiftUI version of the API. Use it to display a button that launches the identity verification flow and requests information from IDs in Wallet. If you're not using SwiftUI in your app, you can also use the PKIdentityButton and PKIdentityAuthorization Controller classes to accomplish the same thing. OK, so, now you've requested the information, the user's approved the request, and your app has sent the encrypted response to your server. Now, let's talk about what your server needs to do to decrypt and verify that response. I'm only going to skim the surface on this topic, so please check the developer documentation for more details. The response format uses several international standards, so I strongly recommend familiarizing yourself with those as well. The response data you'll receive is in a CBOR-encoded encryption envelope. CBOR is a data format defined in RFC 8949. It's similar to JSON but uses binary data to encode objects. The encryption envelope contains metadata needed for the decryption process, along with the encrypted data itself. The data is encrypted using HPKE, an encryption scheme defined in RFC 9180. Your server will decrypt this data using its private key. Once decrypted, you'll get an mdoc response object. The mdoc response is defined in ISO 18013 part five, the ISO standard for mobile Driver's Licenses and State IDs. The mdoc response object contains the data elements that you requested. It also includes a number of security features that your server needs to validate to ensure that the response is authentic. Note that your server will perform the decryption and validation itself. Neither Apple servers nor the issuing authority's servers are involved. Before we can talk about decryption and response validation, we need to talk about the session transcript. This is a CBOR structure that binds a response payload to a specific request from a specific app. Your server will need to build this structure and use it during both decryption and validation. The session transcript contains the same nonce and merchant ID you used earlier in your PKIdentityRequest, as well as the team ID of your developer team and the SHA256 hash of your encryption certificate's public key. When building the session transcript, your server should check that the inputs you're using are all valid. That means the nonce shouldn't have been used already, and should be tied to the current user. The other values should match what's expected on your developer account. Now let's talk about decrypting the encrypted data. You'll need the session transcript you just created, along with the metadata from the encryption envelope. You'll also need your private key. This is the private key corresponding to the certificate you setup earlier in your developer account. To protect the confidentiality of user information, you need to make sure your private key stays private. Store it securely on your server and never include it in your app. If your private key is ever compromised, revoke the certificate in your developer account immediately. After decrypting the encrypted data, you'll receive an mdoc response object containing two cryptographic signatures, plus the data elements you requested. You need to check both signatures in the mdoc response before you can use its data elements. First, you need to check the issuer signature. This is a signature from the issuing authority of the user's ID. By checking this signature, you're verifying that the data in the response came from the real issuing authority and wasn't tampered with. You should check that not only is the signature valid, but also that it is signed by an issuer certificate you trust. Take a look at the documentation for more details about the issuer certificates used by IDs in Wallet. Next, you need to verify the device signature. This is a signature created by a key in the Secure Element of the user's iPhone. It proves that the response you received came from the same iPhone that the issuing authority originally issued the ID to. Here, you'll need to use your session transcript again, along with some information covered by the issuer signature. Finally, you're ready to use the data elements that you requested. You should never use these elements without first verifying the issuer and device signatures, because otherwise you don't know whether the data you received is authentic. And with all those steps completed, you're done! Your app has requested the information, and your server has decrypted and verified the response. You might be wondering how to test your implementation if you don't have an ID in Wallet. We've provided a few mechanisms to help you do that. First, you can test in the iOS Simulator, where the API will return a mock response. This response is similar to a real one, but lacks real signatures. Similarly, you can use a test profile to receive a mock response on a real iPhone, even If you don't have an ID in Wallet on that iPhone. See the documentation for more details about how to do this. Note that your server should never treat either of these mock responses like a real one. To help you with your server implementation, the documentation also includes an example response, along with everything you need to decrypt and validate it. And that's how you can perform identity verification with IDs in Wallet in iOS 16. We discussed how to use the API in your app, how to process the response on your server, and how to test your implementation. Lais: This year, we introduced many great new features to Wallet and Apple Pay. These include multi-merchant payments, improved support for automatic payments, order tracking, and identity verification. Please check out the developer documentation for more information. David: Thank you for watching, and have a great WWDC! ♪
-
-
2:39 - AddPassToWalletButton
@State var addedToWallet: Bool @ViewBuilder private var airlineButton: some View { if let pass = createAirlinePass() { AddPassToWalletButton([pass]) { added in addedToWallet = added } .frame(width: 250, height: 50) .addPassToWalletButtonStyle(.blackOutline) } else { // Fallback } }
-
3:40 - PayWithApplePayButton
// Create a payment request let paymentRequest = PKPaymentRequest() // ... // Create a payment authorization change method func authorizationChange(phase: PayWithApplePayButtonPaymentAuthorizationPhase) { ... } PayWithApplePayButton( .plain, request: paymentRequest, onPaymentAuthorizationChange: authorizationChange ) { // Fallback } .frame(width: 250, height: 50) .payWithApplePayButtonStyle(.automatic)
-
6:34 - Multi-merchant payments
// Create a payment request let paymentRequest = PKPaymentRequest() // ... // Set total amount paymentRequest.paymentSummaryItems = [ PKPaymentSummaryItem(label: "Total", amount: 500) ] // Create a multi token context for each additional merchant in the payment let multiTokenContexts = [ PKPaymentTokenContext( merchantIdentifier: "com.example.air-travel", externalIdentifier: "com.example.air-travel", merchantName: "Air Travel", merchantDomain: "air-travel.example.com", amount: 150 ), PKPaymentTokenContext( merchantIdentifier: "com.example.hotel", externalIdentifier: "com.example.hotel", merchantName: "Hotel", merchantDomain: "hotel.example.com", amount: 300 ), PKPaymentTokenContext( merchantIdentifier: "com.example.car-rental", externalIdentifier: "com.example.car-rental", merchantName: "Car Rental", merchantDomain: "car-rental.example.com", amount: 50 ) ] paymentRequest.multiTokenContexts = multiTokenContexts
-
10:14 - Automatic Payments - Recurring payment request
// Specify the amount and billing periods let regularBilling = PKRecurringPaymentSummaryItem(label: "Membership", amount: 20) let trialBilling = PKRecurringPaymentSummaryItem(label: "Trial Membership", amount: 10) let trialEndDate = Calendar.current.date(byAdding: .month, value: 1, to: Date.now) trialBilling.endDate = trialEndDate regularBilling.startDate = trialEndDate // Create a recurring payment request let recurringPaymentRequest = PKRecurringPaymentRequest( paymentDescription: "Book Club Membership", regularBilling: regularBilling, managementURL: URL(string: "https://www.example.com/managementURL")! ) recurringPaymentRequest.trialBilling = trialBilling recurringPaymentRequest.billingAgreement = """ 50% off for the first month. You will be charged $20 every month after that until you cancel. \ You may cancel at any time to avoid future charges. To cancel, go to your Account and click \ Cancel Membership. """ recurringPaymentRequest.tokenNotificationURL = URL( string: "https://www.example.com/tokenNotificationURL" )! // Update the payment request let paymentRequest = PKPaymentRequest() // ... paymentRequest.recurringPaymentRequest = recurringPaymentRequest // Include in the summary items let total = PKRecurringPaymentSummaryItem(label: "Book Club", amount: 10) total.endDate = trialEndDate paymentRequest.paymentSummaryItems = [trialBilling, regularBilling, total]
-
12:39 - Automatic Payments - Automatic reload payment request
// Specify the reload amount and threshold let automaticReloadBilling = PKAutomaticReloadPaymentSummaryItem( label: "Coffee Shop Reload", amount: 25 ) reloadItem.thresholdAmount = 5 // Create an automatic reload payment request let automaticReloadPaymentRequest = PKAutomaticReloadPaymentRequest( paymentDescription: "Coffee Shop", automaticReloadBilling: automaticReloadBilling, managementURL: URL(string: "https://www.example.com/managementURL")! ) automaticReloadPaymentRequest.billingAgreement = """ Coffee Shop will add $25.00 to your card immediately, and will automatically reload your \ card with $25.00 whenever the balance falls below $5.00. You may cancel at any time to avoid \ future charges. To cancel, go to your Account and click Cancel Reload. """ automaticReloadPaymentRequest.tokenNotificationURL = URL( string: "https://www.example.com/tokenNotificationURL" )! // Update the payment request let paymentRequest = PKPaymentRequest() // ... paymentRequest.automaticReloadPaymentRequest = automaticReloadPaymentRequest // Include in the summary items let total = PKAutomaticReloadPaymentSummaryItem( label: "Coffee Shop", amount: 25 ) total.thresholdAmount = 5 paymentRequest.paymentSummaryItems = [total]
-
19:17 - Order Tracking (swift)
func onAuthorizationChange(phase: PayWithApplePayButtonPaymentAuthorizationPhase) { switch phase { // ... case .didAuthorize(let payment, let resultHandler): server.createOrder(with: payment) { serverResult in guard case .success(let orderDetails) = serverResult else { /* handle error */ } let result = PKPaymentAuthorizationResult(status: .success, errors: nil) result.orderDetails = PKPaymentOrderDetails( orderTypeIdentifier: orderDetails.orderTypeIdentifier, orderIdentifier: orderDetails.orderIdentifier, webServiceURL: orderDetails.webServiceURL, authenticationToken: orderDetails.authenticationToken, ) resultHandler(result) } } }
-
20:13 - Order Tracking (JS)
paymentRequest.show().then((response) => { server.createOrder(response).then((orderDetails) => { let details = { }; if (response.methodName === "https://apple.com/apple-pay") { details.data = { orderDetails: { orderTypeIdentifier: orderDetails.orderTypeIdentifier, orderIdentifier: orderDetails.orderIdentifier, webServiceURL: orderDetails.webServiceURL, authenticationToken: orderDetails.authenticationToken, }, }; } response.complete("success", details); }); });
-
27:05 - VerifyIdentityWithWalletButton 2
@ViewBuilder var verifiyIdentityButton: some View { VerifyIdentityWithWalletButton( .verifyIdentity, request: createRequest(), ) { result in // ... } fallback: { // verify identity another way } }
-
27:18 - Create a PKIdentityRequest
func createRequest() -> PKIdentityRequest { let descriptor = PKIdentityDriversLicenseDescriptor() descriptor.addElements([.age(atLeast: 18)], intentToStore: .willNotStore) descriptor.addElements([.givenName, .familyName, .portrait], intentToStore: .mayStore(days: 30)) let request = PKIdentityRequest() request.descriptor = descriptor request.merchantIdentifier = // configured in Developer account request.nonce = // bound to user session }
-
27:19 - VerifyIdentityWithWalletButton 3
@ViewBuilder var verifiyIdentityButton: some View { VerifyIdentityWithWalletButton( .verifyIdentity, request: createRequest(), ) { result in // ... } fallback: { // verify identity another way } }
-
29:37 - VerifyIdentityWithWalletButton 4
@ViewBuilder var verifiyIdentityButton: some View { VerifyIdentityWithWalletButton( .verifyIdentity, request: createRequest(), ) { result in switch result { case .success(let document): // send document to server for decryption and verification case .failure(let error): switch error { case PKIdentityError.cancelled: // handle cancellation default: // handle other errors } } } fallback: { // verify identity another way } }
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.