diff --git a/DysonNetwork.Pass/Wallet/OrderController.cs b/DysonNetwork.Pass/Wallet/OrderController.cs index 05f4ec0..e732545 100644 --- a/DysonNetwork.Pass/Wallet/OrderController.cs +++ b/DysonNetwork.Pass/Wallet/OrderController.cs @@ -1,5 +1,6 @@ using DysonNetwork.Pass.Auth; using DysonNetwork.Shared.Models; +using DysonNetwork.Shared.Proto; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -8,36 +9,87 @@ namespace DysonNetwork.Pass.Wallet; [ApiController] [Route("/api/orders")] -public class OrderController(PaymentService payment, AuthService auth, AppDatabase db) : ControllerBase +public class OrderController( + PaymentService payment, + Pass.Auth.AuthService auth, + AppDatabase db, + CustomAppService.CustomAppServiceClient customApps +) : ControllerBase { + public class CreateOrderRequest + { + public string Currency { get; set; } = null!; + public decimal Amount { get; set; } + public string? Remarks { get; set; } + public string? ProductIdentifier { get; set; } + public Dictionary? Meta { get; set; } + public int DurationHours { get; set; } = 24; + + public string ClientId { get; set; } = null!; + public string ClientSecret { get; set; } = null!; + } + + [HttpPost] + public async Task> CreateOrder([FromBody] CreateOrderRequest request) + { + var clientResp = await customApps.GetCustomAppAsync(new GetCustomAppRequest { Slug = request.ClientId }); + if (clientResp.App is null) return BadRequest("Client not found"); + var client = SnCustomApp.FromProtoValue(clientResp.App); + + var secret = await customApps.CheckCustomAppSecretAsync(new CheckCustomAppSecretRequest + { + AppId = client.Id.ToString(), + Secret = request.ClientSecret, + }); + if (!secret.Valid) return BadRequest("Invalid client secret"); + + var order = await payment.CreateOrderAsync( + default, + request.Currency, + request.Amount, + NodaTime.Duration.FromHours(request.DurationHours), + request.ClientId, + request.ProductIdentifier, + request.Remarks, + request.Meta + ); + + return Ok(order); + } + [HttpGet("{id:guid}")] public async Task> GetOrderById(Guid id) { var order = await db.PaymentOrders.FindAsync(id); - + if (order == null) return NotFound(); - + return Ok(order); } - + + public class PayOrderRequest + { + public string PinCode { get; set; } = string.Empty; + } + [HttpPost("{id:guid}/pay")] [Authorize] public async Task> PayOrder(Guid id, [FromBody] PayOrderRequest request) { if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized(); - + // Validate PIN code if (!await auth.ValidatePinCode(currentUser.Id, request.PinCode)) return StatusCode(403, "Invalid PIN Code"); - + try { // Get the wallet for the current user var wallet = await db.Wallets.FirstOrDefaultAsync(w => w.AccountId == currentUser.Id); if (wallet == null) return BadRequest("Wallet was not found."); - + // Pay the order var paidOrder = await payment.PayOrderAsync(id, wallet); return Ok(paidOrder); @@ -49,7 +101,3 @@ public class OrderController(PaymentService payment, AuthService auth, AppDataba } } -public class PayOrderRequest -{ - public string PinCode { get; set; } = string.Empty; -} \ No newline at end of file diff --git a/DysonNetwork.Shared/Models/CustomApp.cs b/DysonNetwork.Shared/Models/CustomApp.cs index c24fcf7..32731ae 100644 --- a/DysonNetwork.Shared/Models/CustomApp.cs +++ b/DysonNetwork.Shared/Models/CustomApp.cs @@ -34,7 +34,7 @@ public class SnCustomApp : ModelBase, IIdentifiedResource public Guid ProjectId { get; set; } public SnDevProject Project { get; set; } = null!; - + [NotMapped] public SnDeveloper Developer => Project.Developer; @@ -81,36 +81,41 @@ public class SnCustomApp : ModelBase, IIdentifiedResource }; } - public SnCustomApp FromProtoValue(Proto.CustomApp p) + public static SnCustomApp FromProtoValue(Proto.CustomApp p) { - Id = Guid.Parse(p.Id); - Slug = p.Slug; - Name = p.Name; - Description = string.IsNullOrEmpty(p.Description) ? null : p.Description; - Status = p.Status switch + var obj = new SnCustomApp { - Shared.Proto.CustomAppStatus.Developing => CustomAppStatus.Developing, - Shared.Proto.CustomAppStatus.Staging => CustomAppStatus.Staging, - Shared.Proto.CustomAppStatus.Production => CustomAppStatus.Production, - Shared.Proto.CustomAppStatus.Suspended => CustomAppStatus.Suspended, - _ => CustomAppStatus.Developing + Id = Guid.Parse(p.Id), + Slug = p.Slug, + Name = p.Name, + Description = string.IsNullOrEmpty(p.Description) ? null : p.Description, + Status = p.Status switch + { + Shared.Proto.CustomAppStatus.Developing => CustomAppStatus.Developing, + Shared.Proto.CustomAppStatus.Staging => CustomAppStatus.Staging, + Shared.Proto.CustomAppStatus.Production => CustomAppStatus.Production, + Shared.Proto.CustomAppStatus.Suspended => CustomAppStatus.Suspended, + _ => CustomAppStatus.Developing + }, + ProjectId = string.IsNullOrEmpty(p.ProjectId) ? Guid.Empty : Guid.Parse(p.ProjectId), + CreatedAt = p.CreatedAt.ToInstant(), + UpdatedAt = p.UpdatedAt.ToInstant(), }; - ProjectId = string.IsNullOrEmpty(p.ProjectId) ? Guid.Empty : Guid.Parse(p.ProjectId); - CreatedAt = p.CreatedAt.ToInstant(); - UpdatedAt = p.UpdatedAt.ToInstant(); - if (p.Picture is not null) Picture = SnCloudFileReferenceObject.FromProtoValue(p.Picture); - if (p.Background is not null) Background = SnCloudFileReferenceObject.FromProtoValue(p.Background); - if (p.Verification is not null) Verification = SnVerificationMark.FromProtoValue(p.Verification); + + if (p.Picture is not null) obj.Picture = SnCloudFileReferenceObject.FromProtoValue(p.Picture); + if (p.Background is not null) obj.Background = SnCloudFileReferenceObject.FromProtoValue(p.Background); + if (p.Verification is not null) obj.Verification = SnVerificationMark.FromProtoValue(p.Verification); if (p.Links is not null) { - Links = new SnCustomAppLinks + obj.Links = new SnCustomAppLinks { HomePage = string.IsNullOrEmpty(p.Links.HomePage) ? null : p.Links.HomePage, PrivacyPolicy = string.IsNullOrEmpty(p.Links.PrivacyPolicy) ? null : p.Links.PrivacyPolicy, TermsOfService = string.IsNullOrEmpty(p.Links.TermsOfService) ? null : p.Links.TermsOfService }; } - return this; + + return obj; } }