From b74ffebb3e696eebe7e5e6ca08469eed28bda18a Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 4 Oct 2017 14:50:41 +0300 Subject: [PATCH 1/3] Fix null handling --- src/containers/CheckoutPage/CheckoutPageSessionHelpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js b/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js index 6ae93fea..b03fc3a0 100644 --- a/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js +++ b/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js @@ -74,7 +74,7 @@ export const storedData = storageKey => { // Dates are expected to be in format: { date: new Date(), _serializedType: 'SerializableDate' } const reviver = (k, v) => { // eslint-disable-next-line no-underscore-dangle - if (typeof v === 'object' && v._serializedType === 'SerializableDate') { + if (v && typeof v === 'object' && v._serializedType === 'SerializableDate') { return new Date(v.date); } return types.reviver(k, v); From 67acea907b315d910398fd1466d4a227502160a4 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 4 Oct 2017 14:51:01 +0300 Subject: [PATCH 2/3] Show a specific error when the tx amount is too low --- src/containers/CheckoutPage/CheckoutPage.js | 24 +++++++++++++++++---- src/translations/en.json | 1 + src/util/errors.js | 23 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index e69affd9..84296cff 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -9,7 +9,10 @@ import * as propTypes from '../../util/propTypes'; import { ensureListing, ensureUser, ensureTransaction, ensureBooking } from '../../util/data'; import { withFlattenedRoutes } from '../../util/contextHelpers'; import { createSlug } from '../../util/urlHelpers'; -import { isTransactionInitiateListingNotFoundError } from '../../util/errors'; +import { + isTransactionInitiateAmountTooLowError, + isTransactionInitiateListingNotFoundError, +} from '../../util/errors'; import { AvatarMedium, BookingBreakdown, @@ -212,11 +215,24 @@ export class CheckoutPageComponent extends Component { ); - const initiateOrderErrorMessage = !listingNotFound && initiateOrderError - ?

+ + const isAmountTooLowError = isTransactionInitiateAmountTooLowError(initiateOrderError); + let initiateOrderErrorMessage = null; + + if (!listingNotFound && isAmountTooLowError) { + initiateOrderErrorMessage = ( +

+ +

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

- : null; + ); + } + const speculateTransactionErrorMessage = speculateTransactionError ?

diff --git a/src/translations/en.json b/src/translations/en.json index c5f0f03c..f93bcd9b 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -40,6 +40,7 @@ "CheckoutPage.errorlistingLinkText": "the sauna page", "CheckoutPage.goToLandingPage": "Go to homepage", "CheckoutPage.hostedBy": "Hosted by {name}", + "CheckoutPage.initiateOrderAmountTooLow": "Unfortunately we're not able to process this payment, since the payment amount is too low. Please contact the administrators.", "CheckoutPage.initiateOrderError": "Payment request failed. Please go back to {listingLink} and try again. If the error persists, try refreshing the page or contacting the marketplace admin.", "CheckoutPage.listingNotFoundError": "Unfortunately the listing is not available anymore.", "CheckoutPage.loadingData": "Loading checkout data...", diff --git a/src/util/errors.js b/src/util/errors.js index 2c19a322..7ece69da 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -10,6 +10,7 @@ */ const ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED = 'transition-parameter-validation-failed'; +const ERROR_CODE_PAYMENT_FAILED = 'payment-failed'; const ERROR_CODE_EMAIL_TAKEN = 'email-taken'; const ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS = 'too-many-verification-requests'; const ERROR_CODE_UPLOAD_OVER_LIMIT = 'upload-over-limit'; @@ -96,6 +97,28 @@ export const isTransactionInitiateListingNotFoundError = apiError => { }); }; +/** + * Check if the given API error (from `sdk.transaction.initiate()`) is + * due to the transaction total amount being too low for Stripe. + */ +export const isTransactionInitiateAmountTooLowError = apiError => { + return responseErrors(apiError).some(error => { + const isPaymentFailedError = error.status === 402 && error.code === ERROR_CODE_PAYMENT_FAILED; + let isAmountTooLow = false; + + try { + // TODO: This is a temporary solution until a proper error code + // for this specific error is received in the response. + const msg = error.details.msg; + isAmountTooLow = msg.startsWith('Amount must be at least'); + } catch (e) { + // Ignore + } + + return isPaymentFailedError && isAmountTooLow; + }); +}; + /** * Check if the given API error (from `sdk.currentUser.changeEmail(params)`) * is due to giving wrong password. From 5fb5ce42eeb5a9b9f1b7b6cd56288888b9903cd2 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 4 Oct 2017 14:59:42 +0300 Subject: [PATCH 3/3] Remove unneeded translation param --- src/containers/CheckoutPage/CheckoutPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index 84296cff..686523f3 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -222,7 +222,7 @@ export class CheckoutPageComponent extends Component { if (!listingNotFound && isAmountTooLowError) { initiateOrderErrorMessage = (

- +

); } else if (!listingNotFound && initiateOrderError) {