1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-29 18:52:22 +01:00

handle successfull stripe payment

This commit is contained in:
Sylvain 2020-12-07 13:49:11 +01:00
parent 1e43dc9518
commit 96b1cfcbc7
5 changed files with 33 additions and 40 deletions

View File

@ -4,10 +4,11 @@ import { PaymentMethod } from "@stripe/stripe-js";
import PaymentAPI from '../api/payment';
import { CartItems, PaymentConfirmation } from '../models/payment';
import { useTranslation } from 'react-i18next';
import { Reservation } from '../models/reservation';
interface StripeFormProps {
onSubmit: () => void,
onSuccess: (paymentMethod: PaymentMethod) => void,
onSuccess: (result: PaymentMethod|PaymentConfirmation) => void,
onError: (message: string) => void,
className?: string,
processPayment?: boolean,
@ -48,7 +49,7 @@ export const StripeForm: React.FC<StripeFormProps> = ({ onSubmit, onSuccess, onE
if (processPayment) {
// process the full payment pipeline, including SCA validation
const res = await PaymentAPI.confirm(paymentMethod.id, cartItems);
await handleServerConfirmation(res, paymentMethod);
await handleServerConfirmation(res);
} else {
// we don't want to process the payment, only return the payment method
onSuccess(paymentMethod);
@ -58,8 +59,12 @@ export const StripeForm: React.FC<StripeFormProps> = ({ onSubmit, onSuccess, onE
/**
* Process the server response about the Strong-customer authentication (SCA)
* @param response can be a PaymentConfirmation, or a Reservation (if the reservation succeeded), or a Subscription (if the subscription succeeded)
* @see app/controllers/api/payments_controller.rb#on_reservation_success
* @see app/controllers/api/payments_controller.rb#on_subscription_success
* @see app/controllers/api/payments_controller.rb#generate_payment_response
*/
const handleServerConfirmation = async (response: PaymentConfirmation, paymentMethod: PaymentMethod) => {
const handleServerConfirmation = async (response: PaymentConfirmation|any) => {
if (response.error) {
if (response.error.statusText) {
onError(response.error.statusText);
@ -76,13 +81,13 @@ export const StripeForm: React.FC<StripeFormProps> = ({ onSubmit, onSuccess, onE
// The PaymentIntent can be confirmed again on the server
try {
const confirmation = await PaymentAPI.confirm(result.paymentIntent.id, cartItems);
await handleServerConfirmation(confirmation, paymentMethod);
await handleServerConfirmation(confirmation);
} catch (e) {
onError(e);
}
}
} else {
onSuccess(paymentMethod);
onSuccess(response);
}
}

View File

@ -23,7 +23,7 @@ import { StripeForm } from './stripe-form';
import stripeLogo from '../../../images/powered_by_stripe.png';
import mastercardLogo from '../../../images/mastercard.png';
import visaLogo from '../../../images/visa.png';
import { CartItems } from '../models/payment';
import { CartItems, PaymentConfirmation } from '../models/payment';
import WalletAPI from '../api/wallet';
import PriceAPI from '../api/price';
@ -33,7 +33,7 @@ declare var Fablab: IFablab;
interface StripeModalProps {
isOpen: boolean,
toggleModal: () => void,
afterSuccess: (paymentMethod: PaymentMethod) => void,
afterSuccess: (result: PaymentMethod|PaymentConfirmation) => void,
cartItems: CartItems,
currentUser: User,
schedule: PaymentSchedule,
@ -140,9 +140,9 @@ const StripeModal: React.FC<StripeModalProps> = ({ isOpen, toggleModal, afterSuc
/**
* After sending the form with success, process the resulting payment method
*/
const handleFormSuccess = async (paymentMethod: PaymentMethod): Promise<void> => {
const handleFormSuccess = async (result: PaymentMethod|PaymentConfirmation): Promise<void> => {
setSubmitState(false);
afterSuccess(paymentMethod);
afterSuccess(result);
}
/**

View File

@ -735,19 +735,6 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
* @param user {Object} user associated with the slot
*/
const updateMachineSlot = function (slot, reservation, user) {
/* TODO, FIXME
machines.js.erb:741 Uncaught (in promise) TypeError: Cannot read property 'slots' of undefined
at updateMachineSlot (machines.js.erb:741)
at machines.js.erb:664
at Object.forEach (angular.js:386)
at Scope.$scope.afterPayment (machines.js.erb:652)
at afterPayment (cart.js:884)
at $scope.afterStripeSuccess (cart.js:338)
at _callee$ (stripe-modal.tsx:145)
at tryCatch (runtime.js:63)
at Generator.invoke [as _invoke] (runtime.js:293)
at Generator.next (runtime.js:118)
*/
angular.forEach(reservation.slots, function (s) {
if (slot.start.isSame(s.start_at)) {
slot.slot_id = s.id;

View File

@ -70,13 +70,13 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
// Payment schedule
$scope.schedule = {
requested_schedule: false, // does the user requests a payment schedule for his subscription
payment_schedule: null // the effective computed payment schedule
payment_schedule: undefined // the effective computed payment schedule
};
// online payments (stripe)
$scope.stripe = {
showModal: false,
cartItems: null
cartItems: undefined
};
// currently logged-in user
@ -327,10 +327,11 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
/**
* Invoked atfer a successful Stripe payment
* @param result {*} may be a reservation or a subscription
*/
$scope.afterStripeSuccess = () => {
$scope.afterStripeSuccess = (result) => {
$scope.toggleStripeModal();
afterPayment($scope.reservation);
afterPayment(result);
};
/* PRIVATE SCOPE */
@ -638,9 +639,9 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
/**
* Format the parameters expected by /api/prices/compute or /api/reservations and return the resulting object
* @param request {{reservation: object}|{subscription: object}} as returned by mkReservation()
* @param coupon {Object} Coupon as returned from the API
* @return {{reservation:Object, subscription: Object, coupon_code:string}}
* @param request {{reservation: *}|{subscription: *}} as returned by mkReservation()
* @param coupon {{code: string}} Coupon as returned from the API
* @return {CartItems}
*/
const mkRequestParams = function (request, coupon) {
return Object.assign({
@ -870,28 +871,28 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
/**
* Actions to run after the payment was successful
* @param reservation {Object} may be a reservation or a subscription
* @param paymentResult {*} may be a reservation or a subscription
*/
const afterPayment = function (reservation) {
const afterPayment = function (paymentResult) {
// we set the cart content as 'paid' to display a summary of the transaction
$scope.events.paid = $scope.events.reserved;
$scope.amountPaid = $scope.amountTotal;
// we call the external callback if present
if (typeof $scope.afterPayment === 'function') { $scope.afterPayment(reservation); }
if (typeof $scope.afterPayment === 'function') { $scope.afterPayment(paymentResult); }
// we reset the coupon, and the cart content, and we unselect the slot
$scope.coupon.applied = null;
$scope.coupon.applied = undefined;
if ($scope.slot) {
// reservation (+ subscription)
$scope.slot = null;
$scope.slot = undefined;
$scope.events.reserved = [];
} else {
// subscription only
$scope.events = {};
}
$scope.paidPlan = $scope.selectedPlan;
$scope.selectedPlan = null;
$scope.selectedPlan = undefined;
$scope.schedule.requested_schedule = false;
$scope.schedule.payment_schedule = null;
$scope.schedule.payment_schedule = undefined;
};
/**

View File

@ -6,7 +6,7 @@ export interface PaymentConfirmation {
success?: boolean,
error?: {
statusText: string
},
}
}
export enum PaymentMethod {
@ -15,12 +15,12 @@ export enum PaymentMethod {
}
export interface CartItems {
reservation: Reservation,
subscription: {
reservation?: Reservation,
subscription?: {
plan_id: number,
user_id: number,
payment_schedule: boolean,
payment_method: PaymentMethod
},
coupon_code: string
coupon_code?: string
}