Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS error code passthrough #175

Merged
merged 2 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
promise.resolve(
createError(
TerminalException(
TerminalException.TerminalErrorCode.CANCELED,
TerminalException.TerminalErrorCode.CANCEL_FAILED,
"collectPaymentMethod could not be canceled because the command has already been canceled or has completed."
)
)
Expand All @@ -189,7 +189,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
promise.resolve(
createError(
TerminalException(
TerminalException.TerminalErrorCode.CANCELED,
TerminalException.TerminalErrorCode.CANCEL_FAILED,
"collectSetupIntent could not be canceled because the command has already been canceled or has completed."
)
)
Expand Down Expand Up @@ -294,7 +294,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
promise.resolve(
createError(
TerminalException(
TerminalException.TerminalErrorCode.CANCELED,
TerminalException.TerminalErrorCode.CANCEL_FAILED,
"discoverReaders could not be canceled because the command has already been canceled or has completed."
)
)
Expand Down Expand Up @@ -693,7 +693,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
promise.resolve(
createError(
TerminalException(
TerminalException.TerminalErrorCode.CANCELED,
TerminalException.TerminalErrorCode.CANCEL_FAILED,
"readReusableCard could not be canceled because the command has already been canceled or has completed."
)
)
Expand Down
155 changes: 152 additions & 3 deletions ios/Errors.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import StripeTerminal

enum CommonErrorType: String {
case Failed, Canceled, Unknown
case InvalidRequiredParameter
}

class Errors {
Expand All @@ -15,11 +17,158 @@ class Errors {
return joined.isEmpty ? nil : joined
}

class func createError(code: String, message: String) -> NSDictionary {
class func createError(code: ErrorCode.Code, message: String) -> NSDictionary {
return createError(errorCode: code.stringValue, message: message)
}

class func createError(code: CommonErrorType, message: String) -> NSDictionary {
return createError(errorCode: code.rawValue, message: message)
}

class func createError(nsError: NSError) -> NSDictionary {
return createError(code: ErrorCode.Code.init(rawValue: nsError.code) ?? ErrorCode.unexpectedSdkError, message: nsError.localizedDescription)
}

private class func createError(errorCode: String, message: String) -> NSDictionary {
let error: NSDictionary = [
"code": code,
"code": errorCode,
"message": message
]
return ["error": error]
}
}

extension ErrorCode.Code {
var stringValue: String {
switch self {
case .busy:
return "Busy"
case .cancelFailedAlreadyCompleted:
return "CancelFailedAlreadyCompleted"
case .notConnectedToReader:
return "NotConnectedToReader"
case .alreadyConnectedToReader:
return "AlreadyConnectedToReader"
case .connectionTokenProviderCompletedWithNothing:
return "ConnectionTokenProviderCompletedWithNothing"
case .processInvalidPaymentIntent:
return "ProcessInvalidPaymentIntent"
case .nilPaymentIntent:
return "NilPaymentIntent"
case .nilSetupIntent:
return "NilSetupIntent"
case .nilRefundPaymentMethod:
return "NilRefundPaymentMethod"
case .invalidRefundParameters:
return "InvalidRefundParameters"
case .invalidClientSecret:
return "InvalidClientSecret"
case .mustBeDiscoveringToConnect:
return "MustBeDiscoveringToConnect"
case .cannotConnectToUndiscoveredReader:
return "CannotConnectToUndiscoveredReader"
case .invalidDiscoveryConfiguration:
return "InvalidDiscoveryConfiguration"
case .invalidReaderForUpdate:
return "InvalidReaderForUpdate"
case .unsupportedSDK:
return "UnsupportedSDK"
case .featureNotAvailableWithConnectedReader:
return "FeatureNotAvailableWithConnectedReader"
case .featureNotAvailable:
return "FeatureNotAvailable"
case .invalidListLocationsLimitParameter:
return "InvalidListLocationsLimitParameter"
case .bluetoothConnectionInvalidLocationIdParameter:
return "BluetoothConnectionInvalidLocationIdParameter"
case .canceled:
return "Canceled"
case .locationServicesDisabled:
return "LocationServicesDisabled"
case .bluetoothDisabled:
return "BluetoothDisabled"
case .bluetoothAccessDenied:
return "BluetoothAccessDenied"
case .bluetoothScanTimedOut:
return "BluetoothScanTimedOut"
case .bluetoothLowEnergyUnsupported:
return "BluetoothLowEnergyUnsupported"
case .readerSoftwareUpdateFailedBatteryLow:
return "ReaderSoftwareUpdateFailedBatteryLow"
case .readerSoftwareUpdateFailedInterrupted:
return "ReaderSoftwareUpdateFailedInterrupted"
case .readerSoftwareUpdateFailedExpiredUpdate:
return "ReaderSoftwareUpdateFailedExpiredUpdate"
case .bluetoothConnectionFailedBatteryCriticallyLow:
return "BluetoothConnectionFailedBatteryCriticallyLow"
case .cardInsertNotRead:
return "CardInsertNotRead"
case .cardSwipeNotRead:
return "CardSwipeNotRead"
case .cardReadTimedOut:
return "CardReadTimedOut"
case .cardRemoved:
return "CardRemoved"
case .cardLeftInReader:
return "CardLeftInReader"
case .readerBusy:
return "ReaderBusy"
case .incompatibleReader:
return "IncompatibleReader"
case .readerCommunicationError:
return "ReaderCommunicationError"
case .bluetoothError:
return "BluetoothError"
case .bluetoothConnectTimedOut:
return "BluetoothConnectTimedOut"
case .bluetoothDisconnected:
return "BluetoothDisconnected"
case .bluetoothPeerRemovedPairingInformation:
return "BluetoothPeerRemovedPairingInformation"
case .bluetoothAlreadyPairedWithAnotherDevice:
return "BluetoothAlreadyPairedWithAnotherDevice"
case .readerSoftwareUpdateFailed:
return "ReaderSoftwareUpdateFailed"
case .readerSoftwareUpdateFailedReaderError:
return "ReaderSoftwareUpdateFailedReaderError"
case .readerSoftwareUpdateFailedServerError:
return "ReaderSoftwareUpdateFailedServerError"
case .unsupportedReaderVersion:
return "UnsupportedReaderVersion"
case .unknownReaderIpAddress:
return "UnknownReaderIpAddress"
case .internetConnectTimeOut:
return "InternetConnectTimeOut"
case .connectFailedReaderIsInUse:
return "ConnectFailedReaderIsInUse"
case .unexpectedSdkError:
return "UnexpectedSdkError"
case .unexpectedReaderError:
return "UnexpectedReaderError"
case .declinedByStripeAPI:
return "DeclinedByStripeAPI"
case .declinedByReader:
return "DeclinedByReader"
case .commandRequiresCardholderConsent:
return "CommandRequiresCardholderConsent"
case .refundFailed:
return "RefundFailed"
case .notConnectedToInternet:
return "NotConnectedToInternet"
case .requestTimedOut:
return "RequestTimedOut"
case .stripeAPIError:
return "StripeAPIError"
case .stripeAPIResponseDecodingError:
return "StripeAPIResponseDecodingError"
case .internalNetworkError:
return "InternalNetworkError"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh huh, are going to have to manually maintain this and add new errors on every iOS release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah... the enums are written in objective-c, which doesn't retain the name of the enum after compilation so there's no way to get the enum name

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hrm, wonder if we can write a cross-repo code gen 🤔 (more of a long-term-nice-to-have)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can! At Netflix we used QuickType to generate types for Android, iOS, and TS: https://quicktype.io/

case .connectionTokenProviderCompletedWithError:
return "ConnectionTokenProviderCompletedWithError"
case .sessionExpired:
return "SessionExpired"
@unknown default:
return "Unknown"
}
}
}
Loading