Applies to: Mobile Payments SDK - Android | Payments API
Learn how to take offline payments with the Mobile Payments SDK for Android.
Applies to: Mobile Payments SDK - Android | Payments API
Learn how to take offline payments with the Mobile Payments SDK for Android.
The Mobile Payments SDK supports taking payments in offline mode, which allows you to take payments when a reader is used in a location with weak network connection or the application momentarily loses connection to Square servers. Offline payments are stored (queued) locally on the mobile device running the Mobile Payments SDK application and processed by Square the next time the device successfully connects to the Internet and Square servers.
Before upgrading to a new version of the Mobile Payments SDK or a new version of your application, you should ensure all offline payments have been uploaded by verifying that the offline payment queue is empty.
To take offline payments with the Mobile Payments SDK and a bluetooth Square reader:
The Square seller is responsible for any expired, declined, or disputed payments accepted while offline. By providing their merchant ID and using Offline Payments, the seller is aware of and accepting this risk.
Before upgrading to a new version of the Mobile Payments SDK or a new version of your application, you should upload all offline payments and verify that the offline payment queue is empty.
At this time, the Offline Payments feature for the Mobile Payments SDK is in Beta, and requires Square sellers to opt in to this feature. If a seller using your application is interested in taking payments offline with the Mobile Payments SDK, send an email to [email protected]. In your message, include:
Square contacts the seller directly and provides them with a seller onboarding form for this Beta feature. After the seller is successfully onboarded, Square sends you (the developer) a confirmation email letting you know that you can accept offline payments for the seller.
At any time, you can check the isOfflineProcessingAllowed
value within the PaymentSettings
to determine whether the seller that is authorized with your application can take payments offline. If your application tries to take an offline payment for a seller who doesn't have access to this feature, you receive a USAGE_ERROR
.
Each seller taking payments offline with the Mobile Payments SDK has a limit on each offline payment and a limit to the total amount they can store offline on their mobile device. These limits vary by seller. If your application attempts to take an offline payment that exceeds one of these limits, the Mobile Payments SDK returns a USAGE_ERROR
.
Each device running the Mobile Payments SDK can take up to 1000 payments for up to 24 hours before reconnecting to the network. If this limit is reached, the reader fails to connect and your mobile device must connect to a network to process and upload these payments before accepting more.
val paymentSettings = MobilePaymentsSdk.settingsManager().getPaymentSettings()
val isOfflineProcessingAllowed = paymentSettings.isOfflineProcessingAllowed
val offlineTransactionAmountLimit =
paymentSettings.offlineTransactionAmountLimit
val offlineTotalStoredAmountLimit =
paymentSettings.offlineTotalStoredAmountLimit
The payment methods available to customers are limited while offline and not all devices support every type of offline payment. Before taking any payment, your application should query the Payment Manager's getavailableCardEntryMethods()
and display the possible payment methods to customers.
When you're ready to take a payment with the Mobile Payments SDK, you create PaymentParameters
with details about the payment. The processingMode
field determines whether the payment should be taken offline. By default, each payment's processing mode is ONLINE_ONLY
, meaning the payment can only be processed using a network call.
In some situations, such as when a location has a sporadic or weak Internet connection, sellers might want to take all payments offline during a period of time. To do so, set the processingMode
for payments to OFFLINE_ONLY
. All payments made with this mode are initially queued on the mobile device, even if there is a network connection.
Alternatively, you can set the processingMode
for payments to AUTO_DETECT
. In this case, the SDK checks the status of the local network connection and the performance of Square's servers before processing the payment.
val paymentManager = MobilePaymentsSdk.paymentManager()
val baseMoney = Money(100L, USD)
val builder = PaymentParameters.Builder(
amount = baseMoney,
idempotencyKey = UUID.randomUUID().toString(),
).processingMode(ProcessingMode.OFFLINE_ONLY)
val paymentParameters = builder.build()
val promptParameters = PromptParameters(
mode = PromptMode.DEFAULT,
additionalPaymentMethods = listOf(Type.KEYED)
)
viewModel.startPaymentActivity(paymentParameters, promptParameters)
When an offline payment is queued, it hasn't yet been processed by Square. The transaction isn't returned from the ListPayments endpoint and doesn't have a Square payment ID value. If your application's workflow involves delayed payment capture or syncing Square payments with an outside transaction database, you must write logic to query Square for the completed payment and its details and then perform that sync. For more information, see Payment IDs.
The Mobile Payments SDK provides the getOfflinePaymentQueue()
method in the Payment Manager to access all payments taken offline by the application on the current mobile device. This includes queued payments waiting to be processed and completed processed payments. Only payments that have a locationId
matching the current application user's location ID are returned. This prevents two Square sellers logging in to your application on the same mobile device from viewing each other's payments.
The status
of an OfflinePayment
indicates its current point in the payment workflow and whether it failed to upload or process. The status
can be one of the following:
QUEUED
- The payment is stored locally on the device running the Mobile Payments SDK application. The SDK attempts to upload the payment to Square after the network connection is restored.UPLOADED
- The payment has been uploaded to the Square server, but hasn't yet been processed.FAILED_TO_UPLOAD
- The payment couldn't be uploaded due to an unrecoverable error.FAILED_TO_PROCESS
- The connection was restored, but Square couldn't process this specific offline payment. This might be because of a declined card or another error with the card-issuing bank. An offline payment with this status cannot be recovered, and the seller doesn't receive funds from the transaction.PROCESSED
- Square processed your offline payment successfully. It can now be seen in the Square Dashboard.val offlineQueue = MobilePaymentsSdk.paymentManager().getOfflinePaymentQueue()
// Grab total amount stored
when (val totalStoredAmountResult = offlineQueue.getTotalStoredPaymentAmount()) {
is Failure -> { … }
is Success -> {
val totalStoredAmount = totalStoredAmountResult.value
}
}
// Add callback
val callbackReference = offlineQueue.addGetPaymentsCallback { result ->
when (result) {
is Failure -> { … }
is Success -> {
val offlinePayments = result.value
// Number of payments currently stored
val totalNumberOfPayments = offlinePayments.size
// Show each OfflinePayment Status to user
offlinePayments.forEach { offlinePayment ->
when (offlinePayment.status) {
OfflineStatus.QUEUED -> {
//show user via UI
}
OfflineStatus.UPLOADED -> {
//show user via UI
}
OfflineStatus.FAILED_TO_PROCESS -> {
//show user via UI
}
OfflineStatus.FAILED_TO_UPLOAD -> {
//show user via UI
}
OfflineStatus.PROCESSED -> {
//show user via UI
}
}
}
}
}
}
// Start async getPayments()
offlineQueue.getPayments()
// clean up when done fetching
callbackReference.clear()
A payment taken offline with the Mobile Payments SDK has two identification values: localID
, used to identify the payment on your mobile device before it's processed, and id
, which represents the Square payment id
value. The second value is always null
until the SDK uploads the payment to Square and the payment is processed.
When a payment's status changes to PROCESSED
, you can access its id
value from the mobile device and match it to the id
value of payments returned by the ListPayments endpoint. You can now continue your application's payment workflow and use other Square APIs to access and manage the payment. PROCESSED
payments are deleted from the mobile device to conserve storage space.
val paymentManager = MobilePaymentsSdk.paymentManager()
val handle = paymentManager.startPaymentActivity(paymentParams, promptParams) { result ->
when (result) {
is Failure -> { … }
is Success -> {
val payment = result.value
when (payment) {
is OnlinePayment -> {
val paymentId = paymentId.id // not nullable
}
is OfflinePayment -> {
val paymentId = payment.id // nullable
val localPaymentId = payment.localId
val status = payment.status
}
}
}
}
}
// clean up when done fetching
handle.cancel()
The Mobile Payments SDK regularly checks for network connectivity and a connection to Square servers so that queued payments can be processed. This is done automatically while the application is open in the foreground of the device. Assuming that there are no errors in the PaymentParameters
or issues like cards being declined, the funds are available to the seller in the Square Dashboard and the payment can be accessed and managed by the Payments API after this processing is complete.
The following actions result in queued payments being removed from the device. If this happens before the payment is uploaded and processed, it cannot be processed and the seller doesn't receive funds from the transaction:
Queued payments remain on the device when a user force-quits your application, switches to another application, or a seller logs out of your application. As a best practice, your application should query for any QUEUED
payments on the device before calling authorizationManager.deauthorize()
, so that you can alert the seller about any unprocessed payments.
If you need more assistance, contact Developer and App Marketplace Support or ask for help in the Developer Forums.