Checkout v2: Minor fixes (#4345)

* Do not show remaining amount for topup invoices in expiry message

As [reported by @petzsch](https://chat.btcpayserver.org/btcpayserver/pl/gg1zy8t5h3dq7nme1nom93migo).

* Fix links on result page in Checkout Classic

Closes #4344.

* Better way to exclude Lightning if BIP21 is active and we have both PMs


Unify margins
This commit is contained in:
d11n 2022-11-24 15:14:56 +01:00 committed by GitHub
parent a4ee1e9805
commit bb60c2ac48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 24 deletions

View file

@ -47,7 +47,7 @@ namespace BTCPayServer.Tests
s.GoToInvoiceCheckout(invoiceId);
Assert.Equal(2, s.Driver.FindElements(By.CssSelector(".payment-method")).Count);
Assert.Contains("Lightning", s.Driver.FindElement(By.CssSelector(".payment-method.active")).Text);
Assert.Contains("Lightning", s.Driver.WaitForElement(By.CssSelector(".payment-method.active")).Text);
Assert.DoesNotContain("LNURL", s.Driver.PageSource);
var payUrl = s.Driver.FindElement(By.CssSelector(".btn-primary")).GetAttribute("href");
Assert.StartsWith("lightning:", payUrl);
@ -70,6 +70,7 @@ namespace BTCPayServer.Tests
var paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
Assert.Contains("This invoice will expire in", paymentInfo.Text);
Assert.DoesNotContain("Please send", paymentInfo.Text);
TestUtils.Eventually(() =>
{
var expiredSection = s.Driver.FindElement(By.Id("expired"));
@ -109,8 +110,9 @@ namespace BTCPayServer.Tests
Assert.Contains("Created transaction",
s.Driver.WaitForElement(By.Id("CheatSuccessMessage")).Text);
s.Server.ExplorerNode.Generate(1);
Assert.Contains("The invoice hasn't been paid in full",
s.Driver.WaitForElement(By.Id("PaymentInfo")).Text);
paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
Assert.Contains("The invoice hasn't been paid in full", paymentInfo.Text);
Assert.Contains("Please send", paymentInfo.Text);
});
// Mine
@ -157,6 +159,16 @@ namespace BTCPayServer.Tests
payUrl = s.Driver.FindElement(By.CssSelector(".btn-primary")).GetAttribute("href");
Assert.StartsWith("bitcoin:", payUrl);
Assert.DoesNotContain("&LIGHTNING=", payUrl);
// Expiry message should not show amount for topup invoice
expirySeconds = s.Driver.FindElement(By.Id("ExpirySeconds"));
expirySeconds.Clear();
expirySeconds.SendKeys("5");
s.Driver.FindElement(By.Id("Expire")).Click();
paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo"));
Assert.Contains("This invoice will expire in", paymentInfo.Text);
Assert.DoesNotContain("Please send", paymentInfo.Text);
}
[Fact(Timeout = TestTimeout)]

View file

@ -798,13 +798,8 @@ namespace BTCPayServer.Controllers
StoreId = store.Id,
AvailableCryptos = invoice.GetPaymentMethods()
.Where(i => i.Network != null &&
// TODO: These cases and implementation need to be discussed
(storeBlob.CheckoutType == CheckoutType.V1 ||
// Exclude LNURL for non-topup invoices
(invoice.IsUnsetTopUp() || i.GetId().PaymentType is not LNURLPayPaymentType)) &&
// Exclude Lightning if OnChainWithLnInvoiceFallback is active
(!storeBlob.OnChainWithLnInvoiceFallback || i.GetId().PaymentType is not LightningPaymentType)
)
// Exclude LNURL for Checkout v2
(storeBlob.CheckoutType == CheckoutType.V1 || i.GetId().PaymentType is not LNURLPayPaymentType))
.Select(kv =>
{
var availableCryptoPaymentMethodId = kv.GetId();
@ -828,6 +823,16 @@ namespace BTCPayServer.Controllers
.OrderByDescending(a => a.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode).ThenBy(a => a.PaymentMethodName).ThenBy(a => a.IsLightning ? 1 : 0)
.ToList()
};
// Exclude Lightning if OnChainWithLnInvoiceFallback is active and we have both payment methods
if (storeBlob.CheckoutType == CheckoutType.V2 && storeBlob.OnChainWithLnInvoiceFallback)
{
var onchainPM = model.AvailableCryptos.Find(c => c.PaymentMethodId == "BTC");
var lightningPM = model.AvailableCryptos.Find(c => c.PaymentMethodId == "BTC_LightningLike");
if (onchainPM != null && lightningPM != null)
{
model.AvailableCryptos.Remove(lightningPM);
}
}
paymentMethodHandler.PreparePaymentModel(model, dto, storeBlob, paymentMethod);
model.UISettings = paymentMethodHandler.GetCheckoutUISettings();
model.PaymentMethodId = paymentMethodId.ToString();

View file

@ -5,7 +5,7 @@
<div class="qr-container" data-clipboard-confirm-element="QR_Text_@Model.PaymentMethodId" :data-clipboard="model.invoiceBitcoinUrl" :data-destination="model.btcAddress">
<qrcode v-if="model.invoiceBitcoinUrlQR" :value="model.invoiceBitcoinUrlQR" tag="div" :options="qrOptions" />
</div>
<div class="mt-1 mb-3">
<div class="mt-2 mb-4">
<small class="qr-text" id="QR_Text_@Model.PaymentMethodId" v-t="'qr_text'"></small>
@*
<input type="text" class="form-control form-control-sm" :value="model.btcAddress"

View file

@ -204,16 +204,9 @@
</div>
</div>
<div class="success-message">{{$t("This invoice has been paid")}}</div>
<a class="action-button" :href="srvModel.merchantRefLink" v-if="!isModal && srvModel.merchantRefLink">
<span v-if="srvModel.receiptLink != srvModel.merchantRefLink" v-html="$t('Return to StoreName', srvModel)"></span>
<span v-else v-html="$t('View receipt')" id="receipt-btn"></span>
</a>
<a class="action-button" :href="srvModel.receiptLink" :target="isModal?'_blank':'_top'" v-if="srvModel.receiptLink && (srvModel.merchantRefLink != srvModel.receiptLink) || isModal">
<span v-html="$t('View receipt')" id="receipt-btn"></span>
</a>
<button class="action-button close-action" v-show="isModal" v-on:click="close">
<span v-html="$t('Close')"></span>
</button>
<a v-if="srvModel.receiptLink" class="action-button" :href="srvModel.receiptLink" :target="isModal ? '_top' : null" v-html="$t('View receipt')" id="receipt-btn"></a>
<a v-if="storeLink" class="action-button" :href="storeLink" :target="isModal ? '_top' : null" v-html="$t('Return to StoreName', srvModel)"></a>
<button v-else-if="isModal" class="action-button close-action" v-on:click="close" v-html="$t('Close')"></button>
</div>
</div>
<div class="button-wrapper refund-address-form-container" id="refund-overpayment-button">
@ -240,7 +233,7 @@
{{srvModel.orderId}}
</div>
</div>
<a class="action-button" :href="srvModel.merchantRefLink" v-show="!isModal">
<a class="action-button" :href="storeLink" v-show="storeLink">
<span v-html="$t('Return to StoreName', srvModel)"></span>
</a>
<button class="action-button close-action" v-show="isModal" v-on:click="close">

View file

@ -224,6 +224,11 @@
},
invoicePaid: function(){
return ["complete", "confirmed", "paid"].indexOf(this.srvModel.status) >= 0;
},
storeLink () {
return this.srvModel.merchantRefLink && this.srvModel.merchantRefLink !== this.srvModel.receiptLink
? this.srvModel.merchantRefLink
: null;
}
},
mounted: function(){

View file

@ -84,7 +84,7 @@
<vc:icon symbol="info"/>
<span v-t="'partial_payment_info'"></span>
</div>
<div v-html="replaceNewlines($t('still_due', { amount: `${srvModel.btcDue} ${srvModel.cryptoCode}` }))"></div>
<div v-if="showPaymentDueInfo" v-html="replaceNewlines($t('still_due', { amount: `${srvModel.btcDue} ${srvModel.cryptoCode}` }))"></div>
</div>
</div>
<button id="DetailsToggle" class="d-flex align-items-center gap-1 btn btn-link payment-details-button mb-2" type="button" :aria-expanded="displayPaymentDetails ? 'true' : 'false'" v-on:click="displayPaymentDetails = !displayPaymentDetails">
@ -165,7 +165,7 @@
<p class="text-center mt-3" v-html="replaceNewlines($t('invoice_expired_body', { storeName: srvModel.storeName, minutes: @Model.MaxTimeMinutes }))"></p>
</div>
<div class="buttons">
<a v-if="!isModal && 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" :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>
</div>
</div>