From c0287085b5c59f91b53da300f246cfc1a473a757 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 20 Jul 2021 21:26:24 +1000 Subject: [PATCH 01/16] Scaffolding Paytrace --- app/Console/Commands/CreateAccount.php | 1 + app/Models/CompanyGateway.php | 8 +- app/Models/SystemLog.php | 2 +- app/PaymentDrivers/PayTrace/CreditCard.php | 121 +++++++++++++ app/PaymentDrivers/PaytracePaymentDriver.php | 123 +++++++++++++ ...95537_activate_paytrace_payment_driver.php | 29 ++++ database/seeders/PaymentLibrariesSeeder.php | 4 +- .../gateways/paytrace/authorize.blade.php | 162 ++++++++++++++++++ .../ninja2020/gateways/paytrace/pay.blade.php | 0 .../livewire/simple-bootstrap.blade.php | 29 ++++ 10 files changed, 474 insertions(+), 5 deletions(-) create mode 100644 app/PaymentDrivers/PayTrace/CreditCard.php create mode 100644 app/PaymentDrivers/PaytracePaymentDriver.php create mode 100644 database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php create mode 100644 resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php create mode 100644 resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php create mode 100644 resources/views/vendor/livewire/simple-bootstrap.blade.php diff --git a/app/Console/Commands/CreateAccount.php b/app/Console/Commands/CreateAccount.php index 689ba262b0b5..b210981e16ba 100644 --- a/app/Console/Commands/CreateAccount.php +++ b/app/Console/Commands/CreateAccount.php @@ -91,6 +91,7 @@ class CreateAccount extends Command $account = Account::factory()->create(); $company = Company::factory()->create([ 'account_id' => $account->id, + 'domain' => config('ninja.app_url'), ]); $account->default_company_id = $company->id; diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index b9105b566e9e..1204b8e0ea1a 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -69,16 +69,20 @@ class CompanyGateway extends BaseModel // const TYPE_CUSTOM = 306; // const TYPE_BRAINTREE = 307; // const TYPE_WEPAY = 309; + // const TYPE_PAYFAST = 310; + // const TYPE_PAYTRACE = 311; public $gateway_consts = [ '38f2c48af60c7dd69e04248cbb24c36e' => 300, 'd14dd26a37cecc30fdd65700bfb55b23' => 301, + 'd14dd26a47cecc30fdd65700bfb67b34' => 301, '3758e7f7c6f4cecf0f4f348b9a00f456' => 304, '3b6621f970ab18887c4f6dca78d3f8bb' => 305, '54faab2ab6e3223dbe848b1686490baa' => 306, - 'd14dd26a47cecc30fdd65700bfb67b34' => 301, - '8fdeed552015b3c7b44ed6c8ebd9e992' => 309, 'f7ec488676d310683fb51802d076d713' => 307, + '8fdeed552015b3c7b44ed6c8ebd9e992' => 309, + 'd6814fc83f45d2935e7777071e629ef9' => 310, + 'bbd736b3254b0aabed6ad7fda1298c88' => 311, ]; protected $touches = []; diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index 7614c01ecccc..5e933edfe8a1 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_PAYTRACE = 311; const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/PayTrace/CreditCard.php b/app/PaymentDrivers/PayTrace/CreditCard.php new file mode 100644 index 000000000000..58937195e553 --- /dev/null +++ b/app/PaymentDrivers/PayTrace/CreditCard.php @@ -0,0 +1,121 @@ +paytrace_driver = $paytrace_driver; + } + + public function authorizeView($data) + { + + $data['client_key'] = $this->paytrace_driver->getAuthToken(); + + return render('gateways.paytrace.authorize', $data); + } + + + public function authorizeResponse($request) + { + $data = $request->all(); + + return response()->json([], 200); + + } + + public function paymentView($data) + { + + + return render('gateways.paytrace.pay', $data); + + } + + + public function paymentResponse(Request $request) + { + $response_array = $request->all(); + + + + // if($response_array['payment_status'] == 'COMPLETE') { + + // $this->payfast->logSuccessfulGatewayResponse(['response' => $response_array, 'data' => $this->paytrace_driver->payment_hash], SystemLog::TYPE_PAYFAST); + + // return $this->processSuccessfulPayment($response_array); + // } + // else { + // $this->processUnsuccessfulPayment($response_array); + // } + } + + private function processSuccessfulPayment($response_array) + { + + + + // $payment = $this->paytrace_driver->createPayment($payment_record, Payment::STATUS_COMPLETED); + + + } + + private function processUnsuccessfulPayment($server_response) + { + // PaymentFailureMailer::dispatch($this->paytrace_driver->client, $server_response->cancellation_reason, $this->paytrace_driver->client->company, $server_response->amount); + + // PaymentFailureMailer::dispatch( + // $this->paytrace_driver->client, + // $server_response, + // $this->paytrace_driver->client->company, + // $server_response['amount_gross'] + // ); + + // $message = [ + // 'server_response' => $server_response, + // 'data' => $this->paytrace_driver->payment_hash->data, + // ]; + + // SystemLogger::dispatch( + // $message, + // SystemLog::CATEGORY_GATEWAY_RESPONSE, + // SystemLog::EVENT_GATEWAY_FAILURE, + // SystemLog::TYPE_PAYFAST, + // $this->payfast->client, + // $this->payfast->client->company, + // ); + + // throw new PaymentFailed('Failed to process the payment.', 500); + } + +} \ No newline at end of file diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php new file mode 100644 index 000000000000..94049366d250 --- /dev/null +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -0,0 +1,123 @@ + CreditCard::class, //maps GatewayType => Implementation class + ]; + + const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYTRACE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model + + public function init() + { + return $this; /* This is where you boot the gateway with your auth credentials*/ + } + + /* 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) + { + } + + /*Helpers*/ + + public function getAuthToken() + { + + $url = 'https://api.paytrace.com/oauth/token'; + $data = [ + 'grant_type' => 'password', + 'username' => $this->company_gateway->getConfigField('username'), + 'password' => $this->company_gateway->getConfigField('password') + ]; + + $response = CurlUtils::post($url, $data, $headers = false); + + if($response) + { + $auth_data = json_decode($response); + + return $auth_data->access_token; + } + + return false; + } +} diff --git a/database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php b/database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php new file mode 100644 index 000000000000..5d9743c35714 --- /dev/null +++ b/database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php @@ -0,0 +1,29 @@ +where('id', 46)->update(['visible' => true, 'provider' => 'Paytrace']); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index b9ff0f84146f..e6d31f414fe4 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -70,7 +70,7 @@ class PaymentLibrariesSeeder extends Seeder ['id' => 43, 'name' => 'Fasapay', 'provider' => 'Fasapay', 'key' => '1b2cef0e8c800204a29f33953aaf3360', 'fields' => ''], ['id' => 44, 'name' => 'Komoju', 'provider' => 'Komoju', 'key' => '7ea2d40ecb1eb69ef8c3d03e5019028a', 'fields' => '{"apiKey":"","accountId":"","paymentMethod":"credit_card","testMode":false,"locale":"en"}'], ['id' => 45, 'name' => 'Paysafecard', 'provider' => 'Paysafecard', 'key' => '70ab90cd6c5c1ab13208b3cef51c0894', 'fields' => '{"username":"","password":"","testMode":false}'], - ['id' => 46, 'name' => 'Paytrace', 'provider' => 'Paytrace_CreditCard', 'key' => 'bbd736b3254b0aabed6ad7fda1298c88', 'fields' => '{"username":"","password":"","testMode":false,"endpoint":"https:\/\/paytrace.com\/api\/default.pay"}'], + ['id' => 46, 'name' => 'Paytrace', 'provider' => 'Paytrace', 'key' => 'bbd736b3254b0aabed6ad7fda1298c88', 'fields' => '{"username":"","password":"","testMode":false,"endpoint":"https:\/\/paytrace.com\/api\/default.pay"}'], ['id' => 47, 'name' => 'Secure Trading', 'provider' => 'SecureTrading', 'key' => '231cb401487b9f15babe04b1ac4f7a27', 'fields' => '{"siteReference":"","username":"","password":"","applyThreeDSecure":false,"accountType":"ECOM"}'], ['id' => 48, 'name' => 'SecPay', 'provider' => 'SecPay', 'key' => 'bad8699d581d9fa040e59c0bb721a76c', 'fields' => '{"mid":"","vpnPswd":"","remotePswd":"","usageType":"","confirmEmail":"","testStatus":"true","mailCustomer":"true","additionalOptions":""}'], ['id' => 49, 'name' => 'WePay', 'provider' => 'WePay', 'is_offsite' => false, 'sort_order' => 3, 'key' => '8fdeed552015b3c7b44ed6c8ebd9e992', 'fields' => '{"accountId":"","accessToken":"","type":"goods","testMode":false,"feePayer":"payee"}'], @@ -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,15,20,39,46,55,50])->update(['visible' => 1]); if (Ninja::isHosted()) { Gateway::whereIn('id', [20])->update(['visible' => 0]); diff --git a/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php new file mode 100644 index 000000000000..061901fb3dd2 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php @@ -0,0 +1,162 @@ +@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 + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+@endsection + +@section('gateway_footer') + + + + + +@endsection diff --git a/resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php b/resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/resources/views/vendor/livewire/simple-bootstrap.blade.php b/resources/views/vendor/livewire/simple-bootstrap.blade.php new file mode 100644 index 000000000000..dbc374434911 --- /dev/null +++ b/resources/views/vendor/livewire/simple-bootstrap.blade.php @@ -0,0 +1,29 @@ +
+ @if ($paginator->hasPages()) + + @endif +
From df7d20fa76d819eaaf88a5765cc504cd4d53b1a6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 21 Jul 2021 07:53:11 +1000 Subject: [PATCH 02/16] Scaffolding Paytrace --- .../gateways/paytrace/authorize.blade.php | 99 ++----------------- 1 file changed, 7 insertions(+), 92 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php index 061901fb3dd2..794117356a92 100644 --- a/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php @@ -39,103 +39,12 @@ // Minimal Protect.js setup call PTPayment.setup({ - styles: - { - 'code': { - 'font_color':'#5D99CA', - 'border_color':'#EF9F6D', - 'border_style':'dotted', - 'font_size':'13pt', - 'input_border_radius':'10px', - 'input_border_width':'2px', - 'input_font':'serif, cursive, fantasy', - 'input_font_weight':'700', - 'input_margin':'5px 0px 5px 20px', - 'input_padding':'0px 5px 0px 5px', - 'label_color':'#5D99CA', - 'label_size':'16px', - 'label_width':'150px', - 'label_font':'sans-serif, arial, serif', - 'label_font_weight':'bold', - 'label_margin':'5px 0px 0px 20px', - 'label_padding':'2px 5px 2px 5px', - 'label_border_style':'dotted', - 'label_border_color':'#EF9F6D', - 'label_border_radius':'10px', - 'label_border_width':'2px', - 'background_color':'white', - 'height':'25px', - 'width':'110px', - 'padding_bottom':'2px' - }, - 'cc': { - 'font_color':'#5D99CA', - 'border_color':'#EF9F6D', - 'border_style':'solid', - 'font_size':'13pt', - 'input_border_radius':'20px', - 'input_border_width':'2px', - 'input_font':'Times New Roman, arial, fantasy', - 'input_font_weight':'400', - 'input_margin':'5px 0px 5px 0px', - 'input_padding':'0px 5px 0px 5px', - 'label_color':'#5D99CA', - 'label_size':'16px', - 'label_width':'150px', - 'label_font':'Times New Roman, sans-serif, serif', - 'label_font_weight':'light', - 'label_margin':'5px 0px 0px 0px', - 'label_padding':'0px 5px 0px 5px', - 'label_border_style':'solid', - 'label_border_color':'#EF9F6D', - 'label_border_radius':'20px', - 'label_border_width':'2px', - 'background_color':'white', - 'height':'25px', - 'width':'320px', - 'padding_bottom':'0px' - }, - 'exp': { - 'font_color':'#5D99CA', - 'border_color':'#EF9F6D', - 'border_style':'dashed', - 'font_size':'12pt', - 'input_border_radius':'0px', - 'input_border_width':'2px', - 'input_font':'arial, cursive, fantasy', - 'input_font_weight':'400', - 'input_margin':'5px 0px 5px 0px', - 'input_padding':'0px 5px 0px 5px', - 'label_color':'#5D99CA', - 'label_size':'16px', - 'label_width':'150px', - 'label_font':'arial, fantasy, serif', - 'label_font_weight':'normal', - 'label_margin':'5px 0px 0px 0px', - 'label_padding':'2px 5px 2px 5px', - 'label_border_style':'dashed', - 'label_border_color':'#EF9F6D', - 'label_border_radius':'0px', - 'label_border_width':'2px', - 'background_color':'white', - 'height':'25px', - 'width':'85px', - 'padding_bottom':'2px', - 'type':'dropdown' - }, - 'body': { - 'background_color':'white' - } - }, + authorization: { clientKey: "{!! $client_key !!}" } }).then(function(instance){ //use instance object to process and tokenize sensitive data payment fields. PTPayment.theme('above the line'); - }); - - - // this can be any event we chose. We will use the submit event and stop any default event handling and prevent event handling bubbling. document.getElementById("ProtectForm").addEventListener("submit",function(e){ e.preventDefault(); @@ -157,6 +66,12 @@ PTPayment.validate(function(validationErrors) { } });// end of PTPayment.validate });// end of add event listener submit + + }); + + + + @endsection From 75ac7ec48cbc19f612d5f74be6a8773c0d7e291b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 21 Jul 2021 09:21:32 +1000 Subject: [PATCH 03/16] minor fixes --- app/Console/Commands/CreateAccount.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Console/Commands/CreateAccount.php b/app/Console/Commands/CreateAccount.php index b210981e16ba..b6c51e992858 100644 --- a/app/Console/Commands/CreateAccount.php +++ b/app/Console/Commands/CreateAccount.php @@ -91,7 +91,8 @@ class CreateAccount extends Command $account = Account::factory()->create(); $company = Company::factory()->create([ 'account_id' => $account->id, - 'domain' => config('ninja.app_url'), + 'portal_domain' => config('ninja.app_url'), + 'portal_mode' => 'domain', ]); $account->default_company_id = $company->id; From 0d52d57d411f69a1c6d17e40173face4f0529eb5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 21 Jul 2021 10:43:39 +1000 Subject: [PATCH 04/16] Paytrace --- app/PaymentDrivers/PaytracePaymentDriver.php | 12 +- .../gateways/paytrace/authorize.blade.php | 128 ++++++++++++++---- 2 files changed, 110 insertions(+), 30 deletions(-) diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index 94049366d250..8e95e6f4f701 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -115,7 +115,17 @@ class PaytracePaymentDriver extends BaseDriver { $auth_data = json_decode($response); - return $auth_data->access_token; + $headers = []; + $headers[] = 'Content-type: application/json'; + $headers[] = 'Authorization: Bearer '.$auth_data->access_token; + + $response = CurlUtils::post('https://api.paytrace.com/v1/payment_fields/token/create', [], $headers); + + $response = json_decode($response); + + if($response) + return $response->clientKey; + } return false; diff --git a/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php index 794117356a92..ac3968e7808a 100644 --- a/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php @@ -10,6 +10,7 @@ @endif +
@@ -17,7 +18,11 @@
- + + + +

+