Created
April 20, 2016 22:09
-
-
Save ewilliam/caf20f5117331b4c1c02d5130be1e85a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BankAccountForm | |
include Virtus.model | |
include ActiveModel::Model | |
attribute :country, String | |
attribute :routing_number, String | |
attribute :account_number, String | |
attribute :first_name, String | |
attribute :last_name, String | |
attribute :dob, Hash[String => String] | |
attribute :ssn_last4, String | |
attribute :personal_id_number, String | |
attribute :identity_document | |
attribute :line1, String | |
attribute :line2, String | |
attribute :locality, String | |
attribute :region, String | |
attribute :postcode, String | |
attribute :stripe_token, String | |
attribute :wallet_id, Integer | |
attr_reader :bank_account | |
validates_presence_of :first_name, :last_name, :line1, :dob, | |
:locality, :region, :postcode | |
def save | |
if valid? | |
persist! | |
update_stripe_account | |
end | |
end | |
def wallet | |
@wallet ||= Wallet.find(wallet_id) | |
end | |
private | |
def persist! | |
return true if account.external_accounts.empty? | |
ActiveRecord::Base.transaction do | |
@bank_account = BankAccount.find_or_create_by( | |
payment_entity_id: account.external_accounts.first.id | |
) | |
@bank_account.update_attributes( | |
first_name: first_name, | |
last_name: last_name, | |
last4: account.external_accounts.first.last4, | |
brand: account.external_accounts.first.bank_name, | |
wallet_id: wallet.id, | |
) | |
address = Address.find_or_create_by( | |
addressable_id: @bank_account.id, | |
addressable_type: @bank_account.class.name | |
) | |
address.update_attributes( | |
line1: line1, | |
line2: line2, | |
locality: locality, | |
region: region, | |
postcode: postcode, | |
country: "US" | |
) | |
end | |
end | |
def update_stripe_account | |
StripeManagedService.new(wallet).update_account!(params: { | |
legal_entity: { | |
first_name: first_name, | |
last_name: last_name, | |
dob: dob, | |
ssn_last_4: ssn_last4, | |
personal_id_number: personal_id_number, | |
verification: { | |
document: identity_document, | |
}, | |
address: { | |
line1: line1, | |
line2: line2, | |
city: locality, | |
state: region, | |
postal_code: postcode | |
} | |
}, | |
stripe_token: stripe_token | |
}) | |
end | |
def account | |
@account ||= Stripe::Account.retrieve(wallet.payment_entity_id) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BankAccountsController < ApplicationController | |
before_action :authenticate_user! | |
before_action :set_bank_account, only: [:edit, :update] | |
before_action :set_wallet, only: [:new, :create, :edit, :update] | |
def new | |
if current_user.merchant_account.bank_account.blank? | |
@bank_account_form = BankAccountForm.new | |
else | |
redirect_to "/settings/wallet", alert: "You already have a bank account." | |
end | |
end | |
def create | |
params[:bank_account_form][:stripe_token] = params[:stripe_token] | |
@bank_account_form = BankAccountForm.new(bank_account_form_params) | |
if @bank_account_form.save | |
return redirect_to "/settings/wallet", notice: "Bank account added." | |
end | |
render :new | |
end | |
def edit | |
authorize @bank_account | |
@bank_account_form = BankAccountForm.new | |
end | |
def update | |
authorize @bank_account | |
@bank_account_form = BankAccountForm.new(bank_account_form_params) | |
if @bank_account_form.save | |
return redirect_to "/settings/wallet/", notice: "Bank account updated." | |
end | |
flash.now.alert = @bank_account_form.wallet.errors.full_messages | |
render :edit | |
end | |
private | |
def bank_account_form_params | |
params.require(:bank_account_form).permit( | |
:country, | |
:routing_number, | |
:account_number, | |
:first_name, | |
:last_name, | |
:ssn_last4, | |
:personal_id_number, | |
:identity_document, | |
:line1, | |
:line2, | |
:locality, | |
:region, | |
:postcode, | |
:stripe_token, | |
:wallet_id, | |
dob: ["dob(1i)", "dob(2i)", "dob(3i)"] | |
) | |
end | |
def set_bank_account | |
@bank_account = BankAccount.find(params[:id]) | |
end | |
def set_wallet | |
@wallet = current_user.merchant_account | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class StripeManagedService < Struct.new(:wallet) | |
ALLOWED = ['US', 'CA'] # public beta | |
COUNTRIES = [ | |
{ name: 'United States', code: 'US' }, | |
{ name: 'Canada', code: 'CA' }, | |
{ name: 'Australia', code: 'AU' }, | |
{ name: 'United Kingdom', code: 'GB' }, | |
{ name: 'Ireland', code: 'IE' } | |
] | |
def create_account!(country, tos_accepted, ip) | |
return nil unless tos_accepted | |
return nil unless country.in?(COUNTRIES.map { |c| c[:code] }) | |
unless wallet.user.merchant_account.nil? | |
Rails.logger.error "Account Error: User attempted to create extra merchant account." | |
wallet.errors.add :base, "You already have a seller account." | |
return false | |
end | |
begin | |
@account = Stripe::Account.create( | |
managed: true, | |
country: country, | |
email: wallet.user.email, | |
tos_acceptance: { | |
ip: ip, | |
date: Time.now.to_i | |
}, | |
legal_entity: { | |
type: 'individual', | |
} | |
) | |
rescue => e | |
Rails.logger.error "Error: " + e.message | |
wallet.errors.add :base, "Something went wrong. Please try again!" | |
return false | |
end | |
if @account | |
wallet.update_attributes( | |
currency: @account.default_currency, | |
wallet_type_id: 2, | |
payment_entity_id: @account.id, | |
payment_service_id: 1, | |
# secret_key: @account.keys.secret, | |
# publishable_key: @account.keys.publishable, | |
account_status: account_status | |
) | |
end | |
@account | |
end | |
def update_account!(params: nil) | |
if params | |
if params[:stripe_token] | |
account.bank_account = params[:stripe_token] | |
account.save | |
end | |
if params[:legal_entity] | |
# clean up dob fields | |
params[:legal_entity][:dob] = { | |
year: params[:legal_entity][:dob].delete('dob(1i)'), | |
month: params[:legal_entity][:dob].delete('dob(2i)'), | |
day: params[:legal_entity][:dob].delete('dob(3i)') | |
} | |
if params[:legal_entity][:verification][:document] | |
# upload file to Stripe for a token | |
id_doc = Stripe::FileUpload.create( | |
purpose: "identity_document", | |
file: params[:legal_entity][:verification][:document] | |
) | |
# attach file id to account | |
params[:legal_entity][:verification][:document] = id_doc.id | |
end | |
# update legal_entity hash from the params | |
params[:legal_entity].entries.each do |key, value| | |
if [ :address, :dob, :verification ].include? key.to_sym | |
value.entries.each do |akey, avalue| | |
next if avalue.blank? | |
# Rails.logger.error "#{akey} - #{avalue.inspect}" | |
account.legal_entity[key] ||= {} | |
account.legal_entity[key][akey] = avalue | |
end | |
else | |
next if value.blank? | |
# Rails.logger.error "#{key} - #{value.inspect}" | |
account.legal_entity[key] = value | |
end | |
end | |
# copy 'address' as 'personal_address' | |
pa = account.legal_entity['address'].dup.to_h | |
account.legal_entity['personal_address'] = pa | |
account.save | |
end | |
end | |
wallet.update_attributes( | |
account_status: account_status | |
) | |
rescue => e | |
Rails.logger.error "Error: " + e.message | |
wallet.errors.add :base, "Something went wrong. Please try again!" | |
return false | |
end | |
def legal_entity | |
account.legal_entity | |
end | |
def needs?(field) | |
wallet.account_status['fields_needed'].grep( Regexp.new( /#{field}/i ) ).any? | |
end | |
def supported_bank_account_countries | |
country_codes = case account.country | |
when 'US' then %w{ US } | |
when 'CA' then %w{ US CA } | |
when 'IE', 'UK' then %w{ IE UK US } | |
when 'AU' then %w{ AU } | |
end | |
COUNTRIES.select do |country| | |
country[:code].in? country_codes | |
end | |
end | |
protected | |
def account_status | |
{ | |
details_submitted: account.details_submitted, | |
charges_enabled: account.charges_enabled, | |
transfers_enabled: account.transfers_enabled, | |
fields_needed: account.verification.fields_needed, | |
due_by: account.verification.due_by | |
} | |
end | |
def account | |
@account ||= Stripe::Account.retrieve(wallet.payment_entity_id) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment