diff --git a/app/Http/Controllers/AccountGatewayController.php b/app/Http/Controllers/AccountGatewayController.php index a4fd57c7e5f4..c430fb61d816 100644 --- a/app/Http/Controllers/AccountGatewayController.php +++ b/app/Http/Controllers/AccountGatewayController.php @@ -11,6 +11,7 @@ use Validator; use stdClass; use URL; use Utils; +use WePay; use App\Models\Gateway; use App\Models\Account; use App\Models\AccountGateway; @@ -44,6 +45,10 @@ class AccountGatewayController extends BaseController $accountGateway = AccountGateway::scope($publicId)->firstOrFail(); $config = $accountGateway->getConfig(); + if ($accountGateway->gateway_id == GATEWAY_WEPAY) { + return Redirect::to('gateways'); + } + foreach ($config as $field => $value) { $config->$field = str_repeat('*', strlen($value)); } @@ -57,7 +62,6 @@ class AccountGatewayController extends BaseController $data['paymentTypeId'] = $accountGateway->getPaymentType(); $data['selectGateways'] = Gateway::where('id', '=', $accountGateway->gateway_id)->get(); - return View::make('accounts.account_gateway', $data); } @@ -87,7 +91,6 @@ class AccountGatewayController extends BaseController ->where('id', '!=', GATEWAY_GOCARDLESS) ->where('id', '!=', GATEWAY_DWOLLA) ->where('id', '!=', GATEWAY_STRIPE) - ->where('id', '!=', GATEWAY_WEPAY) ->orderBy('name')->get(); $data['hiddenFields'] = Gateway::$hiddenFields; @@ -101,7 +104,8 @@ class AccountGatewayController extends BaseController private function getViewModel($accountGateway = false) { $selectedCards = $accountGateway ? $accountGateway->accepted_credit_cards : 0; - $account = Auth::user()->account; + $user = Auth::user(); + $account =$user->account; $paymentTypes = []; foreach (Gateway::$paymentTypes as $type) { @@ -172,6 +176,7 @@ class AccountGatewayController extends BaseController return [ 'paymentTypes' => $paymentTypes, 'account' => $account, + 'user' => $user, 'accountGateway' => $accountGateway, 'config' => false, 'gateways' => $gateways, @@ -203,6 +208,10 @@ class AccountGatewayController extends BaseController $paymentType = Input::get('payment_type_id'); $gatewayId = Input::get('gateway_id'); + if ($gatewayId == GATEWAY_WEPAY) { + return $this->setupWePay(); + } + if ($paymentType == PAYMENT_TYPE_PAYPAL) { $gatewayId = GATEWAY_PAYPAL_EXPRESS; } 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"); + } } diff --git a/app/Http/routes.php b/app/Http/routes.php index 128a1e9e2ec6..292d6128a070 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -242,6 +242,7 @@ Route::group([ Route::post('/import_csv', 'ImportController@doImportCSV'); 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::post('account_gateways/bulk', 'AccountGatewayController@bulk'); @@ -744,6 +745,14 @@ if (!defined('CONTACT_EMAIL')) { // Pro users who started paying on or before this date will be able to manage users 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 = [ 1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'], diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index c02c719169a4..8e54926e8045 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -15,6 +15,7 @@ use Log; use DateTime; use stdClass; use Carbon; +use WePay; use App\Models\Currency; @@ -990,4 +991,21 @@ class Utils 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); + } + } } diff --git a/app/Ninja/Repositories/AccountGatewayRepository.php b/app/Ninja/Repositories/AccountGatewayRepository.php index b61f854f2dc5..b011ebda765b 100644 --- a/app/Ninja/Repositories/AccountGatewayRepository.php +++ b/app/Ninja/Repositories/AccountGatewayRepository.php @@ -19,6 +19,6 @@ class AccountGatewayRepository extends BaseRepository ->join('gateways', 'gateways.id', '=', 'account_gateways.gateway_id') ->where('account_gateways.deleted_at', '=', null) ->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'); } } diff --git a/app/Services/AccountGatewayService.php b/app/Services/AccountGatewayService.php index bd5635e0dd52..c21902c87374 100644 --- a/app/Services/AccountGatewayService.php +++ b/app/Services/AccountGatewayService.php @@ -2,6 +2,7 @@ use URL; use App\Models\Gateway; +use App\Models\AccountGateway; use App\Services\BaseService; use App\Ninja\Repositories\AccountGatewayRepository; @@ -41,7 +42,38 @@ class AccountGatewayService extends BaseService [ 'name', 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 .= ' ('.trans('texts.action_required').')'; + $url = $updateUri->uri; + $html = "{$linkText}"; + $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'), function ($model) { 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; } ] ]; diff --git a/app/Services/DatatableService.php b/app/Services/DatatableService.php index 3d9001a095b7..222a7b4d7cb6 100644 --- a/app/Services/DatatableService.php +++ b/app/Services/DatatableService.php @@ -82,7 +82,14 @@ class DatatableService $lastIsDivider = true; } else { - $str .= "
  • {$value}
  • "; + $urlVal = $url($model); + $urlStr = is_string($urlVal) ? $urlVal : $urlVal['url']; + $attributes = ''; + if (!empty($urlVal['attributes'])) { + $attributes = ' '.$urlVal['attributes']; + } + + $str .= "
  • {$value}
  • "; $hasAction = true; $lastIsDivider = false; } diff --git a/composer.json b/composer.json index 01c6a26f51cf..cff2d85bcbba 100644 --- a/composer.json +++ b/composer.json @@ -74,7 +74,8 @@ "league/flysystem-rackspace": "~1.0", "barracudanetworks/archivestream-php": "^1.0", "omnipay/braintree": "~2.0@dev", - "gatepay/FedACHdir": "dev-master@dev" + "gatepay/FedACHdir": "dev-master@dev", + "wepay/php-sdk": "^0.2" }, "require-dev": { "phpunit/phpunit": "~4.0", diff --git a/composer.lock b/composer.lock index e167cfb38e9c..d694f04f6960 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "7139e4aedb2ac151079c50ee5c17f93c", - "content-hash": "a314d6c0a16785dd2395a7fd73cdc76d", + "hash": "b2471aea1af5ef67a1379ad95b5138f7", + "content-hash": "df30a311df0341933d4ff2c3aa5974a6", "packages": [ { "name": "agmscode/omnipay-agms", @@ -505,7 +505,7 @@ }, "dist": { "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", "shasum": "" }, @@ -2785,7 +2785,7 @@ }, "dist": { "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", "shasum": "" }, @@ -8057,6 +8057,53 @@ ], "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", "version": "3.0.0", @@ -10024,4 +10071,4 @@ "prefer-lowest": false, "platform": [], "platform-dev": [] -} \ No newline at end of file +} diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 0aebc8b87903..25f9fdd6fabb 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -1293,6 +1293,22 @@ $LANG = array( '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; diff --git a/resources/views/accounts/account_gateway.blade.php b/resources/views/accounts/account_gateway.blade.php index ade161f5b65f..72acd1cff05a 100644 --- a/resources/views/accounts/account_gateway.blade.php +++ b/resources/views/accounts/account_gateway.blade.php @@ -5,15 +5,53 @@ @include('accounts.nav', ['selected' => ACCOUNT_PAYMENTS]) - {!! Former::open($url)->method($method)->rule()->addClass('warn-on-exit') !!} - {!! Former::populateField('token_billing_type_id', $account->token_billing_type_id) !!} - + @if(!$accountGateway && WEPAY_CLIENT_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) !!} +
    +
    +

    {!! trans('texts.online_payments') !!}

    +
    +
    + {!! 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'=>''.trans('texts.wepay_tos_link_text').''] + ))->value('true') !!} +
    + {!! Button::primary(trans('texts.sign_up_with_wepay')) + ->submit() + ->large() !!}

    + {{ trans('texts.use_another_provider') }} +
    +
    +
    + + + {!! Former::close() !!} + @endif +

    {!! trans($title) !!}

    + {!! Former::open($url)->method($method)->rule()->addClass('warn-on-exit') !!} + {!! Former::populateField('token_billing_type_id', $account->token_billing_type_id) !!} @if ($accountGateway) {!! Former::populateField('gateway_id', $accountGateway->gateway_id) !!} @@ -173,7 +211,6 @@
    @endif
    -
    @@ -183,6 +220,7 @@ $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'))) !!} {!! Former::close() !!} +