Composable Frontend 2.0 Learn more 

  • Payments/
    Payment Gateways/
    Integrate Apple Pay

    Integrate Apple Pay with Swift

    This walkthrough shows you how to integrate Apple Pay into an existing iOS app. After you integrate with Apple Pay, end users can pay for an order on their iPhones.

    Prerequisites

    If you want to follow along, you need the following items:

    • An Apple Developer account.
    • A Composable Commerce account with an existing project. At minimum, you need:
      • Configured products
      • Configured payment gateway (manual)

    Step-by-step walkthrough

    Feel free to skip to the end, and grab the completed example project by clicking the source code links under Further Reading, or follow the step-by-step walkthrough.

    1. Get the code from GitHub.
    2. Set up the iOS app project.
    3. Display a product.
    4. Update your store.
    5. Set up Apple Pay credentials.
    6. Set up an Apple Pay project.
    7. Add an Apple Pay button.
    8. Create an Apple Pay request.
    9. Handle shipping.
    10. Implement Apple Pay delegates.
    11. Create a checkout in Composable Commerce.
    12. Create payment transactions.

    Get the code from GitHub

    In a terminal:

    git clone https://github.com/moltin-examples/applepay-starter.git
    

    Then navigate into the new directory, and install the CocoPods:

    pod install
    

    Set up the iOS app project

    Open the workspace project in Xcode, and run to confirm everything is working.

    Open the workspace project.

    Display a product

    The app as it stands is a simple Master/Detail application that shows a list of products from a demo store in the master view. Tap on any product to navigate to a detail view which shows a bigger picture of the swag as well as a more detailed description.

    Update your store

    Update the store ID in MoltinProductsViewController to use your products:

    //Replace with your client id
    let moltin = Moltin(withClientID: "u8cV0fAtS8ELXcyxWY2r4deLTHs1i3NkgV8rt7ZqWX")
    

    Set up Apple Pay credentials

    1. Log in to your developer account.
    2. Go to Member Center, and click Certificates, Identifiers & Profilesstrong\Identifiers\App IDs.
    3. Click the + button to create a new App ID.
    4. Name the Apple ID with either your app name or use Apple MoltinProducts, and give it a Bundle ID in the format: com.YOURDOMAIN.MoltinProducts. If you already have a project, substitute the names accordingly.
    5. Make sure that Explicit App ID is selected, as wildcard App IDs aren’t able to make payments with Apple Pay.
    6. Under App Services, enable the Apple Pay checkbox, click Continue, and then click Submit to complete the creation of your new App ID.
    7. Under Identifiers, click Merchant IDs in the left navigation pane.
    8. Click + to create a new merchant ID, and use whatever description and merchant identifier you’d like. Generally, it’s recommended to create merchant identifiers in the reverse domain style that start with merchant, similar to bundle IDs.
    9. Click Continue, and then click Register to create your new merchant ID.

    Now that your App ID and merchant ID are set up, head back to Xcode to get your project ready for Apple Pay.

    Set up Apple Pay project

    1. Select the MoltinProducts project in the left navigation bar, then select the MoltinProducts target, and change the Bundle Identifier to match the one you created previously.
    2. Ensure that the Team selection box is pointing to the development team under which you created your App ID and merchant ID.
    3. Click the Capabilities tab, expand the Apple Pay section, and ensure that the switch on the right is set to ON.
    4. Push the refresh button below the merchant ID list. You should see the list populates with the merchant ID you added on the developer portal, if it wasn’t there already.
    5. Make sure that your merchant ID checkbox is selected.

    At this point, you should have checkmarks next to all sections that deal with setting up a project, displaying a product, and setting up Apple Pay credentials. If any of the sections is not marked as checked, retrace your steps and correct the details to make sure you’ve satisfied Apple’s requirements.

    You now have Apple Pay enabled in your app.

    Add Apple Pay button

    Open Main.storyboard and take a look at the Buy Product scene.

    Add a pay button.

    Apple has a very specific set of Apple Pay guidelines to adhere to, which extends to the buttons in your app. Take a few minutes to review these guidelines at the Apple Pay developer site.

    The Apple Pay Buttons and Resources link at the Apple Pay developer site provides you with a zip file. The file contains an extensive collection of approved button resources for Apple Pay.

    You can find a set of Apple Pay images ready for use in the starter project’s Image.xcassets.

    Using the Buy Product Interface Builder, select the Apple Pay button, and change the image to ApplePay. Give your button an empty title instead of the default “button” title. Your scene should now look as follows:

    Add a button name and image.

    Create Apple Pay request

    1. Open BuyProductViewController.swift and add the following import to the top of the file:

      import PassKit
      
    2. Locate applePayPressed(sender:); you execute this when the user attempts to purchase an item. To do this, you’ll need to create a PKPaymentRequest and a PKPaymentAuthorizationViewController.

    3. Locate applePayPressed(sender:); you execute this when the user attempts to purchase an item. To do this, you’ll need to create a PKPaymentRequest and a PKPaymentAuthorizationViewController.

    4. Add the following code to the body of applePayPressed(sender:):

      // TODO: - Fill in implementation
      let request = PKPaymentRequest()
      let applePayController = PKPaymentAuthorizationViewController(paymentRequest: request)
      self.present(applePayController!, animated: true, completion: nil)
      
    5. Add the following code just under the IBOutlet properties of BuySwagViewController:

      let SupportedPaymentNetworks =[PKPaymentNetwork.visa, PKPaymentNetwork.masterCard, PKPaymentNetwork.amex]
      // Add in any extra support payments.
      let ApplePayMerchantID = "merchant.com.YOURDOMAIN.ApplePayMoltin"
      // Fill in your merchant ID here!
      
    6. In the viewDidLoad, check to see if the user can use Apple Pay.

      applePayButton.hidden = !PKPaymentAuthorizationViewController.canMakePaymentsUsingNetworks(SupportedPaymentNetworks)
      
    7. Now start filling out the request in applePayPressed(sender:), under the let request = PKPaymentRequest().

      request.merchantIdentifier = ApplePayMerchantID
      request.supportedNetworks = SupportedPaymentNetworks
      request.merchantCapabilities = PKMerchantCapability.capability3DS
      request.countryCode = "US"
      request.currencyCode = "USD"
      
    8. Create an array of PKPaymentSummaryItem objects that provide the user with a breakdown the items they’re purchasing. We add more detail to this array in the next step.

      //Item information formatting
      let productToBuy = PKPaymentSummaryItem(label: product?.name ?? "", amount: NSDecimalNumber(decimal:Decimal((self.product?.meta.displayPrice?.withoutTax.amount)!/100)), type: .final)
      let total = PKPaymentSummaryItem(label: "Total with Tax", amount: NSDecimalNumber(decimal:Decimal((self.product?.meta.displayPrice?.withTax.amount)!/100)))
      //PKPaymentSummaryItem Array, we are adding too.
      request.paymentSummaryItems = [productToBuy,total]
      
    9. Run the app to confirm whether you see Apple Pay when you hit the Apple Pay button on the buy scene.

    Verify that you can see Apple Pay.

    Handle shipping

    We add a static billing amount to start. Billing needs are going to differ greatly on what your store is selling.

    let shippingPrice: NSDecimalNumber = NSDecimalNumber(string: "5.0")
    let shipping = PKPaymentSummaryItem(label: "Shipping", amount: shippingPrice)
    let totalPrice = PKPaymentSummaryItem(label: "Total amount", amount: NSDecimalNumber(decimal:Decimal((self.product?.meta.displayPrice?.withTax.amount)!)/100).adding(shippingPrice))
    
    
    //PKPaymentSummaryItem Array
    request.paymentSummaryItems = [productToBuy,shipping, totalPrice]
    

    Implement Apple Pay delegates

    In BuyProductViewController.swift, add the following extension to BuyProductViewController that implements PKPaymentAuthorizationViewControllerDelegate:

    //Bottom of file
    extension BuyProductViewController: PKPaymentAuthorizationViewControllerDelegate {
        func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, completion: @escaping ((PKPaymentAuthorizationStatus) -> Void)) {
            completion(PKPaymentAuthorizationStatus.success)
        }
    
    
        func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {
            controller.dismiss(animated: true, completion: nil)
        }
    }
    

    To be able to use the Apple pay, delegate class you need to set in aboveBuyProductViewController class. In the applePayPressed(sender:), set it up using the following code.

    applePayController?.delegate = self
    

    Create checkout in Composable Commerce

    In BuyProductViewControllerin the PKPaymentAuthorizationViewControllerDelegate, you are sending a successful Apple pay order to Composable Commerce.

    1. Get customers information. It is returned from the PKPaymentAuthorizationViewControllerDelegate in the payment object.

    2. Set up customer.

      let customer = Customer(withEmail: payment.billingContact?.emailAddress, withName: payment.shippingContact?.name?.familyName)
      
    3. Set up the customer address. Note that shipping and billing addresses can vary.

      let address = Address(withFirstName: (payment.shippingContact?.name?.givenName)!, withLastName: payment.shippingContact?.name?.familyName ?? "")
      address.line1 = payment.shippingContact?.postalAddress?.street
      address.county = payment.shippingContact?.postalAddress?.city
      address.country = payment.shippingContact?.postalAddress?.country
      address.postcode = payment.shippingContact?.postalAddress?.postalCode
      
    4. Process an order with Composable Commerce.

      self.moltin.cart.checkout(cart: AppDelegate.cartID, withCustomer: customer, withBillingAddress: address, withShippingAddress: address)
          { (result) in
          switch result {
                  case .success(let order):
                      DispatchQueue.main.async {
                      print(order)
                      }
                  default: break
                  }
          }
      

    Create payment transactions

    Paying for the order can be done by various payment gateways. In this example we use the manual payment type, which allows you to complete the transaction that handles the payment processing any way you want.

    1. In Commerce Manager, enable manual checkout. In Gateways, click Enable within the manual gateway and the click Save.

      let paymentMethod = ManuallyAuthorizePayment()
      self.moltin.cart.pay(forOrderID: order?.id ?? "", withPaymentMethod: paymentMethod) { (result) in
          switch result {
          case .success(let status):
              DispatchQueue.main.async {
                  print("Paid for order: \(status)")
              }
          case .failure(let error):
              print("Could not pay for order: \(error)")
          }
      }
      
    2. Within the checkout specified previously, complete the transaction by adding the following:

      let paymentMethod = ManuallyAuthorizePayment()
          self.moltin.cart.pay(forOrderID: order.id, withPaymentMethod: paymentMethod) { (result) in
              switch result {
                  case .success(let status):
                      DispatchQueue.main.async {
                          controller.dismiss(animated: true, completion: nil)
                          print("Paid for order: \(status)")
                      }
                  case .failure(let error):
                      controller.dismiss(animated: true, completion: nil)
                      print("Could not pay for order: \(error)")
                      }
          }
      
    3. Your PKPaymentAuthorizationViewControllerDelegate should now look like the following:

      extension BuyProductViewController: PKPaymentAuthorizationViewControllerDelegate
      {
      
      
          func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, completion: @escaping
          ((PKPaymentAuthorizationStatus) -> Void))
          {
              completion(PKPaymentAuthorizationStatus.success)
              ///Customer
              let customer = Customer(withEmail: payment.billingContact?.emailAddress, withName: payment.shippingContact?.name?.familyName)
      
      
              //Address
              let address = Address(withFirstName: (payment.shippingContact?.name?.givenName)!, withLastName: payment.shippingContact?.name?.familyName ?? "")
              address.line1 = payment.shippingContact?.postalAddress?.street
              address.county = payment.shippingContact?.postalAddress?.city
              address.country = payment.shippingContact?.postalAddress?.country
              address.postcode = payment.shippingContact?.postalAddress?.postalCode
      
      
              self.moltin.cart.checkout(cart: AppDelegate.cartID, withCustomer: customer, withBillingAddress: address, withShippingAddress: address)
              { (result) in
                  switch result {
                  case .success(let order):
                      DispatchQueue.main.async {
                          let paymentMethod = ManuallyAuthorizePayment()
                          self.moltin.cart.pay(forOrderID: order.id, withPaymentMethod: paymentMethod) { (result) in
                              switch result {
                                  case .success(let status):
                                      DispatchQueue.main.async {
                                          print("Paid for order: \(status)")
                                          controller.dismiss(animated: true, completion: nil)
      
      
                                      }
                                  case .failure(let error):
                                      print("Could not pay for order: \(error)")
                                      controller.dismiss(animated: true, completion: nil)
                                  }
                              }
                          }
                          default: break
                      }
                  }
              }
      
      
          func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController)
          {
              controller.dismiss(animated: true, completion: nil)
      
      
          }
      }
      

    Moving forward

    If you’d like to read more in-depth information about Apple Pay, you can check out their developer site. The site also has a list of other payment platforms, other than Stripe, that support Apple Pay.

    There are many other features of Apple Pay that you could challenge yourself to add to your app:

    • Calculate sales tax on the server and update the tax amount in summaryItems.
    • Change the available shipping methods based on the ZIP code.
    • Read the order information on the server, and verify that the address is valid as a shipping destination.
    • Create your own customized Apple Pay button by following the Apple Pay guidelines.
    Previous
    Implement PayPal Express Checkout