Skip to content

cashapp/cash-app-pay-ios-sdk

Repository files navigation

PayKit for iOS

License Swift Xcode 11.0+ iOS 11.0+ SPM

Pay Kit is an open source software framework that allows you to accept Cash App Pay in your App. The framework provides a modules that can be used out of the box where the customer will be redirected from your checkout experience to Cash App to approve the payment before being redirected back to your App. It is composed of two SPM packages which can each be imported separately.

  • PayKit: This is the best place to start building your app. PayKit provides a protocol called CashAppPayObserver that receives updates from Pay Kit. Your checkout view controller can conform to this protocol, or you can create a dedicated observer class.

  • PayKitUI: Provides the views used across the framework. The views are provided to the user to launch a Pay Kit payment and to present the Cashtag but do not prescribe how they must be used.

Table of Contents

Requirements

The primary PayKit framework codebase supports iOS and requires Xcode 12.0 or newer. The PayKit framework has a Base SDK version of 13.0.

Getting Started

Installation (Option One): SPM

You can install Pay Kit via SPM. Create a new Xcode project and navigate to File > Swift Packages > Add Package Dependency. Enter the url https://github.com/cashapp/cash-app-pay-ios-sdk and tap Next. Choose the main branch, and on the next screen, check off the packages as needed.

Installation (Option Two): Cocoapods

Add Cocoapods to your to your project. Open the Podfile and add pod 'CashAppPayKit' and/or pod 'CashAppPayKitUI' and save your changes. Run pod update and Pay Kit will now be included through Cocoapods

PayKit

CashAppPayObserver

The CashAppPayObserver protocol contains only one method:

func stateDidChange(to state: CashAppPayState) {
    // handle state changes
}

Your implementation should switch on the state parameter and handle the appropriate state changes. Some of these possible states are for information only, but most drive the logic of your integration. The most critical states to handle are listed in the table below:

State Description
ReadyToAuthorize Show a Cash App Pay button in your UI and call authorizeCustomerRequest() when it is tapped
Approved Grants are ready for your backend to use to create a payment
Declined Customer has declined the Cash App Pay authorization and must start the flow over or choose a new payment method
The error states
.integrationError A fixable bug in your integration
.apiError A degradation of Cash App Pay server APIs. Your app should temporarily hide Cash App Pay functionality
.unexpectedError A bug outside the normal flow. Report this bug (and what caused it) to Cash App Developer Support

Implement URL handling

To use Pay Kit iOS, Cash App must be able to call a URL that will redirect back to your app. The simplest way to accomplish this is via Custom URL Schemes, but if your app supports Universal Links you ca use those URLs as well.

Choose a unique scheme for your application and register it in Xcode from the Info tab of your application’s target.

You will pass a URL that uses this scheme (or a Universal Link your app handles) into the createCustomerRequest() method that starts the authorization process.

When your app is called back by Cash App, simply post the CashAppPay.RedirectNotification from your AppDelegate or SceneDelegate, and the SDK will handle the rest:

import UIKit
import PayKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
        func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
                if let url = URLContexts.first?.url {
                    NotificationCenter.default.post(
                        name: CashAppPay.RedirectNotification,
                        object: nil,
                        userInfo: [UIApplication.LaunchOptionsKey.url : url]
                    )
                }
            }
        }
}

Instantiate CashAppPay

When you are ready to authorize a payment using Cash App Pay,

  1. Instantiate the SDK with your Client ID
  2. The SDK defaults to point to the production endpoint; for development, set the endpoint to sandbox
  3. Add your observer to the SDK

For example, from your checkout view controller that implements the CashAppPayObserver protocol, you can instantiate the SDK to be:

private let sandboxClientID = "YOUR_CLIENT_ID"
private lazy var sdk: CashAppPay = {
    let sdk = CashAppPay(clientID: sandboxClientID, endpoint: .sandbox)
    sdk.addObserver(self)
    return sdk
}()

Create a Customer Request

You can create a customer request as soon as you know the amount you’d like to charge or if you'd like to create an on-file payment request. You must create this request as soon as your checkout view controller loads, so that your customer can authorize the request without any delay.

To charge $5.00, your createCustomerRequest call might look like this:

private let sandboxBrandID = "YOUR_BRAND_ID"

override func viewDidLoad() {
    super.viewDidLoad()
    // load view hierarchy
    sdk.createCustomerRequest(
        params: CreateCustomerRequestParams(
            actions: [
                .oneTimePayment(
                    scopeID: brandID,
                    money: Money(amount: 500, currency: .USD)
                )
            ],
            channel: .IN_APP,
            redirectURL: URL(string: "tipmycap://callback")!,
            referenceID: nil,
            metadata: nil
        )
    )
}

Your Observer’s state will change to .creatingCustomerRequest, then .readyToAuthorize with the created CustomerRequest struct as an associated value.

Authorize the Customer Request

Once the SDK is in the .readyToAuthorize state, you can store the associated CustomerRequest and display a Cash App Pay button. When the customer taps the button, you can authorize the customer request.

Example

@objc func cashAppPayButtonTapped() {
   sdk.authorizeCustomerRequest(request)
}

Your app will redirect to Cash App for authorization. When authorization is completed, your redirect URL will be called, the RedirectNotification will post. The SDK will fetch your authorized request and return it to your Observer, as part of the change to the .approved state.

Pass Grants to the Backend and Create Payment

The approved CustomerRequest will have Grants associated with it that can be used with Cash App’s Create Payment API. Pass those Grants to your backend and call the CreatePayment API as a server-to-server call to complete your payment.

PayKitUI

PayKitUI provides an unmanaged CashAppPayButton and a CashAppPaymentMethod view in both UIKit and SwiftUI.

All of the views accept a SizingCategory to dictate the preferred size of the view within your app. They also support light/dark themes by default.

We want you to use these views as-is, without any modification.

CashAppPayButton

The following is an example of the CashAppPayButton:

image

You can instantiate the button as follows:

let button = CashAppPayButton(size: .small, onClickHandler: {})

CashAppPaymentMethod

The following is an example of CashAppPaymentMethod:

image

You can instatiate the CashAppPaymentMethod as follows:

let paymentMethod = CashAppPaymentMethod(size: .small)
paymentMethod.cashTag = "$jack"

Getting Help

GitHub is our primary forum for Pay Kit. To get help, open Issues about questions, problems, or ideas.

License

This project is made available under the terms of a Apache 2.0 license. See the LICENSE file.

Copyright 2023 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.