From 37cb49d785489d8421aed6867feb05ca63b43120 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 8 Aug 2020 10:11:08 -0500 Subject: [PATCH] Adding Shopify scripts with extracted variables --- .../wwwroot/shopify/btcpay-browser-client.js | 88 +++++++++++ .../shopify/btcpay-shopify-checkout.js | 138 ++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 BTCPayServer/wwwroot/shopify/btcpay-browser-client.js create mode 100644 BTCPayServer/wwwroot/shopify/btcpay-shopify-checkout.js diff --git a/BTCPayServer/wwwroot/shopify/btcpay-browser-client.js b/BTCPayServer/wwwroot/shopify/btcpay-browser-client.js new file mode 100644 index 000000000..d73aa9804 --- /dev/null +++ b/BTCPayServer/wwwroot/shopify/btcpay-browser-client.js @@ -0,0 +1,88 @@ +/* Based on @djseeds script: https://github.com/btcpayserver/btcpayserver/issues/36#issuecomment-633109155 */ +/*** Creates a new BTCPayServer Modal + * @param url - BTCPayServer Base URL + * @param storeId - BTCPayServer store ID + * @param data - Data to use for invoice creation +* @returns - A promise that resolves when invoice is paid. +* ***/ +var BtcPayServerModal = (function () { + function waitForPayment(btcPayServerUrl, invoiceId, storeId) { + // Todo: mutex lock on btcpayserver modal. + return new Promise(function (resolve, reject) { + // Don't allow two modals at once. + if (waitForPayment.lock) { + resolve(null); + } + else { + waitForPayment.lock = true; + } + window.btcpay.onModalWillEnter(function () { + var interval = setInterval(function () { + getBtcPayInvoice(btcPayServerUrl, invoiceId, storeId) + .then(function (invoice) { + if (invoice.status == "complete") { + clearInterval(interval); + resolve(invoice); + } + }) + .catch(function (err) { + clearInterval(interval); + reject(err); + }); + }, 1000); + window.btcpay.onModalWillLeave(function () { + waitForPayment.lock = false; + clearInterval(interval); + // If user exited the payment modal, + // indicate that there was no error but invoice did not complete. + resolve(null); + }); + }); + window.btcpay.showInvoice(invoiceId); + }); + } + + function getBtcPayInvoice(btcPayServerUrl, invoiceId, storeId) { + const url = btcPayServerUrl + "/invoices/" + invoiceId + "?storeId=" + storeId; + return fetch(url, { + method: "GET", + mode: "cors", // no-cors, cors, *same-origin, + headers: { + "Content-Type": "application/json", + "accept": "application/json", + } + }) + .then(function (response) { + return response.json(); + }) + .then(function (json) { + return json.data; + }) + } + + return { + show: function (url, storeId, data) { + const path = url + "/invoices?storeId=" + storeId; + return fetch(path, + { + method: "POST", + mode: "cors", + headers: { + "Content-Type": "application/json", + "accept": "application/json", + }, + body: JSON.stringify(data) + } + ) + .then(function (response) { + return response.json(); + }) + .then(function (response) { + return waitForPayment(url, response.data.id, storeId); + }); + }, + hide: function () { + window.btcpay.hideFrame(); + } + } +})() diff --git a/BTCPayServer/wwwroot/shopify/btcpay-shopify-checkout.js b/BTCPayServer/wwwroot/shopify/btcpay-shopify-checkout.js new file mode 100644 index 000000000..c736b9315 --- /dev/null +++ b/BTCPayServer/wwwroot/shopify/btcpay-shopify-checkout.js @@ -0,0 +1,138 @@ +/* Based on @djseeds script: https://github.com/btcpayserver/btcpayserver/issues/36#issuecomment-633109155 */ + +/* + +1. In your BTCPayServer store you need to check "Allow anyone to create invoice" +2. In Shopify Settings > Payment Providers > Manual Payment Methods add one which contains "Bitcoin" +3. In Shopify Settings > Checkout > Additional Scripts input the following script, with the details from your BTCPayServer instead of the placeholder values. + + + + + + */ + +! function () { + "use strict"; + const pageElements = document.querySelector.bind(document), + insertElement = (document.querySelectorAll.bind(document), + (e, + n) => { + n.parentNode.insertBefore(e, + n.nextSibling) + }); + + let pageItems = {}, + pageheader = "Thank you!", + buttonElement = null; + + const setPageItems = () => { + pageItems = { + mainHeader: pageElements("#main-header"), + orderConfirmed: pageElements(".os-step__title"), + orderConfirmedDescription: pageElements(".os-step__description"), + continueButton: pageElements(".step__footer__continue-btn"), + checkMarkIcon: pageElements(".os-header__hanging-icon"), + orderStatus: pageElements(".os-header__title"), + paymentMethod: pageElements(".payment-method-list__item__info"), + price: pageElements(".payment-due__price"), + finalPrice: pageElements(".total-recap__final-price"), + orderNumber: pageElements(".os-order-number"), + } + } + + const orderPaid = () => { + pageItems.mainHeader.innerText = pageheader, + pageItems.orderConfirmed && (pageItems.orderConfirmed.style.display = "block"), + pageItems.orderConfirmedDescription && (pageItems.orderConfirmedDescription.style.display = "block"), + pageItems.continueButton && (pageItems.continueButton.style.visibility = "visible"), + pageItems.checkMarkIcon && (pageItems.checkMarkIcon.style.visibility = "visible"), + buttonElement && (buttonElement.style.display = "none"); + }; + + window.setOrderAsPaid = orderPaid, + window.openBtcPayShopify = function waitForPaymentMethod() { + if (setPageItems(), "Order canceled" === pageItems.orderStatus.innerText) { + return; + } + + const paymentMethod = pageItems.paymentMethod; + + if (null === paymentMethod) { + return void setTimeout(() => { + waitForPaymentMethod(); + }, 10); + } + + if (-1 === paymentMethod.innerText.toLowerCase().indexOf("bitcoin")) return; + + // If payment method is bitcoin, display instructions and payment button. + pageheader = pageItems.mainHeader.innerText, + pageItems.mainHeader && (pageItems.mainHeader.innerText = "Review and pay!"), + pageItems.continueButton && (pageItems.continueButton.style.visibility = "hidden"), + pageItems.checkMarkIcon && (pageItems.checkMarkIcon.style.visibility = "hidden"), + pageItems.orderConfirmed && (pageItems.orderConfirmed.style.display = "none"), + pageItems.orderConfirmedDescription && (pageItems.orderConfirmedDescription.style.display = "none"), + buttonElement = document.createElement("div"); + + const priceElement = pageItems.finalPrice || pageItems.price; + var price = priceElement.innerText.replace(DEFAULT_CURRENCY_SYMBOL, "").replace(THOUSAND_DELIMITER, ""); + if (THOUSAND_DELIMITER === ".") { + price = price.replace(",", "."); // 5.000,00 needs to become 5000.00 + } + const orderId = pageItems.orderNumber.innerText.replace("Order #", ""); + + const url = BTCPAYSERVER_URL + "/invoices" + "?storeId=" + STORE_ID + "&orderId=" + orderId + "&status=complete"; + + // Check if already paid. + fetch(url, { + method: "GET", + mode: "cors", // no-cors, cors, *same-origin, + headers: { + "Content-Type": "application/json", + "accept": "application/json", + }, + }) + .then(function (response) { + return response.json(); + }) + .then(function (json) { + return json.data; + }) + .then(function (data) { + if (data.length != 0) { + orderPaid(); + } + }); + + window.waitForPayment = function () { + BtcPayServerModal.show( + BTCPAYSERVER_URL, + STORE_ID, + { + price: price, + currency: DEFAULT_CURRENCY, + orderId: orderId + } + ) + .then(function (invoice) { + if (invoice != null) { + orderPaid(); + } + }); + } + + // Payment button that opens modal + buttonElement.innerHTML = `\n \n`, + insertElement(buttonElement, pageItems.orderConfirmed); + + } + + window.openBtcPayShopify(); +}();