bank account payment method for orgs

This commit is contained in:
Kyle Spearrin 2017-08-14 10:21:08 -04:00
parent 4749a3da89
commit 226c201925
13 changed files with 587 additions and 342 deletions

View File

@ -6,11 +6,30 @@
$analytics.eventTrack('organizationBillingChangePaymentController', { category: 'Modal' });
$scope.existingPaymentMethod = existingPaymentMethod;
$scope.paymentMethod = 'card';
$scope.showPaymentOptions = false;
$scope.showPaymentOptions = true;
$scope.hidePaypal = true;
$scope.card = {};
$scope.bank = {};
$scope.changePaymentMethod = function (val) {
$scope.paymentMethod = val;
};
$scope.submit = function () {
$scope.submitPromise = stripe.card.createToken($scope.card).then(function (response) {
var stripeReq = null;
if ($scope.paymentMethod === 'card') {
stripeReq = stripe.card.createToken($scope.card);
}
else if ($scope.paymentMethod === 'bank') {
$scope.bank.currency = 'USD';
$scope.bank.country = 'US';
stripeReq = stripe.bankAccount.createToken($scope.bank);
}
else {
return;
}
$scope.submitPromise = stripeReq.then(function (response) {
var request = {
paymentToken: response.id
};

View File

@ -80,6 +80,18 @@
});
};
$scope.verifyBank = function () {
var modal = $uibModal.open({
animation: true,
templateUrl: 'app/organization/views/organizationBillingVerifyBank.html',
controller: 'organizationBillingVerifyBankController'
});
modal.result.then(function () {
load();
});
};
$scope.cancel = function () {
if (!confirm('Are you sure you want to cancel? All users will lose access to the organization ' +
'at the end of this billing cycle.')) {
@ -167,7 +179,8 @@
$scope.paymentSource = {
type: org.PaymentSource.Type,
description: org.PaymentSource.Description,
cardBrand: org.PaymentSource.CardBrand
cardBrand: org.PaymentSource.CardBrand,
needsVerification: org.PaymentSource.NeedsVerification
};
}

View File

@ -0,0 +1,25 @@
angular
.module('bit.organization')
.controller('organizationBillingVerifyBankController', function ($scope, $state, $uibModalInstance, apiService,
$analytics, toastr) {
$analytics.eventTrack('organizationBillingVerifyBankController', { category: 'Modal' });
$scope.submit = function () {
var request = {
amount1: $scope.amount1,
amount2: $scope.amount2
};
$scope.submitPromise = apiService.organizations.postVerifyBank({ id: $state.params.orgId }, request)
.$promise.then(function (response) {
$analytics.eventTrack('Verified Bank Account');
toastr.success('You have successfully verified your bank account.');
$uibModalInstance.close();
});
};
$scope.close = function () {
$uibModalInstance.dismiss('cancel');
};
});

View File

@ -140,6 +140,15 @@
<i class="fa fa-credit-card"></i> No payment method on file.
</div>
<div ng-show="!loading && paymentSource">
<div class="callout callout-warning" ng-if="paymentSource.type === 1 && paymentSource.needsVerification">
<h4><i class="fa fa-warning"></i> You must verify your bank account</h4>
<p>
We have made two micro-deposits to your bank account (it may take 1-2 business days to show up).
Enter these amounts to verify the bank account. Failure to verify the bank account will result in a
missed payment and your organization being disabled.
</p>
<button class="btn btn-default btn-flat" ng-click="verifyBank()">Verify Now</button>
</div>
<i class="fa" ng-class="{'fa-credit-card': paymentSource.type === 0,
'fa-university': paymentSource.type === 1, 'fa-paypal fa-fw text-blue': paymentSource.type === 2}"></i>
{{paymentSource.description}}

View File

@ -0,0 +1,43 @@
<div class="modal-header">
<button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">
<i class="fa fa-check-square-o"></i>
Verify Bank Account
</h4>
</div>
<form name="form" ng-submit="form.$valid && submit()" api-form="submitPromise">
<div class="modal-body">
<p>
Enter the two micro-deposit amounts from your bank account. Both amounts will be less than $1.00 each.
For example, if we deposited $0.32 and $0.45 you would enter the values "32" and "45".
</p>
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in form.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group">
<label for="amount1">Amount 1</label>
<div class="input-group">
<span class="input-group-addon">$ 0.</span>
<input type="number" id="amount1" name="Amount1" ng-model="amount1" class="form-control"
required min="1" max="99" placeholder="xx" />
</div>
</div>
<div class="form-group">
<label for="amount2">Amount 2</label>
<div class="input-group">
<span class="input-group-addon">$ 0.</span>
<input type="number" id="amount2" name="Amount2" ng-model="amount2" class="form-control"
required min="1" max="99" placeholder="xx" />
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="form.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="form.$loading"></i>Submit
</button>
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
</div>
</form>

View File

@ -69,6 +69,7 @@
putCancel: { url: _apiUri + '/organizations/:id/cancel', method: 'POST', params: { id: '@id' } },
putReinstate: { url: _apiUri + '/organizations/:id/reinstate', method: 'POST', params: { id: '@id' } },
postLeave: { url: _apiUri + '/organizations/:id/leave', method: 'POST', params: { id: '@id' } },
postVerifyBank: { url: _apiUri + '/organizations/:id/verify-bank', method: 'POST', params: { id: '@id' } },
del: { url: _apiUri + '/organizations/:id/delete', method: 'POST', params: { id: '@id' } }
});

View File

@ -8,6 +8,7 @@
$scope.paymentMethod = 'card';
$scope.dropinLoaded = false;
$scope.showPaymentOptions = false;
$scope.hideBank = true;
$scope.card = {};
var btInstance = null;

View File

@ -5,6 +5,7 @@
toastr, $analytics, authService, stripe, constants) {
$scope.plans = constants.plans;
$scope.storageGb = constants.storageGb;
$scope.paymentMethod = 'card';
$scope.model = {
plan: 'free',
@ -27,6 +28,10 @@
}
};
$scope.changePaymentMethod = function (val) {
$scope.paymentMethod = val;
};
$scope.changedPlan = function () {
if ($scope.plans[$scope.model.plan].hasOwnProperty('monthPlanType')) {
$scope.model.interval = 'year';
@ -61,7 +66,20 @@
$scope.submitPromise = apiService.organizations.post(freeRequest).$promise.then(finalizeCreate);
}
else {
$scope.submitPromise = stripe.card.createToken(model.card).then(function (response) {
var stripeReq = null;
if ($scope.paymentMethod === 'card') {
stripeReq = stripe.card.createToken(model.card);
}
else if ($scope.paymentMethod === 'bank') {
model.bank.currency = 'USD';
model.bank.country = 'US';
stripeReq = stripe.bankAccount.createToken(model.bank);
}
else {
return;
}
$scope.submitPromise = stripeReq.then(function (response) {
var paidRequest = {
name: model.name,
planType: model.interval === 'month' ? $scope.plans[model.plan].monthPlanType :

View File

@ -21,7 +21,8 @@
additionalStorageGb: null
};
$scope.changePaymentMethod = function () {
$scope.changePaymentMethod = function (val) {
$scope.paymentMethod = val;
if ($scope.paymentMethod !== 'paypal') {
return;
}

View File

@ -14,19 +14,72 @@
</ul>
</div>
<div ng-if="showPaymentOptions">
<label class="radio-inline radio-boxed">
<label class="radio-inline radio-boxed" ng-show="!hideCard">
<input type="radio" name="PaymentMethod" value="card" ng-model="paymentMethod"
ng-change="changePaymentMethod('card')"><i class="fa fa-fw fa-credit-card"></i> Credit Card
</label>
<label class="radio-inline radio-boxed">
<label class="radio-inline radio-boxed" ng-show="!hidePaypal">
<input type="radio" name="PaymentMethod" value="paypal" ng-model="paymentMethod"
ng-change="changePaymentMethod('paypal')"><i class="fa fa-fw fa-paypal"></i> PayPal
</label>
<label class="radio-inline radio-boxed" ng-show="!hideBank">
<input type="radio" name="PaymentMethod" value="bank" ng-model="paymentMethod"
ng-change="changePaymentMethod('bank')"><i class="fa fa-fw fa-bank"></i>
Bank<span class="hidden-xs"> Account (ACH)</span>
</label>
<hr />
</div>
<div ng-if="paymentMethod === 'paypal'">
<div id="bt-dropin-container"></div>
</div>
<div ng-if="paymentMethod === 'bank'">
<div class="callout callout-warning">
<h4><i class="fa fa-warning"></i> You must verify your bank account</h4>
<p>
Payment with a bank account is <u>only available to customers in the United States</u>.
You will be required to verify your bank account. We will make two micro-deposits within the next
1-2 business days. Enter these amounts in the organization's billing area to verify the bank account.
Failure to verify the bank account will result in a missed payment and your organization being
disabled.
</p>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="routing_number">Routing Number</label>
<input type="text" id="routing_number" name="routing_number"
ng-model="bank.routing_number" class="form-control" required />
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="account_number">Account Number</label>
<input type="text" id="account_number" name="account_number"
ng-model="bank.account_number" class="form-control" required />
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="account_holder_name">Account Holder Name</label>
<input type="text" id="account_holder_name" name="account_holder_name"
ng-model="bank.account_holder_name" class="form-control" required />
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="account_holder_type">Account Type</label>
<select id="account_holder_type" class="form-control" name="account_holder_type"
ng-model="bank.account_holder_type" required>
<option value="">-- Select --</option>
<option value="company">Company (Business)</option>
<option value="individual">Individual (Personal)</option>
</select>
</div>
</div>
</div>
</div>
<div ng-if="paymentMethod === 'card'">
<div class="row">
<div class="col-md-6">

View File

@ -256,12 +256,72 @@
<h3 class="box-title">Payment Information</h3>
</div>
<div class="box-body">
<label class="radio-inline radio-lg radio-boxed">
<input type="radio" name="PaymentMethod" value="card" ng-model="paymentMethod"
ng-change="changePaymentMethod('card')">
<i class="fa fa-fw fa-credit-card"></i> Credit Card
</label>
<label class="radio-inline radio-lg radio-boxed">
<input type="radio" name="PaymentMethod" value="bank" ng-model="paymentMethod"
ng-change="changePaymentMethod('bank')">
<i class="fa fa-fw fa-bank"></i> Bank<span class="hidden-xs"> Account (ACH)</span>
</label>
<hr />
<div ng-if="paymentMethod === 'bank'">
<div class="callout callout-warning">
<h4><i class="fa fa-warning"></i> You must verify your bank account</h4>
<p>
Payment with a bank account is <u>only available to customers in the United States</u>.
You will be required to verify your bank account. We will make two micro-deposits within the next
1-2 business days. Enter these amounts in the organization's billing area to verify the bank account.
Failure to verify the bank account will result in a missed payment and your organization being
disabled.
</p>
</div>
<div class="row">
<div class="col-lg-5 col-sm-6">
<div class="form-group">
<label for="routing_number">Routing Number</label>
<input type="text" id="routing_number" name="routing_number"
ng-model="model.bank.routing_number" class="form-control" required />
</div>
</div>
<div class="col-lg-5 col-sm-6">
<div class="form-group">
<label for="account_number">Account Number</label>
<input type="text" id="account_number" name="account_number"
ng-model="model.bank.account_number" class="form-control" required />
</div>
</div>
</div>
<div class="row">
<div class="col-lg-5 col-sm-6">
<div class="form-group">
<label for="account_holder_name">Account Holder Name</label>
<input type="text" id="account_holder_name" name="account_holder_name"
ng-model="model.bank.account_holder_name" class="form-control" required />
</div>
</div>
<div class="col-lg-5 col-sm-6">
<div class="form-group">
<label for="account_holder_type">Account Type</label>
<select id="account_holder_type" class="form-control" name="account_holder_type"
ng-model="model.bank.account_holder_type" required>
<option value="">-- Select --</option>
<option value="company">Company (Business)</option>
<option value="individual">Individual (Personal)</option>
</select>
</div>
</div>
</div>
</div>
<div ng-if="paymentMethod === 'card'">
<div class="row">
<div class="col-md-5">
<div class="form-group" show-errors>
<label for="card_number">Card Number</label>
<input type="text" id="card_number" name="card_number" ng-model="model.card.number"
class="form-control" cc-number required api-field />
class="form-control" cc-number required api-field autocomplete="cc-number" />
</div>
</div>
<div class="col-md-7">
@ -281,7 +341,7 @@
<div class="form-group" show-errors>
<label for="exp_month">Expiration Month</label>
<select id="exp_month" class="form-control" ng-model="model.card.exp_month" required cc-exp-month
name="exp_month" api-field>
name="exp_month" api-field autocomplete="cc-exp-month">
<option value="">-- Select --</option>
<option value="01">01 - January</option>
<option value="02">02 - February</option>
@ -302,7 +362,7 @@
<div class="form-group" show-errors>
<label for="exp_year">Expiration Year</label>
<select id="exp_year" class="form-control" ng-model="model.card.exp_year" required cc-exp-year
name="exp_year" api-field>
name="exp_year" api-field autocomplete="cc-exp-year">
<option value="">-- Select --</option>
<option value="17">2017</option>
<option value="18">2018</option>
@ -327,7 +387,7 @@
</a>
</label>
<input type="text" id="cvc" ng-model="model.card.cvc" class="form-control" name="cvc"
cc-type="number.$ccType" cc-cvc required api-field />
cc-type="number.$ccType" cc-cvc required api-field autocomplete="cc-csc" />
</div>
</div>
</div>
@ -336,7 +396,7 @@
<div class="form-group" show-errors>
<label for="address_country">Country</label>
<select id="address_country" class="form-control" ng-model="model.card.address_country"
required name="address_country" api-field>
required name="address_country" api-field autocomplete="country">
<option value="">-- Select --</option>
<option value="US">United States</option>
<option value="CN">China</option>
@ -596,7 +656,8 @@
<label for="address_zip"
ng-bind="model.card.address_country === 'US' ? 'Zip Code' : 'Postal Code'"></label>
<input type="text" id="address_zip" ng-model="model.card.address_zip"
class="form-control" required name="address_zip" api-field />
class="form-control" required name="address_zip" api-field autocomplete="postal-code" />
</div>
</div>
</div>
</div>

View File

@ -114,11 +114,11 @@
<div class="box-body">
<label class="radio-inline radio-lg radio-boxed">
<input type="radio" name="PaymentMethod" value="card" ng-model="paymentMethod"
ng-change="changePaymentMethod()"><i class="fa fa-fw fa-credit-card"></i> Credit Card
ng-change="changePaymentMethod('card')"><i class="fa fa-fw fa-credit-card"></i> Credit Card
</label>
<label class="radio-inline radio-lg radio-boxed">
<input type="radio" name="PaymentMethod" value="paypal" ng-model="paymentMethod"
ng-change="changePaymentMethod()"><i class="fa fa-fw fa-paypal"></i> PayPal
ng-change="changePaymentMethod('paypal')"><i class="fa fa-fw fa-paypal"></i> PayPal
</label>
<hr />
<div ng-if="paymentMethod === 'paypal'">

View File

@ -204,6 +204,7 @@
<script src="app/organization/organizationBillingAdjustStorageController.js"></script>
<script src="app/organization/organizationDeleteController.js"></script>
<script src="app/organization/organizationBillingChangePlanController.js"></script>
<script src="app/organization/organizationBillingVerifyBankController.js"></script>
<script src="app/organization/organizationVaultController.js"></script>
<script src="app/organization/organizationVaultAddLoginController.js"></script>
<script src="app/organization/organizationVaultEditLoginController.js"></script>