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.