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 fieldset
28 legend Auto top-up when account balance is low?
29 label
30 | When balance drops below $5, add $
31 input type="number" name="auto_top_up_amount" min="15" value=auto_top_up
32 small Leave blank for no auto top-up.
33
34 input type="hidden" name="customer_id" value=customer_id
35 input type="hidden" name="atfd" value=antifraud
36 input type="hidden" name="braintree_nonce"
37
38script src="https://js.braintreegateway.com/web/dropin/1.33.0/js/dropin.js"
39javascript:
40 document.querySelector("#braintree").innerHTML = "";
41
42 if(window.localStorage) {
43 var atfd = localStorage.getItem("atfd");
44 if(!atfd) {
45 atfd = "#{antifraud}";
46 localStorage.setItem("atfd", atfd);
47 }
48 document.querySelector("input[name=atfd]").value = atfd;
49 }
50
51 if (window.xmpp_xep0050) {
52 xmpp_xep0050.preventDefault();
53
54 window.addEventListener("message", (ev) => {
55 if (ev.data === "xmpp_xep0050/next") {
56 document.querySelector("form").requestSubmit();
57 }
58 });
59 }
60
61 var button = document.createElement("button");
62 button.innerHTML = "Save";
63 document.querySelector("form").appendChild(button);
64 braintree.dropin.create({
65 authorization: #{{token.to_json}},
66 container: "#braintree",
67 card: { vault: { vaultCard: false } },
68 vaultManager: true,
69 threeDSecure: true,
70 translations: {
71 payWithCard: "Add a Card",
72 payingWith: "Default payment source",
73 chooseAnotherWayToPay: "Add a different payment source"
74 }
75 }, function (createErr, instance) {
76 if(createErr) {
77 console.log(createErr);
78 Sentry.captureException(createErr);
79 }
80
81 document.querySelector("form").addEventListener("submit", function(e) {
82 e.preventDefault();
83 instance._mainView.hideSheetError();
84
85 instance.requestPaymentMethod({
86 threeDSecure: {
87 amount: "0.0",
88 requireChallenge: true
89 }
90 }, function(err, payload) {
91 if(err) {
92 console.log(err);
93 } else {
94 instance._mainView.showLoadingIndicator();
95 e.target.braintree_nonce.value = payload.nonce;
96 fetch("", {
97 "method": "POST",
98 "body": new FormData(e.target)
99 }).then(function(response) {
100 instance._mainView.hideLoadingIndicator();
101
102 if(response.status === 200) {
103 if (window.xmpp_xep0050) window.xmpp_xep0050.execute();
104 } else {
105 return Promise.reject(response);
106 }
107 }).catch(function(err) {
108 if(!(err instanceof Response)) return Promise.reject(err);
109
110 return err.text().then(function(msg) {
111 console.log(msg);
112 instance._mainView.hideLoadingIndicator();
113 instance.clearSelectedPaymentMethod();
114 instance._mainView.showSheetError(msg);
115 var errEl = instance._mainView.sheetErrorText;
116 if(errEl.innerHTML === instance._mainView.strings.genericError) {
117 errEl.innerHTML = "Card Issuer Says: " + msg;
118 }
119 });
120 }).catch(function(err) {
121 console.log(err);
122 instance._mainView.hideLoadingIndicator();
123 instance.clearSelectedPaymentMethod();
124 instance._mainView.showSheetError();
125 Sentry.captureException(err);
126 });
127 }
128 });
129 });
130 });