Module 10 Summary
This lesson is a summary of the work we've done in Module 10.0.
š This module's quiz can be found - here.
šļø Solutions for this module's quiz can be found - here.
In this module, we've set-up a Stripe Connect account for our TinyHouse application and we've provided the capability for users in our application to connect with their Stripe account and be a connected Stripe account in our platform.
Server Project#
src/graphql/typeDefs.ts
#
In our GraphQL API type definitions, we've established two new root-level mutation fields - connectStripe
and disconnectStripe
.
The
connectStripe
mutation is to be executed, from the client, when the user proceeds through the Stripe OAuth page to connect their Stripe account and is redirected back to our app.The
disconnectStripe
mutation is to be executed when a user decides to disconnect from Stripe from our TinyHouse application.
type Mutation {
logIn(input: LogInInput): Viewer!
logOut: Viewer!
connectStripe(input: ConnectStripeInput!): Viewer!
disconnectStripe: Viewer!
}
src/graphql/resolvers/Viewer/index.ts
#
We've constructed the resolver functions for the connectStripe
and disconnectStripe
mutations in the viewerResolvers
map within the src/graphql/resolvers/Viewer/index.ts
file.
In the connectStripe()
resolver function, we obtain the value of the authorization code
returned from Stripe's servers and passed into our mutation as part of the input. We then verify that a valid viewer is making the request and then look to obtain the stripe_user_id
of the viewer by interacting with Stripe's API. When the stripe_user_id
is available, we update the user document of the viewer by adding the stripe_user_id
as the value to the walletId
field of the document.
export const viewerResolvers: IResolvers = { connectStripe: async (
_root: undefined,
{ input }: ConnectStripeArgs,
{ db, req }: { db: Database; req: Request }
): Promise<Viewer> => {
try {
const { code } = input;
let viewer = await authorize(db, req);
if (!viewer) {
throw new Error("viewer cannot be found");
}
const wallet = await Stripe.connect(code);
if (!wallet) {
throw new Error("stripe grant error");
}
const updateRes = await db.users.findOneAndUpdate(
{ _id: viewer._id },
{ $set: { walletId: wallet.stripe_user_id } },
{ returnOriginal: false }
);
if (!updateRes.value) {
throw new Error("viewer could not be updated");
}
viewer = updateRes.value;
return {
_id: viewer._id,
token: viewer.token,
avatar: viewer.avatar,
walletId: viewer.walletId,
didRequest: true
};
} catch (error) {
throw new Error(`Failed to connect with Stripe: ${error}`);
}
},};
The disconnectStripe()
resolver function primarily involves removing the value of the walletId
field of the viewer making the request.
export const viewerResolvers: IResolvers = { disconnectStripe: async (
_root: undefined,
_args: {},
{ db, req }: { db: Database; req: Request }
): Promise<Viewer> => {
try {
let viewer = await authorize(db, req);
if (!viewer) {
throw new Error("viewer cannot be found");
}
const updateRes = await db.users.findOneAndUpdate(
{ _id: viewer._id },
{ $set: { walletId: null } },
{ returnOriginal: false }
);
if (!updateRes.value) {
throw new Error("viewer could not be updated");
}
viewer = updateRes.value;
return {
_id: viewer._id,
token: viewer.token,
avatar: viewer.avatar,
walletId: viewer.walletId,
didRequest: true
};
} catch (error) {
throw new Error(`Failed to disconnect with Stripe: ${error}`);
}
}};
src/lib/api/Stripe.ts
#
In the src/lib/api/Stripe.ts
file, we created a Stripe
object instance that consolidates the functionality to interact with Stripe's servers. In the src/lib/api/Stripe.ts
file, we constructed an OAuth client and in the exported Stripe
object, there exists a connect()
function property that uses the Stripe client to fetch the user's credentials from Stripe.
This page is a preview of TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two