mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Checkout fixes (#4375)
* Round buttons on results view * Checkout v2: Fix for BIP21 case with LN as default payment method Fixes #4352. * Update changelog * Add test for fix
This commit is contained in:
@@ -151,6 +151,15 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.StartsWith("bitcoin:", payUrl);
|
Assert.StartsWith("bitcoin:", payUrl);
|
||||||
Assert.Contains("&LIGHTNING=", payUrl);
|
Assert.Contains("&LIGHTNING=", payUrl);
|
||||||
|
|
||||||
|
// BIP21 with LN as default payment method
|
||||||
|
s.GoToHome();
|
||||||
|
invoiceId = s.CreateInvoice(defaultPaymentMethod: "BTC_LightningLike");
|
||||||
|
s.GoToInvoiceCheckout(invoiceId);
|
||||||
|
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
||||||
|
payUrl = s.Driver.FindElement(By.CssSelector(".btn-primary")).GetAttribute("href");
|
||||||
|
Assert.StartsWith("bitcoin:", payUrl);
|
||||||
|
Assert.Contains("&LIGHTNING=", payUrl);
|
||||||
|
|
||||||
// BIP21 with topup invoice (which is only available with Bitcoin onchain)
|
// BIP21 with topup invoice (which is only available with Bitcoin onchain)
|
||||||
s.GoToHome();
|
s.GoToHome();
|
||||||
invoiceId = s.CreateInvoice(amount: null);
|
invoiceId = s.CreateInvoice(amount: null);
|
||||||
|
|||||||
@@ -643,9 +643,23 @@ namespace BTCPayServer.Controllers
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
bool isDefaultPaymentId = false;
|
bool isDefaultPaymentId = false;
|
||||||
|
var storeBlob = store.GetStoreBlob();
|
||||||
|
var btcId = PaymentMethodId.Parse("BTC");
|
||||||
|
var lnId = PaymentMethodId.Parse("BTC_LightningLike");
|
||||||
if (paymentMethodId is null)
|
if (paymentMethodId is null)
|
||||||
{
|
{
|
||||||
var enabledPaymentIds = store.GetEnabledPaymentIds(_NetworkProvider);
|
var enabledPaymentIds = store.GetEnabledPaymentIds(_NetworkProvider)
|
||||||
|
// Exclude LNURL for Checkout v2
|
||||||
|
.Where(pmId => storeBlob.CheckoutType == CheckoutType.V1 || pmId.PaymentType is not LNURLPayPaymentType)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
// Exclude Lightning if OnChainWithLnInvoiceFallback is active and we have both payment methods
|
||||||
|
if (storeBlob.CheckoutType == CheckoutType.V2 && storeBlob.OnChainWithLnInvoiceFallback &&
|
||||||
|
enabledPaymentIds.Contains(btcId) && enabledPaymentIds.Contains(lnId))
|
||||||
|
{
|
||||||
|
enabledPaymentIds = enabledPaymentIds.Where(pmId => pmId != lnId).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
PaymentMethodId? invoicePaymentId = invoice.GetDefaultPaymentMethod();
|
PaymentMethodId? invoicePaymentId = invoice.GetDefaultPaymentMethod();
|
||||||
PaymentMethodId? storePaymentId = store.GetDefaultPaymentId();
|
PaymentMethodId? storePaymentId = store.GetDefaultPaymentId();
|
||||||
if (invoicePaymentId is not null)
|
if (invoicePaymentId is not null)
|
||||||
@@ -676,6 +690,7 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
if (paymentMethodId is null)
|
if (paymentMethodId is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
BTCPayNetworkBase network = _NetworkProvider.GetNetwork<BTCPayNetworkBase>(paymentMethodId.CryptoCode);
|
BTCPayNetworkBase network = _NetworkProvider.GetNetwork<BTCPayNetworkBase>(paymentMethodId.CryptoCode);
|
||||||
if (network is null || !invoice.Support(paymentMethodId))
|
if (network is null || !invoice.Support(paymentMethodId))
|
||||||
{
|
{
|
||||||
@@ -702,12 +717,10 @@ namespace BTCPayServer.Controllers
|
|||||||
return await GetInvoiceModel(invoiceId, paymentMethodId, lang);
|
return await GetInvoiceModel(invoiceId, paymentMethodId, lang);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var dto = invoice.EntityToDTO();
|
var dto = invoice.EntityToDTO();
|
||||||
var storeBlob = store.GetStoreBlob();
|
|
||||||
var accounting = paymentMethod.Calculate();
|
var accounting = paymentMethod.Calculate();
|
||||||
|
|
||||||
var paymentMethodHandler = _paymentMethodHandlerDictionary[paymentMethodId];
|
var paymentMethodHandler = _paymentMethodHandlerDictionary[paymentMethodId];
|
||||||
|
|
||||||
var divisibility = _CurrencyNameTable.GetNumberFormatInfo(paymentMethod.GetId().CryptoCode, false)?.CurrencyDecimalDigits;
|
var divisibility = _CurrencyNameTable.GetNumberFormatInfo(paymentMethod.GetId().CryptoCode, false)?.CurrencyDecimalDigits;
|
||||||
|
|
||||||
switch (lang?.ToLowerInvariant())
|
switch (lang?.ToLowerInvariant())
|
||||||
@@ -810,16 +823,18 @@ namespace BTCPayServer.Controllers
|
|||||||
.OrderByDescending(a => a.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode).ThenBy(a => a.PaymentMethodName).ThenBy(a => a.IsLightning ? 1 : 0)
|
.OrderByDescending(a => a.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode).ThenBy(a => a.PaymentMethodName).ThenBy(a => a.IsLightning ? 1 : 0)
|
||||||
.ToList()
|
.ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Exclude Lightning if OnChainWithLnInvoiceFallback is active and we have both payment methods
|
// Exclude Lightning if OnChainWithLnInvoiceFallback is active and we have both payment methods
|
||||||
if (storeBlob.CheckoutType == CheckoutType.V2 && storeBlob.OnChainWithLnInvoiceFallback)
|
if (storeBlob.CheckoutType == CheckoutType.V2 && storeBlob.OnChainWithLnInvoiceFallback)
|
||||||
{
|
{
|
||||||
var onchainPM = model.AvailableCryptos.Find(c => c.PaymentMethodId == "BTC");
|
var onchainPM = model.AvailableCryptos.Find(c => c.PaymentMethodId == btcId.ToString());
|
||||||
var lightningPM = model.AvailableCryptos.Find(c => c.PaymentMethodId == "BTC_LightningLike");
|
var lightningPM = model.AvailableCryptos.Find(c => c.PaymentMethodId == lnId.ToString());
|
||||||
if (onchainPM != null && lightningPM != null)
|
if (onchainPM != null && lightningPM != null)
|
||||||
{
|
{
|
||||||
model.AvailableCryptos.Remove(lightningPM);
|
model.AvailableCryptos.Remove(lightningPM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paymentMethodHandler.PreparePaymentModel(model, dto, storeBlob, paymentMethod);
|
paymentMethodHandler.PreparePaymentModel(model, dto, storeBlob, paymentMethod);
|
||||||
model.UISettings = paymentMethodHandler.GetCheckoutUISettings();
|
model.UISettings = paymentMethodHandler.GetCheckoutUISettings();
|
||||||
model.PaymentMethodId = paymentMethodId.ToString();
|
model.PaymentMethodId = paymentMethodId.ToString();
|
||||||
|
|||||||
@@ -134,9 +134,9 @@
|
|||||||
<payment-details :srv-model="srvModel" :is-active="isActive" class="mb-5"></payment-details>
|
<payment-details :srv-model="srvModel" :is-active="isActive" class="mb-5"></payment-details>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a v-if="srvModel.receiptLink" class="btn btn-primary" :href="srvModel.receiptLink" :target="isModal ? '_top' : null" v-t="'view_receipt'" id="ReceiptLink"></a>
|
<a v-if="srvModel.receiptLink" class="btn btn-primary rounded-pill w-100" :href="srvModel.receiptLink" :target="isModal ? '_top' : null" v-t="'view_receipt'" id="ReceiptLink"></a>
|
||||||
<a v-if="storeLink" class="btn btn-secondary" :href="storeLink" :target="isModal ? '_top' : null" v-t="{ path: 'return_to_store', args: { storeName: srvModel.storeName }}" id="StoreLink"></a>
|
<a v-if="storeLink" class="btn btn-secondary rounded-pill w-100" :href="storeLink" :target="isModal ? '_top' : null" v-t="{ path: 'return_to_store', args: { storeName: srvModel.storeName }}" id="StoreLink"></a>
|
||||||
<button v-else-if="isModal" class="btn btn-secondary" v-on:click="close" v-t="'Close'"></button>
|
<button v-else-if="isModal" class="btn btn-secondary rounded-pill w-100" v-on:click="close" v-t="'Close'"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="expired" v-if="isUnpayable">
|
<div id="expired" v-if="isUnpayable">
|
||||||
@@ -165,8 +165,8 @@
|
|||||||
<p class="text-center mt-3" v-html="replaceNewlines($t('invoice_expired_body', { storeName: srvModel.storeName, minutes: @Model.MaxTimeMinutes }))"></p>
|
<p class="text-center mt-3" v-html="replaceNewlines($t('invoice_expired_body', { storeName: srvModel.storeName, minutes: @Model.MaxTimeMinutes }))"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a v-if="storeLink" class="btn btn-primary" :href="storeLink" :target="isModal ? '_top' : null" v-t="{ path: 'return_to_store', args: { storeName: srvModel.storeName }}" id="StoreLink"></a>
|
<a v-if="storeLink" class="btn btn-primary rounded-pill w-100" :href="storeLink" :target="isModal ? '_top' : null" v-t="{ path: 'return_to_store', args: { storeName: srvModel.storeName }}" id="StoreLink"></a>
|
||||||
<button v-else-if="isModal" class="btn btn-primary" v-on:click="close" v-t="'Close'"></button>
|
<button v-else-if="isModal" class="btn btn-primary rounded-pill w-100" v-on:click="close" v-t="'Close'"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* Some logos or images wouldn't show up properly if rootPath is used (#4367) @NicolasDorier
|
* Some logos or images wouldn't show up properly if rootPath is used (#4367) @NicolasDorier
|
||||||
* Fix malformed manifest on PoS app (#4373, #4363) @dennisreimann
|
* Fix malformed manifest on PoS app (#4373, #4363) @dennisreimann
|
||||||
* Call to LND would start failing on some conditions @NicolasDorier
|
* Call to LND would start failing on some conditions @NicolasDorier
|
||||||
|
* Checkout v2: Fix for BIP21 case with default payment method other than onchain BTC (#4375) @dennisreimann
|
||||||
|
|
||||||
### Improvement
|
### Improvement
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user