Browse Source

Task/introduce interface for create Stripe checkout session response (#5791)

* Introduce interface
pull/5814/head
Thomas Kaul 4 days ago
committed by GitHub
parent
commit
edcc140428
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      apps/api/src/app/subscription/subscription.controller.ts
  2. 62
      apps/api/src/app/subscription/subscription.service.ts
  3. 7
      apps/client/src/app/components/user-account-membership/user-account-membership.component.ts
  4. 7
      apps/client/src/app/pages/pricing/pricing-page.component.ts
  5. 14
      apps/client/src/app/services/data.service.ts
  6. 2
      libs/common/src/lib/interfaces/index.ts
  7. 3
      libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts

11
apps/api/src/app/subscription/subscription.controller.ts

@ -5,7 +5,10 @@ import {
DEFAULT_LANGUAGE_CODE, DEFAULT_LANGUAGE_CODE,
PROPERTY_COUPONS PROPERTY_COUPONS
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { Coupon } from '@ghostfolio/common/interfaces'; import {
Coupon,
CreateStripeCheckoutSessionResponse
} from '@ghostfolio/common/interfaces';
import type { RequestWithUser } from '@ghostfolio/common/types'; import type { RequestWithUser } from '@ghostfolio/common/types';
import { import {
@ -111,11 +114,11 @@ export class SubscriptionController {
@Post('stripe/checkout-session') @Post('stripe/checkout-session')
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async createCheckoutSession( public createStripeCheckoutSession(
@Body() { couponId, priceId }: { couponId?: string; priceId: string } @Body() { couponId, priceId }: { couponId?: string; priceId: string }
) { ): Promise<CreateStripeCheckoutSessionResponse> {
try { try {
return this.subscriptionService.createCheckoutSession({ return this.subscriptionService.createStripeCheckoutSession({
couponId, couponId,
priceId, priceId,
user: this.request.user user: this.request.user

62
apps/api/src/app/subscription/subscription.service.ts

@ -6,7 +6,10 @@ import {
PROPERTY_STRIPE_CONFIG PROPERTY_STRIPE_CONFIG
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { parseDate } from '@ghostfolio/common/helper'; import { parseDate } from '@ghostfolio/common/helper';
import { SubscriptionOffer } from '@ghostfolio/common/interfaces'; import {
CreateStripeCheckoutSessionResponse,
SubscriptionOffer
} from '@ghostfolio/common/interfaces';
import { import {
SubscriptionOfferKey, SubscriptionOfferKey,
UserWithSettings UserWithSettings
@ -38,7 +41,7 @@ export class SubscriptionService {
} }
} }
public async createCheckoutSession({ public async createStripeCheckoutSession({
couponId, couponId,
priceId, priceId,
user user
@ -46,7 +49,7 @@ export class SubscriptionService {
couponId?: string; couponId?: string;
priceId: string; priceId: string;
user: UserWithSettings; user: UserWithSettings;
}) { }): Promise<CreateStripeCheckoutSessionResponse> {
const subscriptionOffers: { const subscriptionOffers: {
[offer in SubscriptionOfferKey]: SubscriptionOffer; [offer in SubscriptionOfferKey]: SubscriptionOffer;
} = } =
@ -58,33 +61,34 @@ export class SubscriptionService {
} }
); );
const checkoutSessionCreateParams: Stripe.Checkout.SessionCreateParams = { const stripeCheckoutSessionCreateParams: Stripe.Checkout.SessionCreateParams =
cancel_url: `${this.configurationService.get('ROOT_URL')}/${ {
user.settings.settings.language cancel_url: `${this.configurationService.get('ROOT_URL')}/${
}/account`, user.settings.settings.language
client_reference_id: user.id, }/account`,
line_items: [ client_reference_id: user.id,
{ line_items: [
price: priceId, {
quantity: 1 price: priceId,
} quantity: 1
], }
locale: ],
(user.settings?.settings locale:
?.language as Stripe.Checkout.SessionCreateParams.Locale) ?? (user.settings?.settings
DEFAULT_LANGUAGE_CODE, ?.language as Stripe.Checkout.SessionCreateParams.Locale) ??
metadata: subscriptionOffer DEFAULT_LANGUAGE_CODE,
? { subscriptionOffer: JSON.stringify(subscriptionOffer) } metadata: subscriptionOffer
: {}, ? { subscriptionOffer: JSON.stringify(subscriptionOffer) }
mode: 'payment', : {},
payment_method_types: ['card'], mode: 'payment',
success_url: `${this.configurationService.get( payment_method_types: ['card'],
'ROOT_URL' success_url: `${this.configurationService.get(
)}/api/v1/subscription/stripe/callback?checkoutSessionId={CHECKOUT_SESSION_ID}` 'ROOT_URL'
}; )}/api/v1/subscription/stripe/callback?checkoutSessionId={CHECKOUT_SESSION_ID}`
};
if (couponId) { if (couponId) {
checkoutSessionCreateParams.discounts = [ stripeCheckoutSessionCreateParams.discounts = [
{ {
coupon: couponId coupon: couponId
} }
@ -92,7 +96,7 @@ export class SubscriptionService {
} }
const session = await this.stripe.checkout.sessions.create( const session = await this.stripe.checkout.sessions.create(
checkoutSessionCreateParams stripeCheckoutSessionCreateParams
); );
return { return {

7
apps/client/src/app/components/user-account-membership/user-account-membership.component.ts

@ -108,7 +108,10 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
public onCheckout() { public onCheckout() {
this.dataService this.dataService
.createCheckoutSession({ couponId: this.couponId, priceId: this.priceId }) .createStripeCheckoutSession({
couponId: this.couponId,
priceId: this.priceId
})
.pipe( .pipe(
catchError((error) => { catchError((error) => {
this.notificationService.alert({ this.notificationService.alert({
@ -117,7 +120,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
throw error; throw error;
}), }),
switchMap(({ sessionId }: { sessionId: string }) => { switchMap(({ sessionId }) => {
return this.stripeService.redirectToCheckout({ sessionId }); return this.stripeService.redirectToCheckout({ sessionId });
}) })
) )

7
apps/client/src/app/pages/pricing/pricing-page.component.ts

@ -134,9 +134,12 @@ export class GfPricingPageComponent implements OnDestroy, OnInit {
public onCheckout() { public onCheckout() {
this.dataService this.dataService
.createCheckoutSession({ couponId: this.couponId, priceId: this.priceId }) .createStripeCheckoutSession({
couponId: this.couponId,
priceId: this.priceId
})
.pipe( .pipe(
switchMap(({ sessionId }: { sessionId: string }) => { switchMap(({ sessionId }) => {
return this.stripeService.redirectToCheckout({ sessionId }); return this.stripeService.redirectToCheckout({ sessionId });
}), }),
catchError((error) => { catchError((error) => {

14
apps/client/src/app/services/data.service.ts

@ -31,6 +31,7 @@ import {
AssetResponse, AssetResponse,
BenchmarkMarketDataDetailsResponse, BenchmarkMarketDataDetailsResponse,
BenchmarkResponse, BenchmarkResponse,
CreateStripeCheckoutSessionResponse,
DataProviderHealthResponse, DataProviderHealthResponse,
ExportResponse, ExportResponse,
Filter, Filter,
@ -168,17 +169,20 @@ export class DataService {
return params; return params;
} }
public createCheckoutSession({ public createStripeCheckoutSession({
couponId, couponId,
priceId priceId
}: { }: {
couponId?: string; couponId?: string;
priceId: string; priceId: string;
}) { }) {
return this.http.post('/api/v1/subscription/stripe/checkout-session', { return this.http.post<CreateStripeCheckoutSessionResponse>(
couponId, '/api/v1/subscription/stripe/checkout-session',
priceId {
}); couponId,
priceId
}
);
} }
public fetchAccount(aAccountId: string) { public fetchAccount(aAccountId: string) {

2
libs/common/src/lib/interfaces/index.ts

@ -43,6 +43,7 @@ import type { ApiKeyResponse } from './responses/api-key-response.interface';
import type { AssetResponse } from './responses/asset-response.interface'; import type { AssetResponse } from './responses/asset-response.interface';
import type { BenchmarkMarketDataDetailsResponse } from './responses/benchmark-market-data-details-response.interface'; import type { BenchmarkMarketDataDetailsResponse } from './responses/benchmark-market-data-details-response.interface';
import type { BenchmarkResponse } from './responses/benchmark-response.interface'; import type { BenchmarkResponse } from './responses/benchmark-response.interface';
import type { CreateStripeCheckoutSessionResponse } from './responses/create-stripe-checkout-session-response.interface';
import type { DataEnhancerHealthResponse } from './responses/data-enhancer-health-response.interface'; import type { DataEnhancerHealthResponse } from './responses/data-enhancer-health-response.interface';
import type { DataProviderGhostfolioAssetProfileResponse } from './responses/data-provider-ghostfolio-asset-profile-response.interface'; import type { DataProviderGhostfolioAssetProfileResponse } from './responses/data-provider-ghostfolio-asset-profile-response.interface';
import type { DataProviderGhostfolioStatusResponse } from './responses/data-provider-ghostfolio-status-response.interface'; import type { DataProviderGhostfolioStatusResponse } from './responses/data-provider-ghostfolio-status-response.interface';
@ -100,6 +101,7 @@ export {
BenchmarkProperty, BenchmarkProperty,
BenchmarkResponse, BenchmarkResponse,
Coupon, Coupon,
CreateStripeCheckoutSessionResponse,
DataEnhancerHealthResponse, DataEnhancerHealthResponse,
DataProviderGhostfolioAssetProfileResponse, DataProviderGhostfolioAssetProfileResponse,
DataProviderGhostfolioStatusResponse, DataProviderGhostfolioStatusResponse,

3
libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts

@ -0,0 +1,3 @@
export interface CreateStripeCheckoutSessionResponse {
sessionId: string;
}
Loading…
Cancel
Save