Add WePay configuration UI

This commit is contained in:
Joshua Dwire 2016-05-11 22:55:37 -04:00
parent f060a24f12
commit 88c9fc1ac1
10 changed files with 355 additions and 16 deletions

View File

@ -11,6 +11,7 @@ use Validator;
use stdClass; use stdClass;
use URL; use URL;
use Utils; use Utils;
use WePay;
use App\Models\Gateway; use App\Models\Gateway;
use App\Models\Account; use App\Models\Account;
use App\Models\AccountGateway; use App\Models\AccountGateway;
@ -44,6 +45,10 @@ class AccountGatewayController extends BaseController
$accountGateway = AccountGateway::scope($publicId)->firstOrFail(); $accountGateway = AccountGateway::scope($publicId)->firstOrFail();
$config = $accountGateway->getConfig(); $config = $accountGateway->getConfig();
if ($accountGateway->gateway_id == GATEWAY_WEPAY) {
return Redirect::to('gateways');
}
foreach ($config as $field => $value) { foreach ($config as $field => $value) {
$config->$field = str_repeat('*', strlen($value)); $config->$field = str_repeat('*', strlen($value));
} }
@ -57,7 +62,6 @@ class AccountGatewayController extends BaseController
$data['paymentTypeId'] = $accountGateway->getPaymentType(); $data['paymentTypeId'] = $accountGateway->getPaymentType();
$data['selectGateways'] = Gateway::where('id', '=', $accountGateway->gateway_id)->get(); $data['selectGateways'] = Gateway::where('id', '=', $accountGateway->gateway_id)->get();
return View::make('accounts.account_gateway', $data); return View::make('accounts.account_gateway', $data);
} }
@ -87,7 +91,6 @@ class AccountGatewayController extends BaseController
->where('id', '!=', GATEWAY_GOCARDLESS) ->where('id', '!=', GATEWAY_GOCARDLESS)
->where('id', '!=', GATEWAY_DWOLLA) ->where('id', '!=', GATEWAY_DWOLLA)
->where('id', '!=', GATEWAY_STRIPE) ->where('id', '!=', GATEWAY_STRIPE)
->where('id', '!=', GATEWAY_WEPAY)
->orderBy('name')->get(); ->orderBy('name')->get();
$data['hiddenFields'] = Gateway::$hiddenFields; $data['hiddenFields'] = Gateway::$hiddenFields;
@ -101,7 +104,8 @@ class AccountGatewayController extends BaseController
private function getViewModel($accountGateway = false) private function getViewModel($accountGateway = false)
{ {
$selectedCards = $accountGateway ? $accountGateway->accepted_credit_cards : 0; $selectedCards = $accountGateway ? $accountGateway->accepted_credit_cards : 0;
$account = Auth::user()->account; $user = Auth::user();
$account =$user->account;
$paymentTypes = []; $paymentTypes = [];
foreach (Gateway::$paymentTypes as $type) { foreach (Gateway::$paymentTypes as $type) {
@ -172,6 +176,7 @@ class AccountGatewayController extends BaseController
return [ return [
'paymentTypes' => $paymentTypes, 'paymentTypes' => $paymentTypes,
'account' => $account, 'account' => $account,
'user' => $user,
'accountGateway' => $accountGateway, 'accountGateway' => $accountGateway,
'config' => false, 'config' => false,
'gateways' => $gateways, 'gateways' => $gateways,
@ -203,6 +208,10 @@ class AccountGatewayController extends BaseController
$paymentType = Input::get('payment_type_id'); $paymentType = Input::get('payment_type_id');
$gatewayId = Input::get('gateway_id'); $gatewayId = Input::get('gateway_id');
if ($gatewayId == GATEWAY_WEPAY) {
return $this->setupWePay();
}
if ($paymentType == PAYMENT_TYPE_PAYPAL) { if ($paymentType == PAYMENT_TYPE_PAYPAL) {
$gatewayId = GATEWAY_PAYPAL_EXPRESS; $gatewayId = GATEWAY_PAYPAL_EXPRESS;
} elseif ($paymentType == PAYMENT_TYPE_BITCOIN) { } elseif ($paymentType == PAYMENT_TYPE_BITCOIN) {
@ -352,4 +361,129 @@ class AccountGatewayController extends BaseController
} }
} }
protected function getWePayUpdateUri($accountGateway)
{
if ($accountGateway->gateway_id != GATEWAY_WEPAY) {
return null;
}
$wepay = Utils::setupWePay($accountGateway);
$update_uri_data = $wepay->request('account/get_update_uri', array(
'account_id' => $accountGateway->getConfig()->accountId,
'mode' => 'iframe',
'redirect_uri' => URL::to('/gateways'),
));
return $update_uri_data->uri;
}
protected function setupWePay()
{
$user = Auth::user();
$account = $user->account;
$validator = Validator::make(Input::all(), array(
'company_name' => 'required',
'description' => 'required',
'tos_agree' => 'required',
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required',
));
if ($validator->fails()) {
return Redirect::to('gateways/create')
->withErrors($validator)
->withInput();
}
try{
$wepay = Utils::setupWePay();
$wepayUser = $wepay->request('user/register/', array(
'client_id' => WEPAY_CLIENT_ID,
'client_secret' => WEPAY_CLIENT_SECRET,
'email' => Input::get('email'),
'first_name' => Input::get('first_name'),
'last_name' => Input::get('last_name'),
'original_ip' => \Request::getClientIp(true),
'original_device' => \Request::server('HTTP_USER_AGENT'),
'tos_acceptance_time' => time(),
'redirect_uri' => URL::to('/gateways'),
'callback_uri' => URL::to('https://sometechie.ngrok.io/paymenthook/'.$account->account_key.'/'.GATEWAY_WEPAY),
'scope' => 'manage_accounts,collect_payments,view_user,preapprove_payments,send_money',
));
$accessToken = $wepayUser->access_token;
$accessTokenExpires = $wepayUser->expires_in ? (time() + $wepayUser->expires_in) : null;
$wepay = new WePay($accessToken);
$wepayAccount = $wepay->request('account/create/', array(
'name' => Input::get('company_name'),
'description' => Input::get('description'),
'theme_object' => json_decode(WEPAY_THEME),
));
try {
$wepay->request('user/send_confirmation/', []);
$confirmationRequired = true;
} catch(\WePayException $ex){
if ($ex->getMessage() == 'This access_token is already approved.') {
$confirmationRequired = false;
} else {
throw $ex;
}
}
$accountGateway = AccountGateway::createNew();
$accountGateway->gateway_id = GATEWAY_WEPAY;
$accountGateway->setConfig(array(
'userId' => $wepayUser->user_id,
'accessToken' => $accessToken,
'tokenType' => $wepayUser->token_type,
'tokenExpires' => $accessTokenExpires,
'accountId' => $wepayAccount->account_id,
'testMode' => WEPAY_ENVIRONMENT == WEPAY_STAGING,
));
$account->account_gateways()->save($accountGateway);
if ($confirmationRequired) {
Session::flash('message', trans('texts.created_wepay_confirmation_required'));
} else {
$updateUri = $wepay->request('/account/get_update_uri', array(
'account_id' => $wepayAccount->account_id,
'redirect_uri' => URL::to('gateways'),
));
return Redirect::to($updateUri->uri);
}
return Redirect::to("gateways");
} catch (\WePayException $e) {
Session::flash('error', $e->getMessage());
return Redirect::to('gateways/create')
->withInput();
}
}
public function resendConfirmation($publicId = false)
{
$accountGateway = AccountGateway::scope($publicId)->firstOrFail();
if ($accountGateway->gateway_id == GATEWAY_WEPAY) {
try {
$wepay = Utils::setupWePay($accountGateway);
$wepay->request('user/send_confirmation', []);
Session::flash('message', trans('texts.resent_confirmation_email'));
} catch (\WePayException $e) {
Session::flash('error', $e->getMessage());
}
}
return Redirect::to("gateways/{$accountGateway->public_id}/edit");
}
} }

View File

@ -242,6 +242,7 @@ Route::group([
Route::post('/import_csv', 'ImportController@doImportCSV'); Route::post('/import_csv', 'ImportController@doImportCSV');
Route::resource('gateways', 'AccountGatewayController'); Route::resource('gateways', 'AccountGatewayController');
Route::get('gateways/{public_id}/resend_confirmation', 'AccountGatewayController@resendConfirmation');
Route::get('api/gateways', array('as'=>'api.gateways', 'uses'=>'AccountGatewayController@getDatatable')); Route::get('api/gateways', array('as'=>'api.gateways', 'uses'=>'AccountGatewayController@getDatatable'));
Route::post('account_gateways/bulk', 'AccountGatewayController@bulk'); Route::post('account_gateways/bulk', 'AccountGatewayController@bulk');
@ -745,6 +746,14 @@ if (!defined('CONTACT_EMAIL')) {
// Pro users who started paying on or before this date will be able to manage users // Pro users who started paying on or before this date will be able to manage users
define('PRO_USERS_GRANDFATHER_DEADLINE', '2016-05-15'); define('PRO_USERS_GRANDFATHER_DEADLINE', '2016-05-15');
// WePay
define('WEPAY_PRODUCTION', 'production');
define('WEPAY_STAGING', 'staging');
define('WEPAY_CLIENT_ID', env('WEPAY_CLIENT_ID'));
define('WEPAY_CLIENT_SECRET', env('WEPAY_CLIENT_SECRET'));
define('WEPAY_ENVIRONMENT', env('WEPAY_ENVIRONMENT', WEPAY_PRODUCTION));
define('WEPAY_THEME', env('WEPAY_THEME','{"name":"Invoice Ninja","primary_color":"0b4d78","secondary_color":"0b4d78","background_color":"f8f8f8","button_color":"33b753"}'));
$creditCards = [ $creditCards = [
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'], 1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'], 2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'],

View File

@ -15,6 +15,7 @@ use Log;
use DateTime; use DateTime;
use stdClass; use stdClass;
use Carbon; use Carbon;
use WePay;
use App\Models\Currency; use App\Models\Currency;
@ -990,4 +991,21 @@ class Utils
return $url; return $url;
} }
public static function setupWePay($accountGateway = null)
{
if (WePay::getEnvironment() == 'none') {
if (WEPAY_ENVIRONMENT == WEPAY_STAGING) {
WePay::useStaging(WEPAY_CLIENT_ID, WEPAY_CLIENT_SECRET);
} else {
WePay::useProduction(WEPAY_CLIENT_ID, WEPAY_CLIENT_SECRET);
}
}
if ($accountGateway) {
return new WePay($accountGateway->getConfig()->accessToken);
} else {
return new WePay(null);
}
}
} }

View File

@ -19,6 +19,6 @@ class AccountGatewayRepository extends BaseRepository
->join('gateways', 'gateways.id', '=', 'account_gateways.gateway_id') ->join('gateways', 'gateways.id', '=', 'account_gateways.gateway_id')
->where('account_gateways.deleted_at', '=', null) ->where('account_gateways.deleted_at', '=', null)
->where('account_gateways.account_id', '=', $accountId) ->where('account_gateways.account_id', '=', $accountId)
->select('account_gateways.public_id', 'gateways.name', 'account_gateways.deleted_at', 'account_gateways.gateway_id'); ->select('account_gateways.id', 'account_gateways.public_id', 'gateways.name', 'account_gateways.deleted_at', 'account_gateways.gateway_id');
} }
} }

View File

@ -2,6 +2,7 @@
use URL; use URL;
use App\Models\Gateway; use App\Models\Gateway;
use App\Models\AccountGateway;
use App\Services\BaseService; use App\Services\BaseService;
use App\Ninja\Repositories\AccountGatewayRepository; use App\Ninja\Repositories\AccountGatewayRepository;
@ -41,7 +42,38 @@ class AccountGatewayService extends BaseService
[ [
'name', 'name',
function ($model) { function ($model) {
return link_to("gateways/{$model->public_id}/edit", $model->name)->toHtml(); if ($model->gateway_id != GATEWAY_WEPAY) {
return link_to("gateways/{$model->public_id}/edit", $model->name)->toHtml();
} else {
$accountGateway = AccountGateway::find($model->id);
$endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGING ? 'https://stage.wepay.com/' : 'https://www.wepay.com/';
$wepayAccountId = $accountGateway->getConfig()->accountId;
$linkText = $model->name;
$url = $endpoint.'account/'.$wepayAccountId;
$wepay = \Utils::setupWepay($accountGateway);
$html = link_to($url, $linkText, array('target'=>'_blank'))->toHtml();
try {
$wepayAccount = $wepay->request('/account', array('account_id' => $wepayAccountId));
if ($wepayAccount->state == 'action_required') {
$updateUri = $wepay->request('/account/get_update_uri', array(
'account_id' => $wepayAccountId,
'redirect_uri' => URL::to('gateways'),
));
$linkText .= ' <span style="color:#d9534f">('.trans('texts.action_required').')</span>';
$url = $updateUri->uri;
$html = "<a href=\"{$url}\">{$linkText}</a>";
$model->setupUrl = $url;
} elseif ($wepayAccount->state == 'pending') {
$linkText .= ' ('.trans('texts.resend_confirmation_email').')';
$model->resendConfirmationUrl = $url = URL::to("gateways/{$accountGateway->public_id}/resend_confirmation");
$html = link_to($url, $linkText)->toHtml();
}
} catch(\WePayException $ex){}
return $html;
}
} }
], ],
[ [
@ -60,6 +92,38 @@ class AccountGatewayService extends BaseService
uctrans('texts.edit_gateway'), uctrans('texts.edit_gateway'),
function ($model) { function ($model) {
return URL::to("gateways/{$model->public_id}/edit"); return URL::to("gateways/{$model->public_id}/edit");
},
function($model) {
return $model->gateway_id != GATEWAY_WEPAY;
}
], [
uctrans('texts.resend_confirmation_email'),
function ($model) {
return $model->resendConfirmationUrl;
},
function($model) {
return $model->gateway_id == GATEWAY_WEPAY && !empty($model->resendConfirmationUrl);
}
], [
uctrans('texts.finish_setup'),
function ($model) {
return $model->setupUrl;
},
function($model) {
return $model->gateway_id == GATEWAY_WEPAY && !empty($model->setupUrl);
}
] , [
uctrans('texts.manage_wepay_account'),
function ($model) {
$accountGateway = AccountGateway::find($model->id);
$endpoint = WEPAY_ENVIRONMENT == WEPAY_STAGING ? 'https://stage.wepay.com/' : 'https://www.wepay.com/';
return array(
'url' => $endpoint.'account/'.$accountGateway->getConfig()->accountId,
'attributes' => 'target="_blank"'
);
},
function($model) {
return $model->gateway_id == GATEWAY_WEPAY;
} }
] ]
]; ];

View File

@ -82,7 +82,14 @@ class DatatableService
$lastIsDivider = true; $lastIsDivider = true;
} }
else { else {
$str .= "<li><a href=\"{$url($model)}\">{$value}</a></li>"; $urlVal = $url($model);
$urlStr = is_string($urlVal) ? $urlVal : $urlVal['url'];
$attributes = '';
if (!empty($urlVal['attributes'])) {
$attributes = ' '.$urlVal['attributes'];
}
$str .= "<li><a href=\"$urlStr\"{$attributes}>{$value}</a></li>";
$hasAction = true; $hasAction = true;
$lastIsDivider = false; $lastIsDivider = false;
} }

View File

@ -74,7 +74,8 @@
"league/flysystem-rackspace": "~1.0", "league/flysystem-rackspace": "~1.0",
"barracudanetworks/archivestream-php": "^1.0", "barracudanetworks/archivestream-php": "^1.0",
"omnipay/braintree": "~2.0@dev", "omnipay/braintree": "~2.0@dev",
"gatepay/FedACHdir": "dev-master@dev" "gatepay/FedACHdir": "dev-master@dev",
"wepay/php-sdk": "^0.2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "~4.0", "phpunit/phpunit": "~4.0",

55
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "7139e4aedb2ac151079c50ee5c17f93c", "hash": "b2471aea1af5ef67a1379ad95b5138f7",
"content-hash": "a314d6c0a16785dd2395a7fd73cdc76d", "content-hash": "df30a311df0341933d4ff2c3aa5974a6",
"packages": [ "packages": [
{ {
"name": "agmscode/omnipay-agms", "name": "agmscode/omnipay-agms",
@ -505,7 +505,7 @@
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/e97ed532f09e290b91ff7713b785ed7ab11d0812", "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/f7b31bdbdceaaea930c71df20e4180b0b7172b4a",
"reference": "e97ed532f09e290b91ff7713b785ed7ab11d0812", "reference": "e97ed532f09e290b91ff7713b785ed7ab11d0812",
"shasum": "" "shasum": ""
}, },
@ -2785,7 +2785,7 @@
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/labs7in0/omnipay-wechat/zipball/40c9f86df6573ad98ae1dd0d29712ccbc789a74e", "url": "https://api.github.com/repos/labs7in0/omnipay-wechat/zipball/c8d80c3b48bae2bab071f283f75b1cd8624ed3c7",
"reference": "40c9f86df6573ad98ae1dd0d29712ccbc789a74e", "reference": "40c9f86df6573ad98ae1dd0d29712ccbc789a74e",
"shasum": "" "shasum": ""
}, },
@ -8057,6 +8057,53 @@
], ],
"time": "2016-02-25 10:29:59" "time": "2016-02-25 10:29:59"
}, },
{
"name": "wepay/php-sdk",
"version": "0.2.7",
"source": {
"type": "git",
"url": "https://github.com/wepay/PHP-SDK.git",
"reference": "31bfcdd97d2c9c33c9c09129638ae31840822182"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wepay/PHP-SDK/zipball/31bfcdd97d2c9c33c9c09129638ae31840822182",
"reference": "31bfcdd97d2c9c33c9c09129638ae31840822182",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.2.x-dev"
}
},
"autoload": {
"classmap": [
"wepay.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "WePay",
"email": "api@wepay.com"
}
],
"description": "WePay APIv2 SDK for PHP",
"keywords": [
"payment",
"sdk",
"wepay"
],
"time": "2015-08-14 19:42:37"
},
{ {
"name": "wildbit/laravel-postmark-provider", "name": "wildbit/laravel-postmark-provider",
"version": "3.0.0", "version": "3.0.0",

View File

@ -1293,6 +1293,22 @@ $LANG = array(
'no_payment_method_specified' => 'No payment method specified', 'no_payment_method_specified' => 'No payment method specified',
// WePay
'wepay' => 'WePay',
'sign_up_with_wepay' => 'Sign up with WePay',
'use_another_provider' => 'Use another provider',
'company_name' => 'Company Name',
'wepay_company_name_help' => 'This will appear on client\'s credit card statements.',
'wepay_description_help' => 'The purpose of this account.',
'wepay_tos_agree' => 'I agree to the :link.',
'wepay_tos_link_text' => 'WePay Terms of Service',
'resend_confirmation_email' => 'Resend Confirmation Email',
'manage_wepay_account' => 'Manage WePay Account',
'action_required' => 'Action Required',
'finish_setup' => 'Finish Setup',
'created_wepay_confirmation_required' => 'Please check your email and confirm your email address with WePay.'
); );
return $LANG; return $LANG;

View File

@ -5,15 +5,53 @@
@include('accounts.nav', ['selected' => ACCOUNT_PAYMENTS]) @include('accounts.nav', ['selected' => ACCOUNT_PAYMENTS])
{!! Former::open($url)->method($method)->rule()->addClass('warn-on-exit') !!} @if(!$accountGateway && WEPAY_CLIENT_ID)
{!! Former::populateField('token_billing_type_id', $account->token_billing_type_id) !!} {!! Former::open($url)->method($method)->rules(array(
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required',
'description' => 'required',
'company_name' => 'required',
'tos_agree' => 'required',
))->addClass('warn-on-exit') !!}
{!! Former::populateField('company_name', $account->getDisplayName()) !!}
{!! Former::populateField('first_name', $user->first_name) !!}
{!! Former::populateField('last_name', $user->last_name) !!}
{!! Former::populateField('email', $user->email) !!}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.online_payments') !!}</h3>
</div>
<div class="panel-body form-padding-right">
{!! Former::text('first_name') !!}
{!! Former::text('last_name') !!}
{!! Former::text('email') !!}
{!! Former::text('company_name')->help('wepay_company_name_help')->maxlength(255) !!}
{!! Former::text('description')->help('wepay_description_help') !!}
{!! Former::checkbox('tos_agree')->label(' ')->text(trans('texts.wepay_tos_agree',
['link'=>'<a href="https://go.wepay.com/terms-of-service-us" target="_blank">'.trans('texts.wepay_tos_link_text').'</a>']
))->value('true') !!}
<center>
{!! Button::primary(trans('texts.sign_up_with_wepay'))
->submit()
->large() !!}<br><br>
<a href="#" id="show-other-providers">{{ trans('texts.use_another_provider') }}</a>
</center>
</div>
</div>
<style>#other-providers{display:none}</style>
<input type="hidden" name="gateway_id" value="{{ GATEWAY_WEPAY }}">
{!! Former::close() !!}
@endif
<div id="other-providers">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{!! trans($title) !!}</h3> <h3 class="panel-title">{!! trans($title) !!}</h3>
</div> </div>
<div class="panel-body form-padding-right"> <div class="panel-body form-padding-right">
{!! Former::open($url)->method($method)->rule()->addClass('warn-on-exit') !!}
{!! Former::populateField('token_billing_type_id', $account->token_billing_type_id) !!}
@if ($accountGateway) @if ($accountGateway)
{!! Former::populateField('gateway_id', $accountGateway->gateway_id) !!} {!! Former::populateField('gateway_id', $accountGateway->gateway_id) !!}
@ -173,7 +211,6 @@
</div> </div>
@endif @endif
</div> </div>
</div> </div>
</div> </div>
@ -183,6 +220,7 @@
$countGateways > 0 ? Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/online_payments'))->appendIcon(Icon::create('remove-circle')) : false, $countGateways > 0 ? Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/online_payments'))->appendIcon(Icon::create('remove-circle')) : false,
Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))) !!} Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))) !!}
{!! Former::close() !!} {!! Former::close() !!}
</div>
<script type="text/javascript"> <script type="text/javascript">
@ -256,6 +294,11 @@
enableUpdateAddress(); enableUpdateAddress();
$('#enable_ach').change(enablePlaidSettings) $('#enable_ach').change(enablePlaidSettings)
$('#show-other-providers').click(function(){
$(this).hide();
$('#other-providers').show();
})
}) })
</script> </script>