Skip to content

Commit

Permalink
Stripe payment feature draft 1
Browse files Browse the repository at this point in the history
  • Loading branch information
fayazara committed Oct 6, 2023
1 parent c4e09e7 commit b837a98
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 24 deletions.
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
"sanitize-html": "^2.10.0",
"schema-dts": "^1.1.0",
"short-uuid": "^4.2.0",
"stripe": "^9.16.0",
"stripe": "^13.7.0",
"superjson": "1.9.1",
"tailwindcss-radix": "^2.6.0",
"title-case": "^3.0.3",
Expand Down
22 changes: 22 additions & 0 deletions apps/web/pages/api/create-checkout-link/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const stripe = require("stripe")(process.env.STRIPE_PRIVATE_KEY);
const HOST = process.env.NEXT_PUBLIC_WEBSITE_URL || "http://localhost:3000";
export default async function handler(req, res) {
if (req.method === "POST") {
const { email, priceId, bookingInputId } = req.body;
const session = await stripe.checkout.sessions.create({
line_items: [
{
price: priceId,
quantity: 1,
},
],
customer_email: email,
mode: "payment",
success_url: `${HOST}/create-booking?bookingInputId=${bookingInputId}`,
cancel_url: `${HOST}`,
});
res.status(200).json({ url: session.url });
} else {
res.status(405).json({ message: "Method not allowed" });
}
}
40 changes: 40 additions & 0 deletions apps/web/pages/create-booking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useRouter } from "next/router";
import { useEffect } from "react";

import { createBooking, mapBookingToMutationInput } from "@calcom/features/bookings/lib";

import Spinner from "../ui/spinner";

const createBookingUtility = async (bookingInput) => {
const responseData = await createBooking(mapBookingToMutationInput(bookingInput));
return responseData;
};

const CreateBooking = () => {
const router = useRouter();
const { bookingInputId } = router.query;
useEffect(() => {
const confirmBooking = async () => {
if (bookingInputId) {
const bookingData = JSON.parse(localStorage.getItem(bookingInputId));
try {
const data = await createBookingUtility(bookingData);
console.log("Booking created:", data);
router.push(`/booking/${data.uid}`);
} catch (error) {
console.error("Error creating booking:", error);
}
}
};

confirmBooking();
}, [bookingInputId]);

return (
<main className="flex h-screen items-center justify-center">
<Spinner label="Confirming your booking..." />
</main>
);
};

export default CreateBooking;
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,21 @@ import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import type { FieldError } from "react-hook-form";
import { useForm } from "react-hook-form";
import short from "short-uuid";
import { z } from "zod";

import type { EventLocationType } from "@calcom/app-store/locations";
import { createPaymentLink } from "@calcom/app-store/stripepayment/lib/client";
import dayjs from "@calcom/dayjs";
import { VerifyCodeDialog } from "@calcom/features/bookings/components/VerifyCodeDialog";
import {
createBooking,
createRecurringBooking,
mapBookingToMutationInput,
mapRecurringBookingToMutationInput,
useTimePreferences,
} from "@calcom/features/bookings/lib";
import { createBooking, createRecurringBooking, useTimePreferences } from "@calcom/features/bookings/lib";
import getBookingResponsesSchema, {
getBookingResponsesPartialSchema,
} from "@calcom/features/bookings/lib/getBookingResponsesSchema";
import { getFullName } from "@calcom/features/form-builder/utils";
import { useBookingSuccessRedirect } from "@calcom/lib/bookingSuccessRedirect";
import { MINUTES_TO_BOOK } from "@calcom/lib/constants";
import { post } from "@calcom/lib/fetch-wrapper";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { useRouterQuery } from "@calcom/lib/hooks/useRouterQuery";
import { HttpError } from "@calcom/lib/http-error";
Expand Down Expand Up @@ -292,7 +288,24 @@ export const BookEventFormChild = ({
/>
);

const bookEvent = (values: BookingFormValues) => {
interface CheckoutPayload {
bookingInputId: string;
email: string;
priceId: string;
}

interface ApiResponse {
url: string;
}

const generateCheckoutLink = async (data: CheckoutPayload): Promise<string> => {
const response = await post<CheckoutPayload, ApiResponse>("/api/create-checkout-link", data);
const { url } = response;
return url;
};

const bookEvent = async (values: BookingFormValues) => {
console.log(values);
// Clears form values stored in store, so old values won't stick around.
setFormValues({});
bookingForm.clearErrors();
Expand All @@ -304,8 +317,8 @@ export const BookEventFormChild = ({
return;
}

// Ensures that duration is an allowed value, if not it defaults to the
// default eventQuery duration.
// // Ensures that duration is an allowed value, if not it defaults to the
// // default eventQuery duration.
const validDuration =
duration &&
eventQuery.data.metadata?.multipleDuration &&
Expand Down Expand Up @@ -334,13 +347,15 @@ export const BookEventFormChild = ({
),
};

if (eventQuery.data?.recurringEvent?.freq && recurringEventCount) {
createRecurringBookingMutation.mutate(
mapRecurringBookingToMutationInput(bookingInput, recurringEventCount)
);
} else {
createBookingMutation.mutate(mapBookingToMutationInput(bookingInput));
}
const uuid = short.generate();
const bookingInputString = JSON.stringify(bookingInput);
localStorage.setItem(uuid, bookingInputString);
const url = await generateCheckoutLink({
bookingInputId: uuid,
email: values?.responses?.email,
priceId: "price_1NfM8hCt3U7PjutYOXR6zeny",
});
window.location.href = url;
};

if (!eventType) {
Expand Down Expand Up @@ -400,11 +415,7 @@ export const BookEventFormChild = ({
color="primary"
loading={createBookingMutation.isLoading || createRecurringBookingMutation.isLoading}
data-testid={rescheduleUid ? "confirm-reschedule-button" : "confirm-book-button"}>
{rescheduleUid
? t("reschedule")
: renderConfirmNotVerifyEmailButtonCond
? t("confirm")
: t("verify_email_email_button")}
Book
</Button>
</div>
</Form>
Expand Down
21 changes: 20 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4137,7 +4137,7 @@ __metadata:
sanitize-html: ^2.10.0
schema-dts: ^1.1.0
short-uuid: ^4.2.0
stripe: ^9.16.0
stripe: ^13.7.0
superjson: 1.9.1
tailwindcss: ^3.3.1
tailwindcss-animate: ^1.0.6
Expand Down Expand Up @@ -29767,6 +29767,15 @@ __metadata:
languageName: node
linkType: hard

"qs@npm:^6.11.0":
version: 6.11.2
resolution: "qs@npm:6.11.2"
dependencies:
side-channel: ^1.0.4
checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b
languageName: node
linkType: hard

"qs@npm:~6.5.2":
version: 6.5.3
resolution: "qs@npm:6.5.3"
Expand Down Expand Up @@ -33365,6 +33374,16 @@ __metadata:
languageName: node
linkType: hard

"stripe@npm:^13.7.0":
version: 13.7.0
resolution: "stripe@npm:13.7.0"
dependencies:
"@types/node": ">=8.1.0"
qs: ^6.11.0
checksum: 5c0f068662590175d766f703e60f148fa623b40add0f1ba2c828e1114d98c63da05e02cb24befb6740ce51583ad5cb782e2a9bdc52936b6b85251add3ede7af8
languageName: node
linkType: hard

"stripe@npm:^9.16.0":
version: 9.16.0
resolution: "stripe@npm:9.16.0"
Expand Down

0 comments on commit b837a98

Please sign in to comment.