mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-19 05:33:31 +01:00
Checkout v2: Display and copy addresses (#4489)
* Checkout v2: Display and copy addresses Closes #4442. * Refinements
This commit is contained in:
parent
42c5f732a2
commit
2301769419
@ -99,7 +99,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
// Pay partial amount
|
||||
await Task.Delay(200);
|
||||
var address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-destination");
|
||||
var address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
||||
var amountFraction = "0.00001";
|
||||
await s.Server.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(address, Network.RegTest),
|
||||
Money.Parse(amountFraction));
|
||||
|
@ -3,18 +3,28 @@
|
||||
|
||||
<template id="bitcoin-method-checkout-template">
|
||||
<div class="payment-box">
|
||||
<div class="qr-container" data-clipboard-confirm-element="QR_Text_@Model.PaymentMethodId" :data-clipboard="model.invoiceBitcoinUrl" :data-clipboard-confirm="$t('copy_confirm')" :data-destination="model.btcAddress">
|
||||
<qrcode v-if="model.invoiceBitcoinUrlQR" :value="model.invoiceBitcoinUrlQR" tag="div" :options="qrOptions" />
|
||||
</div>
|
||||
<div class="mt-2 mb-4">
|
||||
<div v-if="model.invoiceBitcoinUrlQR" class="qr-container" :data-clipboard="model.btcAddress" data-clipboard-confirm-element="QR_Text_@Model.PaymentMethodId">
|
||||
<div>
|
||||
<qrcode :value="model.invoiceBitcoinUrlQR" tag="div" :options="qrOptions" />
|
||||
</div>
|
||||
<img class="qr-icon" :src="model.cryptoImage" :alt="model.paymentMethodName"/>
|
||||
<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"
|
||||
:data-clipboard="model.btcAddress" :data-clipboard-confirm="`$t('copy_confirm')"
|
||||
data-clipboard-confirm-element="QR_Text_@Model.PaymentMethodId" readonly>
|
||||
*@
|
||||
</div>
|
||||
<a v-if="model.invoiceBitcoinUrl" class="btn btn-primary rounded-pill w-100" target="_top"
|
||||
<div v-if="model.btcAddress" class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<input id="Address_@Model.PaymentMethodId" class="form-control-plaintext" readonly="readonly" :value="model.btcAddress">
|
||||
<label for="Address_@Model.PaymentMethodId" v-t="{ path: 'address', args: { paymentMethod: model.paymentMethodName }}"></label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-link" data-clipboard-target="#Address_@Model.PaymentMethodId" :data-clipboard-confirm="$t('copy_confirm')" v-t="'copy'"></button>
|
||||
</div>
|
||||
<div v-if="BOLT11" class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<input id="BOLT11_@Model.PaymentMethodId" class="form-control-plaintext" readonly="readonly" :value="BOLT11" />
|
||||
<label for="BOLT11_@Model.PaymentMethodId" v-t="'lightning'"></label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-link" data-clipboard-target="#BOLT11_@Model.PaymentMethodId" :data-clipboard-confirm="$t('copy_confirm')" v-t="'copy'"></button>
|
||||
</div>
|
||||
<a v-if="model.invoiceBitcoinUrl" class="btn btn-primary rounded-pill w-100 mt-4" target="_top"
|
||||
:href="model.invoiceBitcoinUrl" :title="$t(hasPayjoin ? 'BIP21 payment link with PayJoin support' : 'BIP21 payment link')" v-t="'pay_in_wallet'"></a>
|
||||
</div>
|
||||
</template>
|
||||
@ -27,12 +37,17 @@
|
||||
qrcode: VueQrcode
|
||||
},
|
||||
data () {
|
||||
console.log(this.model.cryptoImage)
|
||||
// currentTab is needed for backwards-compatibility with old plugin versions
|
||||
return { currentTab: undefined };
|
||||
},
|
||||
computed: {
|
||||
hasPayjoin () {
|
||||
return this.model.invoiceBitcoinUrl.indexOf('@PayjoinClient.BIP21EndpointKey=') !== -1;
|
||||
},
|
||||
BOLT11 () {
|
||||
const match = this.model.invoiceBitcoinUrl.match(/&LIGHTNING=(.*)&?/i);
|
||||
return match ? match[1].toLowerCase() : null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2,18 +2,21 @@
|
||||
|
||||
<template id="lightning-method-checkout-template">
|
||||
<div class="payment-box">
|
||||
<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-2 mb-4">
|
||||
<div v-if="model.invoiceBitcoinUrlQR" class="qr-container" :data-clipboard="model.btcAddress" data-clipboard-confirm-element="QR_Text_@Model.PaymentMethodId">
|
||||
<div>
|
||||
<qrcode :value="model.invoiceBitcoinUrlQR" tag="div" :options="qrOptions" />
|
||||
</div>
|
||||
<img class="qr-icon" :src="model.cryptoImage" :alt="model.paymentMethodName"/>
|
||||
<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"
|
||||
:data-clipboard="model.invoiceBitcoinUrl" :data-clipboard-confirm="$t('copy_confirm')"
|
||||
data-clipboard-confirm-element="QR_Text_@Model.PaymentMethodId" readonly>
|
||||
*@
|
||||
</div>
|
||||
<a v-if="model.invoiceBitcoinUrl" class="btn btn-primary rounded-pill w-100" target="_top"
|
||||
<div v-if="model.btcAddress" class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<input id="Address_@Model.PaymentMethodId" class="form-control-plaintext" readonly="readonly" :value="model.btcAddress">
|
||||
<label for="Address_@Model.PaymentMethodId" v-t="'lightning'"></label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-link" data-clipboard-target="#Address_@Model.PaymentMethodId" :data-clipboard-confirm="$t('copy_confirm')" v-t="'copy'"></button>
|
||||
</div>
|
||||
<a v-if="model.invoiceBitcoinUrl" class="btn btn-primary rounded-pill w-100 mt-4" target="_top"
|
||||
:href="model.invoiceBitcoinUrl" v-t="'pay_in_wallet'"></a>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -241,7 +241,7 @@
|
||||
const statusWsUrl = @Safe.Json(Url.Action("GetStatusWebSocket", new { invoiceId = Model.InvoiceId }));
|
||||
const availableLanguages = ['en']; // @Safe.Json(LangService.GetLanguages().Select(language => language.Code));
|
||||
const initialSrvModel = @Safe.Json(Model);
|
||||
const qrOptions = { margin: 1, type: 'svg', color: { dark: '#000', light: '#fff' } };
|
||||
const qrOptions = { margin: 0, type: 'svg', color: { dark: '#000', light: '#fff' } };
|
||||
</script>
|
||||
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
|
||||
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
|
||||
|
@ -1,6 +1,9 @@
|
||||
:root {
|
||||
--navbutton-size: .8rem;
|
||||
--qr-size: 256px;
|
||||
--icon-size: 64px;
|
||||
--icon-border-size: var(--btcpay-space-s);
|
||||
--icon-border-color: var(--btcpay-body-text);
|
||||
--section-padding: 1.5rem;
|
||||
--border-radius: var(--btcpay-border-radius-l);
|
||||
--wrap-max-width: 400px;
|
||||
@ -123,19 +126,48 @@ section dl > div dd {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
.payment-box .qr-text {
|
||||
display: block;
|
||||
color: var(--btcpay-light-text);
|
||||
}
|
||||
.payment-box .qr-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
min-height: var(--qr-size);
|
||||
}
|
||||
.payment-box .qr-container svg {
|
||||
border-radius: var(--btcpay-border-radius);
|
||||
}
|
||||
.payment-box svg {
|
||||
padding: var(--btcpay-space-s);
|
||||
background: var(--btcpay-white);
|
||||
width: 100%;
|
||||
}
|
||||
.payment-box .qr-container img {
|
||||
box-sizing: content-box;
|
||||
position: absolute;
|
||||
width: var(--icon-size);
|
||||
border-radius: 50%;
|
||||
padding: var(--icon-border-size);
|
||||
background: var(--icon-border-color);
|
||||
}
|
||||
.payment-box .qr-container small {
|
||||
display: none;
|
||||
}
|
||||
.payment-box .input-group {
|
||||
align-items: flex-end;
|
||||
}
|
||||
.payment-box .input-group .form-control-plaintext {
|
||||
padding-left: 3px;
|
||||
padding-bottom: 0;
|
||||
font-weight: var(--btcpay-font-weight-semibold);
|
||||
}
|
||||
.payment-box .input-group label {
|
||||
padding-left: 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .1rem;
|
||||
font-weight: var(--btcpay-font-weight-semibold);
|
||||
}
|
||||
.payment-box .input-group button {
|
||||
padding: var(--btcpay-space-xs) 0;
|
||||
font-weight: var(--btcpay-font-weight-semibold);
|
||||
}
|
||||
.payment-details dl {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -18,11 +18,15 @@
|
||||
"network_cost": "Network Cost",
|
||||
"tx_count": "{{count}} transactions",
|
||||
"qr_text": "Scan the QR code, or tap to copy the address.",
|
||||
"address": "{{paymentMethod}} Address",
|
||||
"lightning": "Lightning",
|
||||
"payment_link": "Payment Link",
|
||||
"invoice_paid": "Invoice Paid",
|
||||
"invoice_expired": "Invoice Expired",
|
||||
"invoice_expired_body": "An invoice is only valid for {{minutes}} minutes.\n\nReturn to {{storeName}} if you like to resubmit a payment.",
|
||||
"view_receipt": "View Receipt",
|
||||
"return_to_store": "Return to {{storeName}}",
|
||||
"copy": "Copy",
|
||||
"copy_confirm": "Copied",
|
||||
"powered_by": "Powered by",
|
||||
"conversion_body": "You can pay {{btcDue}} {{cryptoCode}} using altcoins other than the ones merchant directly supports.\n\nThis service is provided by 3rd party. Please keep in mind that we have no control over how providers will forward your funds. Invoice will only be marked paid once funds are received on {{cryptoCode}} Blockchain."
|
||||
|
Loading…
Reference in New Issue
Block a user