Skip to content

Commit c5b5776

Browse files
committed
8089 No retry button on disconnection errors
When we get an error collecting the payment, caused by the reader disconnecting, any retry attempt will fail. By showing a non-retriable error which dismisses the payment flow, the merchant will be taken back to the order and can see clearly whether the payment has gone through or not, before attempting the payment again.
1 parent b2a9b81 commit c5b5776

File tree

1 file changed

+75
-27
lines changed

1 file changed

+75
-27
lines changed

WooCommerce/Classes/ViewRelated/Orders/Collect Payments/CollectOrderPaymentUseCase.swift

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -333,33 +333,15 @@ private extension CollectOrderPaymentUseCase {
333333

334334
trackPaymentFailure(with: error)
335335

336-
// Inform about the error
337-
alertsPresenter.present(
338-
viewModel: paymentAlerts.error(error: error,
339-
tryAgain: { [weak self] in
340-
341-
// Cancel current payment
342-
self?.paymentOrchestrator.cancelPayment { [weak self] result in
343-
guard let self = self else { return }
344-
345-
switch result {
346-
case .success:
347-
// Retry payment
348-
self.attemptPayment(alertProvider: paymentAlerts,
349-
onCompletion: onCompletion)
350-
351-
case .failure(let cancelError):
352-
// Inform that payment can't be retried.
353-
self.alertsPresenter.present(
354-
viewModel: paymentAlerts.nonRetryableError(error: cancelError) {
355-
onCompletion(.failure(error))
356-
})
357-
}
358-
}
359-
}, dismissCompletion: {
360-
onCompletion(.failure(error))
361-
})
362-
)
336+
if canRetryPayment(with: error) {
337+
presentRetryableError(error: error,
338+
paymentAlerts: paymentAlerts,
339+
onCompletion: onCompletion)
340+
} else {
341+
presentNonRetryableError(error: error,
342+
paymentAlerts: paymentAlerts,
343+
onCompletion: onCompletion)
344+
}
363345
}
364346

365347
private func trackPaymentFailure(with error: Error) {
@@ -370,6 +352,72 @@ private extension CollectOrderPaymentUseCase {
370352
cardReaderModel: connectedReader?.readerType.model))
371353
}
372354

355+
private func canRetryPayment(with error: Error) -> Bool {
356+
guard let serviceError = error as? CardReaderServiceError else {
357+
return true
358+
}
359+
switch serviceError {
360+
case .paymentMethodCollection(let underlyingError),
361+
.paymentCapture(let underlyingError),
362+
.paymentCancellation(let underlyingError):
363+
return canRetryPayment(underlyingError: underlyingError)
364+
default:
365+
return true
366+
}
367+
}
368+
369+
private func canRetryPayment(underlyingError: UnderlyingError) -> Bool {
370+
switch underlyingError {
371+
case .notConnectedToReader,
372+
.commandNotAllowedDuringCall,
373+
.featureNotAvailableWithConnectedReader:
374+
return false
375+
default:
376+
return true
377+
}
378+
}
379+
380+
private func presentRetryableError(error: Error,
381+
paymentAlerts: CardReaderTransactionAlertsProviding,
382+
onCompletion: @escaping (Result<CardPresentCapturedPaymentData, Error>) -> ()) {
383+
alertsPresenter.present(
384+
viewModel: paymentAlerts.error(error: error,
385+
tryAgain: { [weak self] in
386+
387+
// Cancel current payment
388+
self?.paymentOrchestrator.cancelPayment { [weak self] result in
389+
guard let self = self else { return }
390+
391+
switch result {
392+
case .success:
393+
// Retry payment
394+
self.attemptPayment(alertProvider: paymentAlerts,
395+
onCompletion: onCompletion)
396+
397+
case .failure(let cancelError):
398+
// Inform that payment can't be retried.
399+
self.alertsPresenter.present(
400+
viewModel: paymentAlerts.nonRetryableError(error: cancelError) {
401+
onCompletion(.failure(error))
402+
})
403+
}
404+
}
405+
}, dismissCompletion: {
406+
onCompletion(.failure(error))
407+
})
408+
)
409+
}
410+
411+
private func presentNonRetryableError(error: Error,
412+
paymentAlerts: CardReaderTransactionAlertsProviding,
413+
onCompletion: @escaping (Result<CardPresentCapturedPaymentData, Error>) -> ()) {
414+
alertsPresenter.present(
415+
viewModel: paymentAlerts.nonRetryableError(error: error,
416+
dismissCompletion: {
417+
onCompletion(.failure(error))
418+
}))
419+
}
420+
373421
/// Cancels payment and record analytics.
374422
///
375423
func cancelPayment(onCompleted: @escaping () -> ()) {

0 commit comments

Comments
 (0)