credit_cards.slim

  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	});