From b5697966b544956c11a97807c957d716f613e57d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 22 Jul 2021 11:30:16 +1000 Subject: [PATCH 01/33] eway --- app/Models/Gateway.php | 3 + app/PaymentDrivers/Eway/CreditCard.php | 58 ++++++++++ app/PaymentDrivers/EwayPaymentDriver.php | 104 ++++++++++++++++++ app/PaymentDrivers/Sample/CreditCard.php | 72 ++++++++++++ .../PaymentDriver.php} | 7 +- .../Sample/resources/authorize.blade.php | 34 ++++++ .../Sample/resources/pay.blade.php | 64 +++++++++++ composer.json | 1 + composer.lock | 60 +++++++++- ...21_234227_activate_eway_payment_driver.php | 35 ++++++ database/seeders/PaymentLibrariesSeeder.php | 4 +- .../gateways/eway/authorize.blade.php | 34 ++++++ 12 files changed, 468 insertions(+), 8 deletions(-) create mode 100644 app/PaymentDrivers/Eway/CreditCard.php create mode 100644 app/PaymentDrivers/EwayPaymentDriver.php create mode 100644 app/PaymentDrivers/Sample/CreditCard.php rename app/PaymentDrivers/{DriverTemplate.php => Sample/PaymentDriver.php} (89%) create mode 100644 app/PaymentDrivers/Sample/resources/authorize.blade.php create mode 100644 app/PaymentDrivers/Sample/resources/pay.blade.php create mode 100644 database/migrations/2021_07_21_234227_activate_eway_payment_driver.php create mode 100644 resources/views/portal/ninja2020/gateways/eway/authorize.blade.php diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 32fc20999409..a99f27d737e1 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -81,6 +81,9 @@ class Gateway extends StaticModel case 1: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net break; + case 3: + return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//eWay + break; case 15: return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal break; diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php new file mode 100644 index 000000000000..8a4d5a07a248 --- /dev/null +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -0,0 +1,58 @@ +eway = $eway; + } + + public function authorizeView($data) + { + + } + + public function authorizeRequest($request) + { + + } + + public function paymentView($data) + { + + } + + public function processPaymentResponse($request) + { + + } +} \ No newline at end of file diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php new file mode 100644 index 000000000000..a96fd503bdaa --- /dev/null +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -0,0 +1,104 @@ + CreditCard::class, //maps GatewayType => Implementation class + ]; + + const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model + + public function init() + { + $apiKey = $this->company_gateway->getConfigField('apiKey'); + $password = $this->company_gateway->getConfigField('password'); + $apiEndpoint = $this->company_gateway->getConfigField('testMode') ? \Eway\Rapid\Client::MODE_SANDBOX : \Eway\Rapid\Client::MODE_PRODUCTION; + $this->eway = \Eway\Rapid::createClient($apiKey, $apiPassword, $apiEndpoint); + + return $this; + } + + /* Returns an array of gateway types for the payment gateway */ + public function gatewayTypes(): array + { + $types = []; + + $types[] = GatewayType::CREDIT_CARD; + + return $types; + } + + /* Sets the payment method initialized */ + 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 + } + + public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) + { + } +} diff --git a/app/PaymentDrivers/Sample/CreditCard.php b/app/PaymentDrivers/Sample/CreditCard.php new file mode 100644 index 000000000000..12e4d872bfcd --- /dev/null +++ b/app/PaymentDrivers/Sample/CreditCard.php @@ -0,0 +1,72 @@ +driver_class = $driver_class; + } + + public function authorizeView($data) + { + + } + + public function authorizeRequest($request) + { + + } + + public function paymentView($data) + { + + } + + public function processPaymentResponse($request) + { + + } + + + /* Helpers */ + + /* + You will need some helpers to handle successful and unsuccessful responses + + Some considerations after a succesful transaction include: + + Logging of events: success +/- failure + Recording a payment + Notifications + */ + + +} \ No newline at end of file diff --git a/app/PaymentDrivers/DriverTemplate.php b/app/PaymentDrivers/Sample/PaymentDriver.php similarity index 89% rename from app/PaymentDrivers/DriverTemplate.php rename to app/PaymentDrivers/Sample/PaymentDriver.php index 36c0f9bf5b72..401ceec3aed9 100644 --- a/app/PaymentDrivers/DriverTemplate.php +++ b/app/PaymentDrivers/Sample/PaymentDriver.php @@ -17,10 +17,9 @@ use App\Models\GatewayType; use App\Models\Payment; use App\Models\PaymentHash; use App\Models\SystemLog; -use App\PaymentDrivers\Stripe\CreditCard; use App\Utils\Traits\MakesHash; -class DriverTemplate extends BaseDriver +class PaymentDriver extends BaseDriver { use MakesHash; @@ -85,12 +84,12 @@ class DriverTemplate extends BaseDriver public function refund(Payment $payment, $amount, $return_client_response = false) { - return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here + //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 + //this is your custom implementation from here } public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) diff --git a/app/PaymentDrivers/Sample/resources/authorize.blade.php b/app/PaymentDrivers/Sample/resources/authorize.blade.php new file mode 100644 index 000000000000..74773c67172a --- /dev/null +++ b/app/PaymentDrivers/Sample/resources/authorize.blade.php @@ -0,0 +1,34 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) + +@section('gateway_head') +@endsection + +@section('gateway_content') +
+ + @if(!Request::isSecure()) +

{{ ctrans('texts.https_required') }}

+ @endif + + + + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')]) + {{ ctrans('texts.credit_card') }} + @endcomponent + +
+ +
+ +
+@endsection + +@section('gateway_footer') + +@endsection diff --git a/app/PaymentDrivers/Sample/resources/pay.blade.php b/app/PaymentDrivers/Sample/resources/pay.blade.php new file mode 100644 index 000000000000..4f8841bca6bb --- /dev/null +++ b/app/PaymentDrivers/Sample/resources/pay.blade.php @@ -0,0 +1,64 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) + +@section('gateway_head') +@endsection + +@section('gateway_content') +
+ + + + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')]) + {{ ctrans('texts.credit_card') }} + @endcomponent + + @include('portal.ninja2020.gateways.includes.payment_details') + + <-- If there are existing tokens available these are displayed here for you --> + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')]) + @if(count($tokens) > 0) + @foreach($tokens as $token) + + @endforeach + @endisset + + + @endcomponent + + + @include('portal.ninja2020.gateways.includes.save_card') + + + @include('portal.ninja2020.gateways.wepay.includes.credit_card') + + @include('portal.ninja2020.gateways.includes.pay_now') + +
+@endsection + +@section('gateway_footer') + +@endsection + diff --git a/composer.json b/composer.json index 151dd8239ab6..9eb6220ab516 100644 --- a/composer.json +++ b/composer.json @@ -41,6 +41,7 @@ "codedge/laravel-selfupdater": "^3.2", "composer/composer": "^2", "doctrine/dbal": "^2.10", + "eway/eway-rapid-php": "^1.3", "fakerphp/faker": "^1.14", "fideloper/proxy": "^4.2", "fruitcake/laravel-cors": "^2.0", diff --git a/composer.lock b/composer.lock index 15b58365b9a7..243a75a5c5d6 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": "d2beb37ff5fbee59ad4bb792e944eb10", + "content-hash": "c9f7d76428c6f556ae531570b7761bf5", "packages": [ { "name": "asm/php-ansible", @@ -1964,6 +1964,62 @@ ], "time": "2020-12-29T14:50:06+00:00" }, + { + "name": "eway/eway-rapid-php", + "version": "v1.3.4", + "source": { + "type": "git", + "url": "https://github.com/eWAYPayment/eway-rapid-php.git", + "reference": "5b765d83ef69e1783f391ae85aed48d47dd5f8eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/eWAYPayment/eway-rapid-php/zipball/5b765d83ef69e1783f391ae85aed48d47dd5f8eb", + "reference": "5b765d83ef69e1783f391ae85aed48d47dd5f8eb", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "internations/http-mock": "~0.7", + "jeremeamia/superclosure": "1.0.2", + "phpdocumentor/phpdocumentor": "~2.8", + "phpunit/phpunit": "4.8.*", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Eway\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "eWAY", + "homepage": "https://www.eway.com.au" + } + ], + "description": "eWAY Rapid PHP library", + "homepage": "https://www.eway.com.au", + "keywords": [ + "eway", + "payment processing", + "payments", + "rapid" + ], + "support": { + "issues": "https://github.com/eWAYPayment/eway-rapid-php/issues", + "source": "https://github.com/eWAYPayment/eway-rapid-php/tree/master" + }, + "time": "2016-09-12T05:46:41+00:00" + }, { "name": "fakerphp/faker", "version": "v1.15.0", @@ -14881,5 +14937,5 @@ "platform-dev": { "php": "^7.3|^7.4|^8.0" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } diff --git a/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php b/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php new file mode 100644 index 000000000000..18b23cb826d1 --- /dev/null +++ b/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php @@ -0,0 +1,35 @@ +visible = true; + $eway->provider = 'Eway'; + $eway->save(); + } + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index b9ff0f84146f..4a5374beb2d5 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -27,7 +27,7 @@ class PaymentLibrariesSeeder extends Seeder '], ['id' => 2, 'name' => 'CardSave', 'provider' => 'CardSave', 'key' => '46c5c1fed2c43acf4f379bae9c8b9f76', 'fields' => '{"merchantId":"","password":""} '], - ['id' => 3, 'name' => 'Eway Rapid', 'provider' => 'Eway_RapidShared', 'is_offsite' => true, 'key' => '944c20175bbe6b9972c05bcfe294c2c7', 'fields' => '{"apiKey":"","password":"","testMode":false}'], + ['id' => 3, 'name' => 'Eway Rapid', 'provider' => 'Eway', 'is_offsite' => true, 'key' => '944c20175bbe6b9972c05bcfe294c2c7', 'fields' => '{"apiKey":"","password":"","testMode":false}'], ['id' => 4, 'name' => 'FirstData Connect', 'provider' => 'FirstData_Connect', 'key' => '4e0ed0d34552e6cb433506d1ac03a418', 'fields' => '{"storeId":"","sharedSecret":"","testMode":false}'], ['id' => 5, 'name' => 'Migs ThreeParty', 'provider' => 'Migs_ThreeParty', 'key' => '513cdc81444c87c4b07258bc2858d3fa', 'fields' => '{"merchantId":"","merchantAccessCode":"","secureHash":""}'], ['id' => 6, 'name' => 'Migs TwoParty', 'provider' => 'Migs_TwoParty', 'key' => '99c2a271b5088951334d1302e038c01a', 'fields' => '{"merchantId":"","merchantAccessCode":"","secureHash":""}'], @@ -96,7 +96,7 @@ class PaymentLibrariesSeeder extends Seeder Gateway::query()->update(['visible' => 0]); - Gateway::whereIn('id', [1,15,20,39,55,50])->update(['visible' => 1]); + Gateway::whereIn('id', [1,3,15,20,39,55,50])->update(['visible' => 1]); if (Ninja::isHosted()) { Gateway::whereIn('id', [20])->update(['visible' => 0]); diff --git a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php new file mode 100644 index 000000000000..74773c67172a --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php @@ -0,0 +1,34 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) + +@section('gateway_head') +@endsection + +@section('gateway_content') +
+ + @if(!Request::isSecure()) +

{{ ctrans('texts.https_required') }}

+ @endif + + + + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.method')]) + {{ ctrans('texts.credit_card') }} + @endcomponent + +
+ +
+ +
+@endsection + +@section('gateway_footer') + +@endsection From 437bb735d6baf206f8dec3b290d0628feea1c67b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 22 Jul 2021 16:05:58 +1000 Subject: [PATCH 02/33] Working on eWay --- app/Models/SystemLog.php | 2 +- app/PaymentDrivers/Eway/CreditCard.php | 27 +++++++- app/PaymentDrivers/EwayPaymentDriver.php | 2 +- ...21_234227_activate_eway_payment_driver.php | 5 ++ database/seeders/PaymentLibrariesSeeder.php | 2 +- .../gateways/eway/authorize.blade.php | 69 ++++++++++++++++++- .../eway/includes/credit_card.blade.php | 15 ++++ 7 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 resources/views/portal/ninja2020/gateways/eway/includes/credit_card.blade.php diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index 7614c01ecccc..4e0f739af243 100644 --- a/app/Models/SystemLog.php +++ b/app/Models/SystemLog.php @@ -68,7 +68,7 @@ class SystemLog extends Model const TYPE_BRAINTREE = 307; const TYPE_WEPAY = 309; const TYPE_PAYFAST = 310; - + const TYPE_EWAY = 311; const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 8a4d5a07a248..c4d68ba37af6 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -29,21 +29,42 @@ use Illuminate\Support\Str; class CreditCard { - public $eway; + public $eway_driver; - public function __construct(EwayPaymentDriver $eway) + public function __construct(EwayPaymentDriver $eway_driver) { - $this->eway = $eway; + $this->eway_driver = $eway_driver; } public function authorizeView($data) { + $data['gateway'] = $this->eway_driver; + $data['api_key'] = $this->eway_driver->company_gateway->getConfigField('apiKey'); + $data['public_api_key'] = 'epk-8C1675E6-8E07-4C86-8946-71B3DE390F44'; + + return render('gateways.eway.authorize', $data); + } public function authorizeRequest($request) { + $transaction = [ + 'Title' => 'Mr.', + 'FirstName' => 'John', + 'LastName' => 'Smith', + 'Country' => 'au', + 'Payment' => [ + 'TotalAmount' => 0, + ], + 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, + 'Method' => \Eway\Rapid\Enum\PaymentMethod::CREATE_TOKEN_CUSTOMER, + 'SecuredCardData' => $request->input('SecuredCardData'), + ]; + + $response = $client->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + } public function paymentView($data) diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index a96fd503bdaa..925d1df9589d 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -38,7 +38,7 @@ class EwayPaymentDriver extends BaseDriver GatewayType::CREDIT_CARD => CreditCard::class, //maps GatewayType => Implementation class ]; - const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model + const SYSTEM_LOG_TYPE = SystemLog::TYPE_EWAY; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model public function init() { diff --git a/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php b/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php index 18b23cb826d1..a0fc56152ddd 100644 --- a/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php +++ b/database/migrations/2021_07_21_234227_activate_eway_payment_driver.php @@ -18,6 +18,11 @@ class ActivateEwayPaymentDriver extends Migration { $eway->visible = true; $eway->provider = 'Eway'; + + $fields = json_decode($eway->fields); + $fields->publicApiKey = ''; + $eway->fields = json_encode($fields); + $eway->save(); } diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index 4a5374beb2d5..d90c4692f657 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -27,7 +27,7 @@ class PaymentLibrariesSeeder extends Seeder '], ['id' => 2, 'name' => 'CardSave', 'provider' => 'CardSave', 'key' => '46c5c1fed2c43acf4f379bae9c8b9f76', 'fields' => '{"merchantId":"","password":""} '], - ['id' => 3, 'name' => 'Eway Rapid', 'provider' => 'Eway', 'is_offsite' => true, 'key' => '944c20175bbe6b9972c05bcfe294c2c7', 'fields' => '{"apiKey":"","password":"","testMode":false}'], + ['id' => 3, 'name' => 'Eway Rapid', 'provider' => 'Eway', 'is_offsite' => true, 'key' => '944c20175bbe6b9972c05bcfe294c2c7', 'fields' => '{"apiKey":"","password":"","publicApiKey":"",testMode":false}'], ['id' => 4, 'name' => 'FirstData Connect', 'provider' => 'FirstData_Connect', 'key' => '4e0ed0d34552e6cb433506d1ac03a418', 'fields' => '{"storeId":"","sharedSecret":"","testMode":false}'], ['id' => 5, 'name' => 'Migs ThreeParty', 'provider' => 'Migs_ThreeParty', 'key' => '513cdc81444c87c4b07258bc2858d3fa', 'fields' => '{"merchantId":"","merchantAccessCode":"","secureHash":""}'], ['id' => 6, 'name' => 'Migs TwoParty', 'provider' => 'Migs_TwoParty', 'key' => '99c2a271b5088951334d1302e038c01a', 'fields' => '{"merchantId":"","merchantAccessCode":"","secureHash":""}'], diff --git a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php index 74773c67172a..55912ed4724f 100644 --- a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php @@ -4,8 +4,10 @@ @endsection @section('gateway_content') -
- + + + + @if(!Request::isSecure())

{{ ctrans('texts.https_required') }}

@endif @@ -17,6 +19,8 @@ {{ ctrans('texts.credit_card') }} @endcomponent + @include('portal.ninja2020.gateways.eway.includes.credit_card') +
-
- -
+ @component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card']) + {{ ctrans('texts.add_payment_method') }} + @endcomponent + @endsection @section('gateway_footer') - - + + - - + document + .getElementById('authorize-card') + .addEventListener('click', () => { + console.log('Clicked..'); + // document.getElementById('server_response').submit(); + }); + @endsection From 99e9d6d977c7357d3198ee7507c07207024a16bb Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 26 Jul 2021 13:33:03 +1000 Subject: [PATCH 05/33] Change eway implmentation --- app/PaymentDrivers/Eway/CreditCard.php | 23 +- app/PaymentDrivers/EwayPaymentDriver.php | 6 +- .../gateways/eway/authorize.blade.php | 358 +++++++++++++++--- 3 files changed, 326 insertions(+), 61 deletions(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index c4d68ba37af6..426b19834a1d 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -41,20 +41,34 @@ class CreditCard $data['gateway'] = $this->eway_driver; $data['api_key'] = $this->eway_driver->company_gateway->getConfigField('apiKey'); - $data['public_api_key'] = 'epk-8C1675E6-8E07-4C86-8946-71B3DE390F44'; + $data['public_api_key'] = $this->eway_driver->company_gateway->getConfigField('publicApiKey'); return render('gateways.eway.authorize', $data); } - public function authorizeRequest($request) + public function authorizeResponse($request) { - $transaction = [ + $this->eway_driver->init(); + + $transaction = [ + 'Reference' => 'A12345', 'Title' => 'Mr.', 'FirstName' => 'John', 'LastName' => 'Smith', + 'CompanyName' => 'Demo Shop 123', + 'JobDescription' => 'PHP Developer', + 'Street1' => 'Level 5', + 'Street2' => '369 Queen Street', + 'City' => 'Sydney', + 'State' => 'NSW', + 'PostalCode' => '2000', 'Country' => 'au', + 'Phone' => '09 889 0986', + 'Mobile' => '09 889 6542', + 'Email' => 'demo@example.org', + "Url" => "http://www.ewaypayments.com", 'Payment' => [ 'TotalAmount' => 0, ], @@ -63,8 +77,9 @@ class CreditCard 'SecuredCardData' => $request->input('SecuredCardData'), ]; - $response = $client->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + $response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); +dd($response); } public function paymentView($data) diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index 925d1df9589d..7ed47e69e525 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -43,7 +43,7 @@ class EwayPaymentDriver extends BaseDriver public function init() { $apiKey = $this->company_gateway->getConfigField('apiKey'); - $password = $this->company_gateway->getConfigField('password'); + $apiPassword = $this->company_gateway->getConfigField('password'); $apiEndpoint = $this->company_gateway->getConfigField('testMode') ? \Eway\Rapid\Client::MODE_SANDBOX : \Eway\Rapid\Client::MODE_PRODUCTION; $this->eway = \Eway\Rapid::createClient($apiKey, $apiPassword, $apiEndpoint); @@ -70,12 +70,12 @@ class EwayPaymentDriver extends BaseDriver public function authorizeView(array $data) { - return $this->payment_method->authorizeView($data); //this is your custom implementation from here + return $this->payment_method->authorizeView($data); } public function authorizeResponse($request) { - return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here + return $this->payment_method->authorizeResponse($request); } public function processPaymentView(array $data) diff --git a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php index 1730abdf596e..1081a9980942 100644 --- a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php @@ -7,9 +7,12 @@ ctrans('texts.credit_card')]) @section('gateway_content')
+ @csrf - + + + @if (!Request::isSecure())

{{ ctrans('texts.https_required') }}

@endif @@ -21,7 +24,7 @@ ctrans('texts.credit_card')]) {{ ctrans('texts.credit_card') }} @endcomponent - @include('portal.ninja2020.gateways.eway.includes.credit_card') +
@component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'authorize-card']) {{ ctrans('texts.add_payment_method') }} @@ -31,63 +34,310 @@ ctrans('texts.credit_card')]) @section('gateway_footer') - + - +function doneCallback() { + console.log("done callback"); + var form = document.getElementById("payment_form"); + form.submit(); +} + +function saveAndSubmit() { + eWAY.saveAllFields(doneCallback, 2000); + return false; +} + +document +.getElementById('authorize-card') +.addEventListener('click', () => { + + saveAndSubmit(); + +}); + +function getError(k){ + myArr = k.split(" "); + + var str = ""; + + for(error in myArr){ + str = str.concat(map.get(myArr[error])) + '\n'; + } + + return str; +} + +const map = new Map(); +map.set('V6000', 'Validation error'); +map.set('V6001', 'Invalid CustomerIP'); +map.set('V6002', 'Invalid DeviceID'); +map.set('V6003', 'Invalid Request PartnerID'); +map.set('V6004', 'Invalid Request Method'); +map.set('V6010', 'Invalid TransactionType, account not certified for eCome only MOTO or Recurring available'); +map.set('V6011', 'Invalid Payment TotalAmount'); +map.set('V6012', 'Invalid Payment InvoiceDescription'); +map.set('V6013', 'Invalid Payment InvoiceNumber'); +map.set('V6014', 'Invalid Payment InvoiceReference'); +map.set('V6015', 'Invalid Payment CurrencyCode'); +map.set('V6016', 'Payment Required'); +map.set('V6017', 'Payment CurrencyCode Required'); +map.set('V6018', 'Unknown Payment CurrencyCode'); +map.set('V6019', 'Cardholder identity authentication required'); +map.set('V6020', 'Cardholder Input Required'); +map.set('V6021', 'EWAY_CARDHOLDERNAME Required'); +map.set('V6022', 'EWAY_CARDNUMBER Required'); +map.set('V6023', 'EWAY_CARDCVN Required'); +map.set('V6024', 'Cardholder Identity Authentication One Time Password Not Active Yet'); +map.set('V6025', 'PIN Required'); +map.set('V6033', 'Invalid Expiry Date'); +map.set('V6034', 'Invalid Issue Number'); +map.set('V6035', 'Invalid Valid From Date'); +map.set('V6039', 'Invalid Network Token Status'); +map.set('V6040', 'Invalid TokenCustomerID'); +map.set('V6041', 'Customer Required'); +map.set('V6042', 'Customer FirstName Required'); +map.set('V6043', 'Customer LastName Required'); +map.set('V6044', 'Customer CountryCode Required'); +map.set('V6045', 'Customer Title Required'); +map.set('V6046', 'TokenCustomerID Required'); +map.set('V6047', 'RedirectURL Required'); +map.set('V6048', 'CheckoutURL Required when CheckoutPayment specified'); +map.set('V6049', 'nvalid Checkout URL'); +map.set('V6051', 'Invalid Customer FirstName'); +map.set('V6052', 'Invalid Customer LastName'); +map.set('V6053', 'Invalid Customer CountryCode'); +map.set('V6058', 'Invalid Customer Title'); +map.set('V6059', 'Invalid RedirectURL'); +map.set('V6060', 'Invalid TokenCustomerID'); +map.set('V6061', 'Invalid Customer Reference'); +map.set('V6062', 'Invalid Customer CompanyName'); +map.set('V6063', 'Invalid Customer JobDescription'); +map.set('V6064', 'Invalid Customer Street1'); +map.set('V6065', 'Invalid Customer Street2'); +map.set('V6066', 'Invalid Customer City'); +map.set('V6067', 'Invalid Customer State'); +map.set('V6068', 'Invalid Customer PostalCode'); +map.set('V6069', 'Invalid Customer Email'); +map.set('V6070', 'Invalid Customer Phone'); +map.set('V6071', 'Invalid Customer Mobile'); +map.set('V6072', 'Invalid Customer Comments'); +map.set('V6073', 'Invalid Customer Fax'); +map.set('V6074', 'Invalid Customer URL'); +map.set('V6075', 'Invalid ShippingAddress FirstName'); +map.set('V6076', 'Invalid ShippingAddress LastName'); +map.set('V6077', 'Invalid ShippingAddress Street1'); +map.set('V6078', 'Invalid ShippingAddress Street2'); +map.set('V6079', 'Invalid ShippingAddress City'); +map.set('V6080', 'Invalid ShippingAddress State'); +map.set('V6081', 'Invalid ShippingAddress PostalCode'); +map.set('V6082', 'Invalid ShippingAddress Email'); +map.set('V6083', 'Invalid ShippingAddress Phone'); +map.set('V6084', 'Invalid ShippingAddress Country'); +map.set('V6085', 'Invalid ShippingAddress ShippingMethod'); +map.set('V6086', 'Invalid ShippingAddress Fax'); +map.set('V6091', 'Unknown Customer CountryCode'); +map.set('V6092', 'Unknown ShippingAddress CountryCode'); +map.set('V6093', 'Insufficient Address Information'); +map.set('V6100', 'Invalid EWAY_CARDNAME'); +map.set('V6101', 'Invalid EWAY_CARDEXPIRYMONTH'); +map.set('V6102', 'Invalid EWAY_CARDEXPIRYYEAR'); +map.set('V6103', 'Invalid EWAY_CARDSTARTMONTH'); +map.set('V6104', 'Invalid EWAY_CARDSTARTYEAR'); +map.set('V6105', 'Invalid EWAY_CARDISSUENUMBER'); +map.set('V6106', 'Invalid EWAY_CARDCVN'); +map.set('V6107', 'Invalid EWAY_ACCESSCODE'); +map.set('V6108', 'Invalid CustomerHostAddress'); +map.set('V6109', 'Invalid UserAgent'); +map.set('V6110', 'Invalid EWAY_CARDNUMBER'); +map.set('V6111', 'Unauthorised API Access, Account Not PCI Certified'); +map.set('V6112', 'Redundant card details other than expiry year and month'); +map.set('V6113', 'Invalid transaction for refund'); +map.set('V6114', 'Gateway validation error'); +map.set('V6115', 'Invalid DirectRefundRequest, Transaction ID'); +map.set('V6116', 'Invalid card data on original TransactionID'); +map.set('V6117', 'Invalid CreateAccessCodeSharedRequest, FooterText'); +map.set('V6118', 'Invalid CreateAccessCodeSharedRequest, HeaderText'); +map.set('V6119', 'Invalid CreateAccessCodeSharedRequest, Language'); +map.set('V6120', 'Invalid CreateAccessCodeSharedRequest, LogoUrl'); +map.set('V6121', 'Invalid TransactionSearch, Filter Match Type'); +map.set('V6122', 'Invalid TransactionSearch, Non numeric Transaction ID'); +map.set('V6123', 'Invalid TransactionSearch,no TransactionID or AccessCode specified'); +map.set('V6124', 'Invalid Line Items. The line items have been provided however the totals do not match the TotalAmount field'); +map.set('V6125', 'Selected Payment Type not enabled'); +map.set('V6126', 'Invalid encrypted card number, decryption failed'); +map.set('V6127', 'Invalid encrypted cvn, decryption failed'); +map.set('V6128', 'Invalid Method for Payment Type'); +map.set('V6129', 'Transaction has not been authorised for Capture/Cancellation'); +map.set('V6130', 'Generic customer information error'); +map.set('V6131', 'Generic shipping information error'); +map.set('V6132', 'Transaction has already been completed or voided, operation not permitted'); +map.set('V6133', 'Checkout not available for Payment Type'); +map.set('V6134', 'Invalid Auth Transaction ID for Capture/Void'); +map.set('V6135', 'PayPal Error Processing Refund'); +map.set('V6136', 'Original transaction does not exist or state is incorrect'); +map.set('V6140', 'Merchant account is suspended'); +map.set('V6141', 'Invalid PayPal account details or API signature'); +map.set('V6142', 'Authorise not available for Bank/Branch'); +map.set('V6143', 'Invalid Public Key'); +map.set('V6144', 'Method not available with Public API Key Authentication'); +map.set('V6145', 'Credit Card not allow if Token Customer ID is provided with Public API Key Authentication'); +map.set('V6146', 'Client Side Encryption Key Missing or Invalid'); +map.set('V6147', 'Unable to Create One Time Code for Secure Field'); +map.set('V6148', 'Secure Field has Expired'); +map.set('V6149', 'Invalid Secure Field One Time Code'); +map.set('V6150', 'Invalid Refund Amount'); +map.set('V6151', 'Refund amount greater than original transaction'); +map.set('V6152', 'Original transaction already refunded for total amount'); +map.set('V6153', 'Card type not support by merchant'); +map.set('V6154', 'Insufficent Funds Available For Refund'); +map.set('V6155', 'Missing one or more fields in request'); +map.set('V6160', 'Encryption Method Not Supported'); +map.set('V6161', 'Encryption failed, missing or invalid key'); +map.set('V6165', 'Invalid Click-to-Pay (Visa Checkout) data or decryption failed'); +map.set('V6170', 'Invalid TransactionSearch, Invoice Number is not unique'); +map.set('V6171', 'Invalid TransactionSearch, Invoice Number not found'); +map.set('V6220', 'Three domain secure XID invalid'); +map.set('V6221', 'Three domain secure ECI invalid'); +map.set('V6222', 'Three domain secure AVV invalid'); +map.set('V6223', 'Three domain secure XID is required'); +map.set('V6224', 'Three Domain Secure ECI is required'); +map.set('V6225', 'Three Domain Secure AVV is required'); +map.set('V6226', 'Three Domain Secure AuthStatus is required'); +map.set('V6227', 'Three Domain Secure AuthStatus invalid'); +map.set('V6228', 'Three domain secure Version is required'); +map.set('V6230', 'Three domain secure Directory Server Txn ID invalid'); +map.set('V6231', 'Three domain secure Directory Server Txn ID is required'); +map.set('V6232', 'Three domain secure Version is invalid'); +map.set('V6501', 'Invalid Amex InstallementPlan'); +map.set('V6502', 'Invalid Number Of Installements for Amex. Valid values are from 0 to 99 inclusive'); +map.set('V6503', 'Merchant Amex ID required'); +map.set('V6504', 'Invalid Merchant Amex ID'); +map.set('V6505', 'Merchant Terminal ID required'); +map.set('V6506', 'Merchant category code required'); +map.set('V6507', 'Invalid merchant category code'); +map.set('V6508', 'Amex 3D ECI required'); +map.set('V6509', 'Invalid Amex 3D ECI'); +map.set('V6510', 'Invalid Amex 3D verification value'); +map.set('V6511', 'Invalid merchant location data'); +map.set('V6512', 'Invalid merchant street address'); +map.set('V6513', 'Invalid merchant city'); +map.set('V6514', 'Invalid merchant country'); +map.set('V6515', 'Invalid merchant phone'); +map.set('V6516', 'Invalid merchant postcode'); +map.set('V6517', 'Amex connection error'); +map.set('V6518', 'Amex EC Card Details API returned invalid data'); +map.set('V6520', 'Invalid or missing Amex Point Of Sale Data'); +map.set('V6521', 'Invalid or missing Amex transaction date time'); +map.set('V6522', 'Invalid or missing Amex Original transaction date time'); +map.set('V6530', 'Credit Card Number in non Credit Card Field'); + + + + @endsection From c0c9c00c809b7a364481c7a2df8fe367ea1db757 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 26 Jul 2021 13:53:02 +1000 Subject: [PATCH 06/33] eWay error codes --- app/PaymentDrivers/Eway/CreditCard.php | 122 +++++++++++++++++++++---- app/PaymentDrivers/Eway/ErrorCode.php | 94 +++++++++++++++++++ 2 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 app/PaymentDrivers/Eway/ErrorCode.php diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 426b19834a1d..c340a7db9734 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -47,28 +47,91 @@ class CreditCard } + /* + Eway\Rapid\Model\Response\CreateCustomerResponse {#2374 ▼ + #fillable: array:16 [▶] + #errors: [] + #attributes: array:11 [▼ + "AuthorisationCode" => null + "ResponseCode" => "00" + "ResponseMessage" => "A2000" + "TransactionID" => null + "TransactionStatus" => false + "TransactionType" => "MOTO" + "BeagleScore" => null + "Verification" => Eway\Rapid\Model\Verification {#2553 ▼ + #fillable: array:5 [▶] + #attributes: array:5 [▶] + } + "Customer" => Eway\Rapid\Model\Customer {#2504 ▼ + #fillable: array:38 [▶] + #attributes: array:20 [▼ + "CardDetails" => Eway\Rapid\Model\CardDetails {#2455 ▼ + #fillable: array:8 [▶] + #attributes: array:7 [▼ + "Number" => "411111XXXXXX1111" + "Name" => "Joey Diaz" + "ExpiryMonth" => "10" + "ExpiryYear" => "23" + "StartMonth" => null + "StartYear" => null + "IssueNumber" => null + ] + } + "TokenCustomerID" => 917047257342 + "Reference" => "A12345" + "Title" => "Mr." + "FirstName" => "John" + "LastName" => "Smith" + "CompanyName" => "Demo Shop 123" + "JobDescription" => "PHP Developer" + "Street1" => "Level 5" + "Street2" => "369 Queen Street" + "City" => "Sydney" + "State" => "NSW" + "PostalCode" => "2000" + "Country" => "au" + "Email" => "demo@example.org" + "Phone" => "09 889 0986" + "Mobile" => "09 889 6542" + "Comments" => "" + "Fax" => "" + "Url" => "http://www.ewaypayments.com" + ] + } + "Payment" => Eway\Rapid\Model\Payment {#2564 ▼ + #fillable: array:5 [▶] + #attributes: array:5 [▼ + "TotalAmount" => 0 + "InvoiceNumber" => "" + "InvoiceDescription" => "" + "InvoiceReference" => "" + "CurrencyCode" => "AUD" + ] + } + "Errors" => null + ] +} + */ + public function authorizeResponse($request) { - $this->eway_driver->init(); - - $transaction = [ - 'Reference' => 'A12345', - 'Title' => 'Mr.', - 'FirstName' => 'John', - 'LastName' => 'Smith', - 'CompanyName' => 'Demo Shop 123', - 'JobDescription' => 'PHP Developer', - 'Street1' => 'Level 5', - 'Street2' => '369 Queen Street', - 'City' => 'Sydney', - 'State' => 'NSW', - 'PostalCode' => '2000', - 'Country' => 'au', - 'Phone' => '09 889 0986', - 'Mobile' => '09 889 6542', - 'Email' => 'demo@example.org', - "Url" => "http://www.ewaypayments.com", + $transaction = [ + 'Reference' => $this->eway_driver->client->number, + 'Title' => '', + 'FirstName' => $this->eway_driver->client->primary_contact()->present()->last_name(), + 'LastName' => $this->eway_driver->client->primary_contact()->present()->first_name(), + 'CompanyName' => $this->eway_driver->client->name, + 'Street1' => $this->eway_driver->client->address1, + 'Street2' => $this->eway_driver->client->address2, + 'City' => $this->eway_driver->client->city, + 'State' => $this->eway_driver->client->state, + 'PostalCode' => $this->eway_driver->client->postal_code, + 'Country' => $this->eway_driver->client->country->iso_3166_2, + 'Phone' => $this->eway_driver->client->phone, + 'Email' => $this->eway_driver->client->primary_contact()->email, + "Url" => $this->eway_driver->client->website, 'Payment' => [ 'TotalAmount' => 0, ], @@ -79,7 +142,26 @@ class CreditCard $response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); -dd($response); + nlog($response); + + //success + $cgt = []; + $cgt['token'] = $data['token']; + $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; + + $payment_meta = new \stdClass; + $payment_meta->exp_month = 'xx'; + $payment_meta->exp_year = 'xx'; + $payment_meta->brand = 'CC'; + $payment_meta->last4 = 'xxxx'; + $payment_meta->type = GatewayType::CREDIT_CARD; + + $cgt['payment_meta'] = $payment_meta; + + $token = $this->eway_driver->storeGatewayToken($cgt, []); + + return redirect()->route('client.payment_methods.index'); + } public function paymentView($data) diff --git a/app/PaymentDrivers/Eway/ErrorCode.php b/app/PaymentDrivers/Eway/ErrorCode.php new file mode 100644 index 000000000000..71a44fad27bc --- /dev/null +++ b/app/PaymentDrivers/Eway/ErrorCode.php @@ -0,0 +1,94 @@ + "Transaction Approved"], + ["A2008" => "Honour With Identification"], + ["A2010" => "Approved For Partial Amount"], + ["A2011" => "Approved, VIP"], + ["A2016" => "Approved, Update Track 3"], + ], + + public $failure = [ + ["D4401" => "Refer to Issuer"], + ["D4402" => "Refer to Issuer, special"], + ["D4403" => "No Merchant"], + ["D4404" => "Pick Up Card"], + ["D4405" => "Do Not Honour"], + ["D4406" => "Error"], + ["D4407" => "Pick Up Card, Special"], + ["D4409" => "Request In Progress"], + ["D4412" => "Invalid Transaction"], + ["D4413" => "Invalid Amount"], + ["D4414" => "Invalid Card Number"], + ["D4415" => "No Issuer"], + ["D4417" => "3D Secure Error"], + ["D4419" => "Re-enter Last Transaction"], + ["D4421" => "No Action Taken"], + ["D4422" => "Suspected Malfunction"], + ["D4423" => "Unacceptable Transaction Fee"], + ["D4425" => "Unable to Locate Record On File"], + ["D4430" => "Format Error"], + ["D4431" => "Bank Not Supported By Switch"], + ["D4433" => "Expired Card, Capture"], + ["D4434" => "Suspected Fraud, Retain Card"], + ["D4435" => "Card Acceptor, Contact Acquirer, Retain Card"], + ["D4436" => "Restricted Card, Retain Card"], + ["D4437" => "Contact Acquirer Security Department, Retain Card"], + ["D4438" => "PIN Tries Exceeded, Capture"], + ["D4439" => "No Credit Account"], + ["D4440" => "Function Not Supported"], + ["D4441" => "Lost Card"], + ["D4442" => "No Universal Account"], + ["D4443" => "Stolen Card"], + ["D4444" => "No Investment Account"], + ["D4450" => "Click-to-Pay (Visa Checkout) Transaction"], + ["D4451" => "Insufficient Funds"], + ["D4452" => "No Cheque Account"], + ["D4453" => "No Savings Account"], + ["D4454" => "Expired Card"], + ["D4455" => "Incorrect PIN"], + ["D4456" => "No Card Record"], + ["D4457" => "Function Not Permitted to Cardholder"], + ["D4458" => "Function Not Permitted to Terminal"], + ["D4459" => "Suspected Fraud"], + ["D4460" => "Acceptor Contact Acquirer"], + ["D4461" => "Exceeds Withdrawal Limit"], + ["D4462" => "Restricted Card"], + ["D4463" => "Security Violation"], + ["D4464" => "Original Amount Incorrect"], + ["D4466" => "Acceptor Contact Acquirer, Security"], + ["D4467" => "Capture Card"], + ["D4475" => "PIN Tries Exceeded"], + ["D4476" => "Invalidate Txn Reference"], + ["D4481" => "Accumulated Transaction Counter (Amount) Exceeded"], + ["D4482" => "CVV Validation Error"], + ["D4483" => "Acquirer Is Not Accepting Transactions From You At This Time"], + ["D4484" => "Acquirer Is Not Accepting This Transaction"], + ["D4490" => "Cut off In Progress"], + ["D4491" => "Card Issuer Unavailable"], + ["D4492" => "Unable To Route Transaction"], + ["D4493" => "Cannot Complete, Violation Of The Law"], + ["D4494" => "Duplicate Transaction"], + ["D4495" => "Amex Declined"], + ["D4496" => "System Error"], + ["D4497" => "MasterPass Error"], + ["D4498" => "PayPal Create Transaction Error"], + ["D4499" => "Invalid Transaction for Auth/Void"], + ]; + +} \ No newline at end of file From 90198e6b7a7e9be53251559400acf9b5822e3156 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 27 Jul 2021 07:03:33 +1000 Subject: [PATCH 07/33] Minor fixes for entity sent description --- app/Mail/Admin/EntitySentObject.php | 4 ++-- app/Notifications/Admin/EntitySentNotification.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Mail/Admin/EntitySentObject.php b/app/Mail/Admin/EntitySentObject.php index 3b9003e07e59..570c149b1cfe 100644 --- a/app/Mail/Admin/EntitySentObject.php +++ b/app/Mail/Admin/EntitySentObject.php @@ -121,7 +121,7 @@ class EntitySentObject ctrans( $this->template_subject, [ - 'client' => $this->contact->present()->name(), + 'client' => $this->contact->client->present()->name(), 'invoice' => $this->entity->number, ] ); @@ -133,7 +133,7 @@ class EntitySentObject $this->template_body, [ 'amount' => $this->getAmount(), - 'client' => $this->contact->present()->name(), + 'client' => $this->contact->client->present()->name(), 'invoice' => $this->entity->number, ] ); diff --git a/app/Notifications/Admin/EntitySentNotification.php b/app/Notifications/Admin/EntitySentNotification.php index 33a735bce188..4d38c3c083a4 100644 --- a/app/Notifications/Admin/EntitySentNotification.php +++ b/app/Notifications/Admin/EntitySentNotification.php @@ -103,14 +103,14 @@ class EntitySentNotification extends Notification "texts.notification_{$this->entity_name}_sent_subject", [ 'amount' => $amount, - 'client' => $this->contact->present()->name(), + 'client' => $this->contact->client->present()->name(), 'invoice' => $this->entity->number, ] )) ->attachment(function ($attachment) use ($amount) { $attachment->title(ctrans('texts.invoice_number_placeholder', ['invoice' => $this->entity->number]), $this->invitation->getAdminLink()) ->fields([ - ctrans('texts.client') => $this->contact->present()->name(), + ctrans('texts.client') => $this->contact->client->present()->name(), ctrans('texts.amount') => $amount, ]); }); From 8db20c1fcade0168d22cf5a9af58e98003e79589 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 27 Jul 2021 12:49:13 +1000 Subject: [PATCH 08/33] Fixes for eWay --- app/PaymentDrivers/Eway/CreditCard.php | 28 ++-- app/PaymentDrivers/Eway/ErrorCode.php | 159 ++++++++++++----------- app/PaymentDrivers/EwayPaymentDriver.php | 43 ++++++ 3 files changed, 144 insertions(+), 86 deletions(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index c340a7db9734..a04aea1a4cfd 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -22,6 +22,7 @@ use App\Models\PaymentHash; use App\Models\PaymentType; use App\Models\SystemLog; use App\PaymentDrivers\EwayPaymentDriver; +use App\PaymentDrivers\Eway\ErrorCode; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; @@ -120,8 +121,8 @@ class CreditCard $transaction = [ 'Reference' => $this->eway_driver->client->number, 'Title' => '', - 'FirstName' => $this->eway_driver->client->primary_contact()->present()->last_name(), - 'LastName' => $this->eway_driver->client->primary_contact()->present()->first_name(), + 'FirstName' => $this->eway_driver->client->contacts()->first()->present()->last_name(), + 'LastName' => $this->eway_driver->client->contacts()->first()->present()->first_name(), 'CompanyName' => $this->eway_driver->client->name, 'Street1' => $this->eway_driver->client->address1, 'Street2' => $this->eway_driver->client->address2, @@ -130,30 +131,33 @@ class CreditCard 'PostalCode' => $this->eway_driver->client->postal_code, 'Country' => $this->eway_driver->client->country->iso_3166_2, 'Phone' => $this->eway_driver->client->phone, - 'Email' => $this->eway_driver->client->primary_contact()->email, + 'Email' => $this->eway_driver->client->contacts()->first()->email, "Url" => $this->eway_driver->client->website, - 'Payment' => [ - 'TotalAmount' => 0, - ], - 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, + // 'Payment' => [ + // 'TotalAmount' => 0, + // ], + // 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, 'Method' => \Eway\Rapid\Enum\PaymentMethod::CREATE_TOKEN_CUSTOMER, 'SecuredCardData' => $request->input('SecuredCardData'), ]; $response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); - nlog($response); + $response_status = ErrorCode::getStatus($response->ResponseMessage); + + if(!$response_status['success']) + throw new PaymentFailed($response_status['message'], 400); //success $cgt = []; - $cgt['token'] = $data['token']; + $cgt['token'] = $response->Customer->TokenCustomerID; $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; $payment_meta = new \stdClass; - $payment_meta->exp_month = 'xx'; - $payment_meta->exp_year = 'xx'; + $payment_meta->exp_month = $response->Customer->CardDetails->ExpiryMonth; + $payment_meta->exp_year = $response->Customer->CardDetails->ExpiryYear; $payment_meta->brand = 'CC'; - $payment_meta->last4 = 'xxxx'; + $payment_meta->last4 = $response->Customer->CardDetails->Number; $payment_meta->type = GatewayType::CREDIT_CARD; $cgt['payment_meta'] = $payment_meta; diff --git a/app/PaymentDrivers/Eway/ErrorCode.php b/app/PaymentDrivers/Eway/ErrorCode.php index 71a44fad27bc..94a0bc138a93 100644 --- a/app/PaymentDrivers/Eway/ErrorCode.php +++ b/app/PaymentDrivers/Eway/ErrorCode.php @@ -15,80 +15,91 @@ namespace App\PaymentDrivers\Eway; class ErrorCode { - public $success = [ - ["A2000" => "Transaction Approved"], - ["A2008" => "Honour With Identification"], - ["A2010" => "Approved For Partial Amount"], - ["A2011" => "Approved, VIP"], - ["A2016" => "Approved, Update Track 3"], - ], - - public $failure = [ - ["D4401" => "Refer to Issuer"], - ["D4402" => "Refer to Issuer, special"], - ["D4403" => "No Merchant"], - ["D4404" => "Pick Up Card"], - ["D4405" => "Do Not Honour"], - ["D4406" => "Error"], - ["D4407" => "Pick Up Card, Special"], - ["D4409" => "Request In Progress"], - ["D4412" => "Invalid Transaction"], - ["D4413" => "Invalid Amount"], - ["D4414" => "Invalid Card Number"], - ["D4415" => "No Issuer"], - ["D4417" => "3D Secure Error"], - ["D4419" => "Re-enter Last Transaction"], - ["D4421" => "No Action Taken"], - ["D4422" => "Suspected Malfunction"], - ["D4423" => "Unacceptable Transaction Fee"], - ["D4425" => "Unable to Locate Record On File"], - ["D4430" => "Format Error"], - ["D4431" => "Bank Not Supported By Switch"], - ["D4433" => "Expired Card, Capture"], - ["D4434" => "Suspected Fraud, Retain Card"], - ["D4435" => "Card Acceptor, Contact Acquirer, Retain Card"], - ["D4436" => "Restricted Card, Retain Card"], - ["D4437" => "Contact Acquirer Security Department, Retain Card"], - ["D4438" => "PIN Tries Exceeded, Capture"], - ["D4439" => "No Credit Account"], - ["D4440" => "Function Not Supported"], - ["D4441" => "Lost Card"], - ["D4442" => "No Universal Account"], - ["D4443" => "Stolen Card"], - ["D4444" => "No Investment Account"], - ["D4450" => "Click-to-Pay (Visa Checkout) Transaction"], - ["D4451" => "Insufficient Funds"], - ["D4452" => "No Cheque Account"], - ["D4453" => "No Savings Account"], - ["D4454" => "Expired Card"], - ["D4455" => "Incorrect PIN"], - ["D4456" => "No Card Record"], - ["D4457" => "Function Not Permitted to Cardholder"], - ["D4458" => "Function Not Permitted to Terminal"], - ["D4459" => "Suspected Fraud"], - ["D4460" => "Acceptor Contact Acquirer"], - ["D4461" => "Exceeds Withdrawal Limit"], - ["D4462" => "Restricted Card"], - ["D4463" => "Security Violation"], - ["D4464" => "Original Amount Incorrect"], - ["D4466" => "Acceptor Contact Acquirer, Security"], - ["D4467" => "Capture Card"], - ["D4475" => "PIN Tries Exceeded"], - ["D4476" => "Invalidate Txn Reference"], - ["D4481" => "Accumulated Transaction Counter (Amount) Exceeded"], - ["D4482" => "CVV Validation Error"], - ["D4483" => "Acquirer Is Not Accepting Transactions From You At This Time"], - ["D4484" => "Acquirer Is Not Accepting This Transaction"], - ["D4490" => "Cut off In Progress"], - ["D4491" => "Card Issuer Unavailable"], - ["D4492" => "Unable To Route Transaction"], - ["D4493" => "Cannot Complete, Violation Of The Law"], - ["D4494" => "Duplicate Transaction"], - ["D4495" => "Amex Declined"], - ["D4496" => "System Error"], - ["D4497" => "MasterPass Error"], - ["D4498" => "PayPal Create Transaction Error"], - ["D4499" => "Invalid Transaction for Auth/Void"], + private static $success = [ + "A2000" => "Transaction Approved", + "A2008" => "Honour With Identification", + "A2010" => "Approved For Partial Amount", + "A2011" => "Approved, VIP", + "A2016" => "Approved, Update Track 3", ]; + private static $failure = [ + "D4401" => "Refer to Issuer", + "D4402" => "Refer to Issuer, special", + "D4403" => "No Merchant", + "D4404" => "Pick Up Card", + "D4405" => "Do Not Honour", + "D4406" => "Error", + "D4407" => "Pick Up Card, Special", + "D4409" => "Request In Progress", + "D4412" => "Invalid Transaction", + "D4413" => "Invalid Amount", + "D4414" => "Invalid Card Number", + "D4415" => "No Issuer", + "D4417" => "3D Secure Error", + "D4419" => "Re-enter Last Transaction", + "D4421" => "No Action Taken", + "D4422" => "Suspected Malfunction", + "D4423" => "Unacceptable Transaction Fee", + "D4425" => "Unable to Locate Record On File", + "D4430" => "Format Error", + "D4431" => "Bank Not Supported By Switch", + "D4433" => "Expired Card, Capture", + "D4434" => "Suspected Fraud, Retain Card", + "D4435" => "Card Acceptor, Contact Acquirer, Retain Card", + "D4436" => "Restricted Card, Retain Card", + "D4437" => "Contact Acquirer Security Department, Retain Card", + "D4438" => "PIN Tries Exceeded, Capture", + "D4439" => "No Credit Account", + "D4440" => "Function Not Supported", + "D4441" => "Lost Card", + "D4442" => "No Universal Account", + "D4443" => "Stolen Card", + "D4444" => "No Investment Account", + "D4450" => "Click-to-Pay (Visa Checkout) Transaction", + "D4451" => "Insufficient Funds", + "D4452" => "No Cheque Account", + "D4453" => "No Savings Account", + "D4454" => "Expired Card", + "D4455" => "Incorrect PIN", + "D4456" => "No Card Record", + "D4457" => "Function Not Permitted to Cardholder", + "D4458" => "Function Not Permitted to Terminal", + "D4459" => "Suspected Fraud", + "D4460" => "Acceptor Contact Acquirer", + "D4461" => "Exceeds Withdrawal Limit", + "D4462" => "Restricted Card", + "D4463" => "Security Violation", + "D4464" => "Original Amount Incorrect", + "D4466" => "Acceptor Contact Acquirer, Security", + "D4467" => "Capture Card", + "D4475" => "PIN Tries Exceeded", + "D4476" => "Invalidate Txn Reference", + "D4481" => "Accumulated Transaction Counter (Amount) Exceeded", + "D4482" => "CVV Validation Error", + "D4483" => "Acquirer Is Not Accepting Transactions From You At This Time", + "D4484" => "Acquirer Is Not Accepting This Transaction", + "D4490" => "Cut off In Progress", + "D4491" => "Card Issuer Unavailable", + "D4492" => "Unable To Route Transaction", + "D4493" => "Cannot Complete, Violation Of The Law", + "D4494" => "Duplicate Transaction", + "D4495" => "Amex Declined", + "D4496" => "System Error", + "D4497" => "MasterPass Error", + "D4498" => "PayPal Create Transaction Error", + "D4499" => "Invalid Transaction for Auth/Void", + ]; + + + public static function getStatus($code) + { + if(array_key_exists($code, self::$success)) + return ['success' => true, 'message' => self::$success[$code]]; + + if(array_key_exists($code, self::$failure)) + return ['success' => false, 'message' => self::$failure[$code]]; + + return ['success' => false, 'message' => "Unknown error message code - {$code}"]; + } } \ No newline at end of file diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index 7ed47e69e525..260723172bff 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -101,4 +101,47 @@ class EwayPaymentDriver extends BaseDriver public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) { } + + public function getClientRequiredFields(): array + { + $fields = []; + $fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required,email:rfc']; + $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; + + if ($this->company_gateway->require_client_name) { + $fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required']; + } + + // if ($this->company_gateway->require_contact_name) { + // } + + // if ($this->company_gateway->require_contact_email) { + // } + + if ($this->company_gateway->require_client_phone) { + $fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required']; + } + + if ($this->company_gateway->require_billing_address) { + $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; + } + + if($this->company_gateway->require_postal_code) + $fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required']; + + if ($this->company_gateway->require_shipping_address) { + $fields[] = ['name' => 'client_shipping_address_line_1', 'label' => ctrans('texts.shipping_address1'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_city', 'label' => ctrans('texts.shipping_city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_state', 'label' => ctrans('texts.shipping_state'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_postal_code', 'label' => ctrans('texts.shipping_postal_code'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_country_id', 'label' => ctrans('texts.shipping_country'), 'type' => 'text', 'validation' => 'required']; + } + + + return $fields; + } } From 8040b0a8f99bbab474e163d38df78dee07064f3d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 27 Jul 2021 14:03:04 +1000 Subject: [PATCH 09/33] eWay Process Payment --- app/PaymentDrivers/Eway/CreditCard.php | 7 +- .../gateways/eway/authorize.blade.php | 290 +---------------- .../eway/includes/credit_card.blade.php | 304 +++++++++++++++++- .../ninja2020/gateways/eway/pay.blade.php | 94 ++++++ 4 files changed, 391 insertions(+), 304 deletions(-) create mode 100644 resources/views/portal/ninja2020/gateways/eway/pay.blade.php diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index a04aea1a4cfd..c656ec8b0922 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -157,7 +157,7 @@ class CreditCard $payment_meta->exp_month = $response->Customer->CardDetails->ExpiryMonth; $payment_meta->exp_year = $response->Customer->CardDetails->ExpiryYear; $payment_meta->brand = 'CC'; - $payment_meta->last4 = $response->Customer->CardDetails->Number; + $payment_meta->last4 = substr($response->Customer->CardDetails->Number, -4);; $payment_meta->type = GatewayType::CREDIT_CARD; $cgt['payment_meta'] = $payment_meta; @@ -171,6 +171,11 @@ class CreditCard public function paymentView($data) { + $data['gateway'] = $this->eway_driver; + $data['public_api_key'] = $this->eway_driver->company_gateway->getConfigField('publicApiKey'); + + return render('gateways.eway.pay', $data); + } public function processPaymentResponse($request) diff --git a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php index 1081a9980942..cd41a3b9a283 100644 --- a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php @@ -36,122 +36,14 @@ ctrans('texts.credit_card')]) +@include('portal.ninja2020.gateways.eway.includes.credt_card') + @endsection diff --git a/resources/views/portal/ninja2020/gateways/eway/includes/credit_card.blade.php b/resources/views/portal/ninja2020/gateways/eway/includes/credit_card.blade.php index e462c5d42fdf..3d2730fcf759 100644 --- a/resources/views/portal/ninja2020/gateways/eway/includes/credit_card.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/includes/credit_card.blade.php @@ -1,15 +1,289 @@ -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ \ No newline at end of file diff --git a/resources/views/portal/ninja2020/gateways/eway/pay.blade.php b/resources/views/portal/ninja2020/gateways/eway/pay.blade.php new file mode 100644 index 000000000000..e58ffcabc759 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/eway/pay.blade.php @@ -0,0 +1,94 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) + +@section('gateway_head') +@endsection + +@section('gateway_content') + + @csrf + + + + + + + + + + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) + {{ ctrans('texts.credit_card') }} + @endcomponent + + @include('portal.ninja2020.gateways.includes.payment_details') + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')]) + @if(count($tokens) > 0) + @foreach($tokens as $token) + + @endforeach + @endisset + + + @endcomponent + +
+ + + @include('portal.ninja2020.gateways.includes.save_card') +
+ + + + @include('portal.ninja2020.gateways.includes.pay_now') +@endsection + +@section('gateway_footer') + + @include('portal.ninja2020.gateways.eway.includes.credit_card') + + + + + +@endsection From b061506091f6b5df761a66bcd7b9c26f787ec7b8 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 27 Jul 2021 15:14:29 +1000 Subject: [PATCH 10/33] Token Payments --- app/PaymentDrivers/Eway/Token.php | 111 +++++++++++++++++++++++ app/PaymentDrivers/EwayPaymentDriver.php | 20 +++- app/PaymentDrivers/Sample/CreditCard.php | 41 +++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 app/PaymentDrivers/Eway/Token.php diff --git a/app/PaymentDrivers/Eway/Token.php b/app/PaymentDrivers/Eway/Token.php new file mode 100644 index 000000000000..1bdbc2ed18a0 --- /dev/null +++ b/app/PaymentDrivers/Eway/Token.php @@ -0,0 +1,111 @@ +eway_driver = $eway_driver; + } + + public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) + { + + $amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total; + + $transaction = [ + 'Customer' => [ + 'TokenCustomerID' => $cgt->token, + ], + 'Payment' => [ + 'TotalAmount' => $this->eway_driver->convertAmount($amount), + ], + 'TransactionType' => \Eway\Rapid\Enum\TransactionType::RECURRING, + ]; + + $response = $this->eway_driver->init()->eway->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + + $response_status = ErrorCode::getStatus($response->ResponseMessage); + + if(!$response_status['success']) + return $this->processUnsuccessfulPayment($response); + + $payment = $this->processSuccessfulPayment($response); + + return $payment; + + } + + + private function processSuccessfulPayment($response) + { + $amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total; + + $data = [ + 'gateway_type_id' => $cgt->gateway_type_id, + 'payment_type' => GatewayType::CREDIT_CARD_OTHER, + 'transaction_reference' => $response->Customer->Reference, + 'amount' => $amount, + ]; + + $payment = $this->eway_driver->createPayment($data); + $payment->meta = $cgt->meta; + $payment->save(); + + $payment_hash->payment_id = $payment->id; + $payment_hash->save(); + + return $payment; + + } + + private function processUnsuccessfulPayment($response) + { + + $response_status = ErrorCode::getStatus($response->ResponseMessage); + + $error = $response_status['message'] + $error_code = $response->ResponseMessage; + + $data = [ + 'response' => $response, + 'error' => $error, + 'error_code' => $error_code, + ]; + + return $this->driver_class->processUnsuccessfulTransaction($data); + + } + +} \ No newline at end of file diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index 260723172bff..5a6154fda388 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -18,6 +18,7 @@ use App\Models\Payment; use App\Models\PaymentHash; use App\Models\SystemLog; use App\PaymentDrivers\Eway\CreditCard; +use App\PaymentDrivers\Eway\Token; use App\Utils\Traits\MakesHash; class EwayPaymentDriver extends BaseDriver @@ -95,13 +96,30 @@ class EwayPaymentDriver extends BaseDriver public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) { - return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here + return (new Token($this))->tokenBilling($cgt, $payment_hash); } public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) { } + public function convertAmount($amount) + { + $precision = $this->client->currency()->precision; + + if($precision == 0) + return $amount; + + if($precision == 1) + return $amount*10; + + if$precision == 2) + return $amount*100; + + + return $amount; + } + public function getClientRequiredFields(): array { $fields = []; diff --git a/app/PaymentDrivers/Sample/CreditCard.php b/app/PaymentDrivers/Sample/CreditCard.php index 12e4d872bfcd..44c404ae2611 100644 --- a/app/PaymentDrivers/Sample/CreditCard.php +++ b/app/PaymentDrivers/Sample/CreditCard.php @@ -21,12 +21,14 @@ use App\Models\Payment; use App\Models\PaymentHash; use App\Models\PaymentType; use App\Models\SystemLog; +use App\Utils\Traits\MakesHash; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; class CreditCard { + use MakesHash; public $driver_class; @@ -55,6 +57,43 @@ class CreditCard } + /* This method is stubbed ready to go - you just need to harvest the equivalent 'transaction_reference' */ + private function processSuccessfulPayment($response) + { + $amount = array_sum(array_column($this->driver_class->payment_hash->invoices(), 'amount')) + $this->driver_class->payment_hash->fee_total; + + $payment_record = []; + $payment_record['amount'] = $amount; + $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER; + $payment_record['gateway_type_id'] = GatewayType::CREDIT_CARD; + // $payment_record['transaction_reference'] = $response->transaction_id; + + $payment = $this->driver_class->createPayment($payment_record, Payment::STATUS_COMPLETED); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + + } + + private function processUnsuccessfulPayment($response) + { + /*Harvest your own errors here*/ + // $error = $response->status_message; + + // if(property_exists($response, 'approval_message') && $response->approval_message) + // $error .= " - {$response->approval_message}"; + + // $error_code = property_exists($response, 'approval_message') ? $response->approval_message : 'Undefined code'; + + $data = [ + 'response' => $response, + 'error' => $error, + 'error_code' => $error_code, + ]; + + return $this->driver_class->processUnsuccessfulTransaction($data); + + } + /* Helpers */ @@ -69,4 +108,6 @@ class CreditCard */ + + } \ No newline at end of file From 9ef77e8b534302bab69f66657a78d69a96143bca Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 27 Jul 2021 15:41:31 +1000 Subject: [PATCH 11/33] Token and Refunding from eWay --- app/Models/User.php | 1 - app/PaymentDrivers/EwayPaymentDriver.php | 35 +++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index 8533c211784c..0960745a4d63 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -182,7 +182,6 @@ class User extends Authenticatable implements MustVerifyEmail return $company_token->company; } - // return false; throw new \Exception('No Company Found'); //return Company::find(config('ninja.company_id')); diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index 5a6154fda388..0c6f15fbfe29 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -91,7 +91,40 @@ class EwayPaymentDriver extends BaseDriver public function refund(Payment $payment, $amount, $return_client_response = false) { - return $this->payment_method->yourRefundImplementationHere(); //this is your custom implementation from here + + $refund = [ + 'Refund' => [ + 'TransactionID' => $payment->transaction_reference, + 'TotalAmount' => $this->convertAmount($amount) + ], + ]; + + $response = $this->init()->eway->client->refund($refund); + + $transaction_reference = ''; + $refund_status = true; + $refund_message = ''; + + if ($response->TransactionStatus) { + $transaction_reference = $response->TransactionID; + } else { + if ($response->getErrors()) { + foreach ($response->getErrors() as $error) { + $refund_status = false; + $refund_message = \Eway\Rapid::getMessage($error); + } + } else { + $refund_status = false; + $refund_message 'Sorry, your refund failed'; + } + } + return [ + 'transaction_reference' => $response->TransactionID, + 'transaction_response' => json_encode($response), + 'success' => $refund_status, + 'description' => $refund_message, + 'code' => '', + ]; } public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) From 01852f94361ce8b91dda857c79156d8b0048c628 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 9 Aug 2021 15:44:28 +1000 Subject: [PATCH 12/33] Fixes for eway --- app/PaymentDrivers/EwayPaymentDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index 0c6f15fbfe29..66dc23c9a443 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -115,7 +115,7 @@ class EwayPaymentDriver extends BaseDriver } } else { $refund_status = false; - $refund_message 'Sorry, your refund failed'; + $refund_message = 'Sorry, your refund failed'; } } return [ @@ -146,7 +146,7 @@ class EwayPaymentDriver extends BaseDriver if($precision == 1) return $amount*10; - if$precision == 2) + if($precision == 2) return $amount*100; From f7727da19291f7d3cb1bca1cdf47ed4887a14fe7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 12 Aug 2021 14:34:44 +1000 Subject: [PATCH 13/33] Check that contacts are an array --- app/Http/Requests/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index 5ad2e358ba1a..c90d9485c742 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -134,7 +134,7 @@ class Request extends FormRequest } } - if (isset($input['contacts'])) { + if (isset($input['contacts']) && is_array($input['contacts'])) { foreach ($input['contacts'] as $key => $contact) { if (array_key_exists('id', $contact) && is_numeric($contact['id'])) { unset($input['contacts'][$key]['id']); From 68c9ee33af3e385f87716851210e06ccb7844380 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 12 Aug 2021 21:02:12 +1000 Subject: [PATCH 14/33] fixes for eway --- app/PaymentDrivers/Eway/CreditCard.php | 5 +++-- .../portal/ninja2020/gateways/eway/authorize.blade.php | 6 +++--- .../ninja2020/gateways/eway/includes/credit_card.blade.php | 7 +++++-- .../views/portal/ninja2020/gateways/eway/pay.blade.php | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index c656ec8b0922..3338c8aaf5b9 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -138,7 +138,7 @@ class CreditCard // ], // 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, 'Method' => \Eway\Rapid\Enum\PaymentMethod::CREATE_TOKEN_CUSTOMER, - 'SecuredCardData' => $request->input('SecuredCardData'), + 'SecuredCardData' => $request->input('securefieldcode'), ]; $response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); @@ -178,7 +178,8 @@ class CreditCard } - public function processPaymentResponse($request) + + public function paymentResponse($request) { } diff --git a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php index cd41a3b9a283..19fced509956 100644 --- a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php @@ -6,10 +6,10 @@ ctrans('texts.credit_card')]) @section('gateway_content')
+ method="post" id="server-response"> @csrf - + @@ -36,7 +36,7 @@ ctrans('texts.credit_card')]) -@include('portal.ninja2020.gateways.eway.includes.credt_card') +@include('portal.ninja2020.gateways.eway.includes.credit_card') + -@include('portal.ninja2020.gateways.eway.includes.credit_card') + + if (document.getElementById('authorize-card')) { + document.getElementById('authorize-card').disabled = false; + } + + document.querySelector("input[name=securefieldcode]").value = event.secureFieldCode; + } + + handleErrors(errors) { + let _errors = errors.split(' '); + let shouldShowGenericError = false; + let message = ''; + + _errors.forEach((error) => { + message = message.concat(this.errorCodes.get(error) + '
'); + }) + + document.getElementById('errors').innerHTML = message; + document.getElementById('errors').hidden = false; + } + + handleAuthorization(event) { + event.target.parentElement.disabled = true; + + document.getElementById('server-response').submit(); + } + + initialize() { + this.eWAY = eWAY.setupSecureField(this.groupFieldConfig, (event) => this.securePanelCallback(event)) + } + + handle() { + this.initialize(); + + document + .getElementById('authorize-card') + ?.addEventListener('click', (e) => this.handleAuthorization(e)) + } + } + + new EwayRapid().handle() + @endsection From b91449f7274c0f2f698f1f972bb06adab4eb1840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 15:47:01 +0200 Subject: [PATCH 16/33] Add option to pass `disabled` to `pay_now` component --- .../views/portal/ninja2020/gateways/includes/pay_now.blade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/views/portal/ninja2020/gateways/includes/pay_now.blade.php b/resources/views/portal/ninja2020/gateways/includes/pay_now.blade.php index ea005a0cb8cd..74f8189f811b 100644 --- a/resources/views/portal/ninja2020/gateways/includes/pay_now.blade.php +++ b/resources/views/portal/ninja2020/gateways/includes/pay_now.blade.php @@ -4,7 +4,8 @@ type="{{ $type ?? 'button' }}" id="{{ $id ?? 'pay-now' }}" @isset($data) @foreach($data as $prop => $value) data-{{ $prop }}="{{ $value }}" @endforeach @endisset - class="button button-primary bg-primary {{ $class ?? '' }}"> + class="button button-primary bg-primary {{ $class ?? '' }}" + {{ isset($disabled) && $disabled === true ? 'disabled' : '' }}> + + + + + @endsection @section('gateway_content') @@ -226,7 +230,7 @@ ctrans('texts.credit_card')]) styles: "margin-top: 15px;", label: { fieldColSpan: 4, - text: "Card Name:", + text: document.querySelector('meta[name=translation-card-name]')?.content, styles: "", }, field: { @@ -241,7 +245,7 @@ ctrans('texts.credit_card')]) styles: "margin-top: 15px;", label: { fieldColSpan: 4, - text: "Expiry:", + text: document.querySelector('meta[name=translation-expiry_date]')?.content, styles: "", }, field: { @@ -260,7 +264,7 @@ ctrans('texts.credit_card')]) styles: "margin-top: 15px;", label: { fieldColSpan: 4, - text: "Card Number:", + text: document.querySelector('meta[name=translation-card_number]')?.content, styles: "", }, field: { @@ -274,7 +278,7 @@ ctrans('texts.credit_card')]) styles: "margin-top: 15px;", label: { fieldColSpan: 4, - text: "CVV Number:", + text: document.querySelector('meta[name=translation-cvv]')?.content, styles: "", }, field: { From 393c218c4c12be249cecdbdaccbb9b95a9dc6bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:12:23 +0200 Subject: [PATCH 18/33] Refactor Eway payment page --- .../ninja2020/gateways/eway/pay.blade.php | 418 ++++++++++++++++-- 1 file changed, 375 insertions(+), 43 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/eway/pay.blade.php b/resources/views/portal/ninja2020/gateways/eway/pay.blade.php index c45af17bb420..1d73902f7168 100644 --- a/resources/views/portal/ninja2020/gateways/eway/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/pay.blade.php @@ -1,6 +1,12 @@ -@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => ctrans('texts.credit_card')]) +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.credit_card'), 'card_title' => +ctrans('texts.credit_card')]) @section('gateway_head') + + + + + @endsection @section('gateway_content') @@ -24,72 +30,398 @@ @include('portal.ninja2020.gateways.includes.payment_details') @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')]) - @if(count($tokens) > 0) - @foreach($tokens as $token) + @if (count($tokens) > 0) + @foreach ($tokens as $token) @endforeach @endisset @endcomponent -
- - + @component('portal.ninja2020.components.general.card-element-single') +
+ @endcomponent + @include('portal.ninja2020.gateways.includes.save_card') -
- - - @include('portal.ninja2020.gateways.includes.pay_now') + @include('portal.ninja2020.gateways.includes.pay_now', ['disabled' => true]) @endsection @section('gateway_footer') + - @include('portal.ninja2020.gateways.eway.includes.credit_card') - + + document.querySelector("input[name=securefieldcode]").value = event.secureFieldCode; + } + handleErrors(errors) { + let _errors = errors.split(' '); + let shouldShowGenericError = false; + let message = ''; + + _errors.forEach((error) => { + message = message.concat(this.errorCodes.get(error) + '
'); + }) + + document.getElementById('errors').innerHTML = message; + document.getElementById('errors').hidden = false; + } + + completeAuthorization(event) { + event.target.parentElement.disabled = true; + + document.getElementById('server-response').submit(); + } + + completePaymentUsingToken(event) { + event.target.parentElement.disabled = true; + + document.getElementById('server-response').submit(); + } + + completePaymentWithoutToken(event) { + event.target.parentElement.disabled = true; + + let tokenBillingCheckbox = document.querySelector( + 'input[name="token-billing-checkbox"]:checked' + ); + + if (tokenBillingCheckbox) { + document.querySelector('input[name="store_card"]').value = + tokenBillingCheckbox.value; + } + + document.getElementById('server-response').submit(); + } + + initialize() { + this.eWAY = eWAY.setupSecureField(this.groupFieldConfig, (event) => this.securePanelCallback(event)) + } + + handle() { + this.initialize(); + + document + .getElementById('authorize-card') + ?.addEventListener('click', (e) => this.completeAuthorization(e)) + + Array + .from(document.getElementsByClassName('toggle-payment-with-token')) + .forEach((element) => element.addEventListener('click', (element) => { + document.getElementById('eway-secure-panel').classList.add('hidden'); + document.getElementById('save-card--container').style.display = 'none'; + document.querySelector('input[name=token]').value = element.target.dataset.token; + document.getElementById('pay-now').disabled = false; + })); + + document + .getElementById('toggle-payment-with-credit-card') + .addEventListener('click', (element) => { + document.getElementById('eway-secure-panel').classList.remove('hidden'); + document.getElementById('save-card--container').style.display = 'grid'; + document.querySelector('input[name=token]').value = ""; + document.getElementById('pay-now').disabled = true; + }); + + document + .getElementById('pay-now') + ?.addEventListener('click', (e) => { + let tokenInput = document.querySelector('input[name=token]'); + + if (tokenInput.value) { + return this.completePaymentUsingToken(e); + } + + return this.completePaymentWithoutToken(e); + }); + } + } + + new EwayRapid().handle() + @endsection From 0a7a0566154e5db1d1dde8d0cbccdbbd131249fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:16:23 +0200 Subject: [PATCH 19/33] Extract scripts to separate file --- .../js/clients/payments/eway-credit-card.js | 510 ++++++++++++++++++ .../gateways/eway/authorize.blade.php | 307 +---------- .../ninja2020/gateways/eway/pay.blade.php | 367 +------------ webpack.mix.js | 4 + 4 files changed, 516 insertions(+), 672 deletions(-) create mode 100644 resources/js/clients/payments/eway-credit-card.js diff --git a/resources/js/clients/payments/eway-credit-card.js b/resources/js/clients/payments/eway-credit-card.js new file mode 100644 index 000000000000..3b0c3f6053c8 --- /dev/null +++ b/resources/js/clients/payments/eway-credit-card.js @@ -0,0 +1,510 @@ +/** + * Invoice Ninja (https://invoiceninja.com). + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://www.elastic.co/licensing/elastic-license + */ + +class EwayRapid { + constructor() { + this.cardStyles = + 'padding: 2px; border: 1px solid #AAA; border-radius: 3px; height: 34px; width: 100%;'; + + this.errorCodes = new Map(); + + this.errorCodes.set('V6000', 'Validation error'); + this.errorCodes.set('V6001', 'Invalid CustomerIP'); + this.errorCodes.set('V6002', 'Invalid DeviceID'); + this.errorCodes.set('V6003', 'Invalid Request PartnerID'); + this.errorCodes.set('V6004', 'Invalid Request Method'); + this.errorCodes.set( + 'V6010', + 'Invalid TransactionType, account not certified for eCome only MOTO or Recurring available' + ); + this.errorCodes.set('V6011', 'Invalid Payment TotalAmount'); + this.errorCodes.set('V6012', 'Invalid Payment InvoiceDescription'); + this.errorCodes.set('V6013', 'Invalid Payment InvoiceNumber'); + this.errorCodes.set('V6014', 'Invalid Payment InvoiceReference'); + this.errorCodes.set('V6015', 'Invalid Payment CurrencyCode'); + this.errorCodes.set('V6016', 'Payment Required'); + this.errorCodes.set('V6017', 'Payment CurrencyCode Required'); + this.errorCodes.set('V6018', 'Unknown Payment CurrencyCode'); + this.errorCodes.set( + 'V6019', + 'Cardholder identity authentication required' + ); + this.errorCodes.set('V6020', 'Cardholder Input Required'); + this.errorCodes.set('V6021', 'EWAY_CARDHOLDERNAME Required'); + this.errorCodes.set('V6022', 'EWAY_CARDNUMBER Required'); + this.errorCodes.set('V6023', 'EWAY_CARDCVN Required'); + this.errorCodes.set( + 'V6024', + 'Cardholder Identity Authentication One Time Password Not Active Yet' + ); + this.errorCodes.set('V6025', 'PIN Required'); + this.errorCodes.set('V6033', 'Invalid Expiry Date'); + this.errorCodes.set('V6034', 'Invalid Issue Number'); + this.errorCodes.set('V6035', 'Invalid Valid From Date'); + this.errorCodes.set('V6039', 'Invalid Network Token Status'); + this.errorCodes.set('V6040', 'Invalid TokenCustomerID'); + this.errorCodes.set('V6041', 'Customer Required'); + this.errorCodes.set('V6042', 'Customer FirstName Required'); + this.errorCodes.set('V6043', 'Customer LastName Required'); + this.errorCodes.set('V6044', 'Customer CountryCode Required'); + this.errorCodes.set('V6045', 'Customer Title Required'); + this.errorCodes.set('V6046', 'TokenCustomerID Required'); + this.errorCodes.set('V6047', 'RedirectURL Required'); + this.errorCodes.set( + 'V6048', + 'CheckoutURL Required when CheckoutPayment specified' + ); + this.errorCodes.set('V6049', 'nvalid Checkout URL'); + this.errorCodes.set('V6051', 'Invalid Customer FirstName'); + this.errorCodes.set('V6052', 'Invalid Customer LastName'); + this.errorCodes.set('V6053', 'Invalid Customer CountryCode'); + this.errorCodes.set('V6058', 'Invalid Customer Title'); + this.errorCodes.set('V6059', 'Invalid RedirectURL'); + this.errorCodes.set('V6060', 'Invalid TokenCustomerID'); + this.errorCodes.set('V6061', 'Invalid Customer Reference'); + this.errorCodes.set('V6062', 'Invalid Customer CompanyName'); + this.errorCodes.set('V6063', 'Invalid Customer JobDescription'); + this.errorCodes.set('V6064', 'Invalid Customer Street1'); + this.errorCodes.set('V6065', 'Invalid Customer Street2'); + this.errorCodes.set('V6066', 'Invalid Customer City'); + this.errorCodes.set('V6067', 'Invalid Customer State'); + this.errorCodes.set('V6068', 'Invalid Customer PostalCode'); + this.errorCodes.set('V6069', 'Invalid Customer Email'); + this.errorCodes.set('V6070', 'Invalid Customer Phone'); + this.errorCodes.set('V6071', 'Invalid Customer Mobile'); + this.errorCodes.set('V6072', 'Invalid Customer Comments'); + this.errorCodes.set('V6073', 'Invalid Customer Fax'); + this.errorCodes.set('V6074', 'Invalid Customer URL'); + this.errorCodes.set('V6075', 'Invalid ShippingAddress FirstName'); + this.errorCodes.set('V6076', 'Invalid ShippingAddress LastName'); + this.errorCodes.set('V6077', 'Invalid ShippingAddress Street1'); + this.errorCodes.set('V6078', 'Invalid ShippingAddress Street2'); + this.errorCodes.set('V6079', 'Invalid ShippingAddress City'); + this.errorCodes.set('V6080', 'Invalid ShippingAddress State'); + this.errorCodes.set('V6081', 'Invalid ShippingAddress PostalCode'); + this.errorCodes.set('V6082', 'Invalid ShippingAddress Email'); + this.errorCodes.set('V6083', 'Invalid ShippingAddress Phone'); + this.errorCodes.set('V6084', 'Invalid ShippingAddress Country'); + this.errorCodes.set('V6085', 'Invalid ShippingAddress ShippingMethod'); + this.errorCodes.set('V6086', 'Invalid ShippingAddress Fax'); + this.errorCodes.set('V6091', 'Unknown Customer CountryCode'); + this.errorCodes.set('V6092', 'Unknown ShippingAddress CountryCode'); + this.errorCodes.set('V6093', 'Insufficient Address Information'); + this.errorCodes.set('V6100', 'Invalid EWAY_CARDNAME'); + this.errorCodes.set('V6101', 'Invalid EWAY_CARDEXPIRYMONTH'); + this.errorCodes.set('V6102', 'Invalid EWAY_CARDEXPIRYYEAR'); + this.errorCodes.set('V6103', 'Invalid EWAY_CARDSTARTMONTH'); + this.errorCodes.set('V6104', 'Invalid EWAY_CARDSTARTYEAR'); + this.errorCodes.set('V6105', 'Invalid EWAY_CARDISSUENUMBER'); + this.errorCodes.set('V6106', 'Invalid EWAY_CARDCVN'); + this.errorCodes.set('V6107', 'Invalid EWAY_ACCESSCODE'); + this.errorCodes.set('V6108', 'Invalid CustomerHostAddress'); + this.errorCodes.set('V6109', 'Invalid UserAgent'); + this.errorCodes.set('V6110', 'Invalid EWAY_CARDNUMBER'); + this.errorCodes.set( + 'V6111', + 'Unauthorised API Access, Account Not PCI Certified' + ); + this.errorCodes.set( + 'V6112', + 'Redundant card details other than expiry year and month' + ); + this.errorCodes.set('V6113', 'Invalid transaction for refund'); + this.errorCodes.set('V6114', 'Gateway validation error'); + this.errorCodes.set( + 'V6115', + 'Invalid DirectRefundRequest, Transaction ID' + ); + this.errorCodes.set( + 'V6116', + 'Invalid card data on original TransactionID' + ); + this.errorCodes.set( + 'V6117', + 'Invalid CreateAccessCodeSharedRequest, FooterText' + ); + this.errorCodes.set( + 'V6118', + 'Invalid CreateAccessCodeSharedRequest, HeaderText' + ); + this.errorCodes.set( + 'V6119', + 'Invalid CreateAccessCodeSharedRequest, Language' + ); + this.errorCodes.set( + 'V6120', + 'Invalid CreateAccessCodeSharedRequest, LogoUrl' + ); + this.errorCodes.set( + 'V6121', + 'Invalid TransactionSearch, Filter Match Type' + ); + this.errorCodes.set( + 'V6122', + 'Invalid TransactionSearch, Non numeric Transaction ID' + ); + this.errorCodes.set( + 'V6123', + 'Invalid TransactionSearch,no TransactionID or AccessCode specified' + ); + this.errorCodes.set( + 'V6124', + 'Invalid Line Items. The line items have been provided however the totals do not match the TotalAmount field' + ); + this.errorCodes.set('V6125', 'Selected Payment Type not enabled'); + this.errorCodes.set( + 'V6126', + 'Invalid encrypted card number, decryption failed' + ); + this.errorCodes.set( + 'V6127', + 'Invalid encrypted cvn, decryption failed' + ); + this.errorCodes.set('V6128', 'Invalid Method for Payment Type'); + this.errorCodes.set( + 'V6129', + 'Transaction has not been authorised for Capture/Cancellation' + ); + this.errorCodes.set('V6130', 'Generic customer information error'); + this.errorCodes.set('V6131', 'Generic shipping information error'); + this.errorCodes.set( + 'V6132', + 'Transaction has already been completed or voided, operation not permitted' + ); + this.errorCodes.set('V6133', 'Checkout not available for Payment Type'); + this.errorCodes.set( + 'V6134', + 'Invalid Auth Transaction ID for Capture/Void' + ); + this.errorCodes.set('V6135', 'PayPal Error Processing Refund'); + this.errorCodes.set( + 'V6136', + 'Original transaction does not exist or state is incorrect' + ); + this.errorCodes.set('V6140', 'Merchant account is suspended'); + this.errorCodes.set( + 'V6141', + 'Invalid PayPal account details or API signature' + ); + this.errorCodes.set('V6142', 'Authorise not available for Bank/Branch'); + this.errorCodes.set('V6143', 'Invalid Public Key'); + this.errorCodes.set( + 'V6144', + 'Method not available with Public API Key Authentication' + ); + this.errorCodes.set( + 'V6145', + 'Credit Card not allow if Token Customer ID is provided with Public API Key Authentication' + ); + this.errorCodes.set( + 'V6146', + 'Client Side Encryption Key Missing or Invalid' + ); + this.errorCodes.set( + 'V6147', + 'Unable to Create One Time Code for Secure Field' + ); + this.errorCodes.set('V6148', 'Secure Field has Expired'); + this.errorCodes.set('V6149', 'Invalid Secure Field One Time Code'); + this.errorCodes.set('V6150', 'Invalid Refund Amount'); + this.errorCodes.set( + 'V6151', + 'Refund amount greater than original transaction' + ); + this.errorCodes.set( + 'V6152', + 'Original transaction already refunded for total amount' + ); + this.errorCodes.set('V6153', 'Card type not support by merchant'); + this.errorCodes.set('V6154', 'Insufficent Funds Available For Refund'); + this.errorCodes.set('V6155', 'Missing one or more fields in request'); + this.errorCodes.set('V6160', 'Encryption Method Not Supported'); + this.errorCodes.set( + 'V6161', + 'Encryption failed, missing or invalid key' + ); + this.errorCodes.set( + 'V6165', + 'Invalid Click-to-Pay (Visa Checkout) data or decryption failed' + ); + this.errorCodes.set( + 'V6170', + 'Invalid TransactionSearch, Invoice Number is not unique' + ); + this.errorCodes.set( + 'V6171', + 'Invalid TransactionSearch, Invoice Number not found' + ); + this.errorCodes.set('V6220', 'Three domain secure XID invalid'); + this.errorCodes.set('V6221', 'Three domain secure ECI invalid'); + this.errorCodes.set('V6222', 'Three domain secure AVV invalid'); + this.errorCodes.set('V6223', 'Three domain secure XID is required'); + this.errorCodes.set('V6224', 'Three Domain Secure ECI is required'); + this.errorCodes.set('V6225', 'Three Domain Secure AVV is required'); + this.errorCodes.set( + 'V6226', + 'Three Domain Secure AuthStatus is required' + ); + this.errorCodes.set('V6227', 'Three Domain Secure AuthStatus invalid'); + this.errorCodes.set('V6228', 'Three domain secure Version is required'); + this.errorCodes.set( + 'V6230', + 'Three domain secure Directory Server Txn ID invalid' + ); + this.errorCodes.set( + 'V6231', + 'Three domain secure Directory Server Txn ID is required' + ); + this.errorCodes.set('V6232', 'Three domain secure Version is invalid'); + this.errorCodes.set('V6501', 'Invalid Amex InstallementPlan'); + this.errorCodes.set( + 'V6502', + 'Invalid Number Of Installements for Amex. Valid values are from 0 to 99 inclusive' + ); + this.errorCodes.set('V6503', 'Merchant Amex ID required'); + this.errorCodes.set('V6504', 'Invalid Merchant Amex ID'); + this.errorCodes.set('V6505', 'Merchant Terminal ID required'); + this.errorCodes.set('V6506', 'Merchant category code required'); + this.errorCodes.set('V6507', 'Invalid merchant category code'); + this.errorCodes.set('V6508', 'Amex 3D ECI required'); + this.errorCodes.set('V6509', 'Invalid Amex 3D ECI'); + this.errorCodes.set('V6510', 'Invalid Amex 3D verification value'); + this.errorCodes.set('V6511', 'Invalid merchant location data'); + this.errorCodes.set('V6512', 'Invalid merchant street address'); + this.errorCodes.set('V6513', 'Invalid merchant city'); + this.errorCodes.set('V6514', 'Invalid merchant country'); + this.errorCodes.set('V6515', 'Invalid merchant phone'); + this.errorCodes.set('V6516', 'Invalid merchant postcode'); + this.errorCodes.set('V6517', 'Amex connection error'); + this.errorCodes.set( + 'V6518', + 'Amex EC Card Details API returned invalid data' + ); + this.errorCodes.set( + 'V6520', + 'Invalid or missing Amex Point Of Sale Data' + ); + this.errorCodes.set( + 'V6521', + 'Invalid or missing Amex transaction date time' + ); + this.errorCodes.set( + 'V6522', + 'Invalid or missing Amex Original transaction date time' + ); + this.errorCodes.set( + 'V6530', + 'Credit Card Number in non Credit Card Field' + ); + } + + get groupFieldConfig() { + return { + publicApiKey: document.querySelector('meta[name=public-api-key]') + ?.content, + fieldDivId: 'eway-secure-panel', + fieldType: 'group', + styles: '', + layout: { + fonts: ['Lobster'], + rows: [ + { + styles: '', + cells: [ + { + colSpan: 12, + styles: 'margin-top: 15px;', + label: { + fieldColSpan: 4, + text: document.querySelector( + 'meta[name=translation-card-name]' + )?.content, + styles: '', + }, + field: { + fieldColSpan: 8, + fieldType: 'name', + styles: this.cardStyles, + divStyles: 'padding-left: 10px;', + }, + }, + { + colSpan: 12, + styles: 'margin-top: 15px;', + label: { + fieldColSpan: 4, + text: document.querySelector( + 'meta[name=translation-expiry_date]' + )?.content, + styles: '', + }, + field: { + fieldColSpan: 8, + fieldType: 'expirytext', + styles: this.cardStyles, + divStyles: 'padding-left: 10px;', + }, + }, + ], + }, + { + styles: '', + cells: [ + { + colSpan: 12, + styles: 'margin-top: 15px;', + label: { + fieldColSpan: 4, + text: document.querySelector( + 'meta[name=translation-card_number]' + )?.content, + styles: '', + }, + field: { + fieldColSpan: 8, + fieldType: 'card', + styles: this.cardStyles, + }, + }, + { + colSpan: 12, + styles: 'margin-top: 15px;', + label: { + fieldColSpan: 4, + text: document.querySelector( + 'meta[name=translation-cvv]' + )?.content, + styles: '', + }, + field: { + fieldColSpan: 8, + fieldType: 'cvn', + styles: this.cardStyles, + }, + }, + ], + }, + ], + }, + }; + } + + securePanelCallback(event) { + document.getElementById('errors').hidden = true; + + if (event.errors) { + return this.handleErrors(event.errors); + } + + if (document.getElementById('authorize-card')) { + document.getElementById('authorize-card').disabled = false; + } + + if (document.getElementById('pay-now')) { + document.getElementById('pay-now').disabled = false; + } + + document.querySelector('input[name=securefieldcode]').value = + event.secureFieldCode; + } + + handleErrors(errors) { + let _errors = errors.split(' '); + let shouldShowGenericError = false; + let message = ''; + + _errors.forEach((error) => { + message = message.concat(this.errorCodes.get(error) + '
'); + }); + + document.getElementById('errors').innerHTML = message; + document.getElementById('errors').hidden = false; + } + + completeAuthorization(event) { + event.target.parentElement.disabled = true; + + document.getElementById('server-response').submit(); + } + + completePaymentUsingToken(event) { + event.target.parentElement.disabled = true; + + document.getElementById('server-response').submit(); + } + + completePaymentWithoutToken(event) { + event.target.parentElement.disabled = true; + + let tokenBillingCheckbox = document.querySelector( + 'input[name="token-billing-checkbox"]:checked' + ); + + if (tokenBillingCheckbox) { + document.querySelector('input[name="store_card"]').value = + tokenBillingCheckbox.value; + } + + document.getElementById('server-response').submit(); + } + + initialize() { + this.eWAY = eWAY.setupSecureField(this.groupFieldConfig, (event) => + this.securePanelCallback(event) + ); + } + + handle() { + this.initialize(); + + document + .getElementById('authorize-card') + ?.addEventListener('click', (e) => this.completeAuthorization(e)); + + Array.from( + document.getElementsByClassName('toggle-payment-with-token') + ).forEach((element) => + element.addEventListener('click', (element) => { + document + .getElementById('eway-secure-panel') + .classList.add('hidden'); + document.getElementById('save-card--container').style.display = + 'none'; + document.querySelector('input[name=token]').value = + element.target.dataset.token; + document.getElementById('pay-now').disabled = false; + }) + ); + + document + .getElementById('toggle-payment-with-credit-card') + .addEventListener('click', (element) => { + document + .getElementById('eway-secure-panel') + .classList.remove('hidden'); + document.getElementById('save-card--container').style.display = + 'grid'; + document.querySelector('input[name=token]').value = ''; + document.getElementById('pay-now').disabled = true; + }); + + document.getElementById('pay-now')?.addEventListener('click', (e) => { + let tokenInput = document.querySelector('input[name=token]'); + + if (tokenInput.value) { + return this.completePaymentUsingToken(e); + } + + return this.completePaymentWithoutToken(e); + }); + } +} + +new EwayRapid().handle(); diff --git a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php index add65701a903..df9553087b8c 100644 --- a/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/authorize.blade.php @@ -36,310 +36,5 @@ ctrans('texts.credit_card')]) @section('gateway_footer') - - + @endsection diff --git a/resources/views/portal/ninja2020/gateways/eway/pay.blade.php b/resources/views/portal/ninja2020/gateways/eway/pay.blade.php index 1d73902f7168..a6b6aef31eab 100644 --- a/resources/views/portal/ninja2020/gateways/eway/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/eway/pay.blade.php @@ -58,370 +58,5 @@ ctrans('texts.credit_card')]) @section('gateway_footer') - - + @endsection diff --git a/webpack.mix.js b/webpack.mix.js index a5eafbedebe1..28be7be1c3b4 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -81,6 +81,10 @@ mix.js("resources/js/app.js", "public/js") .js( "resources/js/clients/payment_methods/wepay-bank-account.js", "public/js/clients/payment_methods/wepay-bank-account.js" + ) + .js( + "resources/js/clients/payments/eway-credit-card.js", + "public/js/clients/payments/eway-credit-card.js" ); mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css'); From e8fb4d4444eeddc69bc31ccc2ebe0f2deb30501a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:16:31 +0200 Subject: [PATCH 20/33] Production builds of assets --- public/js/clients/payments/eway-credit-card.js | 2 ++ .../js/clients/payments/eway-credit-card.js.LICENSE.txt | 9 +++++++++ public/mix-manifest.json | 1 + 3 files changed, 12 insertions(+) create mode 100644 public/js/clients/payments/eway-credit-card.js create mode 100644 public/js/clients/payments/eway-credit-card.js.LICENSE.txt diff --git a/public/js/clients/payments/eway-credit-card.js b/public/js/clients/payments/eway-credit-card.js new file mode 100644 index 000000000000..861a0ce08548 --- /dev/null +++ b/public/js/clients/payments/eway-credit-card.js @@ -0,0 +1,2 @@ +/*! For license information please see eway-credit-card.js.LICENSE.txt */ +!function(e){var r={};function t(s){if(r[s])return r[s].exports;var o=r[s]={i:s,l:!1,exports:{}};return e[s].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=r,t.d=function(e,r,s){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:s})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(t.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(s,o,function(r){return e[r]}.bind(null,o));return s},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="/",t(t.s=21)}({21:function(e,r,t){e.exports=t("7VQy")},"7VQy":function(e,r){function t(e,r){for(var t=0;t")})),document.getElementById("errors").innerHTML=s,document.getElementById("errors").hidden=!1}},{key:"completeAuthorization",value:function(e){e.target.parentElement.disabled=!0,document.getElementById("server-response").submit()}},{key:"completePaymentUsingToken",value:function(e){e.target.parentElement.disabled=!0,document.getElementById("server-response").submit()}},{key:"completePaymentWithoutToken",value:function(e){e.target.parentElement.disabled=!0;var r=document.querySelector('input[name="token-billing-checkbox"]:checked');r&&(document.querySelector('input[name="store_card"]').value=r.value),document.getElementById("server-response").submit()}},{key:"initialize",value:function(){var e=this;this.eWAY=eWAY.setupSecureField(this.groupFieldConfig,(function(r){return e.securePanelCallback(r)}))}},{key:"handle",value:function(){var e,r,t=this;this.initialize(),null===(e=document.getElementById("authorize-card"))||void 0===e||e.addEventListener("click",(function(e){return t.completeAuthorization(e)})),Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach((function(e){return e.addEventListener("click",(function(e){document.getElementById("eway-secure-panel").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=e.target.dataset.token,document.getElementById("pay-now").disabled=!1}))})),document.getElementById("toggle-payment-with-credit-card").addEventListener("click",(function(e){document.getElementById("eway-secure-panel").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value="",document.getElementById("pay-now").disabled=!0})),null===(r=document.getElementById("pay-now"))||void 0===r||r.addEventListener("click",(function(e){return document.querySelector("input[name=token]").value?t.completePaymentUsingToken(e):t.completePaymentWithoutToken(e)}))}}])&&t(r.prototype,s),o&&t(r,o),e}())).handle()}}); \ No newline at end of file diff --git a/public/js/clients/payments/eway-credit-card.js.LICENSE.txt b/public/js/clients/payments/eway-credit-card.js.LICENSE.txt new file mode 100644 index 000000000000..6b30888ddb5b --- /dev/null +++ b/public/js/clients/payments/eway-credit-card.js.LICENSE.txt @@ -0,0 +1,9 @@ +/** + * Invoice Ninja (https://invoiceninja.com). + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://www.elastic.co/licensing/elastic-license + */ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index b2050020b4b2..5d00d93b1188 100755 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -11,6 +11,7 @@ "/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=c35db3cbb65806ab6a8a", "/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=5469146cd629ea1b5c20", "/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=065e5450233cc5b47020", + "/js/clients/payments/eway-credit-card.js": "/js/clients/payments/eway-credit-card.js?id=95d6bedbb7ec7d942e13", "/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=81c2623fc1e5769b51c7", "/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=665ddf663500767f1a17", "/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=f1719b79a2bb274d3f64", From 5d12c331caf8e167d41e015ce4b5a62cb0415d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:18:26 +0200 Subject: [PATCH 21/33] Scaffold CreditCardTest --- .../Gateways/Eway/CreditCardTest.php | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php new file mode 100644 index 000000000000..c038aa926a97 --- /dev/null +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -0,0 +1,35 @@ +driver->manage()->deleteAllCookies(); + } + + $this->browse(function (Browser $browser) { + $browser + ->visit(new Login()) + ->auth(); + }); + } +} From 1d1ca46aac80771ced3ec3f960e05ba7ce9b0a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:23:37 +0200 Subject: [PATCH 22/33] Credit card: Authorizing test --- .../Gateways/Eway/CreditCardTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php index c038aa926a97..63aaaa22ce4b 100644 --- a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -32,4 +32,23 @@ class CreditCardTest extends DuskTestCase ->auth(); }); } + + public function testAddingCreditCardStandalone() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.payment_methods.index') + ->press('Add Payment Method') + ->clickLink('Credit Card') + ->withinFrame('iframe', function (Browser $browser) { + $browser + ->type('EWAY_CARDNAME', 'Invoice Ninja') + ->type('EWAY_CARDNUMBER', '4111 1111 1111 1111') + ->type('EWAY_CARDEXPIRY', '04/22') + ->type('EWAY_CARDCVN', '100'); + }) + ->press('Add Payment Method') + ->waitForText('**** 1111'); + }); + } } From c108a5bcfc168435e58fff4f0d76fcab92d1c02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:24:26 +0200 Subject: [PATCH 23/33] Credit card: Removing test --- .../ClientPortal/Gateways/Eway/CreditCardTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php index 63aaaa22ce4b..6114ee5aa5ae 100644 --- a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -51,4 +51,17 @@ class CreditCardTest extends DuskTestCase ->waitForText('**** 1111'); }); } + + public function testRemoveCreditCard() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.payment_methods.index') + ->clickLink('View') + ->press('Remove Payment Method') + ->waitForText('Confirmation') + ->click('@confirm-payment-removal') + ->assertSee('Payment method has been successfully removed.'); + }); + } } From 79306ec4beeb4ce34c63f9ee67c7af65514eff3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:25:05 +0200 Subject: [PATCH 24/33] Credit card: Pay with new --- .../Gateways/Eway/CreditCardTest.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php index 6114ee5aa5ae..0f3bbeb997bf 100644 --- a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -33,6 +33,26 @@ class CreditCardTest extends DuskTestCase }); } + public function testPaymentWithNewCard() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.invoices.index') + ->click('@pay-now') + ->click('@pay-now-dropdown') + ->clickLink('Credit Card') + ->withinFrame('iframe', function (Browser $browser) { + $browser + ->type('EWAY_CARDNAME', 'Invoice Ninja') + ->type('EWAY_CARDNUMBER', '4111 1111 1111 1111') + ->type('EWAY_CARDEXPIRY', '04/22') + ->type('EWAY_CARDCVN', '100'); + }) + ->click('#pay-now') + ->waitForText('Details of the payment', 60); + }); + } + public function testAddingCreditCardStandalone() { $this->browse(function (Browser $browser) { From f6ee61d9855fe5fdbad48d3bb69c3b60b4f6aed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:25:42 +0200 Subject: [PATCH 25/33] Credit card: Pay with new card and save for future use --- .../Gateways/Eway/CreditCardTest.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php index 0f3bbeb997bf..d4a9c1773723 100644 --- a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -53,6 +53,30 @@ class CreditCardTest extends DuskTestCase }); } + public function testPayWithNewCardAndSaveForFutureUse() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.invoices.index') + ->click('@pay-now') + ->click('@pay-now-dropdown') + ->clickLink('Credit Card') + ->withinFrame('iframe', function (Browser $browser) { + $browser + ->type('EWAY_CARDNAME', 'Invoice Ninja') + ->type('EWAY_CARDNUMBER', '4111 1111 1111 1111') + ->type('EWAY_CARDEXPIRY', '04/22') + ->type('EWAY_CARDCVN', '100'); + }) + ->radio('#proxy_is_default', true) + ->click('#pay-now') + ->waitForText('Details of the payment', 60) + ->visitRoute('client.payment_methods.index') + ->clickLink('View') + ->assertSee('1111'); + }); + } + public function testAddingCreditCardStandalone() { $this->browse(function (Browser $browser) { From fc2094b9518b92592b4d92f053c6487838bc2cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:26:00 +0200 Subject: [PATCH 26/33] Credit card: Pay with saved card --- .../ClientPortal/Gateways/Eway/CreditCardTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php index d4a9c1773723..95357d6ea0a8 100644 --- a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -77,6 +77,20 @@ class CreditCardTest extends DuskTestCase }); } + public function testPayWithSavedCreditCard() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.invoices.index') + ->click('@pay-now') + ->click('@pay-now-dropdown') + ->clickLink('Credit Card') + ->click('.toggle-payment-with-token') + ->click('#pay-now') + ->waitForText('Details of the payment', 60); + }); + } + public function testAddingCreditCardStandalone() { $this->browse(function (Browser $browser) { From ec9d2cc292ce280cb1866680fd9c157540547c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Sun, 15 Aug 2021 16:26:18 +0200 Subject: [PATCH 27/33] Update order of tests --- .../Gateways/Eway/CreditCardTest.php | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php index 95357d6ea0a8..528422ba0759 100644 --- a/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php +++ b/tests/Browser/ClientPortal/Gateways/Eway/CreditCardTest.php @@ -91,6 +91,19 @@ class CreditCardTest extends DuskTestCase }); } + public function testRemoveCreditCard() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.payment_methods.index') + ->clickLink('View') + ->press('Remove Payment Method') + ->waitForText('Confirmation') + ->click('@confirm-payment-removal') + ->assertSee('Payment method has been successfully removed.'); + }); + } + public function testAddingCreditCardStandalone() { $this->browse(function (Browser $browser) { @@ -109,17 +122,4 @@ class CreditCardTest extends DuskTestCase ->waitForText('**** 1111'); }); } - - public function testRemoveCreditCard() - { - $this->browse(function (Browser $browser) { - $browser - ->visitRoute('client.payment_methods.index') - ->clickLink('View') - ->press('Remove Payment Method') - ->waitForText('Confirmation') - ->click('@confirm-payment-removal') - ->assertSee('Payment method has been successfully removed.'); - }); - } } From 46f14392f5fbc05c7a3447cfec0a01a9216a0297 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Aug 2021 19:02:21 +1000 Subject: [PATCH 28/33] Process payments with eWay --- app/PaymentDrivers/Eway/CreditCard.php | 32 ++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 3338c8aaf5b9..0eb253fa5e10 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -178,9 +178,37 @@ class CreditCard } - +/* +array:9 [▼ + "_token" => "RpkUNg0gHYfzLKPCJG3EtmshGiwDUeytRG53b1Or" + "gateway_response" => null + "store_card" => true + "payment_hash" => "1wC7J7Jo1jagV5oBaWSxz7b2lSLsvVMp" + "company_gateway_id" => "6" + "payment_method_id" => "1" + "token" => null + "securefieldcode" => "F9802rbHYa0St-w3QpBXvNaiNFMNhmY7OmZimH-HROUzS1K0niXOlqXUzugz4mnTqJVqK" + "q" => "/client/payments/process/response" +] + */ public function paymentResponse($request) { - + dd($request->all()); + + $transaction = [ + 'Payment' => [ + 'TotalAmount' => 1000, + ], + 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, + 'SecuredCardData' => '44DD7jYYyRgaQnVibOAsYbbFIYmSXbS6hmTxosAhG6CK1biw=', + ]; + + $response = $client->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + } + + + private function convertAmountForEway($amount) + { + } } \ No newline at end of file From 6b3938dfb41f7d46614c3e160a591e4e7e715208 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Aug 2021 13:03:38 +1000 Subject: [PATCH 29/33] Working on eWay --- app/PaymentDrivers/Eway/CreditCard.php | 33 +++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 0eb253fa5e10..37ec91d565e2 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -193,22 +193,43 @@ array:9 [▼ */ public function paymentResponse($request) { - dd($request->all()); + $state = [ + 'server_response' => $request->all(), + ]; + + $this->eway_driver->payment_hash->data = array_merge((array) $this->eway_driver->payment_hash->data, $state); + $this->eway_driver->payment_hash->save(); $transaction = [ 'Payment' => [ - 'TotalAmount' => 1000, + 'TotalAmount' => $this->convertAmountForEway(), ], 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, - 'SecuredCardData' => '44DD7jYYyRgaQnVibOAsYbbFIYmSXbS6hmTxosAhG6CK1biw=', + 'SecuredCardData' => $request->input('securefieldcode'), ]; - $response = $client->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + $response = $this->eway_driver->init()->eway->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + +dd($response); + + $response_status = ErrorCode::getStatus($response->ResponseMessage); + + if(!$response_status['success']) + throw new PaymentFailed($response_status['message'], 400); + + } - private function convertAmountForEway($amount) + private function convertAmountForEway() { - + + $amount = $this->eway_driver->payment_hash->data->amount_with_fee; + + if(in_array($this->eway_driver->client->currency()->code, ['VND', 'JPY', 'KRW', 'GNF', 'IDR', 'PYG', 'RWF', 'UGX', 'VUV', 'XAF', 'XPF'])) + return $amount; + + return $amount * 100; } + } \ No newline at end of file From 676d3a52349c8cd63a0a68a92dfa27feb3978a21 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Aug 2021 13:27:44 +1000 Subject: [PATCH 30/33] eWay payments --- app/PaymentDrivers/Eway/CreditCard.php | 51 +++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 37ec91d565e2..fd821e1d70d9 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -23,12 +23,14 @@ use App\Models\PaymentType; use App\Models\SystemLog; use App\PaymentDrivers\EwayPaymentDriver; use App\PaymentDrivers\Eway\ErrorCode; +use App\Utils\Traits\MakesHash; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; class CreditCard { + use MakesHash; public $eway_driver; @@ -210,21 +212,42 @@ array:9 [▼ $response = $this->eway_driver->init()->eway->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); -dd($response); - $response_status = ErrorCode::getStatus($response->ResponseMessage); - if(!$response_status['success']) - throw new PaymentFailed($response_status['message'], 400); + if(!$response_status['success']){ + $this->logResponse($response, false); + + throw new PaymentFailed($response_status['message'], 400); + } + + $this->logResponse($response, true); + + $payment = $this->storePayment($response); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); } + private function storePayment($response) + { + $amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total; + + $payment_record = []; + $payment_record['amount'] = $amount; + $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER; + $payment_record['gateway_type_id'] = GatewayType::CREDIT_CARD; + $payment_record['transaction_reference'] = $response->TransactionID; + + $payment = $this->eway_driver->createPayment($payment_record); + + return $payment; + } private function convertAmountForEway() { - $amount = $this->eway_driver->payment_hash->data->amount_with_fee; + $amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total; if(in_array($this->eway_driver->client->currency()->code, ['VND', 'JPY', 'KRW', 'GNF', 'IDR', 'PYG', 'RWF', 'UGX', 'VUV', 'XAF', 'XPF'])) return $amount; @@ -232,4 +255,22 @@ dd($response); return $amount * 100; } + private function logResponse($response, $success = true) + { + + $logger_message = [ + 'server_response' => $response, + ]; + + SystemLogger::dispatch( + $logger_message, + SystemLog::CATEGORY_GATEWAY_RESPONSE, + $success ? SystemLog::EVENT_GATEWAY_SUCCESS : SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_EWAY, + $this->eway_driver->client, + $this->eway_driver->client->company, + ); + + } + } \ No newline at end of file From f57d6f048fa4d7c7795bc7b5cb4c2642036a0e4a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 18 Aug 2021 18:24:49 +1000 Subject: [PATCH 31/33] Fixes for eWay --- app/Models/SystemLog.php | 2 +- app/PaymentDrivers/Eway/CreditCard.php | 152 ++++++++++--------------- 2 files changed, 64 insertions(+), 90 deletions(-) diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index 4e0f739af243..607cde3688f1 100644 --- a/app/Models/SystemLog.php +++ b/app/Models/SystemLog.php @@ -68,7 +68,7 @@ class SystemLog extends Model const TYPE_BRAINTREE = 307; const TYPE_WEPAY = 309; const TYPE_PAYFAST = 310; - const TYPE_EWAY = 311; + const TYPE_EWAY = 313; const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index fd821e1d70d9..c92b0d7cf430 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -50,76 +50,17 @@ class CreditCard } - /* - Eway\Rapid\Model\Response\CreateCustomerResponse {#2374 ▼ - #fillable: array:16 [▶] - #errors: [] - #attributes: array:11 [▼ - "AuthorisationCode" => null - "ResponseCode" => "00" - "ResponseMessage" => "A2000" - "TransactionID" => null - "TransactionStatus" => false - "TransactionType" => "MOTO" - "BeagleScore" => null - "Verification" => Eway\Rapid\Model\Verification {#2553 ▼ - #fillable: array:5 [▶] - #attributes: array:5 [▶] - } - "Customer" => Eway\Rapid\Model\Customer {#2504 ▼ - #fillable: array:38 [▶] - #attributes: array:20 [▼ - "CardDetails" => Eway\Rapid\Model\CardDetails {#2455 ▼ - #fillable: array:8 [▶] - #attributes: array:7 [▼ - "Number" => "411111XXXXXX1111" - "Name" => "Joey Diaz" - "ExpiryMonth" => "10" - "ExpiryYear" => "23" - "StartMonth" => null - "StartYear" => null - "IssueNumber" => null - ] - } - "TokenCustomerID" => 917047257342 - "Reference" => "A12345" - "Title" => "Mr." - "FirstName" => "John" - "LastName" => "Smith" - "CompanyName" => "Demo Shop 123" - "JobDescription" => "PHP Developer" - "Street1" => "Level 5" - "Street2" => "369 Queen Street" - "City" => "Sydney" - "State" => "NSW" - "PostalCode" => "2000" - "Country" => "au" - "Email" => "demo@example.org" - "Phone" => "09 889 0986" - "Mobile" => "09 889 6542" - "Comments" => "" - "Fax" => "" - "Url" => "http://www.ewaypayments.com" - ] - } - "Payment" => Eway\Rapid\Model\Payment {#2564 ▼ - #fillable: array:5 [▶] - #attributes: array:5 [▼ - "TotalAmount" => 0 - "InvoiceNumber" => "" - "InvoiceDescription" => "" - "InvoiceReference" => "" - "CurrencyCode" => "AUD" - ] - } - "Errors" => null - ] -} - */ - public function authorizeResponse($request) { + $token = $this->createEwayToken($request->input('securefieldcode')); + + return redirect()->route('client.payment_methods.index'); + + } + + private function createEwayToken($securefieldcode) + { $transaction = [ 'Reference' => $this->eway_driver->client->number, 'Title' => '', @@ -135,12 +76,8 @@ class CreditCard 'Phone' => $this->eway_driver->client->phone, 'Email' => $this->eway_driver->client->contacts()->first()->email, "Url" => $this->eway_driver->client->website, - // 'Payment' => [ - // 'TotalAmount' => 0, - // ], - // 'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE, 'Method' => \Eway\Rapid\Enum\PaymentMethod::CREATE_TOKEN_CUSTOMER, - 'SecuredCardData' => $request->input('securefieldcode'), + 'SecuredCardData' => $securefieldcode, ]; $response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); @@ -166,8 +103,7 @@ class CreditCard $token = $this->eway_driver->storeGatewayToken($cgt, []); - return redirect()->route('client.payment_methods.index'); - + return $token; } public function paymentView($data) @@ -180,21 +116,9 @@ class CreditCard } -/* -array:9 [▼ - "_token" => "RpkUNg0gHYfzLKPCJG3EtmshGiwDUeytRG53b1Or" - "gateway_response" => null - "store_card" => true - "payment_hash" => "1wC7J7Jo1jagV5oBaWSxz7b2lSLsvVMp" - "company_gateway_id" => "6" - "payment_method_id" => "1" - "token" => null - "securefieldcode" => "F9802rbHYa0St-w3QpBXvNaiNFMNhmY7OmZimH-HROUzS1K0niXOlqXUzugz4mnTqJVqK" - "q" => "/client/payments/process/response" -] - */ public function paymentResponse($request) { + $state = [ 'server_response' => $request->all(), ]; @@ -202,6 +126,23 @@ array:9 [▼ $this->eway_driver->payment_hash->data = array_merge((array) $this->eway_driver->payment_hash->data, $state); $this->eway_driver->payment_hash->save(); + if(boolval($request->input('store_card'))) + { + $token = $this->createEwayToken($request->input('securefieldcode')); + $payment = $this->tokenBilling($token, $this->eway_driver->payment_hash); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + + } + + if($request->token){ + + $payment = $this->tokenBilling($request->token, $this->eway_driver->payment_hash); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + + } + $transaction = [ 'Payment' => [ 'TotalAmount' => $this->convertAmountForEway(), @@ -244,10 +185,11 @@ array:9 [▼ return $payment; } - private function convertAmountForEway() + private function convertAmountForEway($amount = false) { - $amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total; + if(!$amount) + $amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total; if(in_array($this->eway_driver->client->currency()->code, ['VND', 'JPY', 'KRW', 'GNF', 'IDR', 'PYG', 'RWF', 'UGX', 'VUV', 'XAF', 'XPF'])) return $amount; @@ -273,4 +215,36 @@ array:9 [▼ } + + public function tokenBilling($token, $payment_hash) + { + $amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total; + + $transaction = [ + 'Customer' => [ + 'TokenCustomerID' => $token, + ], + 'Payment' => [ + 'TotalAmount' => $this->convertAmountForEway($amount), + ], + 'TransactionType' => \Eway\Rapid\Enum\TransactionType::RECURRING, + ]; + + $response = $this->eway_driver->init()->eway->createTransaction(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction); + + $response_status = ErrorCode::getStatus($response->ResponseMessage); + + if(!$response_status['success']){ + + $this->logResponse($response, false); + + throw new PaymentFailed($response_status['message'], 400); + } + + $this->logResponse($response, true); + + $payment = $this->storePayment($response); + + return $payment; + } } \ No newline at end of file From c2a1207a6371cc2eda591ee2c249c23ff9e7aae9 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 18 Aug 2021 20:41:29 +1000 Subject: [PATCH 32/33] Verify peer --- app/Models/Presenters/CompanyPresenter.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/Models/Presenters/CompanyPresenter.php b/app/Models/Presenters/CompanyPresenter.php index c9a7d9aafedc..bcc37919afbf 100644 --- a/app/Models/Presenters/CompanyPresenter.php +++ b/app/Models/Presenters/CompanyPresenter.php @@ -54,12 +54,19 @@ class CompanyPresenter extends EntityPresenter $settings = $this->entity->settings; } + $arrContextOptions=array( + "ssl"=>array( + "verify_peer"=>false, + "verify_peer_name"=>false, + ), + ); + if(strlen($settings->company_logo) >= 1 && (strpos($settings->company_logo, 'http') !== false)) - return "data:image/png;base64, ". base64_encode(file_get_contents($settings->company_logo)); + return "data:image/png;base64, ". base64_encode(file_get_contents($settings->company_logo, false, stream_context_create($arrContextOptions))); else if(strlen($settings->company_logo) >= 1) - return "data:image/png;base64, ". base64_encode(file_get_contents(url('') . $settings->company_logo)); + return "data:image/png;base64, ". base64_encode(file_get_contents(url('') . $settings->company_logo, false, stream_context_create($arrContextOptions))); else - return "data:image/png;base64, ". base64_encode(file_get_contents(asset('images/new_logo.png'))); + return "data:image/png;base64, ". base64_encode(file_get_contents(asset('images/new_logo.png'), false, stream_context_create($arrContextOptions))); } From 120038d616b763f68f6ffd269e7ec133b7c11a5e Mon Sep 17 00:00:00 2001 From: = Date: Wed, 18 Aug 2021 21:12:13 +1000 Subject: [PATCH 33/33] eway --- app/Models/Gateway.php | 2 +- app/PaymentDrivers/Eway/CreditCard.php | 2 +- app/PaymentDrivers/EwayPaymentDriver.php | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index a99f27d737e1..539b820c0e19 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -82,7 +82,7 @@ class Gateway extends StaticModel return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net break; case 3: - return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//eWay + return [GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => true]];//eWay break; case 15: return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index c92b0d7cf430..eec96e743f42 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -129,7 +129,7 @@ class CreditCard if(boolval($request->input('store_card'))) { $token = $this->createEwayToken($request->input('securefieldcode')); - $payment = $this->tokenBilling($token, $this->eway_driver->payment_hash); + $payment = $this->tokenBilling($token->token, $this->eway_driver->payment_hash); return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); diff --git a/app/PaymentDrivers/EwayPaymentDriver.php b/app/PaymentDrivers/EwayPaymentDriver.php index 66dc23c9a443..65559abd41dc 100644 --- a/app/PaymentDrivers/EwayPaymentDriver.php +++ b/app/PaymentDrivers/EwayPaymentDriver.php @@ -89,6 +89,7 @@ class EwayPaymentDriver extends BaseDriver return $this->payment_method->paymentResponse($request); //this is your custom implementation from here } + /* We need PCI compliance prior to enabling this */ public function refund(Payment $payment, $amount, $return_client_response = false) { @@ -99,7 +100,7 @@ class EwayPaymentDriver extends BaseDriver ], ]; - $response = $this->init()->eway->client->refund($refund); + $response = $this->init()->eway->refund($refund); $transaction_reference = ''; $refund_status = true; @@ -118,6 +119,7 @@ class EwayPaymentDriver extends BaseDriver $refund_message = 'Sorry, your refund failed'; } } + return [ 'transaction_reference' => $response->TransactionID, 'transaction_response' => json_encode($response),