-
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.
Recursos
- Example Order Packages
- ApplePayPaymentRequest
- Apple Pay Merchant Token Management API
- Wallet Orders
- Human Interface Guidelines: Wallet
- Verifying Wallet identity requests
- Requesting identity data from a Wallet pass
- Apple Pay on the Web Interactive Demo
- Apple Pay on the Web
- PassKit (Apple Pay and Wallet)
- Apple Pay
Videos relacionados
WWDC23
-
Buscar este video…
-
-
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 } }
-