Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Commit

Permalink
split out identity verification from bank account connecting
Browse files Browse the repository at this point in the history
closes #987
  • Loading branch information
Changaco committed Mar 16, 2015
1 parent c56506d commit 3dde58b
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 129 deletions.
2 changes: 2 additions & 0 deletions gratipay/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
# This is shared via class inheritance with jinja2_htmlescaped.
'b64encode': base64.b64encode,
'enumerate': enumerate,
'filter': filter,
'filter_profile_subnav': utils.filter_profile_subnav,
'float': float,
'len': len,
'map': map,
'range': range,
'str': str,
'to_javascript': utils.to_javascript,
Expand Down
18 changes: 0 additions & 18 deletions js/gratipay/payments.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,31 +91,13 @@ Gratipay.payments.ba.submit = function (e) {
routing_number: $('#routing_number').val()
};

Gratipay.payments.ba.merchantData = {
//type: 'person', // Oooh, may need to vary this some day?
street_address: $('#address_1').val(),
postal_code: $('#zip').val(),
phone_number: $('#phone_number').val(),
region: $('#state').val(),
dob_month: $('#dob-month').val(),
dob_year: $('#dob-year').val(),
dob_day: $('#dob-day').val(),
name: $('#name').val()
};
var errors = [];


// Require some fields.
// ====================
// We only require fields that are actually on the page. Since we don't
// load the identity verification fields if they're already verified, not
// all of these will necessarily be present at all.

var requiredFields = {
name: 'Your legal name is required.',
address_1: 'Your street address is required.',
zip: 'Your ZIP or postal code is required.',
phone_number: 'A phone number is required.',
account_name: 'The name on your bank account is required.',
account_number: 'Your bank account number is required.',
routing_number: 'A routing number is required.'
Expand Down
145 changes: 145 additions & 0 deletions www/%username/identity.spt
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import balanced

from gratipay.billing.exchanges import repr_exception
from gratipay.utils import get_participant

[---]
request.allow('GET', 'POST')
participant = get_participant(state, restrict=True)
title = _("Identity Verification")
error = ''

if request.method == 'POST':
account = participant.get_balanced_account()

body = request.body
account.name = body.get('name')
account.address['line1'] = body.get('address_1')
account.address['line2'] = body.get('address_2')
account.address['postal_code'] = body.get('postal_code')
account.address['city'] = body.get('city')
account.address['state'] = body.get('region')
account.address['country_code'] = body.get('country')
account.phone = body.get('phone_number')
account.ssn_last4 = body.get('ssn_last4') or None

dob = body.get('dob', '')
if dob:
try:
account.dob_year, account.dob_month, account.meta['dob_day'] = \
map(int, dob.split('-'))
except ValueError:
error = _("Invalid date of birth.")

if not error:
# This will possibly fail with 400 if formatted badly, or 300 if we
# cannot identify the merchant.
try:
account.save()
except balanced.exc.HTTPError as err:
error = repr_exception(err)
else:
if account.merchant_status != 'underwritten':
error = _("Unable to verify your identity")

elif participant.balanced_customer_href:
account = participant.get_balanced_account()

else:
account = balanced.Customer()

[---] text/html
{% extends "templates/base.html" %}

{% block scripts %}
{{ super() }}
<script>
$(document).ready(function(){
$('select[name="country"]').chosen();
{% if error %}
Gratipay.notification({{ to_javascript(error)|safe }}, 'error', -1);
{% endif %}
});
</script>
{% endblock %}

{% block content %}

<div class="cc-ba">
<form action="" method="POST" autocomplete="off">

<input type="hidden" name="csrf_token" value="{{ csrf_token }}" />

<label>
<span>{{ _("Your Legal Name") }}</span>
<input name="name" value="{{ account.name or '' }}" required />
</label>

<div class="clear"></div>

<label>
<span>{{ _("Address") }}</span>
<input name="address_1" value="{{ account.address.line1 or '' }}" required />
</label>

<label>
<span>{{ _("Address (second line)") }}</span>
<input name="address_2" value="{{ account.address.line2 or '' }}" />
</label>

<label>
<span>{{ _("City") }}</span>
<input name="city" value="{{ account.address.city or '' }}" />
</label>

<label class="half left">
<span>{{ _("State or Province") }}</span>
<input name="region" value="{{ account.address.state or '' }}" />
</label>

<label class="half right">
<span>{{ _("ZIP or Postal Code") }}</span>
<input name="postal_code" value="{{ account.address.postal_code or '' }}" required />
</label>

<div class="clear"></div>

<label>
<span>{{ _("Country") }} (<a href="/about/faq.html#how-withdraw-funds">{{ _("non-US?") }}</a>)</span>
<select name="country" disabled>
{% for each in locale.countries.items() %}
<option value="{{ each[0] }}" {{ 'selected' if each[0] == 'US' }}>{{ each[1] }}</option>
{% endfor %}
</select>
</label>

<label>
<span>{{ _("Contact Phone Number") }}</span>
<input name="phone_number" value="{{ account.phone or '' }}" required />
</label>

<label class="left">
<span>{{ _("Date of Birth") }}</span>
{% set dob = [account.dob_year, account.dob_month, account.meta.dob_day] %}
{% set dob = '-'.join(map(str, filter(none, dob))) %}
<input name="dob" value="{{ dob }}" pattern="[1-2][0-9]{3}-[0-9]{1,2}-[0-9]{1,2}"
placeholder="{{ _('YYYY-MM-DD') }}" title="{{ _('YYYY-MM-DD') }}"
required />
</label>

<div class="clear"></div>

<label class="half left">
<span>{{ _("Last four SSN digits") }} {{ _("(Not required)") }}</span>
<input name="ssn_last4" value="{{ account.ssn_last4 or '' }}" />
</label>

<div class="clear"></div>
<br/>

<button class="selected larger" type="submit">{{ _("Save") }}</button>

</form>
</div>

{% endblock %}
98 changes: 11 additions & 87 deletions www/bank-account.html.spt
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from datetime import datetime

from gratipay import billing, MONTHS
from gratipay import billing
from gratipay.billing.exchanges import MINIMUM_CREDIT

[-----------------------------------------------------------------------------]
Expand All @@ -10,8 +8,9 @@ bank_account = None
status = ". . ."

if not user.ANON:
balanced_customer_href = user.participant.balanced_customer_href
last_ach_result = user.participant.last_ach_result
participant = user.participant
balanced_customer_href = participant.balanced_customer_href
last_ach_result = participant.last_ach_result

status = _("Your bank account is {0}not connected{1}")
if balanced_customer_href:
Expand All @@ -21,8 +20,6 @@ if not user.ANON:
account = participant.get_balanced_account()
bank_account = billing.BalancedBankAccount(balanced_customer_href)

username = user.participant.username

title = _("Bank Account")
[-----------------------------------------------------------------------------]
{% extends "templates/base.html" %}
Expand Down Expand Up @@ -76,90 +73,11 @@ title = _("Bank Account")
{% endif %}
</style>
<div class="cc-ba">
{% if account and account.merchant_status == 'underwritten' %}
<form id="bank-account" autocomplete="off">
<div class="constrain-width clearfix">

{% if account and 'merchant' in account.roles %}
<h2>{{ _("Identity Verification") }} &nbsp; <span>&#x2714;</span></h2>
<h2>{{ _("Routing Information") }}</h2>
{% endif %}


{% if not account or 'merchant' not in account.roles %}
<h2>{{ _("Identity Verification") }}</h2>

<div>
<label for="name">{{ _("Your Legal Name") }}</label>
<input id="name" value="" />
</div>

<div class="clear"></div>

<div>
<label for="address_1">{{ _("Street Address") }}</label>
<input id="address_1" value="" />
</div>

<div>
<label for="city">{{ _("City") }}</label>
<input id="city" value="" />
</div>

<div class="half left">
<label for="state">{{ _("State or Province") }}</label>
<input id="state" value="" />
</div>

<div class="half right">
<label for="zip">{{ _("ZIP or Postal Code") }}</label>
<input id="zip" value="" />
</div>

<div class="clear"></div>

<div>
<label for="country">{{ _("Country") }} (<a href="/about/faq.html#how-withdraw-funds">{{ _("non-US?") }}</a>)</label>
<input id="country" value="{{ locale.countries['US'] }}" disabled="true"
class="disabled" />
</div>

<div>
<label for="phone_number">{{ _("Contact Phone Number") }}</label>
<input id="phone_number" value="" />
</div>

<div class="left">
<label for="dob-year">{{ _("Date of Birth") }}</label>
<select id="dob-month">
{% for i in range(1, 13) %}
<option value="{{ i }}">{{ MONTHS[i] }}</option>
{% endfor %}
</select>
<select id="dob-day">
{% for i in range(1, 32) %}
<option value="{{ i }}">{{ i }}</option>
{% endfor %}
</select>
<select id="dob-year">
{% for i in range(1900, datetime.utcnow().year - 17) %}
<option value="{{ i }}" {{ 'selected="selected"' if i == 1990 else '' }}>{{ i }}</option>
{% endfor %}
</select>
</div>

<div class="clear"></div>

<div class="half left">
<label for="ssn_last4">{{ _("Last four SSN digits") }} {{ _("(Not required)") }}</label>
<input id="ssn_last4" value="" />
</div>

<div class="clear"></div>


<h2>{{ _("Routing Information") }}</h2>
{% endif %}


<div class="float">
<label for="account_name">{{ _("Name on Bank Account") }}</label>
Expand All @@ -180,8 +98,14 @@ title = _("Bank Account")
</div>

<button class="selected larger" id="save" type="submit">{{ _("Save") }}</button>

</form>

{% else %}
<p><a href="/{{ participant.username }}/identity">{{
_("You need to verify your identity first")
}}</a></p>
{% endif %}

{% if bank_account and bank_account.is_setup %}
<div id="delete">
Expand Down
26 changes: 2 additions & 24 deletions www/bank-account.json.spt
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,11 @@ else:
balanced_account = participant.get_balanced_account()


# Ensure the user is a merchant.
# Ensure the user is identified.
# ==============================
# This will possibly fail with 400 if formatted badly, or 300 if we cannot
# identify the merchant.

out = {}
if balanced_account.merchant_status != 'underwritten':

balanced_account.name = body.get('name')
balanced_account.address['line1'] = body.get('street_address')
balanced_account.address['postal_code'] = body.get('postal_code')
balanced_account.address['state'] = body.get('region')
balanced_account.phone = body.get('phone_number')
balanced_account.dob_month = body.get('dob_month')
balanced_account.dob_year = body.get('dob_year')
balanced_account.meta['dob_day'] = body.get('dob_day')
balanced_account.ssn_last4 = body.get('ssn_last4')

try:
balanced_account.save()
except balanced.exc.HTTPError as err:
out = {"problem": "Problem", "error": err.message}

if balanced_account.merchant_status != 'underwritten':
out = { 'problem': 'More Info Needed'
, 'error': 'Unable to verify your identity'
}
out = {'problem': _("You need to verify your identity first.")}


# No errors? Great! Let's add the bank account.
Expand Down

0 comments on commit 3dde58b

Please sign in to comment.