scss: form { margin: auto; max-width: 40em; text-align: center; fieldset { max-width: 25em; margin: 2em auto; label { display: block; } input[type=number] { max-width: 3em; } small { display: block; } } button { display: block; width: 10em; margin: auto; } } form method="post" action="" #braintree | Unfortunately, our credit card processor requires JavaScript. small | Charges will come from MBOA or Soprani.ca Telecom label#amount style="#{'display:none;' unless params['amount']}" div Amount of initial deposit (minimum $15) input type="number" name="amount" min="15" value="#{params.fetch('amount', '')}" fieldset legend Auto top-up when account balance is low? label | When balance drops below $5, add $ input type="number" name="auto_top_up_amount" min="15" max="35" value=auto_top_up small Leave blank for no auto top-up. input type="hidden" name="customer_id" value=customer_id input type="hidden" name="atfd" value=antifraud input type="hidden" name="braintree_nonce" script src="https://js.braintreegateway.com/web/dropin/1.42.0/js/dropin.js" javascript: document.querySelector("#braintree").innerHTML = ""; if(window.localStorage) { var atfd = localStorage.getItem("atfd"); if(!atfd) { atfd = "#{antifraud}"; localStorage.setItem("atfd", atfd); } document.querySelector("input[name=atfd]").value = atfd; } var button = document.createElement("button"); button.innerHTML = "Save"; document.querySelector("form").appendChild(button); if (window.xmpp_xep0050 && window.xmpp_xep0050.preventDefault) { xmpp_xep0050.preventDefault(); window.addEventListener("message", (ev) => { if (ev.data === "xmpp_xep0050/next" && !button.disabled) { document.querySelector("form").requestSubmit(); } if (ev.data === "xmpp_xep0050/cancel") { window.xmpp_xep0050.execute("cancel"); } if (ev.data === "xmpp_xep0050/prev") { window.xmpp_xep0050.execute("prev"); } if (ev.data === "xmpp_xep0050/complete") { window.xmpp_xep0050.execute("complete"); } }); } braintree.dropin.create({ authorization: #{{token.to_json}}, container: "#braintree", card: { vault: { vaultCard: false } }, vaultManager: true, threeDSecure: true, translations: { payWithCard: "Add a Card", payingWith: "Default payment source", chooseAnotherWayToPay: "Add a different payment source" } }, function (createErr, instance) { if(createErr) { console.log(createErr); Sentry.captureException(createErr); } document.querySelector("form").addEventListener("submit", function(e) { button.disabled = true; button.style.display = "none"; e.preventDefault(); instance._mainView.hideSheetError(); instance.requestPaymentMethod({ threeDSecure: { amount: document.querySelector("input[name=amount]").value || "0.0", requireChallenge: true, challengeRequested: true, collectDeviceData: true, email: "#{jid.sub(/@cheogram.com$/, "").gsub(/(%5[cC])|\\/, "=")}@smtp.cheogram.com" } }, function(err, payload) { if(err) { console.log(err); button.disabled = false; button.style.display = "block"; } else { instance._mainView.showLoadingIndicator(); e.target.braintree_nonce.value = payload.nonce; fetch("", { "method": "POST", "body": new FormData(e.target) }).then(function(response) { button.disabled = false; button.style.display = "block"; instance._mainView.hideLoadingIndicator(); if(response.status === 200) { if (window.xmpp_xep0050) window.xmpp_xep0050.execute(); } else { return Promise.reject(response); } }).catch(function(err) { button.disabled = false; button.style.display = "block"; if(!(err instanceof Response)) return Promise.reject(err); return err.text().then(function(msg) { console.log(msg); instance._mainView.hideLoadingIndicator(); instance.clearSelectedPaymentMethod(); instance._mainView.showSheetError(msg); var errEl = instance._mainView.sheetErrorText; if(errEl.innerHTML === instance._mainView.strings.genericError) { errEl.innerHTML = "Card Issuer Says: " + msg; } }); }).catch(function(err) { button.disabled = false; button.style.display = "block"; console.log(err); instance._mainView.hideLoadingIndicator(); instance.clearSelectedPaymentMethod(); instance._mainView.showSheetError(); Sentry.captureException(err); }); } }); }); });