mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Fix: Refunds through API were ignoring BOLT11 expiration at store level (#6644)
This commit is contained in:
@@ -30,6 +30,12 @@ public partial class BTCPayServerClient
|
|||||||
return await SendHttpRequest<StoreData>("api/v1/stores", request, HttpMethod.Post, token);
|
return await SendHttpRequest<StoreData>("api/v1/stores", request, HttpMethod.Post, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<StoreData> UpdateStore(string storeId, StoreData request, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (request is null)
|
||||||
|
throw new ArgumentNullException(nameof(request));
|
||||||
|
return await UpdateStore(storeId, Newtonsoft.Json.JsonConvert.DeserializeObject<UpdateStoreRequest>(Newtonsoft.Json.JsonConvert.SerializeObject(request)), token);
|
||||||
|
}
|
||||||
public virtual async Task<StoreData> UpdateStore(string storeId, UpdateStoreRequest request, CancellationToken token = default)
|
public virtual async Task<StoreData> UpdateStore(string storeId, UpdateStoreRequest request, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (request == null) throw new ArgumentNullException(nameof(request));
|
if (request == null) throw new ArgumentNullException(nameof(request));
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ namespace BTCPayServer.Client.Models
|
|||||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public TimeSpan DisplayExpirationTimer { get; set; } = TimeSpan.FromMinutes(5);
|
public TimeSpan DisplayExpirationTimer { get; set; } = TimeSpan.FromMinutes(5);
|
||||||
|
|
||||||
|
[JsonConverter(typeof(TimeSpanJsonConverter.Days))]
|
||||||
|
[JsonProperty("refundBOLT11Expiration", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public TimeSpan RefundBOLT11Expiration { get; set; } = TimeSpan.FromDays(30);
|
||||||
|
|
||||||
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public TimeSpan MonitoringExpiration { get; set; } = TimeSpan.FromMinutes(60);
|
public TimeSpan MonitoringExpiration { get; set; } = TimeSpan.FromMinutes(60);
|
||||||
|
|||||||
@@ -2293,6 +2293,13 @@ namespace BTCPayServer.Tests
|
|||||||
var user = tester.NewAccount();
|
var user = tester.NewAccount();
|
||||||
await user.RegisterDerivationSchemeAsync("BTC");
|
await user.RegisterDerivationSchemeAsync("BTC");
|
||||||
var client = await user.CreateClient();
|
var client = await user.CreateClient();
|
||||||
|
var store = await client.GetStore(user.StoreId);
|
||||||
|
Assert.Equal(TimeSpan.FromDays(30.0), store.RefundBOLT11Expiration);
|
||||||
|
store.RefundBOLT11Expiration = TimeSpan.FromDays(1);
|
||||||
|
await client.UpdateStore(store.Id, store);
|
||||||
|
store = await client.GetStore(user.StoreId);
|
||||||
|
Assert.Equal(TimeSpan.FromDays(1.0), store.RefundBOLT11Expiration);
|
||||||
|
|
||||||
var invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest() { Amount = 5000.0m, Currency = "USD" });
|
var invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest() { Amount = 5000.0m, Currency = "USD" });
|
||||||
var methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
|
var methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
|
||||||
var method = methods.First();
|
var method = methods.First();
|
||||||
@@ -2354,6 +2361,7 @@ namespace BTCPayServer.Tests
|
|||||||
PayoutMethodId = method.PaymentMethodId,
|
PayoutMethodId = method.PaymentMethodId,
|
||||||
RefundVariant = RefundVariant.RateThen
|
RefundVariant = RefundVariant.RateThen
|
||||||
});
|
});
|
||||||
|
Assert.Equal(pp.BOLT11Expiration, TimeSpan.FromDays(1));
|
||||||
Assert.Equal("BTC", pp.Currency);
|
Assert.Equal("BTC", pp.Currency);
|
||||||
Assert.True(pp.AutoApproveClaims);
|
Assert.True(pp.AutoApproveClaims);
|
||||||
Assert.Equal(1, pp.Amount);
|
Assert.Equal(1, pp.Amount);
|
||||||
|
|||||||
@@ -376,13 +376,11 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
var paidAmount = cryptoPaid.RoundToSignificant(paymentPrompt.Divisibility);
|
var paidAmount = cryptoPaid.RoundToSignificant(paymentPrompt.Divisibility);
|
||||||
var createPullPayment = new CreatePullPayment
|
var createPullPayment = new CreatePullPaymentRequest
|
||||||
{
|
{
|
||||||
BOLT11Expiration = store.GetStoreBlob().RefundBOLT11Expiration,
|
|
||||||
Name = request.Name ?? $"Refund {invoice.Id}",
|
Name = request.Name ?? $"Refund {invoice.Id}",
|
||||||
Description = request.Description,
|
Description = request.Description,
|
||||||
StoreId = storeId,
|
PayoutMethods = new[] { payoutMethodId.ToString() },
|
||||||
PayoutMethods = new[] { payoutMethodId },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.RefundVariant != RefundVariant.Custom)
|
if (request.RefundVariant != RefundVariant.Custom)
|
||||||
@@ -479,8 +477,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
createPullPayment.Amount = Math.Round(createPullPayment.Amount - reduceByAmount, appliedDivisibility);
|
createPullPayment.Amount = Math.Round(createPullPayment.Amount - reduceByAmount, appliedDivisibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
createPullPayment.AutoApproveClaims = createPullPayment.AutoApproveClaims && (await _authorizationService.AuthorizeAsync(User, createPullPayment.StoreId ,Policies.CanCreatePullPayments)).Succeeded;
|
createPullPayment.AutoApproveClaims = createPullPayment.AutoApproveClaims && (await _authorizationService.AuthorizeAsync(User, storeId ,Policies.CanCreatePullPayments)).Succeeded;
|
||||||
var ppId = await _pullPaymentService.CreatePullPayment(createPullPayment);
|
var ppId = await _pullPaymentService.CreatePullPayment(store, createPullPayment);
|
||||||
|
|
||||||
await using var ctx = _dbContextFactory.CreateContext();
|
await using var ctx = _dbContextFactory.CreateContext();
|
||||||
|
|
||||||
|
|||||||
@@ -126,22 +126,25 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}
|
}
|
||||||
|
|
||||||
var supported = _payoutHandlers.GetSupportedPayoutMethods(HttpContext.GetStoreData());
|
var supported = _payoutHandlers.GetSupportedPayoutMethods(HttpContext.GetStoreData());
|
||||||
request.PayoutMethods ??= supported.Select(s => s.ToString()).ToArray();
|
if (request.PayoutMethods is not null)
|
||||||
for (int i = 0; i < request.PayoutMethods.Length; i++)
|
|
||||||
{
|
{
|
||||||
var pmi = request.PayoutMethods[i] is string pm ? PayoutMethodId.TryParse(pm) : null;
|
for (int i = 0; i < request.PayoutMethods.Length; i++)
|
||||||
if (pmi is null || !supported.Contains(pmi))
|
|
||||||
{
|
{
|
||||||
request.AddModelError(paymentRequest => paymentRequest.PayoutMethods[i], "Invalid or unsupported payment method", this);
|
var pmi = request.PayoutMethods[i] is string pm ? PayoutMethodId.TryParse(pm) : null;
|
||||||
|
if (pmi is null || !supported.Contains(pmi))
|
||||||
|
{
|
||||||
|
request.AddModelError(paymentRequest => paymentRequest.PayoutMethods[i], "Invalid or unsupported payment method", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request.PayoutMethods.Length is 0)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(request.PayoutMethods), "At least one payout method is required");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (request.PayoutMethods.Length is 0)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(nameof(request.PayoutMethods), "At least one payout method is required");
|
|
||||||
}
|
}
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
return this.CreateValidationError(ModelState);
|
return this.CreateValidationError(ModelState);
|
||||||
var ppId = await _pullPaymentService.CreatePullPayment(storeId, request);
|
|
||||||
|
var ppId = await _pullPaymentService.CreatePullPayment(HttpContext.GetStoreData(), request);
|
||||||
var pp = await _pullPaymentService.GetPullPayment(ppId, false);
|
var pp = await _pullPaymentService.GetPullPayment(ppId, false);
|
||||||
return this.Ok(CreatePullPaymentData(pp));
|
return this.Ok(CreatePullPaymentData(pp));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Amazon.Runtime.Internal;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
@@ -18,6 +19,7 @@ using Microsoft.AspNetCore.Cors;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
using StoreData = BTCPayServer.Data.StoreData;
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers.Greenfield
|
namespace BTCPayServer.Controllers.Greenfield
|
||||||
@@ -174,6 +176,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
Website = data.StoreWebsite,
|
Website = data.StoreWebsite,
|
||||||
Archived = data.Archived,
|
Archived = data.Archived,
|
||||||
BrandColor = storeBlob.BrandColor,
|
BrandColor = storeBlob.BrandColor,
|
||||||
|
RefundBOLT11Expiration = storeBlob.RefundBOLT11Expiration,
|
||||||
ApplyBrandColorToBackend = storeBlob.ApplyBrandColorToBackend,
|
ApplyBrandColorToBackend = storeBlob.ApplyBrandColorToBackend,
|
||||||
CssUrl = storeBlob.CssUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), storeBlob.CssUrl),
|
CssUrl = storeBlob.CssUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), storeBlob.CssUrl),
|
||||||
LogoUrl = storeBlob.LogoUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), storeBlob.LogoUrl),
|
LogoUrl = storeBlob.LogoUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), storeBlob.LogoUrl),
|
||||||
@@ -258,6 +261,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
blob.ApplyBrandColorToBackend = restModel.ApplyBrandColorToBackend;
|
blob.ApplyBrandColorToBackend = restModel.ApplyBrandColorToBackend;
|
||||||
blob.LogoUrl = restModel.LogoUrl is null ? null : UnresolvedUri.Create(restModel.LogoUrl);
|
blob.LogoUrl = restModel.LogoUrl is null ? null : UnresolvedUri.Create(restModel.LogoUrl);
|
||||||
blob.CssUrl = restModel.CssUrl is null ? null : UnresolvedUri.Create(restModel.CssUrl);
|
blob.CssUrl = restModel.CssUrl is null ? null : UnresolvedUri.Create(restModel.CssUrl);
|
||||||
|
blob.RefundBOLT11Expiration = restModel.RefundBOLT11Expiration;
|
||||||
blob.PaymentSoundUrl = restModel.PaymentSoundUrl is null ? null : UnresolvedUri.Create(restModel.PaymentSoundUrl);
|
blob.PaymentSoundUrl = restModel.PaymentSoundUrl is null ? null : UnresolvedUri.Create(restModel.PaymentSoundUrl);
|
||||||
if (restModel.AutoDetectLanguage.HasValue)
|
if (restModel.AutoDetectLanguage.HasValue)
|
||||||
blob.AutoDetectLanguage = restModel.AutoDetectLanguage.Value;
|
blob.AutoDetectLanguage = restModel.AutoDetectLanguage.Value;
|
||||||
@@ -295,6 +299,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(request.Name), "DefaultPaymentMethod is invalid");
|
ModelState.AddModelError(nameof(request.Name), "DefaultPaymentMethod is invalid");
|
||||||
}
|
}
|
||||||
|
if (request.RefundBOLT11Expiration < TimeSpan.FromDays(0) ||
|
||||||
|
request.RefundBOLT11Expiration > TimeSpan.FromDays(365 * 10))
|
||||||
|
ModelState.AddModelError(nameof(request.RefundBOLT11Expiration), "refundBOLT11Expiration should be between 0 and 36500");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(request.Name))
|
if (string.IsNullOrEmpty(request.Name))
|
||||||
ModelState.AddModelError(nameof(request.Name), "Name is missing");
|
ModelState.AddModelError(nameof(request.Name), "Name is missing");
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ namespace BTCPayServer.Controllers
|
|||||||
var cdCurrency = _CurrencyNameTable.GetCurrencyData(invoice.Currency, true);
|
var cdCurrency = _CurrencyNameTable.GetCurrencyData(invoice.Currency, true);
|
||||||
RateRules rules;
|
RateRules rules;
|
||||||
RateResult rateResult;
|
RateResult rateResult;
|
||||||
CreatePullPayment createPullPayment;
|
CreatePullPaymentRequest createPullPayment;
|
||||||
|
|
||||||
var pmis = _payoutHandlers.GetSupportedPayoutMethods(store);
|
var pmis = _payoutHandlers.GetSupportedPayoutMethods(store);
|
||||||
if (!pmis.Contains(pmi))
|
if (!pmis.Contains(pmi))
|
||||||
@@ -414,12 +414,10 @@ namespace BTCPayServer.Controllers
|
|||||||
return View("_RefundModal", model);
|
return View("_RefundModal", model);
|
||||||
|
|
||||||
case RefundSteps.SelectRate:
|
case RefundSteps.SelectRate:
|
||||||
createPullPayment = new CreatePullPayment
|
createPullPayment = new CreatePullPaymentRequest
|
||||||
{
|
{
|
||||||
Name = StringLocalizer["Refund {0}", invoice.Id],
|
Name = StringLocalizer["Refund {0}", invoice.Id],
|
||||||
PayoutMethods = new[] { pmi },
|
PayoutMethods = new[] { pmi.ToString() }
|
||||||
StoreId = invoice.StoreId,
|
|
||||||
BOLT11Expiration = store.GetStoreBlob().RefundBOLT11Expiration
|
|
||||||
};
|
};
|
||||||
var authorizedForAutoApprove = (await
|
var authorizedForAutoApprove = (await
|
||||||
_authorizationService.AuthorizeAsync(User, invoice.StoreId, Policies.CanCreatePullPayments))
|
_authorizationService.AuthorizeAsync(User, invoice.StoreId, Policies.CanCreatePullPayments))
|
||||||
@@ -529,7 +527,7 @@ namespace BTCPayServer.Controllers
|
|||||||
createPullPayment.Amount = Math.Round(createPullPayment.Amount - reduceByAmount, ppDivisibility);
|
createPullPayment.Amount = Math.Round(createPullPayment.Amount - reduceByAmount, ppDivisibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ppId = await _paymentHostedService.CreatePullPayment(createPullPayment);
|
var ppId = await _paymentHostedService.CreatePullPayment(store, createPullPayment);
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||||
{
|
{
|
||||||
Html = "Refund successfully created!<br />Share the link to this page with a customer.<br />The customer needs to enter their address and claim the refund.<br />Once a customer claims the refund, you will get a notification and would need to approve and initiate it from your Store > Payouts.",
|
Html = "Refund successfully created!<br />Share the link to this page with a customer.<br />The customer needs to enter their address and claim the refund.<br />Once a customer claims the refund, you will get a notification and would need to approve and initiate it from your Store > Payouts.",
|
||||||
|
|||||||
@@ -147,14 +147,13 @@ namespace BTCPayServer.Controllers
|
|||||||
return View(model);
|
return View(model);
|
||||||
model.AutoApproveClaims = model.AutoApproveClaims && (await
|
model.AutoApproveClaims = model.AutoApproveClaims && (await
|
||||||
_authorizationService.AuthorizeAsync(User, storeId, Policies.CanCreatePullPayments)).Succeeded;
|
_authorizationService.AuthorizeAsync(User, storeId, Policies.CanCreatePullPayments)).Succeeded;
|
||||||
await _pullPaymentService.CreatePullPayment(new CreatePullPayment
|
await _pullPaymentService.CreatePullPayment(CurrentStore, new CreatePullPaymentRequest
|
||||||
{
|
{
|
||||||
Name = model.Name,
|
Name = model.Name,
|
||||||
Description = model.Description,
|
Description = model.Description,
|
||||||
Amount = model.Amount,
|
Amount = model.Amount,
|
||||||
Currency = model.Currency,
|
Currency = model.Currency,
|
||||||
StoreId = storeId,
|
PayoutMethods = selectedPaymentMethodIds.Select(p => p.ToString()).ToArray(),
|
||||||
PayoutMethods = selectedPaymentMethodIds,
|
|
||||||
BOLT11Expiration = TimeSpan.FromDays(model.BOLT11Expiration),
|
BOLT11Expiration = TimeSpan.FromDays(model.BOLT11Expiration),
|
||||||
AutoApproveClaims = model.AutoApproveClaims
|
AutoApproveClaims = model.AutoApproveClaims
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using BTCPayServer.Services.Notifications;
|
|||||||
using BTCPayServer.Services.Notifications.Blobs;
|
using BTCPayServer.Services.Notifications.Blobs;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -33,20 +34,6 @@ using PullPaymentData = BTCPayServer.Data.PullPaymentData;
|
|||||||
|
|
||||||
namespace BTCPayServer.HostedServices
|
namespace BTCPayServer.HostedServices
|
||||||
{
|
{
|
||||||
public class CreatePullPayment
|
|
||||||
{
|
|
||||||
public DateTimeOffset? ExpiresAt { get; set; }
|
|
||||||
public DateTimeOffset? StartsAt { get; set; }
|
|
||||||
public string StoreId { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public decimal Amount { get; set; }
|
|
||||||
public string Currency { get; set; }
|
|
||||||
public PayoutMethodId[] PayoutMethods { get; set; }
|
|
||||||
public bool AutoApproveClaims { get; set; }
|
|
||||||
public TimeSpan? BOLT11Expiration { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PullPaymentHostedService : BaseAsyncService
|
public class PullPaymentHostedService : BaseAsyncService
|
||||||
{
|
{
|
||||||
private readonly string[] _lnurlSupportedCurrencies = { "BTC", "SATS" };
|
private readonly string[] _lnurlSupportedCurrencies = { "BTC", "SATS" };
|
||||||
@@ -110,26 +97,14 @@ namespace BTCPayServer.HostedServices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Task<string> CreatePullPayment(string storeId, CreatePullPaymentRequest request)
|
public async Task<string> CreatePullPayment(Data.StoreData store, CreatePullPaymentRequest create)
|
||||||
{
|
{
|
||||||
if (request.PayoutMethods.Length == 0)
|
var supported = this._handlers.GetSupportedPayoutMethods(store);
|
||||||
|
create.PayoutMethods ??= supported.Select(s => s.ToString()).ToArray();
|
||||||
|
create.PayoutMethods = create.PayoutMethods.Where(pm => _handlers.Support(PayoutMethodId.Parse(pm))).ToArray();
|
||||||
|
if (create.PayoutMethods.Length == 0)
|
||||||
throw new InvalidOperationException("request.PayoutMethods should have at least one payout method");
|
throw new InvalidOperationException("request.PayoutMethods should have at least one payout method");
|
||||||
return CreatePullPayment(new CreatePullPayment()
|
|
||||||
{
|
|
||||||
StartsAt = request.StartsAt,
|
|
||||||
ExpiresAt = request.ExpiresAt,
|
|
||||||
BOLT11Expiration = request.BOLT11Expiration,
|
|
||||||
Name = request.Name,
|
|
||||||
Description = request.Description,
|
|
||||||
Amount = request.Amount,
|
|
||||||
Currency = request.Currency,
|
|
||||||
StoreId = storeId,
|
|
||||||
PayoutMethods = request.PayoutMethods.Select(p => PayoutMethodId.Parse(p)).ToArray(),
|
|
||||||
AutoApproveClaims = request.AutoApproveClaims
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public async Task<string> CreatePullPayment(CreatePullPayment create)
|
|
||||||
{
|
|
||||||
ArgumentNullException.ThrowIfNull(create);
|
ArgumentNullException.ThrowIfNull(create);
|
||||||
if (create.Amount <= 0.0m)
|
if (create.Amount <= 0.0m)
|
||||||
throw new ArgumentException("Amount out of bound", nameof(create));
|
throw new ArgumentException("Amount out of bound", nameof(create));
|
||||||
@@ -140,7 +115,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
: DateTimeOffset.UtcNow - TimeSpan.FromSeconds(1.0);
|
: DateTimeOffset.UtcNow - TimeSpan.FromSeconds(1.0);
|
||||||
o.EndDate = create.ExpiresAt is DateTimeOffset date2 ? new DateTimeOffset?(date2) : null;
|
o.EndDate = create.ExpiresAt is DateTimeOffset date2 ? new DateTimeOffset?(date2) : null;
|
||||||
o.Id = Encoders.Base58.EncodeData(RandomUtils.GetBytes(20));
|
o.Id = Encoders.Base58.EncodeData(RandomUtils.GetBytes(20));
|
||||||
o.StoreId = create.StoreId;
|
o.StoreId = store.Id;
|
||||||
o.Currency = create.Currency;
|
o.Currency = create.Currency;
|
||||||
o.Limit = create.Amount;
|
o.Limit = create.Amount;
|
||||||
|
|
||||||
@@ -148,7 +123,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
{
|
{
|
||||||
Name = create.Name ?? string.Empty,
|
Name = create.Name ?? string.Empty,
|
||||||
Description = create.Description ?? string.Empty,
|
Description = create.Description ?? string.Empty,
|
||||||
SupportedPayoutMethods = create.PayoutMethods,
|
SupportedPayoutMethods = create.PayoutMethods.Select(p => PayoutMethodId.Parse(p)).ToArray(),
|
||||||
AutoApproveClaims = create.AutoApproveClaims,
|
AutoApproveClaims = create.AutoApproveClaims,
|
||||||
View = new PullPaymentBlob.PullPaymentView
|
View = new PullPaymentBlob.PullPaymentView
|
||||||
{
|
{
|
||||||
@@ -156,7 +131,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
Description = create.Description ?? string.Empty,
|
Description = create.Description ?? string.Empty,
|
||||||
Email = null
|
Email = null
|
||||||
},
|
},
|
||||||
BOLT11Expiration = create.BOLT11Expiration ?? TimeSpan.FromDays(30.0)
|
BOLT11Expiration = create.BOLT11Expiration ?? store.GetStoreBlob().RefundBOLT11Expiration
|
||||||
});
|
});
|
||||||
ctx.PullPayments.Add(o);
|
ctx.PullPayments.Add(o);
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
|||||||
@@ -126,6 +126,15 @@
|
|||||||
"format": "seconds",
|
"format": "seconds",
|
||||||
"description": "A span of times in seconds"
|
"description": "A span of times in seconds"
|
||||||
},
|
},
|
||||||
|
"TimeSpanDays": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/TimeSpan"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"format": "days",
|
||||||
|
"description": "A span of times in days"
|
||||||
|
},
|
||||||
"TimeSpanMinutes": {
|
"TimeSpanMinutes": {
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -518,6 +518,17 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"refundBOLT11Expiration": {
|
||||||
|
"default": 30,
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 3650,
|
||||||
|
"description": "The minimum expiry of BOLT11 invoices accepted for refunds by default. (in days)",
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/TimeSpanDays"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"displayExpirationTimer": {
|
"displayExpirationTimer": {
|
||||||
"default": 300,
|
"default": 300,
|
||||||
"minimum": 60,
|
"minimum": 60,
|
||||||
|
|||||||
Reference in New Issue
Block a user