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