diff --git a/public/package-lock.json b/public/package-lock.json index b6fdb0900..3f98ccf46 100644 --- a/public/package-lock.json +++ b/public/package-lock.json @@ -9,8 +9,9 @@ "version": "1.0.0", "license": "GPL-3.0", "dependencies": { + "@stripe/react-stripe-js": "^2.7.0", + "@stripe/stripe-js": "^3.3.0", "@types/markdown-it": "^12.2.1", - "@types/stripe-v3": "^3.1.23", "chart.js": "^2.9.4", "d3": "^7.8.3", "d3-sankey": "^0.12.3", @@ -105,6 +106,27 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "node_modules/@stripe/react-stripe-js": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.7.0.tgz", + "integrity": "sha512-kTkIZl2ZleBuDR9c6fDy/s4m33llII8a5al6BDAMSTrfVq/4gSZv3RBO5KS/xvnxS+fDapJ3bKvjD8Lqj+AKdQ==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "@stripe/stripe-js": "^1.44.1 || ^2.0.0 || ^3.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@stripe/stripe-js": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-3.3.0.tgz", + "integrity": "sha512-dUgAsko9KoYC1U2TIawHzbkQJzPoApxCc1Qf6/j318d1ArViyh6ROHVYTxnU3RlOQL/utUD9I4/QoyiCowsgrw==", + "engines": { + "node": ">=12.16" + } + }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -568,11 +590,6 @@ "@types/node": "*" } }, - "node_modules/@types/stripe-v3": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/@types/stripe-v3/-/stripe-v3-3.1.23.tgz", - "integrity": "sha512-fqCnai832M6o6qH6A+Dqk1I/SXAzx629bknbrDigyvkuAPGZGrjkLCMxfnrtWswHXNPjj/TtuGf4lQnDXc815w==" - }, "node_modules/@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", @@ -2876,8 +2893,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "peer": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -2968,7 +2984,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -5833,6 +5848,14 @@ "inBundle": true, "license": "ISC" }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -6068,6 +6091,16 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -6185,6 +6218,11 @@ "react": "^18.2.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", diff --git a/public/package.json b/public/package.json index 2cea58138..f459b10d2 100644 --- a/public/package.json +++ b/public/package.json @@ -17,8 +17,9 @@ "webpack-merge": "^5.8.0" }, "dependencies": { + "@stripe/react-stripe-js": "^2.7.0", + "@stripe/stripe-js": "^3.3.0", "@types/markdown-it": "^12.2.1", - "@types/stripe-v3": "^3.1.23", "chart.js": "^2.9.4", "d3": "^7.8.3", "d3-sankey": "^0.12.3", diff --git a/public/ts/cartpage.tsx b/public/ts/cartpage.tsx index 0e87dd667..9e30783d1 100644 --- a/public/ts/cartpage.tsx +++ b/public/ts/cartpage.tsx @@ -154,10 +154,10 @@ const PaymentButton = ({ e.preventDefault(); setInProgress(true); try { - const result = await stripe.createPaymentMethod( - "card", - element, - ); + const result = await stripe!.createPaymentMethod({ + type: "card", + card: element, + }); if (result.error) { throw result.error; } else { diff --git a/public/ts/payment_common.tsx b/public/ts/payment_common.tsx index 2394a2ba0..4743ca0e3 100644 --- a/public/ts/payment_common.tsx +++ b/public/ts/payment_common.tsx @@ -1,4 +1,10 @@ -/// +import { + loadStripe, + PaymentMethod, + Stripe, + StripeCardElement, + StripeError, +} from "@stripe/stripe-js"; import { useEffect, useRef } from "preact/hooks"; import Cart, { Item } from "./cart"; import * as common from "./common"; @@ -13,20 +19,20 @@ import { useTranslation } from "./translations"; declare var UIkit: any; -export var stripe: stripe.Stripe; -var card: stripe.elements.Element; +export var stripe: Stripe | null; +var card: StripeCardElement; var spinner: any; var payButton: HTMLInputElement; var errorElement: any; -export function initializeStripe() { +export async function initializeStripe() { // Create a Stripe client. - stripe = Stripe(window.stripeKey); + stripe = await loadStripe(window.stripeKey); } export function mountStripe() { // Create an instance of Elements. - const elements = stripe.elements({ locale: "sv" }); + const elements = stripe!.elements({ locale: "sv" }); // Custom styling can be passed to options when creating an Element. const stripeStyle = { base: { @@ -64,7 +70,7 @@ interface ResponseFunction { export interface PaymentFlowDefinition { initiate_payment: InitializePaymentFunction; before_initiate_payment?: Function; - on_stripe_error?: (error: stripe.Error) => void; + on_stripe_error?: (error: StripeError) => void; handle_backend_response?: ( json: ServerResponse, ) => void; @@ -337,7 +343,7 @@ export function ProductDataFromProducts( export const StripeCardInput = ({ element, }: { - element: stripe.elements.Element; + element: StripeCardElement; }) => { const mountPoint = useRef(null); @@ -350,7 +356,7 @@ export const StripeCardInput = ({ export const createStripeCardInput = () => { // Create an instance of Elements. - const elements = stripe.elements({ locale: "sv" }); + const elements = stripe!.elements({ locale: "sv" }); // Custom styling can be passed to options when creating an Element. const stripeStyle = { base: { @@ -566,10 +572,12 @@ export const extractRelevantProducts = ( }; export async function createPaymentMethod( - element: stripe.elements.Element, + element: StripeCardElement, memberInfo: member_t, -): Promise { - const result = await stripe.createPaymentMethod("card", element, { +): Promise { + const result = await stripe!.createPaymentMethod({ + type: "card", + card: element, billing_details: { name: `${memberInfo.firstname} ${memberInfo.lastname}`, email: memberInfo.email, @@ -649,7 +657,7 @@ export async function handleStripeSetupIntent< res.data.action_info!.type === PaymentIntentNextActionType.USE_STRIPE_SDK ) { - const stripeResult = await stripe.confirmCardSetup( + const stripeResult = await stripe!.confirmCardSetup( res.data.action_info!.client_secret, ); if (stripeResult.error) { @@ -705,7 +713,7 @@ export async function negotiatePayment< res.data.action_info!.type === PaymentIntentNextActionType.USE_STRIPE_SDK ) { - const stripeResult = await stripe.handleCardAction( + const stripeResult = await stripe!.handleCardAction( res.data.action_info!.client_secret, ); if (stripeResult.error) { @@ -729,7 +737,7 @@ export async function negotiatePayment< } export async function pay( - paymentMethod: stripe.paymentMethod.PaymentMethod, + paymentMethod: PaymentMethod, cart: Cart, productData: ProductData, discount: Discount, diff --git a/public/ts/register.tsx b/public/ts/register.tsx index cffbe375a..14d71cda2 100644 --- a/public/ts/register.tsx +++ b/public/ts/register.tsx @@ -1,3 +1,4 @@ +import { PaymentMethod, StripeCardElement } from "@stripe/stripe-js"; import { ComponentChildren, render } from "preact"; import { StateUpdater, useEffect, useMemo, useState } from "preact/hooks"; import { PopupModal, useCalendlyEventListener } from "react-calendly"; @@ -423,7 +424,7 @@ const Confirmation = ({ productData: ProductData; discount: Discount; discountInfo: DiscountsInfo; - card: stripe.elements.Element; + card: StripeCardElement; onRegistered: (r: RegistrationSuccess) => void; onBack: () => void; }) => { @@ -538,7 +539,7 @@ type RegistrationSuccess = { }; async function registerMember( - paymentMethod: stripe.paymentMethod.PaymentMethod, + paymentMethod: PaymentMethod, productData: ProductData, memberInfo: MemberInfoValidated, selectedPlan: Plan, diff --git a/public/ts/subscriptions.tsx b/public/ts/subscriptions.tsx index 15372b0f5..3c629873a 100644 --- a/public/ts/subscriptions.tsx +++ b/public/ts/subscriptions.tsx @@ -1,3 +1,4 @@ +import { StripeCardElement } from "@stripe/stripe-js"; import { render } from "preact"; import { useState } from "preact/hooks"; import Cart from "./cart"; @@ -60,7 +61,7 @@ const PayDialog = ({ onCancel, onPay, }: { - stripe: stripe.elements.Element; + stripe: StripeCardElement; productData: ProductData; products: Product[]; currentMemberships: SubscriptionType[];