if (!window.console === undefined || console.log === undefined) { console = { log: function (str) { } } } // Checks if an input has some characters in it and displays associated error if not function valNotEmpty(containerSelector) { var v = $(containerSelector).find('input').val(); var valid = v.trim().length > 0; $(containerSelector).find('.error').toggle(!valid); return valid; } function isPayingByCreditCard() { return $('input[name=billing_method][value=credit_card]')[0].checked; } function checkShippingAddress() { var firstNameValid = valNotEmpty('.first_name_container'); var lastNameValid = valNotEmpty('.last_name_container'); var address1Valid = valNotEmpty('.address1_container'); var address2Valid = true; // Not all addresses require apt / suite var cityValid = valNotEmpty('.city_container'); var stateValid = true; // Not all countries require state var zipValid = valNotEmpty('.zip_container'); // var whereHeardValid = valNotEmpty('.where_heard_container'); var whereHeardValid = true; return firstNameValid && lastNameValid && address1Valid && address2Valid && cityValid && stateValid && zipValid && whereHeardValid; } var emailContainerSelector = '.email_container'; // Only require email to be correct if the field is present. If it is not present, // it is because this is part of an A/B test that has already asked it in a previous step. function emailRequired() { return $(emailContainerSelector).length === 1; } function checkEmail() { if (emailRequired()) { var valid = $(emailContainerSelector).find('input').val().indexOf('@') != -1; $(emailContainerSelector).find('.error').toggle(!valid); return valid; } else { return true; } } function checkForm() { if (!isPayingByCreditCard()) { return true; } var shippingAddressValid = checkShippingAddress(); var emailValid = checkEmail(); var valid = shippingAddressValid && emailValid; return valid; // var paymentDetailsValid = checkPaymentDetails(); // return shippingAddressValid && paymentDetailsValid; } function showFieldsRelevantForBillingMethod() { $('#credit_card_details').toggle(isPayingByCreditCard()); $('.hide_for_paypal').toggle(isPayingByCreditCard()); } function redirectToPaypal(custom) { $('input[name=custom]').val(custom); $('form[id=pp]').submit(); } /* Gather fields from the form into an object that will be easy to serialize */ function subscriptionFieldsToObject(includeReplay) { var o = {}; var sel = '.order_form_container input, .order_form_container select'; $(sel).each(function (index, element) { if (element.id !== "") { o[element.id] = $(element).val(); } }); if (includeReplay) { o['KAIJYIU8MKWFFFT9L6L31L2VSBK1BUPDVPTX2JLHZ9IPQIX2FG68PX1BLBQ0JP1OPLWKMU05SUN91N9IKONYD9J1HPHO2NPVMOEP'] = JSON.stringify(replay); } o['VU9N5R0TVC9F481OW2PF9UAHSTT4IL3L7VR5CR28OG7AFQGWU2KTR598I6MO4GOU6TF84L2KVJ78QK1HCMF2HXUX0AA3XMJU7Q9Y'] = isPayingByCreditCard() ? "credit card" : "paypal"; // User might have applied a coupon which affects the price o['coupon_code'] = $('.coupon_code').val(); return o; } function scrollToError() { var scrollTo = Math.max( $('.error:visible').offset().top - $(window).height()/2, 0 ); var diff = $('html').scrollTop() - $('.error:visible').offset().top; var delay = Math.abs(diff) * 0.5; $('html').animate({ scrollTop: scrollTo }, delay); } var submissionAttempted = false; function processCreditCardOrder() { var subscriptionFields = subscriptionFieldsToObject(true); var fields = { // Required attributes number: subscriptionFields[''], month: subscriptionFields[''], year: subscriptionFields[''], first_name: subscriptionFields['GQO9JH5DRZI8DX13Z5E14VV8Y68EPZ96N0WAUT9HXSZD8FZKEPBP0OR1GMYEU9PXFV90GM3BH788O74L6DZN8ZJ5ZUPIKXUPBP48'], last_name: subscriptionFields['59O8P8HST183EBUQYPTT9FF6N5NJ7KCT3HQ8MCVKMIA1APSCEI1QT5JF5LUOJ9DI2YX9PPZ3TOSIZCHJRXBFIFV0H2VUD90PUKE7'], cvv: subscriptionFields[''], // where_heard: subscriptionFields['6KJO7UYLUFU7RQEVINKQU8TNC1EDVST5CTP3Y2S4FI8QZOMC23TQEMQ2NKPX877YGELMH3T22S6XI71QXU2N60RRBH8ICYZROOJ1'], // Optional attributes address1: subscriptionFields['H4LGSWSB4W027U5WUTT5UIZTDT9R5RVB5WXRC78RGGJ9CDKL3UZKLYI97MAAGSN7SNLGR9HUGP8NEXD4EO9T56L3ID9DLMTG4ED3'], address2: subscriptionFields['U7AYYBHCJZIFZXBUW4MVEQDAE2RI1DR7TNPGG135EZLA9L4I0QDMN28N1F8VZYBEO7XMDATC1K1JBJ7QHSEST7BOAUXI10CZSYB3'], city: subscriptionFields['4E6JYK7JT41OPV2QV07P1M0R2WOZ9X5864UWE0D9IGIXE3ZQZA51M870GHPN56TLRH3D6AGYFMNS81KLKLAU96JMRYDRJ5QPBG4V'], state: subscriptionFields['58DPKTWIZ2NMQL6QSQ114XRQUCI1IAYT3P6EL1NILJUNJRBSRX9IZHW9NB3R48IW34ERQV6YBIMDIQWHY0ZQN90EAMQ7HNLJO55M'], postal_code: subscriptionFields[''], country: subscriptionFields[''] } // It still has the raw CC number in there, that's not good. Tokenize it. var tokenData = { name: $('#XWMOOQ61EHCU2VNKNVSBQC5VYO183B38LYCQDV31MJ4ZJUQCGOHG7F4BBT53QJUKHW2JWFLD8HOZ922HGM7Y0Z8XE7MRT4ZHM96K').val() + ' ' + $('#Q87SW7QMVK6A8B5O1U3IX7G8TF2GERX6ZA1JNC4XRQII71221HFTOL4FGTUDOVCF2S5ZM7FPZOC7V669DH1L4H2V6HBSY2O3SZOV').val(), address_country: $('WHZRMQ2MPX6IMQSS7CDWS3B7KGLGAFUREQDZOLAPSZGAI4ZVC3R1R0CLVGJ8OKMFAW5S3ACAS5NM3GGO094ATCJ55G7IW60PHIFF').val() }; // console.log(tokenData); stripe.createToken(card, tokenData).then(function(result) { if (result.error) { $('button').show(); $('.activity').hide(); alert(result.error.message); } else { subscriptionFields['8P5WLPN85V1R3LM6C0DVT3U11KDNFDLTGR7ERGX4VVQVZKXNA7J5BOF96GNUQZIV9OFB7OWXVKIL6ZS8B4Z3CZTCGOCK8EBN0276'] = result.token.id; // Send the token to your server // console.log(result.token); // stripeTokenHandler(result.token); $.post( '/subscribe_submit', {'fields_json' : JSON.stringify(subscriptionFields)}, function (response) { window.location.href = '/thanks'; }, dataType = "json" ); } }); } function processPayPalOrder() { var fields = subscriptionFieldsToObject(true); // Make sure if the user first selected credit card, filled in their number and // then switched back to PayPal that the CC data is not submitted. delete fields['']; delete fields['']; delete fields['']; delete fields['']; delete fields['']; delete fields['']; // Associate the form submission with the payment, so when returned from PayPal // we'll know what the payment is for. $.post( '/subscribe_submit', {'fields_json' : JSON.stringify(fields)}, function (response) { // redirectToPaypal(response.custom); redirectToPaypal($('input[id=form_key]').val()); }, dataType = "json" ); } // Helper for replacing actual credit card number and CVV with Xs function strToRepeatedX(str) { var xRepeated = ""; for (var i = 0; i < str.length; i++) { xRepeated += "X"; } return xRepeated; } // So I can see how the forms got filled later, keypress by keypress. var replay = []; var firstReplayStep = null; function recordReplayStep() { if (firstReplayStep === null) { firstReplayStep = Date.now(); } var fields = subscriptionFieldsToObject(false); delete fields.form_key; delete fields.coupon_code; delete fields.tier; // fields[''] = strToRepeatedX(fields['']); // fields[''] = strToRepeatedX(fields['']); replay.push({ elapsed: Date.now() - firstReplayStep, fields: fields }); } function applyCoupon() { $('.have_coupon_code').show(); $('.coupon_code_entry').hide(); var couponCode = $('.coupon_code').val(); // If you are reading the source, please use the "SOURCE" coupon to get as much off as any of the others here. var validCoupons = ['YEAR2018', 'TWOFORKS', 'INJECT', 'SOURCE', 'ALEK', '3OFF', 'TUBE', 'HACKERNEWS', 'ENTREPRENEUR', 'URBAN', 'BOND', 'ANSHIE', 'ARISU', 'ZOEY', 'CHIIKA', 'PHARAOH', 'SZU', 'IZABELA', 'WORLD', 'SARAH', 'BLACKNEO', 'MYCHAN', 'FUN', 'AANDK', 'MARACONT', 'WENDYLAND', 'LOWEN', 'JADE', 'FUINUR', 'HOLLY', 'CLARITA', 'AMBER', 'CORDEWA', 'MILLI', 'CRAFTY', 'MAI', 'GWENDY', 'SADIQ', 'FABIO', 'MIYU', 'REI', 'ZONA', 'NOMNOM', 'YUE', 'KYU', 'KAIGUYS']; var isValid = false; for (var i = 0; i < validCoupons.length; i++) { if (couponCode.toUpperCase().indexOf(validCoupons[i]) !== -1) { isValid = true; } } if (isValid) { $('.usdprice').text('$26'); $('input[name=a3]').val('26.00'); // Set PayPal price $('#coupon_code').val(couponCode); $('.coupon_applied').show(); $('.have_coupon_code').hide(); $('.coupon_line_item').show(); } else { alert("Sorry, that wasn't a valid coupon."); $('.coupon_code').val(''); } return false; } function initCouponFields() { $('.coupon_code_entry button').click(applyCoupon); $('.coupon_code_entry form').on('submit', applyCoupon); $('.have_coupon_code').click(function() { $('.have_coupon_code').hide(); $('.coupon_code_entry').show(); $('.coupon_code').focus(); }); }; function copyNameFromShippingToCard() { // If credit card name is empty but there is a name in shipping, use that by default var fieldsToCopy = ['.first_name_container', '.last_name_container']; fieldsToCopy.forEach(function (field) { var shipVal = $('#shipping_address ' + field + ' input').val(); var ccValSelector = '#credit_card_details ' + field + ' input'; if (shipVal && !$(ccValSelector).val()) { $(ccValSelector).val(shipVal); } }); } function initStripe() { stripe = Stripe('pk_live_Lh9RxfYBEjLco30J7VLUeGEP'); var elements = stripe.elements(); var style = { base: { iconColor: '#666ee8', color: '#31325f', fontWeight: 400, fontFamily: 'sans-serif', fontSmoothing: 'antialiased', lineHeight: '30px', fontSize: '18px', '::placeholder': { color: '#aab7c4', }, ':-webkit-autofill': { color: '#666ee8', }, }, }; card = elements.create('card', {style: style}); card.mount('#card_mount'); } $(function () { // Don't show CC form if PayPal selected $('input[name=billing_method]').change(showFieldsRelevantForBillingMethod); showFieldsRelevantForBillingMethod(); // Subscription attempt $('.subscribeSubmit2').click(function (event) { event.preventDefault(); submissionAttempted = true; // See if there are any errors var valid = checkForm(); if (!valid) { scrollToError(); return; } $('button').hide(); $('.activity').show(); if (isPayingByCreditCard()) { processCreditCardOrder(); } else { processPayPalOrder(); } }); // Show relevant errors if fields become invalid, but not on initial fill $('input,select').change(function () { copyNameFromShippingToCard(); if (submissionAttempted) { checkForm(); } }); $('input,select').on('input', recordReplayStep); // Order summary is in two places, let the left one be the defacto content $('.order_summary_container_bottom section').replaceWith($('.order_summary_container_left section').clone()); initCouponFields(); initStripe(); });