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 var button = document.createElement("button");
52 button.innerHTML = "Save";
53 document.querySelector("form").appendChild(button);
54 braintree.dropin.create({
55 authorization: #{{token.to_json}},
56 container: "#braintree",
57 card: { vault: { vaultCard: false } },
58 vaultManager: true,
59 threeDSecure: true,
60 translations: {
61 payWithCard: "Add a Card",
62 payingWith: "Default payment source",
63 chooseAnotherWayToPay: "Add a different payment source"
64 }
65 }, function (createErr, instance) {
66 if(createErr) {
67 console.log(createErr);
68 Sentry.captureException(createErr);
69 }
70
71 document.querySelector("form").addEventListener("submit", function(e) {
72 e.preventDefault();
73 instance._mainView.hideSheetError();
74
75 instance.requestPaymentMethod({
76 threeDSecure: {
77 amount: "0.0",
78 requireChallenge: true
79 }
80 }, function(err, payload) {
81 if(err) {
82 console.log(err);
83 } else {
84 instance._mainView.showLoadingIndicator();
85 e.target.braintree_nonce.value = payload.nonce;
86 fetch("", {
87 "method": "POST",
88 "body": new FormData(e.target)
89 }).then(function(response) {
90 instance._mainView.hideLoadingIndicator();
91
92 if(response.status === 200) {
93 if (window.xmpp_xep0050) window.xmpp_xep0050.execute();
94 } else {
95 return Promise.reject(response);
96 }
97 }).catch(function(err) {
98 if(!(err instanceof Response)) return Promise.reject(err);
99
100 return err.text().then(function(msg) {
101 console.log(msg);
102 instance._mainView.hideLoadingIndicator();
103 instance.clearSelectedPaymentMethod();
104 instance._mainView.showSheetError(msg);
105 var errEl = instance._mainView.sheetErrorText;
106 if(errEl.innerHTML === instance._mainView.strings.genericError) {
107 errEl.innerHTML = "Card Issuer Says: " + msg;
108 }
109 });
110 }).catch(function(err) {
111 console.log(err);
112 instance._mainView.hideLoadingIndicator();
113 instance.clearSelectedPaymentMethod();
114 instance._mainView.showSheetError();
115 Sentry.captureException(err);
116 });
117 }
118 });
119 });
120 });