1scss:
2 form {
3 margin: auto;
4 max-width: 40em;
5 text-align: center;
6
7 fieldset {
8 max-width: 25em;
9 margin: 2em auto;
10 label { display: block; }
11 input[type=number] { max-width: 3em; }
12 small { display: block; }
13 }
14
15 button {
16 display: block;
17 width: 10em;
18 margin: auto;
19 }
20
21 }
22
23form method="post" action=""
24 #braintree
25 | Unfortunately, our credit card processor requires JavaScript.
26
27 small
28 | Charges will come from MBOA or Soprani.ca Telecom
29
30 label#amount style="#{'display:none;' unless params['amount']}"
31 div Amount of initial deposit (minimum $15)
32 input type="number" name="amount" min="15" value="#{params.fetch('amount', '')}"
33
34 fieldset
35 legend Auto top-up when account balance is low?
36 label
37 | When balance drops below $5, add $
38 input type="number" name="auto_top_up_amount" min="15" max="35" value=auto_top_up
39 small Leave blank for no auto top-up.
40
41 input type="hidden" name="customer_id" value=customer_id
42 input type="hidden" name="atfd" value=antifraud
43 input type="hidden" name="braintree_nonce"
44
45script src="https://js.braintreegateway.com/web/dropin/1.42.0/js/dropin.js"
46javascript:
47 document.querySelector("#braintree").innerHTML = "";
48
49 if(window.localStorage) {
50 var atfd = localStorage.getItem("atfd");
51 if(!atfd) {
52 atfd = "#{antifraud}";
53 localStorage.setItem("atfd", atfd);
54 }
55 document.querySelector("input[name=atfd]").value = atfd;
56 }
57
58 var button = document.createElement("button");
59 button.innerHTML = "Save";
60 document.querySelector("form").appendChild(button);
61
62 if (window.xmpp_xep0050 && window.xmpp_xep0050.preventDefault) {
63 xmpp_xep0050.preventDefault();
64
65 window.addEventListener("message", (ev) => {
66 if (ev.data === "xmpp_xep0050/next" && !button.disabled) {
67 document.querySelector("form").requestSubmit();
68 }
69 if (ev.data === "xmpp_xep0050/cancel") {
70 window.xmpp_xep0050.execute("cancel");
71 }
72 if (ev.data === "xmpp_xep0050/prev") {
73 window.xmpp_xep0050.execute("prev");
74 }
75 if (ev.data === "xmpp_xep0050/complete") {
76 window.xmpp_xep0050.execute("complete");
77 }
78 });
79 }
80
81 braintree.dropin.create({
82 authorization: #{{token.to_json}},
83 container: "#braintree",
84 card: { vault: { vaultCard: false } },
85 vaultManager: true,
86 threeDSecure: true,
87 translations: {
88 payWithCard: "Add a Card",
89 payingWith: "Default payment source",
90 chooseAnotherWayToPay: "Add a different payment source"
91 }
92 }, function (createErr, instance) {
93 if(createErr) {
94 console.log(createErr);
95 Sentry.captureException(createErr);
96 }
97
98 document.querySelector("form").addEventListener("submit", function(e) {
99 button.disabled = true;
100 button.style.display = "none";
101 e.preventDefault();
102 instance._mainView.hideSheetError();
103
104 instance.requestPaymentMethod({
105 threeDSecure: {
106 amount: document.querySelector("input[name=amount]").value || "0.0",
107 requireChallenge: true,
108 challengeRequested: true,
109 collectDeviceData: true,
110 email: "#{jid.sub(/@cheogram.com$/, "").gsub(/(%5[cC])|\\/, "=")}@smtp.cheogram.com"
111 }
112 }, function(err, payload) {
113 if(err) {
114 console.log(err);
115 button.disabled = false;
116 button.style.display = "block";
117 } else {
118 instance._mainView.showLoadingIndicator();
119 e.target.braintree_nonce.value = payload.nonce;
120 fetch("", {
121 "method": "POST",
122 "body": new FormData(e.target)
123 }).then(function(response) {
124 button.disabled = false;
125 button.style.display = "block";
126 instance._mainView.hideLoadingIndicator();
127
128 if(response.status === 200) {
129 if (window.xmpp_xep0050) window.xmpp_xep0050.execute();
130 } else {
131 return Promise.reject(response);
132 }
133 }).catch(function(err) {
134 button.disabled = false;
135 button.style.display = "block";
136 if(!(err instanceof Response)) return Promise.reject(err);
137
138 return err.text().then(function(msg) {
139 console.log(msg);
140 instance._mainView.hideLoadingIndicator();
141 instance.clearSelectedPaymentMethod();
142 instance._mainView.showSheetError(msg);
143 var errEl = instance._mainView.sheetErrorText;
144 if(errEl.innerHTML === instance._mainView.strings.genericError) {
145 errEl.innerHTML = "Card Issuer Says: " + msg;
146 }
147 });
148 }).catch(function(err) {
149 button.disabled = false;
150 button.style.display = "block";
151 console.log(err);
152 instance._mainView.hideLoadingIndicator();
153 instance.clearSelectedPaymentMethod();
154 instance._mainView.showSheetError();
155 Sentry.captureException(err);
156 });
157 }
158 });
159 });
160 });