Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storing failed and successful payments for Stripe Plugin #241

Merged
merged 14 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/vendure-plugin-stripe-subscription/codegen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ generates:
plugins:
- typescript
- typescript-operations
- typed-document-node
config:
avoidOptionals: false
scalars:
Expand Down
20 changes: 20 additions & 0 deletions packages/vendure-plugin-stripe-subscription/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@
"start:no-admin": "yarn ts-node test/dev-server.ts",
"generate": "graphql-codegen"
},
"devDependencies": {
"@graphql-codegen/cli": "^2.4.0",
"@graphql-codegen/typescript": "^2.4.8",
"@graphql-codegen/typescript-operations": "^2.3.5",
"@graphql-codegen/typed-document-node": "^5.0.1",
"@swc/core": "^1.3.59",
"@types/localtunnel": "^2.0.1",
"@types/nock": "^11.1.0",
"@vendure/admin-ui-plugin": "2.0.5",
"@vendure/core": "2.0.5",
"@vendure/testing": "2.0.5",
"@vendure/ui-devkit": "2.0.5",
"copyfiles": "^2.4.1",
"nock": "^13.2.9",
"node-fetch": "^2.0.0",
"ts-node": "^10.9.1",
"typescript": "4.9.5",
"unplugin-swc": "^1.3.2",
"vitest": "^0.30.1"
},
"dependencies": {
"date-fns": "2.29.3",
"stripe": "11.1.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ const _scalar = gql`
scalar DateTime
`;

const _interface = gql`
interface Node {
id: ID!
createdAt: DateTime
}
interface PaginatedList {
items: [Node!]!
totalItems: Int!
}
`;

const sharedTypes = gql`
enum SubscriptionInterval {
week
Expand All @@ -18,7 +29,10 @@ const sharedTypes = gql`
time_of_purchase
fixed_startdate
}
type StripeSubscriptionSchedule {
"""
For codegen to work this must implement Node
"""
type StripeSubscriptionSchedule implements Node {
id: ID!
createdAt: DateTime
updatedAt: DateTime
Expand All @@ -35,6 +49,20 @@ const sharedTypes = gql`
useProration: Boolean
autoRenew: Boolean
}
"""
For codegen to work this must implement Node
"""
type StripeSubscriptionPayment implements Node {
id: ID!
createdAt: DateTime
updatedAt: DateTime
collectionMethod: String
charge: String
currency: String
orderCode: String
channelId: ID
subscriptionId: String
}
input UpsertStripeSubscriptionScheduleInput {
id: ID
name: String!
Expand Down Expand Up @@ -108,9 +136,39 @@ export const adminSchemaExtensions = gql`
STRIPE_SUBSCRIPTION_NOTIFICATION
}

"""
For codegen to work this must be non-empty
"""
input StripeSubscriptionPaymentListOptions {
skip: Int
}

"""
For codegen to work this must be non-empty
"""
input StripeSubscriptionScheduleListOptions {
skip: Int
}

type StripeSubscriptionPaymentList implements PaginatedList {
items: [StripeSubscriptionPayment!]!
totalItems: Int!
}

type StripeSubscriptionScheduleList implements PaginatedList {
items: [StripeSubscriptionSchedule!]!
totalItems: Int!
}

extend type Query {
stripeSubscriptionSchedules: [StripeSubscriptionSchedule!]!
stripeSubscriptionSchedules(
options: StripeSubscriptionScheduleListOptions
): StripeSubscriptionScheduleList!
stripeSubscriptionPayments(
options: StripeSubscriptionPaymentListOptions
): StripeSubscriptionPaymentList!
}

extend type Mutation {
upsertStripeSubscriptionSchedule(
input: UpsertStripeSubscriptionScheduleInput!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Injectable } from '@nestjs/common';
import {
ID,
ListQueryBuilder,
RequestContext,
TransactionalConnection,
UserInputError,
} from '@vendure/core';
import {
StripeSubscriptionSchedule,
StripeSubscriptionScheduleList,
StripeSubscriptionScheduleListOptions,
SubscriptionStartMoment,
UpsertStripeSubscriptionScheduleInput,
} from '../ui/generated/graphql';
Expand All @@ -15,18 +18,24 @@ import { Schedule } from './schedule.entity';

@Injectable()
export class ScheduleService {
constructor(private connection: TransactionalConnection) {}
constructor(
private listQueryBuilder: ListQueryBuilder,
private connection: TransactionalConnection
) {}

async getSchedules(
ctx: RequestContext
): Promise<StripeSubscriptionSchedule[]> {
const schedules = await this.connection
.getRepository(ctx, Schedule)
.find({ where: { channelId: String(ctx.channelId) } });

return schedules.map((schedule) => {
return cloneSchedule(ctx, schedule);
});
ctx: RequestContext,
options: StripeSubscriptionScheduleListOptions
): Promise<StripeSubscriptionScheduleList> {
return this.listQueryBuilder
.build(Schedule, options, { ctx })
.getManyAndCount()
.then(([items, totalItems]) => ({
items: items.map((schedule) => {
return cloneSchedule(ctx, schedule);
}),
totalItems,
}));
}

async upsert(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { DeepPartial } from '@vendure/common/lib/shared-types';
import { VendureEntity, ID } from '@vendure/core';
import { Column, Entity } from 'typeorm';

@Entity()
export class StripeSubscriptionPayment extends VendureEntity {
constructor(input?: DeepPartial<StripeSubscriptionPayment>) {
super(input);
}

@Column({ nullable: true })
invoiceId!: string;

@Column({ nullable: true })
collectionMethod!: string;

@Column({ nullable: true })
charge!: string;

@Column({ nullable: true })
currency!: string;

@Column({ nullable: true })
orderCode!: string;

@Column({ nullable: true })
channelId!: string;

@Column({ nullable: true })
subscriptionId!: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import {
Allow,
Ctx,
ID,
ListQueryOptions,
Logger,
OrderService,
PaginatedList,
Permission,
ProductService,
RequestContext,
Expand All @@ -22,9 +24,14 @@ import { Request } from 'express';
import { loggerCtx, PLUGIN_INIT_OPTIONS } from '../constants';
import { StripeSubscriptionPluginOptions } from '../stripe-subscription.plugin';
import {
QueryStripeSubscriptionPaymentsArgs,
StripeSubscriptionPaymentList,
StripeSubscriptionPaymentListOptions,
StripeSubscriptionPricing,
StripeSubscriptionPricingInput,
StripeSubscriptionSchedule,
StripeSubscriptionScheduleList,
StripeSubscriptionScheduleListOptions,
UpsertStripeSubscriptionScheduleInput,
} from '../ui/generated/graphql';
import { ScheduleService } from './schedule.service';
Expand All @@ -34,6 +41,7 @@ import {
OrderLineWithSubscriptionFields,
VariantWithSubscriptionFields,
} from './subscription-custom-fields';
import { StripeSubscriptionPayment } from './stripe-subscription-payment.entity';

export type RequestWithRawBody = Request & { rawBody: any };

Expand Down Expand Up @@ -119,14 +127,27 @@ export class AdminPriceIncludesTaxResolver {

@Resolver()
export class AdminResolver {
constructor(private scheduleService: ScheduleService) {}
constructor(
private stripeSubscriptionService: StripeSubscriptionService,
private scheduleService: ScheduleService
) {}

@Allow(Permission.ReadSettings)
@Query()
async stripeSubscriptionSchedules(
@Ctx() ctx: RequestContext
): Promise<StripeSubscriptionSchedule[]> {
return this.scheduleService.getSchedules(ctx);
@Ctx() ctx: RequestContext,
@Args('options') options: StripeSubscriptionScheduleListOptions
): Promise<StripeSubscriptionScheduleList> {
return this.scheduleService.getSchedules(ctx, options);
}

@Allow(Permission.ReadSettings)
@Query()
async stripeSubscriptionPayments(
@Ctx() ctx: RequestContext,
@Args('options') options: StripeSubscriptionPaymentListOptions
): Promise<StripeSubscriptionPaymentList> {
return this.stripeSubscriptionService.getPayments(ctx, options);
}

@Allow(Permission.UpdateSettings)
Expand Down Expand Up @@ -227,6 +248,12 @@ export class StripeSubscriptionController {
body,
order
);
} else if (body.type === 'invoice.payment_action_required') {
await this.stripeSubscriptionService.handleInvoicePaymentFailed(
ctx,
body,
order
);
}
Logger.info(`Successfully handled webhook ${body.type}`, loggerCtx);
} catch (error) {
Expand Down
Loading
Loading