From 8c00bce71b829206d526b3dcb2e4105975ffc6e1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 May 2021 14:29:58 +1000 Subject: [PATCH 1/6] We Pay signup --- .../Controllers/StripeConnectController.php | 1 - app/Http/Controllers/WePayController.php | 62 ++++++ app/Http/Livewire/WepaySignup.php | 73 +++++++ app/Models/SystemLog.php | 1 + app/PaymentDrivers/Stripe/Connect/Account.php | 159 -------------- app/PaymentDrivers/WePay/CreditCard.php | 31 +++ app/PaymentDrivers/WePay/Setup.php | 206 ++++++++++++++++++ app/PaymentDrivers/WePayPaymentDriver.php | 110 ++++++++++ composer.json | 3 +- composer.lock | 53 ++++- config/ninja.php | 5 + .../2021_05_05_014713_activate_we_pay.php | 30 +++ database/seeders/PaymentLibrariesSeeder.php | 2 +- .../gateways/wepay/signup/index.blade.php | 14 ++ .../wepay/signup/wepay-signup.blade.php | 93 ++++++++ routes/api.php | 2 + routes/client.php | 1 + 17 files changed, 683 insertions(+), 163 deletions(-) create mode 100644 app/Http/Controllers/WePayController.php create mode 100644 app/Http/Livewire/WepaySignup.php create mode 100644 app/PaymentDrivers/WePay/CreditCard.php create mode 100644 app/PaymentDrivers/WePay/Setup.php create mode 100644 app/PaymentDrivers/WePayPaymentDriver.php create mode 100644 database/migrations/2021_05_05_014713_activate_we_pay.php create mode 100644 resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php create mode 100644 resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php diff --git a/app/Http/Controllers/StripeConnectController.php b/app/Http/Controllers/StripeConnectController.php index 7410f3766174..73e1651bdc99 100644 --- a/app/Http/Controllers/StripeConnectController.php +++ b/app/Http/Controllers/StripeConnectController.php @@ -34,7 +34,6 @@ class StripeConnectController extends BaseController if(!is_array($request->getTokenContent())) abort(400, 'Invalid token'); - MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']); $data = [ diff --git a/app/Http/Controllers/WePayController.php b/app/Http/Controllers/WePayController.php new file mode 100644 index 000000000000..6dfe7496fbe8 --- /dev/null +++ b/app/Http/Controllers/WePayController.php @@ -0,0 +1,62 @@ + auth()->user()->id, + // 'company_key'=> auth()->user()->company()->company_key, + // 'context' => $request->input('context'), + // ]; + + $hash = Cache::get($token); + + //temporarily comment this out + // if(!$hash) + // abort(400, 'Link expired'); + // MultiDB::findAndSetDbByCompanyKey($hash['company_key']); + // $data['user_id'] = $this->encodePrimaryKey($hash['user_id']); + // $data['company_key'] = $hash['company_key']; + + $data['user_id'] = 1; + $user = User::first(); + + $data['company_key'] = $user->account->companies()->first()->company_key; + + $wepay_driver = new WePayPaymentDriver(new CompanyGateway, null, null); + + return $wepay_driver->setup($data); + + } + + public function processSignup(Request $request) + { + + } +} diff --git a/app/Http/Livewire/WepaySignup.php b/app/Http/Livewire/WepaySignup.php new file mode 100644 index 000000000000..d90b77c18d52 --- /dev/null +++ b/app/Http/Livewire/WepaySignup.php @@ -0,0 +1,73 @@ + ['sometimes'], + 'last_name' => ['sometimes'], + 'email' => ['required', 'email'], + ]; + + public function mount() + { + $user = User::find($this->user_id); + $company = Company::where('company_key', $this->company_key)->first(); + + $this->fill([ + 'user' => $user, + 'first_name' => $user->first_name, + 'last_name' => $user->last_name, + 'email' => $user->email, + 'company_name' => $company->present()->name(), + 'saved' => ctrans('texts.confirm'), + 'terms' => ''.ctrans('texts.terms_of_service').'', + 'privacy_policy' => ''.ctrans('texts.privacy_policy').'', + ]); + } + + public function render() + { + return render('gateways.wepay.signup.wepay-signup'); + } + + public function submit() + { + + $data = $this->validate($this->rules); + + // $this->user + // ->fill($data) + // ->save(); + + $this->saved = ctrans('texts.saved_at', ['time' => now()->toTimeString()]); + } +} diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index 816846ba255f..c263df95328f 100644 --- a/app/Models/SystemLog.php +++ b/app/Models/SystemLog.php @@ -65,6 +65,7 @@ class SystemLog extends Model const TYPE_CHECKOUT = 304; const TYPE_AUTHORIZE = 305; const TYPE_CUSTOM = 306; + const TYPE_WEPAY = 309; const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/Stripe/Connect/Account.php b/app/PaymentDrivers/Stripe/Connect/Account.php index 69c85d771e7c..4d837cb2ea11 100644 --- a/app/PaymentDrivers/Stripe/Connect/Account.php +++ b/app/PaymentDrivers/Stripe/Connect/Account.php @@ -47,164 +47,5 @@ class Account ]); } -/*** If this is a new account (ie there is no account_id in company_gateways.config, the we need to create an account as below. - -/// -// $stripe = new \Stripe\StripeClient( -// 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' -// ); -// $stripe->accounts->create([ -// 'type' => 'standard', -// 'country' => 'US', //if we have it - inject -// 'email' => 'jenny.rosen@example.com', //if we have it - inject -// ]); -/// - - -//response - -//******************* We should store the 'id' as a property in the config with the key `account_id` - -/** - * { - "id": "acct_1032D82eZvKYlo2C", - "object": "account", - "business_profile": { - "mcc": null, - "name": "Stripe.com", - "product_description": null, - "support_address": null, - "support_email": null, - "support_phone": null, - "support_url": null, - "url": null - }, - "capabilities": { - "card_payments": "active", - "transfers": "active" - }, - "charges_enabled": false, - "country": "US", - "default_currency": "usd", - "details_submitted": false, - "email": "site@stripe.com", - "metadata": {}, - "payouts_enabled": false, - "requirements": { - "current_deadline": null, - "currently_due": [ - "business_profile.product_description", - "business_profile.support_phone", - "business_profile.url", - "external_account", - "tos_acceptance.date", - "tos_acceptance.ip" - ], - "disabled_reason": "requirements.past_due", - "errors": [], - "eventually_due": [ - "business_profile.product_description", - "business_profile.support_phone", - "business_profile.url", - "external_account", - "tos_acceptance.date", - "tos_acceptance.ip" - ], - "past_due": [], - "pending_verification": [] - }, - "settings": { - "bacs_debit_payments": {}, - "branding": { - "icon": null, - "logo": null, - "primary_color": null, - "secondary_color": null - }, - "card_issuing": { - "tos_acceptance": { - "date": null, - "ip": null - } - }, - "card_payments": { - "decline_on": { - "avs_failure": true, - "cvc_failure": false - }, - "statement_descriptor_prefix": null - }, - "dashboard": { - "display_name": "Stripe.com", - "timezone": "US/Pacific" - }, - "payments": { - "statement_descriptor": null, - "statement_descriptor_kana": null, - "statement_descriptor_kanji": null - }, - "payouts": { - "debit_negative_balances": true, - "schedule": { - "delay_days": 7, - "interval": "daily" - }, - "statement_descriptor": null - }, - "sepa_debit_payments": {} - }, - "type": "standard" -} - - */ - - -//At this stage we have an account, so we need to generate the account link -//then create the account link - -// now we start the stripe onboarding flow -// https://stripe.com/docs/api/account_links/object -// -/** - * $stripe = new \Stripe\StripeClient( - 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' -); -$stripe->accountLinks->create([ - 'account' => 'acct_1032D82eZvKYlo2C', - 'refresh_url' => 'https://example.com/reauth', - 'return_url' => 'https://example.com/return', - 'type' => 'account_onboarding', -]); - */ - -/** - * Response = - * { - "object": "account_link", - "created": 1618869558, - "expires_at": 1618869858, - "url": "https://connect.stripe.com/setup/s/9BhFaPdfseRF" -} - */ - -//The users account may not be active yet, we need to pull the account back and check for the property `charges_enabled` -// -// - - -// What next? -// -// Now we need to create a superclass of the StripePaymentDriver, i believe the only thing we need to change is the way we initialize the gateway.. - -/** - * -\Stripe\Stripe::setApiKey("{{PLATFORM_SECRET_KEY}}"); <--- platform secret key = Invoice Ninja secret key -\Stripe\Customer::create( - ["email" => "person@example.edu"], - ["stripe_account" => "{{CONNECTED_STRIPE_ACCOUNT_ID}}"] <------ company_gateway.config.account_id -); - - - */ } diff --git a/app/PaymentDrivers/WePay/CreditCard.php b/app/PaymentDrivers/WePay/CreditCard.php new file mode 100644 index 000000000000..2b54246784d2 --- /dev/null +++ b/app/PaymentDrivers/WePay/CreditCard.php @@ -0,0 +1,31 @@ +wepay = $wepay; + } + + public function authorizeView($data) + { + + } + +} diff --git a/app/PaymentDrivers/WePay/Setup.php b/app/PaymentDrivers/WePay/Setup.php new file mode 100644 index 000000000000..740ef8025520 --- /dev/null +++ b/app/PaymentDrivers/WePay/Setup.php @@ -0,0 +1,206 @@ +wepay = $wepay; + } + + public function boot($data) + { + /* + 'user_id', + 'company_key', + */ + + return render('gateways.wepay.signup.index', $data); + } + + + public function processSignup(Request $request) + { + + } +} + + +/* +protected function setupWePay($accountGateway, &$response) + { + $user = Auth::user(); + $account = $user->account; + + $rules = [ + 'company_name' => 'required', + 'tos_agree' => 'required', + 'first_name' => 'required', + 'last_name' => 'required', + 'email' => 'required|email', + 'country' => 'required|in:US,CA,GB', + ]; + + $validator = Validator::make(Input::all(), $rules); + + if ($validator->fails()) { + return Redirect::to('gateways/create') + ->withErrors($validator) + ->withInput(); + } + + if (! $user->email) { + $user->email = trim(Input::get('email')); + $user->first_name = trim(Input::get('first_name')); + $user->last_name = trim(Input::get('last_name')); + $user->save(); + } + + try { + $wepay = Utils::setupWePay(); + + $userDetails = [ + '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'), + 'scope' => 'manage_accounts,collect_payments,view_user,preapprove_payments,send_money', + ]; + + $wepayUser = $wepay->request('user/register/', $userDetails); + + $accessToken = $wepayUser->access_token; + $accessTokenExpires = $wepayUser->expires_in ? (time() + $wepayUser->expires_in) : null; + + $wepay = new WePay($accessToken); + + $accountDetails = [ + 'name' => Input::get('company_name'), + 'description' => trans('texts.wepay_account_description'), + 'theme_object' => json_decode(WEPAY_THEME), + 'callback_uri' => $accountGateway->getWebhookUrl(), + 'rbits' => $account->present()->rBits, + 'country' => Input::get('country'), + ]; + + if (Input::get('country') == 'CA') { + $accountDetails['currencies'] = ['CAD']; + $accountDetails['country_options'] = ['debit_opt_in' => boolval(Input::get('debit_cards'))]; + } elseif (Input::get('country') == 'GB') { + $accountDetails['currencies'] = ['GBP']; + } + + $wepayAccount = $wepay->request('account/create/', $accountDetails); + + 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->gateway_id = GATEWAY_WEPAY; + $accountGateway->setConfig([ + 'userId' => $wepayUser->user_id, + 'accessToken' => $accessToken, + 'tokenType' => $wepayUser->token_type, + 'tokenExpires' => $accessTokenExpires, + 'accountId' => $wepayAccount->account_id, + 'state' => $wepayAccount->state, + 'testMode' => WEPAY_ENVIRONMENT == WEPAY_STAGE, + 'country' => Input::get('country'), + ]); + + if ($confirmationRequired) { + Session::flash('message', trans('texts.created_wepay_confirmation_required')); + } else { + $updateUri = $wepay->request('/account/get_update_uri', [ + 'account_id' => $wepayAccount->account_id, + 'redirect_uri' => URL::to('gateways'), + ]); + + $response = Redirect::to($updateUri->uri); + + return true; + } + + $response = Redirect::to("gateways/{$accountGateway->public_id}/edit"); + + return true; + } catch (\WePayException $e) { + Session::flash('error', $e->getMessage()); + $response = Redirect::to('gateways/create') + ->withInput(); + + return false; + } + } + */ + + +/* + + +rbits + + + private function createRBit($type, $source, $properties) + { + $data = new stdClass(); + $data->receive_time = time(); + $data->type = $type; + $data->source = $source; + $data->properties = new stdClass(); + + foreach ($properties as $key => $val) { + $data->properties->$key = $val; + } + + return $data; + } + + public function rBits() + { + $account = $this->entity; + $user = $account->users()->first(); + $data = []; + + $data[] = $this->createRBit('business_name', 'user', ['business_name' => $account->name]); + $data[] = $this->createRBit('industry_code', 'user', ['industry_detail' => $account->present()->industry]); + $data[] = $this->createRBit('comment', 'partner_database', ['comment_text' => 'Logo image not present']); + $data[] = $this->createRBit('business_description', 'user', ['business_description' => $account->present()->size]); + + $data[] = $this->createRBit('person', 'user', ['name' => $user->getFullName()]); + $data[] = $this->createRBit('email', 'user', ['email' => $user->email]); + $data[] = $this->createRBit('phone', 'user', ['phone' => $user->phone]); + $data[] = $this->createRBit('website_uri', 'user', ['uri' => $account->website]); + $data[] = $this->createRBit('external_account', 'partner_database', ['is_partner_account' => 'yes', 'account_type' => 'Invoice Ninja', 'create_time' => time()]); + + return $data; + } + */ \ No newline at end of file diff --git a/app/PaymentDrivers/WePayPaymentDriver.php b/app/PaymentDrivers/WePayPaymentDriver.php new file mode 100644 index 000000000000..79253491029c --- /dev/null +++ b/app/PaymentDrivers/WePayPaymentDriver.php @@ -0,0 +1,110 @@ + CreditCard::class, //maps GatewayType => Implementation class + ]; + + const SYSTEM_LOG_TYPE = SystemLog::TYPE_WEPAY; + + public function init() + { + + if (WePay::getEnvironment() == 'none') { + + if(config('ninja.wepay.environment') == 'staging') + WePay::useStaing(config('ninja.wepay.client_id'), config('ninja.wepay.client_secret')); + else + WePay::useProduction(config('ninja.wepay.client_id'), config('ninja.wepay.client_secret')); + + } + + if ($this->company_gateway) + $this->wepay = new WePay($this->company_gateway->getConfig()->accessToken); + + $this->wepay = new WePay(null); + + } + + public function setup(array $data) + { + return (new Setup($this))->boot($data); + } + + public function processSetup(Request $request) + { + return (new Setup($this))->processSignup($request); + } + + public function setPaymentMethod($payment_method_id) + { + $class = self::$methods[$payment_method_id]; + $this->payment_method = new $class($this); + return $this; + } + + public function authorizeView(array $data) + { + return $this->payment_method->authorizeView($data); //this is your custom implementation from here + } + + public function authorizeResponse($request) + { + return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here + } + + public function processPaymentView(array $data) + { + return $this->payment_method->paymentView($data); //this is your custom implementation from here + } + + public function processPaymentResponse($request) + { + return $this->payment_method->paymentResponse($request); //this is your custom implementation from here + } + + public function refund(Payment $payment, $amount, $return_client_response = false) + { + return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here + } + + public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) + { + return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here + } +} diff --git a/composer.json b/composer.json index 569fda98006f..72dc4b702128 100644 --- a/composer.json +++ b/composer.json @@ -70,6 +70,7 @@ "turbo124/beacon": "^1.0", "turbo124/laravel-gmail": "^5", "webpatser/laravel-countries": "dev-master#75992ad", + "wepay/php-sdk": "^0.3", "wildbit/swiftmailer-postmark": "^3.3" }, "require-dev": { @@ -136,4 +137,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 8fa65833cc1f..ada9fd8b8449 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "38a79899673526624db4d62a76dd9a5e", + "content-hash": "8ebeefd50035c907152aebf54d1dbd21", "packages": [ { "name": "asm/php-ansible", @@ -10155,6 +10155,57 @@ }, "time": "2019-07-12T14:06:05+00:00" }, + { + "name": "wepay/php-sdk", + "version": "0.3.1", + "source": { + "type": "git", + "url": "https://github.com/wepay/PHP-SDK.git", + "reference": "2a89ceb2954d117d082f869d3bfcb7864e6c2a7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wepay/PHP-SDK/zipball/2a89ceb2954d117d082f869d3bfcb7864e6c2a7d", + "reference": "2a89ceb2954d117d082f869d3bfcb7864e6c2a7d", + "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" + ], + "support": { + "issues": "https://github.com/wepay/PHP-SDK/issues", + "source": "https://github.com/wepay/PHP-SDK/tree/master" + }, + "time": "2017-01-21T07:03:26+00:00" + }, { "name": "wildbit/swiftmailer-postmark", "version": "3.3.0", diff --git a/config/ninja.php b/config/ninja.php index 4481e81ae629..b2ef34d1616d 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -148,4 +148,9 @@ return [ 'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false), 'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false), 'ninja_stripe_key' => env('NINJA_STRIPE_KEY', null), + 'wepay' => [ + 'environment' => env('WEPAY_ENVIRONMENT', 'staging'), + 'client_id' => env('WEPAY_CLIENT_ID', ''), + 'client_secret' => env('WEPAY_CLIENT_SECRET',''), + ] ]; diff --git a/database/migrations/2021_05_05_014713_activate_we_pay.php b/database/migrations/2021_05_05_014713_activate_we_pay.php new file mode 100644 index 000000000000..37ab245249c9 --- /dev/null +++ b/database/migrations/2021_05_05_014713_activate_we_pay.php @@ -0,0 +1,30 @@ +=1) + Gateway::whereIn('id', [49])->update(['visible' => true]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index 3f358f131534..1ddbef36d5e3 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -95,7 +95,7 @@ class PaymentLibrariesSeeder extends Seeder Gateway::query()->update(['visible' => 0]); - Gateway::whereIn('id', [1,15,20,39,55])->update(['visible' => 1]); + Gateway::whereIn('id', [1,15,20,39,55,49])->update(['visible' => 1]); Gateway::all()->each(function ($gateway) { $gateway->site_url = $gateway->getHelp(); diff --git a/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php b/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php new file mode 100644 index 000000000000..f8df912e7ea4 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php @@ -0,0 +1,14 @@ +@extends('portal.ninja2020.layout.clean') +@section('meta_title', ctrans('texts.sign_up_with_wepay')) + +@section('body') + + @livewire('wepay-signup', ['user_id' => $user_id, 'company_key' => $company_key]) + + +@endsection + +@push('footer') + +@endpush \ No newline at end of file diff --git a/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php b/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php new file mode 100644 index 000000000000..5d61f82f9256 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php @@ -0,0 +1,93 @@ +
+ +
+ @csrf + @method('POST') +
+
+
+
+ + + @error('first_name') +
+ {{ $message }} +
+ @enderror +
+ +
+ + + @error('last_name') +
+ {{ $message }} +
+ @enderror +
+ +
+ + + @error('email') +
+ {{ $message }} +
+ @enderror +
+ +
+ + + @error('company_name') +
+ {{ $message }} +
+ @enderror +
+ +
+ + +
+ + {{ ctrans('texts.country_United States') }} +
+ +
+ + {{ ctrans('texts.country_Canada') }} +
+ +
+ + {{ ctrans('texts.country_United Kingdom') }} +
+ +
+ +
+ +
+ + {{ ctrans('texts.enable_ach')}} +
+
+ +
+ +
+ + {!! ctrans('texts.wepay_payment_tos_agree', ['terms' => $terms, 'privacy_policy' => $privacy_policy]) !!} +
+
+ +
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 2e84a7977cc1..b18c8a593d47 100644 --- a/routes/api.php +++ b/routes/api.php @@ -199,6 +199,8 @@ Route::get('webcron', 'WebCronController@index'); Route::group(['middleware' => ['locale']], function () { Route::get('stripe_connect/{token}', 'StripeConnectController@initialize')->name('stripe_connect.initialization'); Route::get('stripe_connect/completed', 'StripeConnectController@completed')->name('stripe_connect.return'); + Route::get('wepay/signup/{token}', 'WePayController@signup')->name('wepay.signup'); + Route::post('wepay/processSignup', 'WePayController@processSignup')->name('wepay.process_signup'); }); Route::fallback('BaseController@notFound'); diff --git a/routes/client.php b/routes/client.php index fb228c2e7688..e2bc84f8618a 100644 --- a/routes/client.php +++ b/routes/client.php @@ -79,6 +79,7 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence Route::post('upload', 'ClientPortal\UploadController')->name('upload.store'); Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout'); + }); Route::get('client/subscription/{subscription}/purchase/', 'ClientPortal\SubscriptionPurchaseController@index')->name('client.subscription.purchase'); From d61e7f57a2906899715612b3f67b734f23e13beb Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 May 2021 16:21:37 +1000 Subject: [PATCH 2/6] Fixes for wepay --- app/Http/Controllers/WePayController.php | 2 +- .../ninja2020/gateways/wepay/signup/wepay-signup.blade.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/WePayController.php b/app/Http/Controllers/WePayController.php index 6dfe7496fbe8..978360948f88 100644 --- a/app/Http/Controllers/WePayController.php +++ b/app/Http/Controllers/WePayController.php @@ -44,8 +44,8 @@ class WePayController extends BaseController // $data['user_id'] = $this->encodePrimaryKey($hash['user_id']); // $data['company_key'] = $hash['company_key']; - $data['user_id'] = 1; $user = User::first(); + $data['user_id'] = $user->id; $data['company_key'] = $user->account->companies()->first()->company_key; diff --git a/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php b/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php index 5d61f82f9256..5a7f470e282d 100644 --- a/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php +++ b/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php @@ -82,6 +82,12 @@ +
+ + {{ ctrans('texts.standard_fees_apply')}} + +
+
From eb54e0705a7aedac6cd1b32cd2bd2550dcb4bf1c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 5 May 2021 16:51:45 +1000 Subject: [PATCH 3/6] We Pay logo --- public/images/wepay.svg | 383 ++++++++++++++++++ .../gateways/wepay/signup/index.blade.php | 5 + 2 files changed, 388 insertions(+) create mode 100644 public/images/wepay.svg diff --git a/public/images/wepay.svg b/public/images/wepay.svg new file mode 100644 index 000000000000..25f541e8c251 --- /dev/null +++ b/public/images/wepay.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php b/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php index f8df912e7ea4..2152b2a1a235 100644 --- a/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php +++ b/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php @@ -2,6 +2,11 @@ @section('meta_title', ctrans('texts.sign_up_with_wepay')) @section('body') + + +
+ We Pay +
@livewire('wepay-signup', ['user_id' => $user_id, 'company_key' => $company_key]) From b6c538564e7ab796b91fc98c225dde01fa7dc5b9 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 5 May 2021 19:06:55 +1000 Subject: [PATCH 4/6] Background --- .../portal/ninja2020/gateways/wepay/signup/index.blade.php | 4 ++-- routes/api.php | 3 +-- routes/web.php | 3 +++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php b/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php index 2152b2a1a235..d3149dc1b4f1 100644 --- a/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php +++ b/resources/views/portal/ninja2020/gateways/wepay/signup/index.blade.php @@ -2,7 +2,7 @@ @section('meta_title', ctrans('texts.sign_up_with_wepay')) @section('body') - +
We Pay @@ -10,7 +10,7 @@ @livewire('wepay-signup', ['user_id' => $user_id, 'company_key' => $company_key]) - +
@endsection @push('footer') diff --git a/routes/api.php b/routes/api.php index b18c8a593d47..bf3031e2688a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -199,8 +199,7 @@ Route::get('webcron', 'WebCronController@index'); Route::group(['middleware' => ['locale']], function () { Route::get('stripe_connect/{token}', 'StripeConnectController@initialize')->name('stripe_connect.initialization'); Route::get('stripe_connect/completed', 'StripeConnectController@completed')->name('stripe_connect.return'); - Route::get('wepay/signup/{token}', 'WePayController@signup')->name('wepay.signup'); - Route::post('wepay/processSignup', 'WePayController@processSignup')->name('wepay.process_signup'); + }); Route::fallback('BaseController@notFound'); diff --git a/routes/web.php b/routes/web.php index 119d7cd21921..3b3c57457606 100644 --- a/routes/web.php +++ b/routes/web.php @@ -20,6 +20,9 @@ Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail' Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset'); Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update'); +Route::get('wepay/signup/{token}', 'WePayController@signup')->name('wepay.signup'); +Route::post('wepay/processSignup', 'WePayController@processSignup')->name('wepay.process_signup'); + /* * Social authentication */ From 46d5b84fb702edd53334bd9dab369330ba949c6e Mon Sep 17 00:00:00 2001 From: = Date: Wed, 5 May 2021 19:45:31 +1000 Subject: [PATCH 5/6] Fixes for created_at and updated_at timestamps in migration --- app/Jobs/Util/Import.php | 40 +++++++++++++++++++ .../Migration/InvoiceMigrationRepository.php | 9 ++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index 9fc0a4ec0511..fc8354cd4d3a 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -488,6 +488,14 @@ class Import implements ShouldQueue ) ); + if(array_key_exists('created_at', $modified)) + $client->created_at = $modified['created_at']; + + if(array_key_exists('updated_at', $modified)) + $client->updated_at = $modified['updated_at']; + + $client->save(['timestamps' => false]); + $client->contacts()->forceDelete(); if (array_key_exists('contacts', $resource)) { // need to remove after importing new migration.json @@ -891,6 +899,14 @@ class Import implements ShouldQueue QuoteFactory::create($this->company->id, $modified['user_id']) ); + if(array_key_exists('created_at', $modified)) + $quote->created_at = $modified['created_at']; + + if(array_key_exists('updated_at', $modified)) + $quote->updated_at = $modified['updated_at']; + + $quote->save(['timestamps' => false]); + $old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id; $key = "quotes_{$resource['id']}"; @@ -957,6 +973,14 @@ class Import implements ShouldQueue PaymentFactory::create($this->company->id, $modified['user_id']) ); + if(array_key_exists('created_at', $modified)) + $payment->created_at = $modified['created_at']; + + if(array_key_exists('updated_at', $modified)) + $payment->updated_at = $modified['updated_at']; + + $payment->save(['timestamps' => false]); + if (array_key_exists('company_gateway_id', $resource) && isset($resource['company_gateway_id']) && $resource['company_gateway_id'] != 'NULL') { $payment->company_gateway_id = $this->transformId('company_gateways', $resource['company_gateway_id']); $payment->save(); @@ -1319,6 +1343,14 @@ class Import implements ShouldQueue $task = Task::Create($modified); + if(array_key_exists('created_at', $modified)) + $task->created_at = $modified['created_at']; + + if(array_key_exists('updated_at', $modified)) + $task->updated_at = $modified['updated_at']; + + $task->save(['timestamps' => false]); + $old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id; $this->ids['tasks'] = [ @@ -1399,6 +1431,14 @@ class Import implements ShouldQueue $expense = Expense::Create($modified); + if(array_key_exists('created_at', $modified)) + $expense->created_at = $modified['created_at']; + + if(array_key_exists('updated_at', $modified)) + $expense->updated_at = $modified['updated_at']; + + $expense->save(['timestamps' => false]); + $old_user_key = array_key_exists('user_id', $resource) ?? $this->user->id; $key = "expenses_{$resource['id']}"; diff --git a/app/Repositories/Migration/InvoiceMigrationRepository.php b/app/Repositories/Migration/InvoiceMigrationRepository.php index ee142650f2ba..90d8cb171a76 100644 --- a/app/Repositories/Migration/InvoiceMigrationRepository.php +++ b/app/Repositories/Migration/InvoiceMigrationRepository.php @@ -71,7 +71,14 @@ class InvoiceMigrationRepository extends BaseRepository $model->fill($tmp_data); $model->status_id = $tmp_data['status_id']; - $model->save(); + + if(array_key_exists('created_at', $data)) + $model->created_at = $data['created_at']; + + if(array_key_exists('updated_at', $data)) + $model->updated_at = $data['updated_at']; + + $model->save(['timestamps' => false]); if (array_key_exists('documents', $data)) { $this->saveDocuments($data['documents'], $model); From d3f14887e17d66f6abdd92c9ed269d020bd6cd5a Mon Sep 17 00:00:00 2001 From: = Date: Wed, 5 May 2021 20:50:36 +1000 Subject: [PATCH 6/6] WePay --- app/Http/Livewire/WepaySignup.php | 77 +++++++++++++++++-- app/PaymentDrivers/WePayPaymentDriver.php | 2 + .../wepay/signup/wepay-signup.blade.php | 15 ++-- routes/web.php | 2 +- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/app/Http/Livewire/WepaySignup.php b/app/Http/Livewire/WepaySignup.php index d90b77c18d52..0b2636d60769 100644 --- a/app/Http/Livewire/WepaySignup.php +++ b/app/Http/Livewire/WepaySignup.php @@ -13,9 +13,12 @@ namespace App\Http\Livewire; use App\Models\Company; +use App\Models\CompanyGateway; use App\Models\User; +use App\PaymentDrivers\WePayPaymentDriver; use Illuminate\Support\Facades\Hash; use Livewire\Component; +use WePay; class WepaySignup extends Component { @@ -25,6 +28,10 @@ class WepaySignup extends Component public $first_name; public $last_name; public $email; + public $company_name; + public $country; + public $ach; + public $wepay_payment_tos_agree; public $terms; public $privacy_policy; @@ -32,9 +39,13 @@ class WepaySignup extends Component public $saved; protected $rules = [ - 'first_name' => ['sometimes'], - 'last_name' => ['sometimes'], + 'first_name' => ['required'], + 'last_name' => ['required'], 'email' => ['required', 'email'], + 'company_name' => ['required'], + 'country' => ['required'], + 'ach' => ['sometimes'], + 'wepay_payment_tos_agree' => ['accepted'], ]; public function mount() @@ -43,6 +54,9 @@ class WepaySignup extends Component $company = Company::where('company_key', $this->company_key)->first(); $this->fill([ + 'wepay_payment_tos_agree' => '', + 'ach' => '', + 'country' => 'US', 'user' => $user, 'first_name' => $user->first_name, 'last_name' => $user->last_name, @@ -64,10 +78,61 @@ class WepaySignup extends Component $data = $this->validate($this->rules); - // $this->user - // ->fill($data) - // ->save(); + $this->saved = ctrans('texts.processing'); + + $wepay_driver = new WePayPaymentDriver(new CompanyGateway, null, null); + + $wepay_driver->init(); + + $user_details = [ + 'client_id' => config('ninja.wepay.client_id'), + 'client_secret' => config('ninja.wepay.client_secret'), + 'email' => $data['email'], + 'first_name' => $data['first_name'], + 'last_name' => $data['last_name'], + 'original_ip' => request()->ip(), + 'original_device' => request()->server('HTTP_USER_AGENT'), + 'tos_acceptance_time' => time(), + 'redirect_uri' => route('wepay.process_signup'), + 'scope' => 'manage_accounts,collect_payments,view_user,preapprove_payments,send_money', + ]; + + $wepay_user = $wepay_driver->request('user/register/', $user_details); + + $access_token = $wepay_user->access_token; + + $access_token_expires = $wepay_user->expires_in ? (time() + $wepay_user->expires_in) : null; + + $wepay = new WePay($access_token); + + $account_details = [ + 'name' => $data['company_name']), + 'description' => ctrans('texts.wepay_account_description'), + 'theme_object' => json_decode({"name":"Invoice Ninja","primary_color":"0b4d78","secondary_color":"0b4d78","background_color":"f8f8f8","button_color":"33b753"}), + 'callback_uri' => $accountGateway->getWebhookUrl(), + 'rbits' => $account->present()->rBits, + 'country' => $data['country'], + ]; + + if (Input::get('country') == 'CA') { + $accountDetails['currencies'] = ['CAD']; + $accountDetails['country_options'] = ['debit_opt_in' => boolval(Input::get('debit_cards'))]; + } elseif (Input::get('country') == 'GB') { + $accountDetails['currencies'] = ['GBP']; + } + + $wepayAccount = $wepay->request('account/create/', $accountDetails); + + 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; + } + } - $this->saved = ctrans('texts.saved_at', ['time' => now()->toTimeString()]); } } diff --git a/app/PaymentDrivers/WePayPaymentDriver.php b/app/PaymentDrivers/WePayPaymentDriver.php index 79253491029c..d6f281893dfe 100644 --- a/app/PaymentDrivers/WePayPaymentDriver.php +++ b/app/PaymentDrivers/WePayPaymentDriver.php @@ -59,6 +59,8 @@ class WePayPaymentDriver extends BaseDriver $this->wepay = new WePay(null); + return $this; + } public function setup(array $data) diff --git a/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php b/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php index 5a7f470e282d..74f37735eee4 100644 --- a/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php +++ b/resources/views/portal/ninja2020/gateways/wepay/signup/wepay-signup.blade.php @@ -50,17 +50,17 @@
- + {{ ctrans('texts.country_United States') }}
- + {{ ctrans('texts.country_Canada') }}
- + {{ ctrans('texts.country_United Kingdom') }}
@@ -69,7 +69,7 @@
- + {{ ctrans('texts.enable_ach')}}
@@ -77,9 +77,14 @@
- + {!! ctrans('texts.wepay_payment_tos_agree', ['terms' => $terms, 'privacy_policy' => $privacy_policy]) !!}
+ @error('wepay_payment_tos_agree') +
+ {{ $message }} +
+ @enderror
diff --git a/routes/web.php b/routes/web.php index 3b3c57457606..60fb651c3a11 100644 --- a/routes/web.php +++ b/routes/web.php @@ -21,7 +21,7 @@ Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update'); Route::get('wepay/signup/{token}', 'WePayController@signup')->name('wepay.signup'); -Route::post('wepay/processSignup', 'WePayController@processSignup')->name('wepay.process_signup'); +Route::get('wepay/processSignup', 'WePayController@processSignup')->name('wepay.process_signup'); /* * Social authentication