Applies to: Mobile Payments SDK - iOS | Payments API | Orders API
Learn how to use the Mobile Payments SDK for iOS to take a payment with a Square Reader or Square Stand.
Applies to: Mobile Payments SDK - iOS | Payments API | Orders API
Learn how to use the Mobile Payments SDK for iOS to take a payment with a Square Reader or Square Stand.
Payments in the Mobile Payments SDK are handled by the PaymentManager
and must conform to the PaymentManagerDelegate
protocol. The PaymentManagerDelegate
is called when a payment starts and finishes successfully, fails, or is canceled. Your application should include logic to handle each of these scenarios. To learn about error messages produced by the Mobile Payments SDK and ways to resolve them, see Handling Errors. If the payment completes successfully, a Payment
object is returned, describing details of the payment. This can be either an OnlinePayment
or an OfflinePayment
.
extension <#YourViewController#>: PaymentManagerDelegate { func paymentManager(_ paymentManager: PaymentManager, didFinish payment: Payment) { // You can further inspect each payment once cast if let onlinePayment = payment as? OnlinePayment { print("Online Payment - ID: \(onlinePayment.id!), status: \(onlinePayment.status.description)") } else if let offlinePayment = payment as? OfflinePayment { print("Offline Payment - ID: \(offlinePayment.localID), status: \(offlinePayment.status.description)") } } func paymentManager(_ paymentManager: PaymentManager, didFail payment: Payment, withError error: Error) { // Handle this the same way as `didFinish` } func paymentManager(_ paymentManager: PaymentManager, didCancel payment: Payment) { // Handle this the same way as `didFinish` } }
Before taking a payment with the SDK in a production environment, ensure that you've done the following:
Additionally, before taking a payment in production, you can test your application using mock readers and the Square Sandbox or download the Mobile Payments SDK sample application to see an example payment implementation.
To begin a payment with the Mobile Payments SDK, you create a PaymentParameters
object, which includes attributes describing the payment you want to take. For example, there are parameters for the payment amount, payment attempt ID, optional tip, application fee (if applicable), and the processing mode, which determines whether payments can be taken offline. autoDetect
is the recommended processingMode
, as this directs the payment online or offline based on the highest chance of success. For this reason, the resulting Payment object might be an OnlinePayment
or OfflinePayment
, and your application should account for both if you're using the autoDetect
processing mode. For the complete list of payment parameter values and details, see the iOS technical reference.
In the Mobile Payments SDK version 2.2.2
and earlier, you generated and added your own idempotency key in your paymentParameters
. In version 2.3.0
and later, the idempotencyKey
parameter is deprecated and you instead provide a paymentAttemptID
.
This is the recommended way to handle idempotent payment requests in the Mobile Payments SDK, and offers both idempotency protection and support for Strong Customer Authentication (SCA) requirements.
Square payment requests contain an idempotency key, a unique string identifier that accompanies an API operation, allowing Square to recognize potential duplicate calls. Using an idempotency key for each payment request ensures that a payment can only occur once, protecting against unintended outcomes like charging a customer twice for the same transaction.
When you provide a paymentAttemptID
in your paymentParameters
for each call to startPayment
, the Mobile Payments SDK generates a unique idempotency key for the payment request, and stores it along with your payment attempt ID. If multiple requests are made for the same payment attempt (for example, during SCA flows), the SDK generates a new idempotency key for each request and updates the stored idempotency key for the given payment attempt ID. You can't include both an idempotencyKey
and a paymentAttemptID
in your paymentParameters
, only one.
Along with a paymentAttemptID
, you should include a unique referenceID
value in your paymentParameters
for each payment. This persists with the payment and can be used to identify the payment within your own system if you need to reference it later. Your attempt ID and reference ID are not interchangeable. You shouldn't use the same value for both parameters because sometimes a payment requires multiple attempts (for example, if the first payment attempt is declined for expiration or insufficient funds, you can retry the payment with the same referenceID
and a new paymentAttemptID
). Typically, the referenceID
is used to match Square payments to an external system, but it can also be used to identify payments within Square.
If you don't receive a server response from a payment made with the Mobile Payments SDK, you should check its status to determine whether to attempt the payment again. Use the ListPayments endpoint and query by location ID, total payment amount, or other fields to filter the list. You can use your unique referenceID
to identify the correct payment and check its status. You might need to make a new payment attempt if the prior payment exists, but can't be completed. In this situation, retrieve the final idempotency key used for the payment attempt with PaymentManager.getIdempotencyKey
, and cancel the incomplete payment by using CancelPaymentByIdempotencyKey.
The following is an example of payment parameters created for a payment of $1 USD. The parameters include a paymentAttemptID
, unique referenceID
, and an optional orderID
that allows you to associate a payment with an itemized Square order.
import UIKit import SquareMobilePaymentsSDK extension <#YourViewController#> { func makePaymentParameters() -> PaymentParameters { let amount = Money(amount: 100, currency: .USD) // This is the ID used to reference the payment in your own system. let referenceID = "MY_REFERENCE_ID_1234" // This is the ID of the payment attempt for idempotent payment requests. let paymentAttemptID = "paymentAttemptID" // allow the payment to be taken online or offline let processingMode = processingMode.autoDetect // Create the payment parameters let paymentParams = PaymentParameters( paymentAttemptID: paymentAttemptID, amountMoney: amount, processingMode: processingMode ) // An optional note to add to the payment. paymentParams.note = "My Note" // Optional parameter to associate this payment with a previously created Square order. paymentParams.orderID = "CAISENgvlJ6jLWAzERDzjyHVybY" // A user-defined ID to associate with the payment. You can use this field // to associate the payment to an entity in an external system. paymentParams.referenceID = referenceID return paymentParams } }
Each payment must also have PromptParameters
configured. The PromptParameters
contain a PromptMode
and AdditionalPaymentMethods
. PromptParameters.mode
determines whether your application uses the default
Square-provided payment prompt UI or a custom payment prompt where you build your own UI. The default UI provided by Square is presented on top of the viewController
passed to PaymentManager.startPayment
and presents buyers with the payment options available from PaymentManager.availableCardInputMethods
.
PromptParameters.additionalMethods
specifies a list of additional payment methods available to use for this payment. The current option is keyed
(a manually entered credit card payment). If you're using the default PromptMode
, you can make AdditionalPaymentMethods
an empty list to remove the manual card entry button from the payment prompt.
If you create your own custom
PromptMode
, you should use the additionalPaymentMethods
available from the PaymentHandle
to render these options for buyers in your own payment prompt UI.
To begin processing a payment, call PaymentManager.startPayment()
with the PaymentParameters
and PromptParameters
you previously created. During the payment, Square takes control of the screen display to ensure that buyer information is handled securely and that the final confirmation of the payment is correctly shown to the buyer. You must conform to the PaymentManagerDelegate
to handle results and errors from the payment flow.
When the payment begins, the Payment Manager provides a PaymentHandle
as a way for you to interact with the ongoing payment (for example, if you need to cancel the payment). When the payment completes, regardless of whether it completed successfully, control is returned to the user interface and your application is notified of the result using PaymentManagerDelegate
. Your application can display receipt or error information to the user and continue other processing.
Only one payment can be in process at a given moment. If you make a second call to startPayment
before the first has completed, triggering the PaymentManagerDelegate
, the second call fails immediately with a paymentAlreadyInProgress
error. The first payment call continues.
import SquareMobilePaymentsSDK class <#YourViewController#>: UIViewController { private var paymentHandle: PaymentHandle? func startPayment() { paymentHandle = MobilePaymentsSDK.shared.paymentManager.startPayment( makePaymentParameters(), promptParameters: PromptParameters( mode: .default, additionalMethods: .all ), from: self, delegate: self ) } func makePaymentParameters() -> PaymentParameters { PaymentParameters( paymentAttemptID: UUID().uuidString, amountMoney: Money(amount: 100, currency: .USD) ) } }
As part of your application's workflow, you might want to authorize a customer's transaction but delay the capture of the payment (the transfer of funds from customer to seller) for a period of time. For example, in a restaurant with a kiosk ordering system, you might want to authorize a customer's credit card when they order, but not complete the payment until they receive their food.
While creating PaymentParameters
, set the autocomplete
value to false
if you want to delay the capture of the payment. While the payment is delayed, use the Payments API to complete or cancel the payment. You can also update the payment to add a tip using the tip_money
parameter.
When autocomplete
is false
, there are two more PaymentParameter
values which handle the delayed payment:
delayDuration
: The number of seconds to wait before canceling the payment or taking another delayAction
, specified as a TimeInterval
, with a minimum value of 60 seconds. Use a value of “0” to fallback to the default 36 hours for card present payments, or 7 days for manually entered payments.delayAction
: The action to take once the delayDuration
has passed with no other action on the payment. The possible options are cancel
(default) or complete
.Only one of autocomplete
and acceptPartialAuthorization
can be true
. If you are accepting multiple payment methods for a single purchase (such as a gift card and credit card), you must set autocomplete
to false
and manage the delayed capture of the payment.
For more information about delayed payment capture using the Payments API, see Delayed Capture of a Card Payment.
The PaymentHandle
provided by the Mobile Payments SDK during a payment can be used to cancel that payment. Note that only a payment where autocomplete
is set to false
can be canceled during processing. You can first check the value of PaymentHandle.isPaymentCancelable
. If it's set to true
, the payment can be canceled by calling paymentHandle.cancelPayment()
. For example, if your code dismisses the view controller passed to PaymentManager.startPayment
and the payment was not successful, you must call cancelPayment
.
During any payment flow, if the application is backgrounded or the application activity is interrupted, the payment in progress is canceled.
Your application must provide buyers with the option to receive a digital or printed receipt. These receipts aren't sent directly by Square. Therefore, to remain compliant with EMV-certification requirements, you must generate receipts including the following fields from the payment response cardDetails
object, when available:
cardholderName
(example: James Smith)cardBrand
and last4
(example: Visa 0094)applicationName
(example: AMERICAN EXPRESS)applicationIdentifier
(example: AID: A0 00 00 00 25 01 09 01)entryMethod
(example: Contactless)If you need more assistance, contact Developer and App Marketplace Support or ask for help in the Developer Forums.