From f661428db28457bbeab9ea4f1e8d90aae12c41c9 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 23 Dec 2020 15:29:56 +0100 Subject: [PATCH] better error handling in stripe::subscription creation process --- .../api/payment_schedules_controller.rb | 2 +- app/controllers/api/payments_controller.rb | 4 +- app/frontend/src/javascript/api/api-client.ts | 15 ++-- .../src/javascript/components/stripe-form.tsx | 14 +++- .../javascript/components/stripe-modal.tsx | 1 + app/frontend/src/javascript/models/user.ts | 1 + app/services/payment_schedule_service.rb | 2 +- app/services/reservations/reserve.rb | 30 ++++---- app/services/stripe_service.rb | 71 +++++++++++++++++++ app/services/subscriptions/subscribe.rb | 30 ++++---- app/views/api/members/_member.json.jbuilder | 1 + app/workers/payment_schedule_worker.rb | 21 ++++++ app/workers/stripe_worker.rb | 53 -------------- ...027101809_create_payment_schedule_items.rb | 1 + db/structure.sql | 68 +++++++++++------- 15 files changed, 196 insertions(+), 118 deletions(-) create mode 100644 app/services/stripe_service.rb create mode 100644 app/workers/payment_schedule_worker.rb diff --git a/app/controllers/api/payment_schedules_controller.rb b/app/controllers/api/payment_schedules_controller.rb index e40af2920..f1a653d3d 100644 --- a/app/controllers/api/payment_schedules_controller.rb +++ b/app/controllers/api/payment_schedules_controller.rb @@ -7,7 +7,7 @@ class API::PaymentSchedulesController < API::ApiController def download authorize @payment_schedule - # TODO, send_file File.join(Rails.root, @payment_schedule.file), type: 'application/pdf', disposition: 'attachment' + send_file File.join(Rails.root, @payment_schedule.file), type: 'application/pdf', disposition: 'attachment' end private diff --git a/app/controllers/api/payments_controller.rb b/app/controllers/api/payments_controller.rb index ad1eaa2dd..1c692a679 100644 --- a/app/controllers/api/payments_controller.rb +++ b/app/controllers/api/payments_controller.rb @@ -89,8 +89,8 @@ class API::PaymentsController < API::ApiController end render generate_payment_response(intent, res) - rescue Stripe::InvalidRequestError - render json: { error: 'no such setup intent' }, status: :unprocessable_entity + rescue Stripe::InvalidRequestError => e + render json: e, status: :unprocessable_entity end private diff --git a/app/frontend/src/javascript/api/api-client.ts b/app/frontend/src/javascript/api/api-client.ts index 8c8aae7cc..e0c41ca30 100644 --- a/app/frontend/src/javascript/api/api-client.ts +++ b/app/frontend/src/javascript/api/api-client.ts @@ -19,15 +19,16 @@ client.interceptors.response.use(function (response) { }); function extractHumanReadableMessage(error: any): string { - if (error.match(/^/)) { - // parse ruby error pages - const parser = new DOMParser(); - const htmlDoc = parser.parseFromString(error, 'text/html'); - return htmlDoc.querySelector('h2').textContent; + if (typeof error === 'string') { + if (error.match(/^/)) { + // parse ruby error pages + const parser = new DOMParser(); + const htmlDoc = parser.parseFromString(error, 'text/html'); + return htmlDoc.querySelector('h2').textContent; + } + return error; } - if (typeof error === 'string') return error; - // parse Rails errors (as JSON) let message = ''; if (error instanceof Object) { diff --git a/app/frontend/src/javascript/components/stripe-form.tsx b/app/frontend/src/javascript/components/stripe-form.tsx index a96af73a3..ba0cdcfba 100644 --- a/app/frontend/src/javascript/components/stripe-form.tsx +++ b/app/frontend/src/javascript/components/stripe-form.tsx @@ -11,6 +11,7 @@ interface StripeFormProps { onSuccess: (result: SetupIntent|PaymentConfirmation|any) => void, onError: (message: string) => void, customer: User, + operator: User, className?: string, paymentSchedule?: boolean, cartItems?: CartItems @@ -20,7 +21,7 @@ interface StripeFormProps { * A form component to collect the credit card details and to create the payment method on Stripe. * The form validation button must be created elsewhere, using the attribute form="stripe-form". */ -export const StripeForm: React.FC = ({ onSubmit, onSuccess, onError, children, className, paymentSchedule = false, cartItems, customer }) => { +export const StripeForm: React.FC = ({ onSubmit, onSuccess, onError, children, className, paymentSchedule = false, cartItems, customer, operator }) => { const { t } = useTranslation('shared'); @@ -57,7 +58,16 @@ export const StripeForm: React.FC = ({ onSubmit, onSuccess, onE // we start by associating the payment method with the user const { client_secret } = await PaymentAPI.setupIntent(customer.id); const { setupIntent, error } = await stripe.confirmCardSetup(client_secret, { - payment_method: paymentMethod.id + payment_method: paymentMethod.id, + mandate_data: { + customer_acceptance: { + type: 'online', + online: { + ip_address: operator.ip_address, + user_agent: navigator.userAgent + } + } + } }) if (error) { onError(error.message); diff --git a/app/frontend/src/javascript/components/stripe-modal.tsx b/app/frontend/src/javascript/components/stripe-modal.tsx index f106aebcd..a2d14f594 100644 --- a/app/frontend/src/javascript/components/stripe-modal.tsx +++ b/app/frontend/src/javascript/components/stripe-modal.tsx @@ -178,6 +178,7 @@ const StripeModal: React.FC = ({ isOpen, toggleModal, afterSuc