diff --git a/CHANGELOG.md b/CHANGELOG.md index fce9a42a..894cc200 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ way to update this template, but currently, we follow a pattern: ## Upcoming version 2019-XX-XX +- [fix] missing provider information (like SSN in US), might cause payment to fail on + `CheckoutPage`. This improves related error message. + [#10967](https://github.com/sharetribe/flex-template-web/pull/1097) - [fix] Menu needs to wait for mounting to calculate dimensions properly. [#1096](https://github.com/sharetribe/flex-template-web/pull/1096) - [fix] Renamed Component.example.css files to ComponentExample.css to fix bug introduced in one of diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index 2c7f580f..3ce296d8 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -16,6 +16,7 @@ import { isTransactionInitiateListingNotFoundError, isTransactionInitiateMissingStripeAccountError, isTransactionInitiateBookingTimeNotAvailableError, + isTransactionChargeDisabledError, isTransactionZeroPaymentError, transactionInitiateOrderStripeErrors, } from '../../util/errors'; @@ -304,6 +305,7 @@ export class CheckoutPageComponent extends Component { ); const isAmountTooLowError = isTransactionInitiateAmountTooLowError(initiateOrderError); + const isChargeDisabledError = isTransactionChargeDisabledError(initiateOrderError); const isBookingTimeNotAvailableError = isTransactionInitiateBookingTimeNotAvailableError( initiateOrderError ); @@ -323,6 +325,12 @@ export class CheckoutPageComponent extends Component {

); + } else if (!listingNotFound && isChargeDisabledError) { + initiateOrderErrorMessage = ( +

+ +

+ ); } else if (!listingNotFound && stripeErrors && stripeErrors.length > 0) { // NOTE: Error messages from Stripes are not part of translations. // By default they are in English. diff --git a/src/translations/en.json b/src/translations/en.json index 3356b8ee..efb05999 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -79,6 +79,7 @@ "BookingPanel.perUnit": "per unit", "BookingPanel.subTitleClosedListing": "Sorry, this listing has been closed.", "CheckoutPage.bookingTimeNotAvailableMessage": "Unfortunately, the requested time is already booked.", + "CheckoutPage.chargeDisabledMessage": "This provider's payout information is incomplete so this listing cannot be booked. Please contact the administrator.", "CheckoutPage.errorlistingLinkText": "the sauna page", "CheckoutPage.goToLandingPage": "Go to homepage", "CheckoutPage.hostedBy": "Hosted by {name}", diff --git a/src/util/errors.js b/src/util/errors.js index ada559bc..0cb126b7 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -140,6 +140,31 @@ export const isTransactionInitiateAmountTooLowError = error => { return isZeroPayment || tooLowAmount; }; +/** + * Check if the given API error (from `sdk.transaction.initiate()`) is + * due to the transaction charge creation disabled by Stripe. + */ +export const isTransactionChargeDisabledError = error => { + const chargeCreationDisabled = errorAPIErrors(error).some(apiError => { + const isPaymentFailedError = + apiError.status === 402 && apiError.code === ERROR_CODE_PAYMENT_FAILED; + + let isChargeCreationDisabled = false; + try { + const msg = apiError.meta.stripeMessage; + isChargeCreationDisabled = + msg.startsWith('Your account cannot currently make charges.') || + msg.match(/verification.disabled_reason/); + } catch (e) { + // Ignore + } + + return isPaymentFailedError && isChargeCreationDisabled; + }); + + return chargeCreationDisabled; +}; + /** * Check if the given API error (from `sdk.transaction.initiate()`) is * due to other error in Stripe.