From 5f94cad8b122b5a2cfc55160cad18e1dcbaae4cf Mon Sep 17 00:00:00 2001 From: valzav <i@valzav.com> Date: Thu, 15 Sep 2016 18:14:33 -0400 Subject: [PATCH] work in progress --- app/assets/static/credit_card.js | 9 +- server/server_pages/credit_card_form.jsx | 279 +++++++++++--------- server/server_pages/enter_confirm_email.jsx | 10 +- 3 files changed, 161 insertions(+), 137 deletions(-) diff --git a/app/assets/static/credit_card.js b/app/assets/static/credit_card.js index eb387b387..d16d35cfa 100644 --- a/app/assets/static/credit_card.js +++ b/app/assets/static/credit_card.js @@ -9,6 +9,7 @@ $('#credit-card-form').on('submit', function(e){ event.preventDefault(); $('form-errors').hide(); Stripe.card.createToken({ + name: $('#card-holder-name').val(), number: $('#card-number').val(), cvc: $('#cvv').val(), exp_month: $('#expiry-month').val(), @@ -20,17 +21,11 @@ $('#credit-card-form').on('submit', function(e){ function stripeResponseHandler(status, response) { var $form = $('#credit-card-form'); if (response.error) { - // Show the errors on the form $('#form-errors').show(); $('#form-errors').html(response.error.message); $('#submit-btn').prop("disabled", false); } else { - // response contains id and card, which contains additional card details - var token = response.id; - // Insert the token into the form so it gets submitted to the server - $form.append($('<input type="hidden" name="stripeToken" />').val(token)); - // and submit - console.log($form.get(0)); + $form.append($('<input type="hidden" name="stripeToken" />').val(response.id)); $form.get(0).submit(); } } diff --git a/server/server_pages/credit_card_form.jsx b/server/server_pages/credit_card_form.jsx index 553091240..75d3c4dfd 100644 --- a/server/server_pages/credit_card_form.jsx +++ b/server/server_pages/credit_card_form.jsx @@ -15,12 +15,8 @@ import Iso from 'iso'; const stripe = Stripe(config.stripe.secret_key); -let assets; -if (process.env.NODE_ENV === 'production') { - assets = Object.assign({}, require('tmp/webpack-stats-prod.json'), {script: []}); -} else { - assets = Object.assign({}, require('tmp/webpack-stats-dev.json'), {script: []}); -} +const assets_file = process.env.NODE_ENV === 'production' ? 'tmp/webpack-stats-prod.json' : 'tmp/webpack-stats-dev.json'; +const assets = Object.assign({}, require(assets_file), {script: []}); assets.script.push('https://js.stripe.com/v2/'); assets.script.push('https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js'); assets.script.push('/static/credit_card.js'); @@ -40,6 +36,112 @@ const header = <header className="Header"> </div> </header>; +function renderPage(content) { + const body = renderToString(<div className="App"> + {header} + <br /> + <div className="row"> + {content} + </div> + </div>); + const props = { body: Iso.render(body, {stripe_key: config.stripe.publishable_key}), title: 'Credit Card Details', assets, meta: [] }; + return '<!DOCTYPE html>' + renderToString(<ServerHTML { ...props } />); +} + +function renderCreditCardForm(csrf, error) { + return <form className="column small-12 medium-10 large-7" id="credit-card-form" action="/credit_card" method="POST"> + <input type="hidden" name="csrf" value={csrf} /> + <div className="row"> + <div className="column"> + Please enter your credit card details below.<br /> + <span className="secondary">This information allows Steemit...</span> + </div> + </div> + <hr /> + <div className="row"> + <div className="small-3 columns"> + <label htmlFor="card-holder-name" className="text-right middle">Name on Card</label> + </div> + <div className="small-9 columns"> + <input type="text" name="card-holder-name" id="card-holder-name" placeholder="Card Holder's Name" /> + </div> + </div> + <div className="row"> + <div className="small-3 columns"> + <label htmlFor="card-number" className="text-right middle">Card Number</label> + </div> + <div className="small-9 columns"> + <input type="text" name="card-number" id="card-number" placeholder="Debit/Credit Card Number" /> + </div> + </div> + <div className="row"> + <div className="small-3 columns"> + <label htmlFor="expiry-month" className="text-right middle">Expiration Date</label> + </div> + <div className="small-5 columns"> + <select name="expiry-month" id="expiry-month"> + <option>Month</option> + <option value="01">Jan (01)</option> + <option value="02">Feb (02)</option> + <option value="03">Mar (03)</option> + <option value="04">Apr (04)</option> + <option value="05">May (05)</option> + <option value="06">June (06)</option> + <option value="07">July (07)</option> + <option value="08">Aug (08)</option> + <option value="09">Sep (09)</option> + <option value="10">Oct (10)</option> + <option value="11">Nov (11)</option> + <option value="12">Dec (12)</option> + </select> + </div> + <div className="small-4 columns"> + <select name="expiry-year" id="expiry-year"> + <option value="16">2016</option> + <option value="17">2017</option> + <option value="18">2018</option> + <option value="19">2019</option> + <option value="20">2020</option> + <option value="21">2021</option> + <option value="22">2022</option> + <option value="23">2023</option> + </select> + </div> + </div> + <div className="row"> + <div className="small-3 columns"> + <label htmlFor="cvv" className="text-right middle">Card CVV</label> + </div> + <div className="small-3 columns"> + <input type="text" name="cvv" id="cvv" placeholder="Security Code" /> + </div> + </div> + <div className="row"> + <div className="small-12 columns"> + <div id="form-errors" className="error">{error}</div> + </div> + </div> + <div className="row"> + <div className="small-12 columns"> + <input type="submit" id="submit-btn" className="button float-right" value="Pay and Continue" /> + </div> + </div> + </form>; +} + +function stripeCharge(card, amount) { + return new Promise((resolve, reject) => { + stripe.charges.create({card, currency: 'usd', amount}, + (err, charge) => { + if (err) { + reject(err); + } else { + resolve(charge); + } + } + ); + }); +} export default function useCreditCardForm(app) { const router = koa_router(); @@ -50,129 +152,60 @@ export default function useCreditCardForm(app) { console.log('-- /credit_card -->', this.session.uid, this.session.user); const user_id = this.session.user; if (!user_id) { this.body = 'user not found'; return; } - // const eid = yield models.Identity.findOne( - // {attributes: ['provider_user_id'], where: {user_id, provider: 'credit_card'}, order: 'id DESC'} - // ); - const body = renderToString(<div className="App"> - {header} - <br /> - <div className="row"> - <form className="column small-6" id="credit-card-form" action="/charge_credit_card" method="POST"> - <input type="hidden" name="csrf" value={this.csrf} /> - <div class="row"> - Please enter your credit card details below.<br /> - <span className="secondary">This information allows Steemit...</span> - </div> - <hr /> - <div className="row"> - <div className="small-3 columns"> - <label htmlFor="card-holder-name" className="text-right middle">Name on Card</label> - </div> - <div className="small-9 columns"> - <input type="text" name="card-holder-name" id="card-holder-name" placeholder="Card Holder's Name" /> - </div> - </div> - <div className="row"> - <div className="small-3 columns"> - <label htmlFor="card-number" className="text-right middle">Card Number</label> - </div> - <div className="small-9 columns"> - <input type="text" name="card-number" id="card-number" placeholder="Debit/Credit Card Number" /> - </div> - </div> - <div className="row"> - <div className="small-3 columns"> - <label htmlFor="expiry-month" className="text-right middle">Expiration Date</label> - </div> - <div className="small-5 columns"> - <select name="expiry-month" id="expiry-month"> - <option>Month</option> - <option value="01">Jan (01)</option> - <option value="02">Feb (02)</option> - <option value="03">Mar (03)</option> - <option value="04">Apr (04)</option> - <option value="05">May (05)</option> - <option value="06">June (06)</option> - <option value="07">July (07)</option> - <option value="08">Aug (08)</option> - <option value="09">Sep (09)</option> - <option value="10">Oct (10)</option> - <option value="11">Nov (11)</option> - <option value="12">Dec (12)</option> - </select> - </div> - <div className="small-4 columns"> - <select name="expiry-year" id="expiry-year"> - <option value="16">2016</option> - <option value="17">2017</option> - <option value="18">2018</option> - <option value="19">2019</option> - <option value="20">2020</option> - <option value="21">2021</option> - <option value="22">2022</option> - <option value="23">2023</option> - </select> - </div> - </div> - <div className="row"> - <div className="small-3 columns"> - <label htmlFor="cvv" className="text-right middle">Card CVV</label> - </div> - <div className="small-3 columns"> - <input type="text" name="cvv" id="cvv" placeholder="Security Code" /> - </div> - </div> - <div className="row"> - <div className="small-12 columns"> - <div id="form-errors" className="error">{this.flash.error}</div> - </div> - </div> - <div className="row"> - <div className="small-12 columns"> - <input type="submit" id="submit-btn" className="button float-right" value="Pay and Continue" /> - </div> - </div> - </form> - </div> - </div>); - const props = { body: Iso.render(body, {stripe_key: config.stripe.publishable_key}), title: 'Credit Card Details', assets, meta: [] }; - this.body = '<!DOCTYPE html>' + renderToString(<ServerHTML { ...props } />); + const cid = yield models.Identity.findOne( + {attributes: ['id'], where: {user_id, provider: 'credit_card'}} + ); + if (cid) { + const content = <div className="column"> + <p>We have determined that your you already used credit card verification.</p> + <a href="/create_account" className="button">Continue</a> + </div>; + this.body = renderPage(content); + return; + } + this.body = renderPage(renderCreditCardForm(this.csrf, '')); }); - router.post('/charge_credit_card', koaBody, function *() { - console.log('-- /charge_credit_card -->', this.request.body); + router.post('/credit_card', koaBody, function *() { if (!checkCSRF(this, this.request.body.csrf)) return; const user_id = this.session.user; if (!user_id) { this.body = 'user not found'; return; } - const stripeToken = this.request.body.stripeToken; - - stripe.charges.create({card: stripeToken, currency: 'usd', amount: 100}, - (err, charge) => { - if (err) { - console.log('---> charge error:', err); - // res.send('error'); - } else { - console.log('---> charge:', charge); - // res.send('success'); - } - } + let stripe_res; + try { + stripe_res = yield stripeCharge(this.request.body.stripeToken, 100); + } catch (err) { + console.log('---> charge error:', err); + this.body = renderPage(renderCreditCardForm(this.csrf, err.raw.message)); + return; + } + const card = stripe_res.card; + console.log('-- POST /credit_card -->', this.session.uid, this.session.user, card); + const cid = yield models.Identity.findOne( + {attributes: ['id'], where: {provider: 'credit_card', provider_user_id: card.fingerprint}} ); - // let eid = yield models.Identity.findOne( - // {attributes: ['id', 'email'], where: {user_id, provider: 'email'}, order: 'id'} - // ); - // if (eid) { - // yield eid.update({confirmation_code}); - // } else { - // eid = yield models.Identity.create({ - // provider: 'email', - // user_id, - // uid: this.session.uid, - // email, - // verified: false, - // confirmation_code - // }); - // } - this.body = 'ok'; + if (cid) { + const content = <div className="column"> + <p>This card was already used.</p> + <a href="/create_account" className="button">Continue</a> + </div>; + this.body = renderPage(content); + return; + } + yield models.Identity.create({ + provider: 'credit_card', + user_id, + uid: this.session.uid, + name: card.name, + provider_user_id: card.fingerprint, + verified: false, // is used here to determine if it was used to credit user's account + }); + + const content = <div className="column"> + <h4>Congratulations, your identity has been verified.</h4> + <p>Your account will be credited with $50 worth of SP.</p> + <a href="/create_account" className="button">Continue</a> + </div>; + this.body = renderPage(content); }); } diff --git a/server/server_pages/enter_confirm_email.jsx b/server/server_pages/enter_confirm_email.jsx index 964979ebc..442d0da56 100644 --- a/server/server_pages/enter_confirm_email.jsx +++ b/server/server_pages/enter_confirm_email.jsx @@ -11,13 +11,9 @@ import sendEmail from '../sendEmail'; import {checkCSRF} from '../utils'; import config from '../../config'; -let assets; -if (process.env.NODE_ENV === 'production') { - assets = Object.assign({}, require('tmp/webpack-stats-prod.json'), {script: ['https://www.google.com/recaptcha/api.js']}); -} else { - assets = Object.assign({}, require('tmp/webpack-stats-dev.json')); - assets.script.push('https://www.google.com/recaptcha/api.js'); -} +const assets_file = process.env.NODE_ENV === 'production' ? 'tmp/webpack-stats-prod.json' : 'tmp/webpack-stats-dev.json'; +const assets = Object.assign({}, require(assets_file), {script: []}); +assets.script.push('https://www.google.com/recaptcha/api.js'); const header = <header className="Header"> <div className="Header__top header"> -- GitLab