Skip to main content

Handle errors and unclear outcomes

All calls throw TapToPayError. Most errors mean that no payment occurred. One error, outcomeUnknown, means that the card can be charged. Handle it as described in Unclear outcome.

Handle errors in code​

do {
let result = try await TapToPay.acceptPayment(
amount: amountInCents, orderId: orderId, callbackUrl: webhookUrl)
show(result)
} catch let error as TapToPayError {
switch error {
case .outcomeUnknown(let orderId):
showPending(orderId) // Do not retry.
case .cancelled:
break // No payment occurred.
case .tokenExpired, .notPrepared, .invalidToken:
await renewTokenAndPrepare()
case .locationDenied:
showLocationSettingsHint()
case .termsDeclined:
showTermsRequired()
case .paymentFailed(let code):
showFailure(code)
default:
showError(error)
}
} catch {
showError(error)
}

A switch without a default case needs @unknown default. See Switch statements.

Errors​

ErrorThrown byMeaningWhat to do
notSupportedAll callsThe device or the iOS version does not support Tap to Pay on iPhone.Hide Tap to Pay on iPhone.
locationDeniedprepare, acceptPaymentThe user did not allow location access, or Info.plist has no NSLocationWhenInUseUsageDescription.If the user did not allow access: tell the user to allow location access in Settings, then try again. If the key is missing: add it to Info.plist and release a corrected app.
termsDeclinedacceptPaymentThe user did not accept Apple's terms, or the link of the account failed.Tell the user that the terms are necessary. The next acceptPayment shows the terms again.
invalidArgumentacceptPaymentamount is 0 or less, or orderId is empty.Correct the value.
tokenExpiredprepare, acceptPaymentThe token expired.Get a new token from your server. Call prepare. Then try again.
invalidTokenprepareThe SDK cannot read the token.Send only the token field. Get a new token and call prepare. Until then, acceptPayment throws notPrepared.
notPreparedacceptPaymentNo valid token is stored.Call prepare first.
busyacceptPaymentA payment is in progress.Wait until it ends. Disable your pay button during a payment.
cancelledacceptPaymentThe user cancelled on Apple's screen. No payment occurred.Start a new payment when the customer is ready.
sdkUpgradeRequiredprepare, acceptPaymentMONEI blocked this SDK version. prepare and acceptPayment fail with this error.Update to a newer SDK version and release your app.
outcomeUnknown(orderId:)acceptPaymentThe SDK cannot tell if the payment reached MONEI. The card can be charged.Do not retry. Wait for the signed webhook, or find the orderId in MONEI. See Unclear outcome.
paymentFailed(code:)All callsThe payment or the setup failed.See Failure codes.

Failure codes​

paymentFailed(code:) has one of these TapToPayErrorCode values:

CodeMeaningWhat to do
cardDeclinedThe card was declined during the read. No payment occurred.Ask for a different card.
readerNotReadyThe reader session was not ready or expired.Try again. The SDK prepares the reader again on the next call.
locationTimeoutThe device did not get a location in 15 seconds.Make sure that Location Services are on. Then try again.
unknownThe payment did not start. No payment occurred.Try again. If the error continues, contact MONEI.

Declined payments are not errors​

A PaymentResult with the status .declined is not an error. The card was read and the issuer declined the payment. The payment is in MONEI with its paymentId. Ask the customer for a different card, and start a new payment.

Unclear outcome​

outcomeUnknown(orderId:) means that the SDK cannot tell if the payment reached MONEI. The card can be charged.

Causes:

  • A connection or server error at any step of the payment.
  • A card read error, a PIN entry error, or a lost reader session during the payment.
  • A reply that is not a clear approval or a clear decline. This can also occur when the card is declined.
  • A cancelled task.

Some of these occur before the card is charged, but the SDK cannot tell which.

Do not retry

Do not retry the payment, and do not charge again with a new orderId. The customer can pay twice.

  1. Show a pending state with the orderId.

  2. Wait for the signed webhook for this orderId.

  3. If no webhook arrives, find the orderId in MONEI:

    • In the MONEI Dashboard, open Payments and filter by order ID.

    • With the GraphQL API, use the charges query with filter.orderId:

      query {
      charges(filter: {orderId: {eq: "order-1042"}}) {
      items {
      id
      status
      amount
      }
      }
      }
  4. If no payment shows, this does not prove that the card was not charged. Contact MONEI support with the orderId before you charge the customer again.

Common questions​

Can I try again after cancelled?​

Yes. cancelled means that the user cancelled on Apple's screen and no payment occurred. Start a new payment when the customer is ready.

Why do I get notPrepared after prepare failed?​

When prepare throws invalidToken or tokenExpired, the SDK does not keep a token. Get a new token from your server, send only the token field, and call prepare again.

What does sdkUpgradeRequired mean?​

MONEI blocked the SDK version in your app. prepare and acceptPayment fail with this error. Update to a newer SDK version and release a new version of your app. See Versions and compatibility.

Why is a card read error an unclear outcome?​

Some reader errors can occur after the SDK sent the payment to MONEI. The SDK cannot tell these errors from errors that occur before, so it throws outcomeUnknown for all of them. This prevents a second charge to the customer by mistake.