diff --git a/BTCPayServer.Tests/ThirdPartyTests.cs b/BTCPayServer.Tests/ThirdPartyTests.cs
index 19c7cf006..8e8f283f2 100644
--- a/BTCPayServer.Tests/ThirdPartyTests.cs
+++ b/BTCPayServer.Tests/ThirdPartyTests.cs
@@ -494,6 +494,10 @@ retry:
version = Regex.Match(actual, "Original file: /npm/decimal\\.js@([0-9]+.[0-9]+.[0-9]+)/decimal\\.js").Groups[1].Value;
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/decimal.js@{version}/decimal.min.js")).Content.ReadAsStringAsync()).Trim();
EqualJsContent(expected, actual);
+
+ actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "bbqr", "bbqr.iife.js").Trim();
+ expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/bbqr@1.0.0/dist/bbqr.iife.js")).Content.ReadAsStringAsync()).Trim();
+ EqualJsContent(expected, actual);
}
private void EqualJsContent(string expected, string actual)
diff --git a/BTCPayServer/Views/Shared/CameraScanner.cshtml b/BTCPayServer/Views/Shared/CameraScanner.cshtml
index 06725d814..f9154cf72 100644
--- a/BTCPayServer/Views/Shared/CameraScanner.cshtml
+++ b/BTCPayServer/Views/Shared/CameraScanner.cshtml
@@ -51,6 +51,12 @@
+
+
BBQR: {{bbqrDecoder.total}} parts, {{bbqrDecoder.progress * 100}}% completed
+
+
@@ -85,6 +91,7 @@ function initCameraScanningApp(title, onDataSubmit, modalId, submitOnScan = fals
noStreamApiSupport: false,
qrData: null,
decoder: null,
+ bbqrDecoder: null,
errorMessage: null,
successMessage: null,
camera: 0,
@@ -135,6 +142,7 @@ function initCameraScanningApp(title, onDataSubmit, modalId, submitOnScan = fals
this.successMessage = null;
this.errorMessage = null;
this.decoder = null;
+ this.bbqrDecoder = null;
},
close() {
if (this.modalId) {
@@ -146,12 +154,51 @@ function initCameraScanningApp(title, onDataSubmit, modalId, submitOnScan = fals
onDecode(content) {
if (this.qrData) return;
const isUR = content.toLowerCase().startsWith("ur:");
- console.debug(1, content);
-
+ const isBBQr = content.startsWith("B$");
+ console.debug(content);
try {
- if (!isUR) {
+ if (isBBQr){
+ this.decoder = null;
+ const total = parseInt(content.substr(4, 2), 36);
+ const current = parseInt(content.substr(6, 2), 36);
+ const format = content.substr(2,1);
+ const type = content.substr(3, 1);
+
+ if (!this.bbqrDecoder ||
+ this.bbqrDecoder.total !== total ||
+ this.bbqrDecoder.format !== format ||
+ this.bbqrDecoder.type !== type) {
+ this.bbqrDecoder = {
+ total,
+ format,
+ type,
+ data: new Array(total),
+ progress: 1/total
+ };
+ }
+ this.bbqrDecoder.data[current] = content;
+
+ const progress = this.bbqrDecoder.data.filter(value => value !== undefined).length / total;
+ this.bbqrDecoder.progress = progress;
+ if (progress >= 1) {
+ try {
+ const joinResult = BBQr.joinQRs(this.bbqrDecoder.data);
+ function buf2hex(buffer) { // buffer is an ArrayBuffer
+ return [...new Uint8Array(buffer)]
+ .map(x => x.toString(16).padStart(2, '0'))
+ .join('');
+ }
+ const result = buf2hex(joinResult.raw);
+ this.setQrData(result);
+ this.successMessage = `BBQr ${type} decoded`;
+ }catch (error){
+ this.errorMessage = error.message;
+ }
+ }
+ } else if (!isUR) {
this.setQrData(content);
} else {
+ this.bbqrDecoder = null;
this.decoder = this.decoder || new window.URlib.URRegistryDecoder();
if (this.decoder.receivePart(content)) {
if (this.decoder.isComplete()) {
diff --git a/BTCPayServer/Views/UIStores/ImportWallet/Scan.cshtml b/BTCPayServer/Views/UIStores/ImportWallet/Scan.cshtml
index efd9f6f47..62c2a4e1f 100644
--- a/BTCPayServer/Views/UIStores/ImportWallet/Scan.cshtml
+++ b/BTCPayServer/Views/UIStores/ImportWallet/Scan.cshtml
@@ -78,6 +78,7 @@
+
+
+