From 2b810772b3c0bcd773d5e28425893fa9f83fa686 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 20 Mar 2024 01:10:44 -0400 Subject: [PATCH] Added endpoint to create a sessionCheckout with stripe --- Directory.Packages.props | 1 + .../Common/Interfaces/IStripeService.cs | 7 +++ .../Commands/CreateSessionCheckoutCommand.cs | 31 +++++++++++++ src/Infrastructure/DependencyInjection.cs | 2 + src/Infrastructure/Infrastructure.csproj | 15 +++--- src/Infrastructure/Stripe/StripeService.cs | 46 +++++++++++++++++++ src/Web/Endpoints/Stripe.cs | 17 +++++++ src/Web/wwwroot/api/specification.json | 45 ++++++++++++++++++ 8 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 src/Application/Common/Interfaces/IStripeService.cs create mode 100644 src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs create mode 100644 src/Infrastructure/Stripe/StripeService.cs create mode 100644 src/Web/Endpoints/Stripe.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index ba78a5d..74620e0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -37,6 +37,7 @@ + \ No newline at end of file diff --git a/src/Application/Common/Interfaces/IStripeService.cs b/src/Application/Common/Interfaces/IStripeService.cs new file mode 100644 index 0000000..1231a8e --- /dev/null +++ b/src/Application/Common/Interfaces/IStripeService.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Application.Common.Interfaces; + + +public interface IStripeService +{ + public Task CreateCheckoutSession(int price, string currency); +} diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs new file mode 100644 index 0000000..3fa96c0 --- /dev/null +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -0,0 +1,31 @@ +using Hutopy.Application.Common.Interfaces; + + +namespace Hutopy.Application.Stripe.Commands; +public record CreateSessionCheckoutCommand : IRequest +{ + public required int Price { get; init; } + + public string Currency { get; init; } = "cad"; +} + + +public class CreateSessionCheckoutCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IStripeService _stripeService; + + + public CreateSessionCheckoutCommandHandler(IApplicationDbContext context, IStripeService stripeService) + { + _context = context; + _stripeService = stripeService; + } + + public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) + { + var stripeSecret = await _stripeService.CreateCheckoutSession(request.Price, request.Currency); + + return stripeSecret; + } +} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index f466e8f..7481df3 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -3,6 +3,7 @@ using Hutopy.Domain.Constants; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Data.Interceptors; using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Stripe; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -49,6 +50,7 @@ public static class DependencyInjection services.AddSingleton(TimeProvider.System); services.AddTransient(); + services.AddTransient(); services.AddAuthorization(options => options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator))); diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index ab862ba..2958bd6 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -4,18 +4,19 @@ Hutopy.Infrastructure - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - + + + + + - + diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs new file mode 100644 index 0000000..dc18c62 --- /dev/null +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -0,0 +1,46 @@ +using Stripe; +using Stripe.Checkout; +using Hutopy.Application.Common.Interfaces; + + +namespace Hutopy.Infrastructure.Stripe; + +public class StripeService : IStripeService +{ + public StripeService() + { + // I removed the key to push. Will need to be in config. + StripeConfiguration.ApiKey = ""; + } + + public async Task CreateCheckoutSession(int price, string currency = "cad") + { + var options = new SessionCreateOptions + { + LineItems = new List + { + new SessionLineItemOptions + { + PriceData = new SessionLineItemPriceDataOptions + { + UnitAmount = price, + Currency = currency, + ProductData = new SessionLineItemPriceDataProductDataOptions + { + Name = "Tip", + }, + }, + Quantity = 1, + }, + }, + Mode = "payment", + UiMode = "embedded", + ReturnUrl = "http://localhost:5174", + }; + + var service = new SessionService(); + Session session = await service.CreateAsync(options); + + return session.ClientSecret; + } +} diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs new file mode 100644 index 0000000..c7753b0 --- /dev/null +++ b/src/Web/Endpoints/Stripe.cs @@ -0,0 +1,17 @@ +using Hutopy.Application.Stripe.Commands; + +namespace Hutopy.Web.Endpoints; + +public class Stripe : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapPost(CreateSessionCheckout); + } + + public Task CreateSessionCheckout(ISender sender, CreateSessionCheckoutCommand command) + { + return sender.Send(command); + } +} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index c4ab40c..158be32 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -39,6 +39,38 @@ } } }, + "/api/Stripe": { + "post": { + "tags": [ + "Stripe" + ], + "operationId": "CreateSessionCheckout", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSessionCheckoutCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/api/TodoItems": { "get": { "tags": [ @@ -814,6 +846,19 @@ } } }, + "CreateSessionCheckoutCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "price": { + "type": "integer", + "format": "int32" + }, + "currency": { + "type": "string" + } + } + }, "PaginatedListOfTodoItemBriefDto": { "type": "object", "additionalProperties": false,