diff --git a/Plugins/BTCPayServer.Plugins.Subscriptions/BTCPayServer.Plugins.Subscriptions.csproj b/Plugins/BTCPayServer.Plugins.Subscriptions/BTCPayServer.Plugins.Subscriptions.csproj index 38640b4..8157c3f 100644 --- a/Plugins/BTCPayServer.Plugins.Subscriptions/BTCPayServer.Plugins.Subscriptions.csproj +++ b/Plugins/BTCPayServer.Plugins.Subscriptions/BTCPayServer.Plugins.Subscriptions.csproj @@ -10,7 +10,7 @@ Subscriptions Offer and manage subscriptions through BTCPay Server - 1.0.0 + 1.0.1 true diff --git a/Plugins/BTCPayServer.Plugins.Subscriptions/GreenfieldSubscriptionsController.cs b/Plugins/BTCPayServer.Plugins.Subscriptions/GreenfieldSubscriptionsController.cs index 2efe4e4..e99d472 100644 --- a/Plugins/BTCPayServer.Plugins.Subscriptions/GreenfieldSubscriptionsController.cs +++ b/Plugins/BTCPayServer.Plugins.Subscriptions/GreenfieldSubscriptionsController.cs @@ -33,6 +33,23 @@ public class GreenfieldSubscriptionsController : ControllerBase var ss = app.GetSettings(); return Ok(ss); + } + [HttpGet("~/api/v1/apps/subscriptions/{appId}/{subscriptionId}")] + [AllowAnonymous] + public async Task GetSubscriptionId(string appId, string subscriptionId) + { + var app = await _appService.GetApp(appId, SubscriptionApp.AppType, includeArchived: true); + if (app == null) + { + return AppNotFound(); + } + + var ss = app.GetSettings(); + if (!ss.Subscriptions.TryGetValue(subscriptionId, out var subscriber)) + { + return this.CreateAPIError(404, "subscription-not-found", "The subscription with specified ID was not found"); + } + return Ok(subscriber); } private IActionResult AppNotFound() diff --git a/Plugins/BTCPayServer.Plugins.Subscriptions/Resources/swagger.subscriptions.json b/Plugins/BTCPayServer.Plugins.Subscriptions/Resources/swagger.subscriptions.json new file mode 100644 index 0000000..cc6e95e --- /dev/null +++ b/Plugins/BTCPayServer.Plugins.Subscriptions/Resources/swagger.subscriptions.json @@ -0,0 +1,230 @@ +{ + "paths": { + "/api/v1/apps/subscriptions/{appId}": { + "parameters": [ + { + "name": "appId", + "in": "path", + "required": true, + "description": "The ID of the subscription app", + "schema": { + "type": "string" + } + } + ], + "get": { + "operationId": "Subscriptions_GetSubscriptionApp", + "summary": "Get a subscription app and all of its details", + "responses": { + "200": { + "description": "Subscription details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionAppSettings" + } + } + } + }, + "404": { + "description": "The subscription was not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + }, + "tags": [ + "Subscriptions" + ], + "security": [ + { + "API_Key": [ + "btcpay.store.canmodifystoresettings" + ], + "Basic": [] + } + ] + } + }, + "/api/v1/apps/subscriptions/{appId}/{subscriptionId}": { + "parameters": [ + { + "name": "appId", + "in": "path", + "required": true, + "description": "The ID of the subscription app", + "schema": { + "type": "string" + } + }, + { + "name": "subscriptionId", + "in": "path", + "required": true, + "description": "The ID of the subscription", + "schema": { + "type": "string" + } + } + ], + "get": { + "operationId": "Subscriptions_GetSubscriptionOfApp", + "summary": "Get a subscription of a subscription app", + "responses": { + "200": { + "description": "Subscription details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Subscription" + } + } + } + }, + "404": { + "description": "The subscription was not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + }, + "tags": [ + "Subscriptions (Public)" + ], + "security": [ ] + } + } + }, + "components": { + "schemas": { + + "SubscriptionDurationType": { + "type": "string", + "description": "", + "x-enumNames": [ + "Day", + "Month" + ], + "enum": [ + "Day", + "Month" + ] + }, + "SubscriptionStatus": { + "type": "string", + "description": "", + "x-enumNames": [ + "Active", + "Inactive" + ], + "enum": [ + "Active", + "Inactive" + ] + }, + + "SubscriptionPayment": { + "type": "object", + "properties": { + "paymentRequestId": { + "type": "string", + "description": "The payment request Id that handles this payment." + }, + + "periodStart": { + "description": "What period starts with this payment", + "allOf": [ { "$ref": "#/components/schemas/UnixTimestamp" } ] + }, + "periodEnd": { + "description": "What period ends with this payment", + "allOf": [ { "$ref": "#/components/schemas/UnixTimestamp" } ] + }, + "settled": { + "type": "boolean", + "description": "Whether the payment has been settled" + } + } + }, + "Subscription": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the subscription user" + }, + "status": { + "$ref": "#/components/schemas/SubscriptionStatus" + }, + "start": { + "description": "When the subscription was first activated", + "allOf": [ { "$ref": "#/components/schemas/UnixTimestamp" } ] + }, + "payments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubscriptionPayment" + } + } + } + },"SubscriptionSet": { + "type": "object", + "additionalProperties": { + + "$ref": "#/components/schemas/Subscription" + } + }, + "SubscriptionAppSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "type": "string", + "description": "Description of the subscription app" + }, + "duration": { + "type": "number", + "description": "Duration of the subscription (type of duration is defined in the `durationType` field)" + }, + "durationType": { + "$ref": "#/components/schemas/SubscriptionDurationType" + }, + "formId": { + "type": "string", + "description": "Form ID to request customer data", + "nullable": true + }, + "price": { + "type": "string", + "description": "The price of the subscription" + }, + "currency": { + "type": "string", + "description": "The currency of the subscription" + }, + "subscriptions": { + "$ref": "#/components/schemas/SubscriptionSet" + } + } + + + } + }, + "tags": [ + { + "name": "Subscriptions", + "description": "Subscriptions operations" + } , { + "name": "Subscriptions (Public)", + "description": "Subscriptions public endpoints" + } + ] + } +} diff --git a/Plugins/BTCPayServer.Plugins.Subscriptions/SubscriptionPlugin.cs b/Plugins/BTCPayServer.Plugins.Subscriptions/SubscriptionPlugin.cs index 6074a54..ac3ce82 100644 --- a/Plugins/BTCPayServer.Plugins.Subscriptions/SubscriptionPlugin.cs +++ b/Plugins/BTCPayServer.Plugins.Subscriptions/SubscriptionPlugin.cs @@ -1,10 +1,16 @@ +using System.IO; +using System.Threading.Tasks; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Services; using BTCPayServer.HostedServices.Webhooks; +using BTCPayServer.Services; using BTCPayServer.Services.Apps; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; +using Newtonsoft.Json.Linq; namespace BTCPayServer.Plugins.Subscriptions { @@ -17,6 +23,8 @@ namespace BTCPayServer.Plugins.Subscriptions public override void Execute(IServiceCollection applicationBuilder) { + + applicationBuilder.AddSingleton(); applicationBuilder.AddSingleton(); applicationBuilder.AddSingleton(o => o.GetRequiredService()); applicationBuilder.AddHostedService(s => s.GetRequiredService()); @@ -26,4 +34,23 @@ namespace BTCPayServer.Plugins.Subscriptions base.Execute(applicationBuilder); } } + + public class SubscriptionsSwaggerProvider: ISwaggerProvider + { + private readonly IFileProvider _fileProvider; + + public SubscriptionsSwaggerProvider(IWebHostEnvironment webHostEnvironment) + { + + _fileProvider = webHostEnvironment.WebRootFileProvider; + } + + public async Task Fetch() + { + + var file = _fileProvider.GetFileInfo("Resources/swagger.subscriptions.json"); + using var reader = new StreamReader(file.CreateReadStream()); + return JObject.Parse(await reader.ReadToEndAsync()); + } + } } \ No newline at end of file