From d1bf9aed4c5637e775b6d19ff6426bdb1f395d80 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 3 Jan 2018 15:59:56 +0200 Subject: [PATCH 1/7] Update lock file --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 106b2e0a..28e0b679 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7214,9 +7214,9 @@ sharetribe-scripts@1.0.14: optionalDependencies: fsevents "1.1.2" -"sharetribe-sdk@git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#ff76ef91e1e3b1e26b035a04d643d328ea3d1d61": +"sharetribe-sdk@git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#267efc4ca52dd1ad54db6bf3c37ab8ebcd8a86ab": version "0.0.1" - resolved "git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#ff76ef91e1e3b1e26b035a04d643d328ea3d1d61" + resolved "git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#267efc4ca52dd1ad54db6bf3c37ab8ebcd8a86ab" dependencies: axios "^0.15.3" js-cookie "^2.1.3" From bf6e7ed6dee57dd71e331d11ed99ba090502d766 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 3 Jan 2018 16:00:10 +0200 Subject: [PATCH 2/7] Log also code and data --- src/util/log.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/log.js b/src/util/log.js index 70e9595c..e3eeb7f1 100644 --- a/src/util/log.js +++ b/src/util/log.js @@ -56,5 +56,6 @@ export const error = (e, code, data) => { Raven.captureException(e, { tags: { code }, extra: data }); } else { console.error(e); // eslint-disable-line + console.error('Error code:', code, 'data:', data); } }; From e0eddc7db87f64c88c23e05984175925f4a4d25e Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 3 Jan 2018 16:01:01 +0200 Subject: [PATCH 3/7] Update error respnse format --- src/util/propTypes.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/propTypes.js b/src/util/propTypes.js index fa233053..53a39c47 100644 --- a/src/util/propTypes.js +++ b/src/util/propTypes.js @@ -373,6 +373,7 @@ export const ERROR_CODE_EMAIL_NOT_FOUND = 'email-not-found'; export const ERROR_CODE_EMAIL_NOT_VERIFIED = 'email-unverified'; export const ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS = 'email-too-many-verification-requests'; export const ERROR_CODE_UPLOAD_OVER_LIMIT = 'request-upload-over-limit'; +export const ERROR_CODE_VALIDATION_INVALID_PARAMS = 'validation-invalid-params'; const ERROR_CODES = [ ERROR_CODE_TRANSACTION_LISTING_NOT_FOUND, ERROR_CODE_TRANSACTION_INVALID_TRANSITION, @@ -384,6 +385,7 @@ const ERROR_CODES = [ ERROR_CODE_EMAIL_NOT_VERIFIED, ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS, ERROR_CODE_UPLOAD_OVER_LIMIT, + ERROR_CODE_VALIDATION_INVALID_PARAMS, ]; // API error @@ -393,6 +395,7 @@ export const apiError = shape({ status: number.isRequired, code: oneOf(ERROR_CODES).isRequired, title: string.isRequired, + meta: object, }); // Storable error prop type. (Error object should not be stored as it is.) From b9f23e77147fd86f45c842ef51a5b6d331e92c22 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 3 Jan 2018 16:01:26 +0200 Subject: [PATCH 4/7] Add Stripe error message to Sentry data --- src/ducks/user.duck.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ducks/user.duck.js b/src/ducks/user.duck.js index 6b2aa25a..e4ec2d0b 100644 --- a/src/ducks/user.duck.js +++ b/src/ducks/user.duck.js @@ -380,9 +380,13 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) => .then(() => { dispatch(stripeAccountCreateSuccess(accountResponse)); }) - .catch(e => { - dispatch(stripeAccountCreateError(storableError(e))); - log.error(e, 'create-stripe-account-failed'); + .catch(err => { + const e = storableError(err); + dispatch(stripeAccountCreateError(e)); + const stripeMessage = e.apiErrors && e.apiErrors.length > 0 && e.apiErrors[0].meta + ? e.apiErrors[0].meta.stripe_message + : null; + log.error(err, 'create-stripe-account-failed', { stripeMessage }); throw e; }); }; From 51576fa1e298333c3df59564b19aad22ac088602 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 3 Jan 2018 16:01:49 +0200 Subject: [PATCH 5/7] Avoid unhandled promise errors --- src/components/EditListingPhotosPanel/EditListingPhotosPanel.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js b/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js index 1734f44e..59dca557 100644 --- a/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js +++ b/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js @@ -69,6 +69,8 @@ class EditListingPhotosPanel extends Component { this.setState({ showPayoutDetails: false }); this.props.onManageDisableScrolling('EditListingPhotosPanel.payoutModal', false); this.props.onSubmit(this.state.submittedValues); + }).catch(() => { + // do nothing }); } From 9e98466661bd26d052501dcabd1ed38e974b6cae Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Wed, 3 Jan 2018 16:02:12 +0200 Subject: [PATCH 6/7] Detect invalid postal code error in Stripe account creation --- .../PayoutDetailsForm/PayoutDetailsForm.js | 22 ++++++++++++++----- src/translations/en.json | 1 + src/util/errors.js | 16 ++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/containers/PayoutDetailsForm/PayoutDetailsForm.js b/src/containers/PayoutDetailsForm/PayoutDetailsForm.js index a10e6509..c1ad34e4 100644 --- a/src/containers/PayoutDetailsForm/PayoutDetailsForm.js +++ b/src/containers/PayoutDetailsForm/PayoutDetailsForm.js @@ -15,6 +15,7 @@ import { TextInputField, } from '../../components'; import * as validators from '../../util/validators'; +import { isStripeInvalidPostalCode } from '../../util/errors'; import css from './PayoutDetailsForm.css'; @@ -191,11 +192,22 @@ const PayoutDetailsFormComponent = props => { const submitReady = false; const submitInProgress = submitting || inProgress; const submitDisabled = pristine || invalid || disabled || submitInProgress; - const error = createStripeAccountError ? ( -
- -
- ) : null; + + let error = null; + + if (isStripeInvalidPostalCode(createStripeAccountError)) { + error = ( +
+ +
+ ); + } else if (createStripeAccountError) { + error = ( +
+ +
+ ); + } return (
diff --git a/src/translations/en.json b/src/translations/en.json index 160ced5c..72e439a8 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -395,6 +395,7 @@ "PayoutDetailsForm.countryPlaceholder": "Select your country…", "PayoutDetailsForm.countryRequired": "This field is required", "PayoutDetailsForm.createStripeAccountFailed": "Whoops, something went wrong. Please try again.", + "PayoutDetailsForm.createStripeAccountFailedInvalidPostalCode": "Whoops, check that the selected country and postal code are correct and try again.", "PayoutDetailsForm.firstNameLabel": "First name", "PayoutDetailsForm.firstNamePlaceholder": "John", "PayoutDetailsForm.firstNameRequired": "This field is required", diff --git a/src/util/errors.js b/src/util/errors.js index a17ce45a..ba773105 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -157,6 +157,22 @@ export const isChangeEmailWrongPassword = error => error && error.status === 403 */ export const isChangePasswordWrongPassword = error => error && error.status === 403; + +/** + * Check if the given API error (from + * 'sdk.currentUser.createStripeAccount(payoutDetails)') is due to + * invalid postal code in the given country. +*/ +export const isStripeInvalidPostalCode = error => { + const msgRe = /^Invalid [A-Z]{2} postal code$/; + return errorAPIErrors(error).some(apiError => { + // Stripe doesn't seem to give an error code for this specific + // case, so we have to recognize it from the message. + const msg = apiError.meta && apiError.meta.stripe_message ? apiError.meta.stripe_message : ''; + return msgRe.test(msg); + }); +}; + export const storableError = error => { const { name, message, status, statusText } = error; // Status, statusText, and data.errors are (possibly) added to the error object by SDK From 86e750610e788825ba9568d6d82ec465bfe35378 Mon Sep 17 00:00:00 2001 From: Kimmo Puputti Date: Thu, 4 Jan 2018 12:35:32 +0200 Subject: [PATCH 7/7] Update snapshots and formatting after rebase --- .../EditListingPhotosPanel.js | 17 +++-- .../TransactionPanel.test.js.snap | 70 +++++++++++++++++++ src/ducks/user.duck.js | 7 +- src/util/errors.js | 3 +- 4 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js b/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js index 59dca557..d9a27248 100644 --- a/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js +++ b/src/components/EditListingPhotosPanel/EditListingPhotosPanel.js @@ -65,13 +65,16 @@ class EditListingPhotosPanel extends Component { bankAccountToken, address: omitBy(address, isUndefined), }; - this.props.onPayoutDetailsSubmit(params).then(() => { - this.setState({ showPayoutDetails: false }); - this.props.onManageDisableScrolling('EditListingPhotosPanel.payoutModal', false); - this.props.onSubmit(this.state.submittedValues); - }).catch(() => { - // do nothing - }); + this.props + .onPayoutDetailsSubmit(params) + .then(() => { + this.setState({ showPayoutDetails: false }); + this.props.onManageDisableScrolling('EditListingPhotosPanel.payoutModal', false); + this.props.onSubmit(this.state.submittedValues); + }) + .catch(() => { + // do nothing + }); } render() { diff --git a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap index 19a9c1fe..98bf9e7b 100644 --- a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap +++ b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap @@ -4388,6 +4388,10 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -4401,6 +4405,9 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -4642,6 +4649,10 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -4655,6 +4666,9 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -4764,6 +4778,10 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -4777,6 +4795,9 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -5004,6 +5025,10 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -5017,6 +5042,9 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -5220,6 +5248,10 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -5233,6 +5265,9 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -5345,6 +5380,10 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -5358,6 +5397,9 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -5467,6 +5509,10 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -5480,6 +5526,9 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -5589,6 +5638,10 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -5602,6 +5655,9 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -5829,6 +5885,10 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -5842,6 +5902,9 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -100, "currency": "USD", @@ -6039,6 +6102,10 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` "lineItems": Array [ Object { "code": "line-item/night", + "includeFor": Array [ + "customer", + "provider", + ], "lineTotal": Money { "amount": 16500, "currency": "USD", @@ -6052,6 +6119,9 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` }, Object { "code": "line-item/provider-commission", + "includeFor": Array [ + "provider", + ], "lineTotal": Money { "amount": -1000, "currency": "USD", diff --git a/src/ducks/user.duck.js b/src/ducks/user.duck.js index e4ec2d0b..a5996b85 100644 --- a/src/ducks/user.duck.js +++ b/src/ducks/user.duck.js @@ -383,9 +383,10 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) => .catch(err => { const e = storableError(err); dispatch(stripeAccountCreateError(e)); - const stripeMessage = e.apiErrors && e.apiErrors.length > 0 && e.apiErrors[0].meta - ? e.apiErrors[0].meta.stripe_message - : null; + const stripeMessage = + e.apiErrors && e.apiErrors.length > 0 && e.apiErrors[0].meta + ? e.apiErrors[0].meta.stripe_message + : null; log.error(err, 'create-stripe-account-failed', { stripeMessage }); throw e; }); diff --git a/src/util/errors.js b/src/util/errors.js index ba773105..a361f1cc 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -157,12 +157,11 @@ export const isChangeEmailWrongPassword = error => error && error.status === 403 */ export const isChangePasswordWrongPassword = error => error && error.status === 403; - /** * Check if the given API error (from * 'sdk.currentUser.createStripeAccount(payoutDetails)') is due to * invalid postal code in the given country. -*/ + */ export const isStripeInvalidPostalCode = error => { const msgRe = /^Invalid [A-Z]{2} postal code$/; return errorAPIErrors(error).some(apiError => {