import { useState } from 'react';
import {
CardNumberElement,
CardCvcElement,
CardExpiryElement,
useElements,
useStripe,
} from '@stripe/react-stripe-js';
export const StripePaymentForm = () => {
...
const { error, onSubmit } = useHandleSubmit();
return (
<div>
<h1>Payment Form</h1>
<Formik
initialValues={...}
onSubmit={onSubmit}
validateOnBlur
validateOnChange={false}
>
{props => (
<FormikForm>
<CheckboxField name="savePaymentForFutureUse" label="Save new payment?" />
<CardNumberElement ... />
<InputField name="nameOnAccount" autoComplete="cc-name" />
<CardCvcElement ... />
<CardExpiryElement ... />
...
<button type="submit">Submit</button>
</FormikForm>
)}
</Formik>
</div>
)
}
const useHandleSubmit = () => {
const stripe = useStripe();
const elements = useElements();
const [error, setError] = useState();
const [stripeError, setStripeError] = useState();
const onSubmit = async (data, actions): Promise<void> => {
const { savePaymentForFutureUse, ...billingAddress } = data;
const billing_details = {
...billingAddress,
email: emailAddress,
};
let paymentMethod;
let displayAttributes= {};
let paymentName;
// selectedSavedPaymentMethod - one of the created saved payment method from PaymentTransactionServices
if (!isEmpty(selectedSavedPaymentMethod)) {
paymentMethod = {
id: selectedSavedPaymentMethod.id,
};
displayAttributes = selectedSavedPaymentMethod.displayAttributes;
paymentName = selectedSavedPaymentMethod.name;
} else {
const stripeResponse = await stripe.createPaymentMethod({
type: 'card',
card: elements.getElement(CardNumberElement),
billing_details,
});
if (!isEmpty(stripeResponse.error)) {
setStripeError(stripeResponse.error);
return;
}
paymentMethod = stripeResponse.paymentMethod;
// these are optional and only support displaying info about the card on the frontend
displayAttributes = {
creditCardType: paymentMethod.card.brand.toUpperCase(),
creditCardNumber: maskCardNumber(paymentMethod.card.last4),
creditCardExpDateMonth: padStart(
`${paymentMethod.card.exp_month}`,
2,
'0'
),
creditCardExpDateYear: `${paymentMethod.card.exp_year}`,
};
paymentName = `${displayAttributes.creditCardType} | ${displayAttributes.creditCardNumber} ${displayAttributes.creditCardExpDateMonth}/${displayAttributes.creditCardExpDateYear}`;
}
// these are required to pass to the backend as part of the payment
const paymentMethodProperties = {
PAYMENT_METHOD_ID: paymentMethod.id,
CUSTOMER_ID: paymentMethod.customer
};
const paymentRequest = {
name: paymentName,
savedPaymentMethodId: selectedSavedPaymentMethod.id,
type: 'CREDIT_CARD',
gatewayType: 'STRIPE',
amount: { amount: 11, currency: 'USD' },
subtotal: cart.cartPricing.subtotal,
adjustmentsTotal: cart.cartPricing.adjustmentsTotal,
fulfillmentTotal: cart.cartPricing.fulfillmentTotal,
taxTotal: cart.cartPricing.totalTax,
billingAddress,
shouldSavePaymentForFutureUse: savePaymentForFutureUse,
paymentMethodProperties,
displayAttributes,
};
try {
// submit the payment request
// "handleSubmitPaymentInfo" - can be obtained from our payment SDK - useSubmitPaymentRequest(). It creates a Payment in PaymentTransactionServices
const paymentSummary = await handleSubmitPaymentInfo(paymentRequest);
...
} catch (err) {
setError(err);
} finally {
...
}
};
return { error, onSubmit, stripeError };
};