From 86e8533e5957b8ab33891afe8394bcff8d66736f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 14 Aug 2021 18:11:45 +1000 Subject: [PATCH 1/8] Square stubs --- app/Models/SystemLog.php | 3 +- app/PaymentDrivers/Square/CreditCard.php | 153 +++++++++++++++ app/PaymentDrivers/SquarePaymentDriver.php | 105 +++++++++++ composer.json | 1 + composer.lock | 175 +++++++++++++++++- ...021_08_14_054458_square_payment_driver.php | 49 +++++ 6 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 app/PaymentDrivers/Square/CreditCard.php create mode 100644 app/PaymentDrivers/SquarePaymentDriver.php create mode 100644 database/migrations/2021_08_14_054458_square_payment_driver.php diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index ab3d8cac8b68..1340bb4cebbe 100644 --- a/app/Models/SystemLog.php +++ b/app/Models/SystemLog.php @@ -70,7 +70,8 @@ class SystemLog extends Model const TYPE_PAYFAST = 310; const TYPE_PAYTRACE = 311; const TYPE_MOLLIE = 312; - + const TYPE_SQUARE = 320; + const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/Square/CreditCard.php b/app/PaymentDrivers/Square/CreditCard.php new file mode 100644 index 000000000000..f83da6137fa6 --- /dev/null +++ b/app/PaymentDrivers/Square/CreditCard.php @@ -0,0 +1,153 @@ +square_class = $square_class; + } + + public function authorizeView($data) + { + + $data['gateway'] = $this->square_class; + + return render('gateways.square.credit_card.authorize', $data); + + } + + public function authorizeRequest($request) + { + + $billing_address = new \Square\Models\Address(); + $billing_address->setAddressLine1($this->square_class->client->address1); + $billing_address->setAddressLine2($this->square_class->client->address2); + $billing_address->setLocality($this->square_class->client->city); + $billing_address->setAdministrativeDistrictLevel1($this->square_class->client->state); + $billing_address->setPostalCode($this->square_class->client->postal_code); + $billing_address->setCountry($this->square_class->client->country->iso_3166_2); + + $card = new \Square\Models\Card(); + $card->setCardholderName('Amelia Earhart'); + $card->setBillingAddress($billing_address); + $card->setCustomerId('VDKXEEKPJN48QDG3BGGFAK05P8'); + $card->setReferenceId('user-id-1'); + + $body = new \Square\Models\CreateCardRequest( + '4935a656-a929-4792-b97c-8848be85c27c', + 'cnon:uIbfJXhXETSP197M3GB', + $card + ); + + $api_response = $client->getCardsApi()->createCard($body); + + if ($api_response->isSuccess()) { + $result = $api_response->getResult(); + } else { + $errors = $api_response->getErrors(); + } + + + return back(); + } + + public function paymentView($data) + { + + $data['gateway'] = $this->square_class; + $data['client_token'] = $this->braintree->gateway->clientToken()->generate(); + + return render('gateways.braintree.credit_card.pay', $data); + + } + + public function processPaymentResponse($request) + { + + } + + /* 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->square_class->payment_hash->invoices(), 'amount')) + $this->square_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->square_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->square_class->processUnsuccessfulTransaction($data); + + } + + + /* 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/SquarePaymentDriver.php b/app/PaymentDrivers/SquarePaymentDriver.php new file mode 100644 index 000000000000..10647bf54992 --- /dev/null +++ b/app/PaymentDrivers/SquarePaymentDriver.php @@ -0,0 +1,105 @@ + CreditCard::class, //maps GatewayType => Implementation class + ]; + + const SYSTEM_LOG_TYPE = SystemLog::TYPE_SQUARE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model + + public function init() + { + + $this->square = new Square\SquareClient([ + 'accessToken' => 'EAAAEHeoSxEUZWXCd0makP0-HA0V4OLZ-S-T2Gmc91llp08ColiOX9NpP-LQZIId', + 'environment' => Square\Environment::SANDBOX, + ]); + + 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) + { + //this is your custom implementation from here + } + + public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) + { + //this is your custom implementation from here + } + + public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) + { + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 8595adacbbc3..41d1d8b1692c 100644 --- a/composer.json +++ b/composer.json @@ -69,6 +69,7 @@ "pragmarx/google2fa": "^8.0", "predis/predis": "^1.1", "sentry/sentry-laravel": "^2", + "square/square": "13.0.0.20210721", "stripe/stripe-php": "^7.50", "symfony/http-client": "^5.2", "tijsverkoyen/css-to-inline-styles": "^2.2", diff --git a/composer.lock b/composer.lock index 89eea29d9e7b..4a0615b198f0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,122 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "275a9dd3910b6ec79607b098406dc6c7", + "content-hash": "93253273cd8399a0e083a064160b70bf", "packages": [ + { + "name": "apimatic/jsonmapper", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/apimatic/jsonmapper.git", + "reference": "f7588f1ab692c402a9118e65cb9fd42b74e5e0db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/apimatic/jsonmapper/zipball/f7588f1ab692c402a9118e65cb9fd42b74e5e0db", + "reference": "f7588f1ab692c402a9118e65cb9fd42b74e5e0db", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "squizlabs/php_codesniffer": "^3.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "apimatic\\jsonmapper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "christian.weiske@netresearch.de", + "homepage": "http://www.netresearch.de/", + "role": "Developer" + }, + { + "name": "Mehdi Jaffery", + "email": "mehdi.jaffery@apimatic.io", + "homepage": "http://apimatic.io/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "mehdi.jaffery@apimatic.io", + "issues": "https://github.com/apimatic/jsonmapper/issues", + "source": "https://github.com/apimatic/jsonmapper/tree/v2.0.3" + }, + "time": "2021-07-16T09:02:23+00:00" + }, + { + "name": "apimatic/unirest-php", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/apimatic/unirest-php.git", + "reference": "b4e399a8970c3a5c611f734282f306381f9d1eee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/apimatic/unirest-php/zipball/b4e399a8970c3a5c611f734282f306381f9d1eee", + "reference": "b4e399a8970c3a5c611f734282f306381f9d1eee", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.6.0" + }, + "require-dev": { + "phpunit/phpunit": "^5 || ^6 || ^7" + }, + "suggest": { + "ext-json": "Allows using JSON Bodies for sending and parsing requests" + }, + "type": "library", + "autoload": { + "psr-0": { + "Unirest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mashape", + "email": "opensource@mashape.com", + "homepage": "https://www.mashape.com", + "role": "Developer" + }, + { + "name": "APIMATIC", + "email": "opensource@apimatic.io", + "homepage": "https://www.apimatic.io", + "role": "Developer" + } + ], + "description": "Unirest PHP", + "homepage": "https://github.com/apimatic/unirest-php", + "keywords": [ + "client", + "curl", + "http", + "https", + "rest" + ], + "support": { + "email": "opensource@apimatic.io", + "issues": "https://github.com/apimatic/unirest-php/issues", + "source": "https://github.com/apimatic/unirest-php/tree/2.0.0" + }, + "time": "2020-04-07T17:16:29+00:00" + }, { "name": "asm/php-ansible", "version": "dev-main", @@ -7459,6 +7573,63 @@ ], "time": "2021-06-16T09:26:40+00:00" }, + { + "name": "square/square", + "version": "13.0.0.20210721", + "source": { + "type": "git", + "url": "https://github.com/square/square-php-sdk.git", + "reference": "03d90445854cd3b500f75061a9c63956799b8ecf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/square/square-php-sdk/zipball/03d90445854cd3b500f75061a9c63956799b8ecf", + "reference": "03d90445854cd3b500f75061a9c63956799b8ecf", + "shasum": "" + }, + "require": { + "apimatic/jsonmapper": "^2.0.2", + "apimatic/unirest-php": "^2.0", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": ">=7.2" + }, + "require-dev": { + "phan/phan": "^3.0", + "phpunit/phpunit": "^7.5 || ^8.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Square\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Square Developer Platform", + "email": "developers@squareup.com", + "homepage": "https://squareup.com/developers" + } + ], + "description": "Use Square APIs to manage and run business including payment, customer, product, inventory, and employee management.", + "homepage": "https://squareup.com/developers", + "keywords": [ + "api", + "sdk", + "square" + ], + "support": { + "issues": "https://github.com/square/square-php-sdk/issues", + "source": "https://github.com/square/square-php-sdk/tree/13.0.0.20210721" + }, + "time": "2021-07-21T06:43:15+00:00" + }, { "name": "stripe/stripe-php", "version": "v7.88.0", @@ -14972,5 +15143,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_08_14_054458_square_payment_driver.php b/database/migrations/2021_08_14_054458_square_payment_driver.php new file mode 100644 index 000000000000..7da0bb5949fa --- /dev/null +++ b/database/migrations/2021_08_14_054458_square_payment_driver.php @@ -0,0 +1,49 @@ +accessToken = ""; + $fields->applicationId = ""; + $fields->locationId = ""; + $fields->testMode = false; + + $square = new Gateway(); + $square->id = 57; + $square->name = "Square"; + $square->provider = "Square"; + $square->key = '65faab2ab6e3223dbe848b1686490baz'; + $square->sort_order = 4343; + $square->is_offsite = false; + $square->visible = true; + $square->fields = json_encode($fields); + $square->save(); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} From 77c072fd10266ba83f7d12aad05f88e17cd1626f Mon Sep 17 00:00:00 2001 From: = Date: Sat, 14 Aug 2021 19:32:16 +1000 Subject: [PATCH 2/8] Square payments --- app/Console/Commands/CreateSingleAccount.php | 21 +++++++ app/Models/Gateway.php | 11 +++- app/PaymentDrivers/SquarePaymentDriver.php | 10 ++-- config/ninja.php | 1 + database/seeders/PaymentLibrariesSeeder.php | 3 +- .../square/credit_card/authorize.blade.php | 57 +++++++++++++++++++ 6 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index ca7201960326..cb56c2e60019 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -787,6 +787,27 @@ class CreateSingleAccount extends Command $cg->fees_and_limits = $fees_and_limits; $cg->save(); } + + if (config('ninja.testvars.square') && ($this->gateway == 'all' || $this->gateway == 'square')) { + $cg = new CompanyGateway; + $cg->company_id = $company->id; + $cg->user_id = $user->id; + $cg->gateway_key = '65faab2ab6e3223dbe848b1686490baz'; + $cg->require_cvv = true; + $cg->require_billing_address = true; + $cg->require_shipping_address = true; + $cg->update_details = true; + $cg->config = encrypt(config('ninja.testvars.square')); + $cg->save(); + + $gateway_types = $cg->driver(new Client)->gatewayTypes(); + + $fees_and_limits = new stdClass; + $fees_and_limits->{$gateway_types[0]} = new FeesAndLimits; + + $cg->fees_and_limits = $fees_and_limits; + $cg->save(); + } } private function createRecurringInvoice($client) diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 424d3b843486..573ac39c5f8f 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -81,9 +81,13 @@ class Gateway extends StaticModel case 1: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net break; - case 1: + case 11: return [GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => false]];//Payfast break; + case 7: + return [ + GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => true], // Mollie + ]; case 15: return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal break; @@ -110,11 +114,12 @@ class Gateway extends StaticModel GatewayType::PAYPAL => ['refund' => true, 'token_billing' => true] ]; break; - case 7: + case 57: return [ - GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => true], // Mollie + GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], //Square ]; break; + break; default: return []; break; diff --git a/app/PaymentDrivers/SquarePaymentDriver.php b/app/PaymentDrivers/SquarePaymentDriver.php index 10647bf54992..d500e420f9ef 100644 --- a/app/PaymentDrivers/SquarePaymentDriver.php +++ b/app/PaymentDrivers/SquarePaymentDriver.php @@ -30,22 +30,22 @@ class SquarePaymentDriver extends BaseDriver public $can_authorise_credit_card = true; //does this gateway support authorizations? - public $square; //initialized gateway + public $square; - public $payment_method; //initialized payment method + public $payment_method; public static $methods = [ GatewayType::CREDIT_CARD => CreditCard::class, //maps GatewayType => Implementation class ]; - const SYSTEM_LOG_TYPE = SystemLog::TYPE_SQUARE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model + const SYSTEM_LOG_TYPE = SystemLog::TYPE_SQUARE; public function init() { $this->square = new Square\SquareClient([ - 'accessToken' => 'EAAAEHeoSxEUZWXCd0makP0-HA0V4OLZ-S-T2Gmc91llp08ColiOX9NpP-LQZIId', - 'environment' => Square\Environment::SANDBOX, + 'accessToken' => $this->company_gateway->getConfigField('accessToken'), + 'environment' => $this->company_gateway->getConfigField('testMode') ? Square\Environment::SANDBOX : Square\Environment::PRODUCTION, ]); return $this; /* This is where you boot the gateway with your auth credentials*/ diff --git a/config/ninja.php b/config/ninja.php index eb3f54f5b066..321ec8e009f6 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -90,6 +90,7 @@ return [ 'decrypted' => env('PAYTRACE_KEYS', ''), ], 'mollie' => env('MOLLIE_KEYS', ''), + 'square' => env('SQUARE_KEYS',''), ], 'contact' => [ 'email' => env('MAIL_FROM_ADDRESS'), diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index c74ab2940ae8..df2ded688cc1 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -80,6 +80,7 @@ class PaymentLibrariesSeeder extends Seeder ['id' => 53, 'name' => 'PagSeguro', 'provider' => 'PagSeguro', 'key' => 'ef498756b54db63c143af0ec433da803', 'fields' => '{"email":"","token":"","sandbox":false}'], ['id' => 54, 'name' => 'PAYMILL', 'provider' => 'Paymill', 'key' => 'ca52f618a39367a4c944098ebf977e1c', 'fields' => '{"apiKey":""}'], ['id' => 55, 'name' => 'Custom', 'provider' => 'Custom', 'is_offsite' => true, 'sort_order' => 21, 'key' => '54faab2ab6e3223dbe848b1686490baa', 'fields' => '{"name":"","text":""}'], + ['id' => 57, 'name' => 'Square', 'provider' => 'Square', 'is_offsite' => false, 'sort_order' => 21, 'key' => '65faab2ab6e3223dbe848b1686490baz', 'fields' => '{"accessToken":"","applicationId":"","locationId":"","testMode":"false"}'], ]; foreach ($gateways as $gateway) { @@ -96,7 +97,7 @@ class PaymentLibrariesSeeder extends Seeder Gateway::query()->update(['visible' => 0]); - Gateway::whereIn('id', [1,7,15,20,39,46,55,50])->update(['visible' => 1]); + Gateway::whereIn('id', [1,7,15,20,39,46,55,50,57])->update(['visible' => 1]); if (Ninja::isHosted()) { Gateway::whereIn('id', [20])->update(['visible' => 0]); diff --git a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php new file mode 100644 index 000000000000..e3a431097476 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php @@ -0,0 +1,57 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' +=> ctrans('texts.payment_type_credit_card')]) + +@section('gateway_head') +@endsection + +@section('gateway_content') +
+ @csrf + + + + + + + + @component('portal.ninja2020.components.general.card-element-single') +
+ +
+ +
+ @endcomponent + +@endsection + +@section('gateway_footer') + +. + + + @endsection \ No newline at end of file From 3119efa3da0353e9c3d8ca0f8ebed37668eb5aa0 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 14 Aug 2021 20:07:27 +1000 Subject: [PATCH 3/8] Square payments --- .../ninja2020/gateways/square/credit_card/authorize.blade.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php index e3a431097476..906608b1e461 100644 --- a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php @@ -31,6 +31,7 @@ . @endsection \ No newline at end of file From 19e9aac12bcd93a51a827c8e481cf69bd732cb8b Mon Sep 17 00:00:00 2001 From: = Date: Sat, 14 Aug 2021 21:00:52 +1000 Subject: [PATCH 6/8] Square payments authorize --- app/PaymentDrivers/Square/CreditCard.php | 213 +++++++++++++++--- .../square/credit_card/authorize.blade.php | 174 +++++++++++--- 2 files changed, 330 insertions(+), 57 deletions(-) diff --git a/app/PaymentDrivers/Square/CreditCard.php b/app/PaymentDrivers/Square/CreditCard.php index f83da6137fa6..89f8e275c8db 100644 --- a/app/PaymentDrivers/Square/CreditCard.php +++ b/app/PaymentDrivers/Square/CreditCard.php @@ -31,17 +31,17 @@ class CreditCard { use MakesHash; - public $square_class; + public $square_driver; - public function __construct(SquarePaymentDriver $square_class) + public function __construct(SquarePaymentDriver $square_driver) { - $this->square_class = $square_class; + $this->square_driver = $square_driver; } public function authorizeView($data) { - $data['gateway'] = $this->square_class; + $data['gateway'] = $this->square_driver; return render('gateways.square.credit_card.authorize', $data); @@ -49,28 +49,21 @@ class CreditCard public function authorizeRequest($request) { + $amount_money = new \Square\Models\Money(); + $amount_money->setAmount(100); //amount in cents + $amount_money->setCurrency($this->square_driver->client->currency()->code); - $billing_address = new \Square\Models\Address(); - $billing_address->setAddressLine1($this->square_class->client->address1); - $billing_address->setAddressLine2($this->square_class->client->address2); - $billing_address->setLocality($this->square_class->client->city); - $billing_address->setAdministrativeDistrictLevel1($this->square_class->client->state); - $billing_address->setPostalCode($this->square_class->client->postal_code); - $billing_address->setCountry($this->square_class->client->country->iso_3166_2); - - $card = new \Square\Models\Card(); - $card->setCardholderName('Amelia Earhart'); - $card->setBillingAddress($billing_address); - $card->setCustomerId('VDKXEEKPJN48QDG3BGGFAK05P8'); - $card->setReferenceId('user-id-1'); - - $body = new \Square\Models\CreateCardRequest( - '4935a656-a929-4792-b97c-8848be85c27c', - 'cnon:uIbfJXhXETSP197M3GB', - $card + $body = new \Square\Models\CreatePaymentRequest( + $request->sourceId, + Str::random(32), + $amount_money ); - $api_response = $client->getCardsApi()->createCard($body); + $body->setAutocomplete(false); + $body->setLocationId($this->square_driver->company_gateway->getConfigField('locationId')); + $body->setReferenceId(Str::random(16)); + + $api_response = $client->getPaymentsApi()->createPayment($body); if ($api_response->isSuccess()) { $result = $api_response->getResult(); @@ -79,13 +72,179 @@ class CreditCard } + +/* +Success response looks like this: + + +{ + "payment": { + "id": "Dv9xlBgSgVB8i6eT0imRYFjcrOaZY", + "created_at": "2021-03-31T20:56:13.220Z", + "updated_at": "2021-03-31T20:56:13.411Z", + "amount_money": { + "amount": 100, + "currency": "USD" + }, + "status": "COMPLETED", + "delay_duration": "PT168H", + "source_type": "CARD", + "card_details": { + "status": "CAPTURED", + "card": { + "card_brand": "AMERICAN_EXPRESS", + "last_4": "6550", + "exp_month": 3, + "exp_year": 2023, + "fingerprint": "sq-1-hPdOWUYtEMft3yQ", + "card_type": "CREDIT", + "prepaid_type": "NOT_PREPAID", + "bin": "371263" + }, + "entry_method": "KEYED", + "cvv_status": "CVV_ACCEPTED", + "avs_status": "AVS_ACCEPTED", + "statement_description": "SQ *DEFAULT TEST ACCOUNT", + "card_payment_timeline": { + "authorized_at": "2021-03-31T20:56:13.334Z", + "captured_at": "2021-03-31T20:56:13.411Z" + } + }, + "location_id": "VJN4XSBFTVPK9", + "total_money": { + "amount": 100, + "currency": "USD" + }, + "approved_money": { + "amount": 100, + "currency": "USD" + } + } +} +*/ + + $billing_address = new \Square\Models\Address(); + $billing_address->setAddressLine1($this->square_driver->client->address1); + $billing_address->setAddressLine2($this->square_driver->client->address2); + $billing_address->setLocality($this->square_driver->client->city); + $billing_address->setAdministrativeDistrictLevel1($this->square_driver->client->state); + $billing_address->setPostalCode($this->square_driver->client->postal_code); + $billing_address->setCountry($this->square_driver->client->country->iso_3166_2); + + $body = new \Square\Models\CreateCustomerRequest(); + $body->setGivenName($this->square_driver->client->present()->name()); + $body->setFamilyName(''); + $body->setEmailAddress($this->square_driver->client->present()->email()); + $body->setAddress($address); + $body->setPhoneNumber($this->square_driver->client->phone); + $body->setReferenceId($this->square_driver->client->number); + $body->setNote('Created by Invoice Ninja.'); + + $api_response = $this->square_driver + ->square + ->getCustomersApi() + ->createCustomer($body); + + if ($api_response->isSuccess()) { + $result = $api_response->getResult(); + } else { + $errors = $api_response->getErrors(); + } + +/*Customer now created response + +{ + "customer": { + "id": "Q6VKKKGW8GWQNEYMDRMV01QMK8", + "created_at": "2021-03-31T18:27:07.803Z", + "updated_at": "2021-03-31T18:27:07Z", + "given_name": "Amelia", + "family_name": "Earhart", + "email_address": "Amelia.Earhart@example.com", + "preferences": { + "email_unsubscribed": false + } + } +} + +*/ + + +$card = new \Square\Models\Card(); +$card->setCardholderName($this->square_driver->client->present()->name()); +$card->setBillingAddress($address); +$card->setCustomerId($result->customer->id); +$card->setReferenceId(Str::random(8)); + +$body = new \Square\Models\CreateCardRequest( + Str::random(32), + $request->sourceId, + $card +); + +$api_response = $client->getCardsApi()->createCard($body); + +if ($api_response->isSuccess()) { + $result = $api_response->getResult(); +} else { + $errors = $api_response->getErrors(); +} + +/** + * +{ + "card": { + "id": "ccof:uIbfJXhXETSP197M3GB", //this is the token + "billing_address": { + "address_line_1": "500 Electric Ave", + "address_line_2": "Suite 600", + "locality": "New York", + "administrative_district_level_1": "NY", + "postal_code": "10003", + "country": "US" + }, + "bin": "411111", + "card_brand": "VISA", + "card_type": "CREDIT", + "cardholder_name": "Amelia Earhart", + "customer_id": "Q6VKKKGW8GWQNEYMDRMV01QMK8", + "enabled": true, + "exp_month": 11, + "exp_year": 2018, + "last_4": "1111", + "prepaid_type": "NOT_PREPAID", + "reference_id": "user-id-1", + "version": 1 + } +} + +*/ + + + + $cgt = []; + $cgt['token'] = $result->card->id; + $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; + + $payment_meta = new \stdClass; + $payment_meta->exp_month = $result->card->exp_month; + $payment_meta->exp_year = $result->card->exp_year; + $payment_meta->brand = $result->card->card_brand; + $payment_meta->last4 = $result->card->last_4; + $payment_meta->type = GatewayType::CREDIT_CARD; + + $cgt['payment_meta'] = $payment_meta; + + $token = $this->square_driver->storeGatewayToken($cgt, []); + + return back(); } public function paymentView($data) { - $data['gateway'] = $this->square_class; + $data['gateway'] = $this->square_driver; $data['client_token'] = $this->braintree->gateway->clientToken()->generate(); return render('gateways.braintree.credit_card.pay', $data); @@ -100,7 +259,7 @@ 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->square_class->payment_hash->invoices(), 'amount')) + $this->square_class->payment_hash->fee_total; + $amount = array_sum(array_column($this->square_driver->payment_hash->invoices(), 'amount')) + $this->square_driver->payment_hash->fee_total; $payment_record = []; $payment_record['amount'] = $amount; @@ -108,7 +267,7 @@ class CreditCard $payment_record['gateway_type_id'] = GatewayType::CREDIT_CARD; // $payment_record['transaction_reference'] = $response->transaction_id; - $payment = $this->square_class->createPayment($payment_record, Payment::STATUS_COMPLETED); + $payment = $this->square_driver->createPayment($payment_record, Payment::STATUS_COMPLETED); return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); @@ -130,7 +289,7 @@ class CreditCard 'error_code' => $error_code, ]; - return $this->square_class->processUnsuccessfulTransaction($data); + return $this->square_driver->processUnsuccessfulTransaction($data); } diff --git a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php index 27d7fc0a1942..81a7a32addd1 100644 --- a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php @@ -8,54 +8,168 @@
@csrf - - - + @component('portal.ninja2020.components.general.card-element-single') -
- +
+
@endcomponent + @component('portal.ninja2020.gateways.includes.pay_now') + {{ ctrans('texts.add_payment_method') }} + @endcomponent @endsection @section('gateway_footer') -. + @endsection \ No newline at end of file From 27cdfd24f119b76da7e10bc43080183a7f4525b0 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 14 Aug 2021 21:37:04 +1000 Subject: [PATCH 7/8] Authorize Credit Card --- app/PaymentDrivers/Square/CreditCard.php | 58 ++++++++++--------- app/PaymentDrivers/SquarePaymentDriver.php | 4 +- .../square/credit_card/authorize.blade.php | 20 ++----- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/app/PaymentDrivers/Square/CreditCard.php b/app/PaymentDrivers/Square/CreditCard.php index 89f8e275c8db..052480e1eff4 100644 --- a/app/PaymentDrivers/Square/CreditCard.php +++ b/app/PaymentDrivers/Square/CreditCard.php @@ -36,6 +36,7 @@ class CreditCard public function __construct(SquarePaymentDriver $square_driver) { $this->square_driver = $square_driver; + $this->square_driver->init(); } public function authorizeView($data) @@ -47,7 +48,7 @@ class CreditCard } - public function authorizeRequest($request) + public function authorizeResponse($request) { $amount_money = new \Square\Models\Money(); $amount_money->setAmount(100); //amount in cents @@ -63,12 +64,14 @@ class CreditCard $body->setLocationId($this->square_driver->company_gateway->getConfigField('locationId')); $body->setReferenceId(Str::random(16)); - $api_response = $client->getPaymentsApi()->createPayment($body); + $api_response = $this->square_driver->square->getPaymentsApi()->createPayment($body); if ($api_response->isSuccess()) { $result = $api_response->getResult(); + nlog($result); } else { $errors = $api_response->getErrors(); + nlog($errors); } @@ -135,7 +138,7 @@ Success response looks like this: $body->setGivenName($this->square_driver->client->present()->name()); $body->setFamilyName(''); $body->setEmailAddress($this->square_driver->client->present()->email()); - $body->setAddress($address); + $body->setAddress($billing_address); $body->setPhoneNumber($this->square_driver->client->phone); $body->setReferenceId($this->square_driver->client->number); $body->setNote('Created by Invoice Ninja.'); @@ -147,8 +150,10 @@ Success response looks like this: if ($api_response->isSuccess()) { $result = $api_response->getResult(); + nlog($result); } else { $errors = $api_response->getErrors(); + nlog($errors); } /*Customer now created response @@ -170,25 +175,28 @@ Success response looks like this: */ -$card = new \Square\Models\Card(); -$card->setCardholderName($this->square_driver->client->present()->name()); -$card->setBillingAddress($address); -$card->setCustomerId($result->customer->id); -$card->setReferenceId(Str::random(8)); + $card = new \Square\Models\Card(); + $card->setCardholderName($this->square_driver->client->present()->name()); + $card->setBillingAddress($billing_address); + $card->setCustomerId($result->getCustomer()->getId()); + $card->setReferenceId(Str::random(8)); -$body = new \Square\Models\CreateCardRequest( - Str::random(32), - $request->sourceId, - $card -); + $body = new \Square\Models\CreateCardRequest( + Str::random(32), + $request->sourceId, + $card + ); -$api_response = $client->getCardsApi()->createCard($body); + $api_response = $this->square_driver + ->square + ->getCardsApi() + ->createCard($body); -if ($api_response->isSuccess()) { - $result = $api_response->getResult(); -} else { - $errors = $api_response->getErrors(); -} + if ($api_response->isSuccess()) { + $result = $api_response->getResult(); + } else { + $errors = $api_response->getErrors(); + } /** * @@ -220,17 +228,15 @@ if ($api_response->isSuccess()) { */ - - $cgt = []; - $cgt['token'] = $result->card->id; + $cgt['token'] = $result->getCard()->getId(); $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; $payment_meta = new \stdClass; - $payment_meta->exp_month = $result->card->exp_month; - $payment_meta->exp_year = $result->card->exp_year; - $payment_meta->brand = $result->card->card_brand; - $payment_meta->last4 = $result->card->last_4; + $payment_meta->exp_month = $result->getCard()->getExpMonth(); + $payment_meta->exp_year = $result->getCard()->getExpYear(); + $payment_meta->brand = $result->getCard()->getCardBrand(); + $payment_meta->last4 = $result->getCard()->getLast4(); $payment_meta->type = GatewayType::CREDIT_CARD; $cgt['payment_meta'] = $payment_meta; diff --git a/app/PaymentDrivers/SquarePaymentDriver.php b/app/PaymentDrivers/SquarePaymentDriver.php index d500e420f9ef..d3c5ab247115 100644 --- a/app/PaymentDrivers/SquarePaymentDriver.php +++ b/app/PaymentDrivers/SquarePaymentDriver.php @@ -43,9 +43,9 @@ class SquarePaymentDriver extends BaseDriver public function init() { - $this->square = new Square\SquareClient([ + $this->square = new \Square\SquareClient([ 'accessToken' => $this->company_gateway->getConfigField('accessToken'), - 'environment' => $this->company_gateway->getConfigField('testMode') ? Square\Environment::SANDBOX : Square\Environment::PRODUCTION, + 'environment' => $this->company_gateway->getConfigField('testMode') ? \Square\Environment::SANDBOX : \Square\Environment::PRODUCTION, ]); return $this; /* This is where you boot the gateway with your auth credentials*/ diff --git a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php index 81a7a32addd1..7bd9f85d4f56 100644 --- a/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/square/credit_card/authorize.blade.php @@ -8,13 +8,12 @@
@csrf - + - @component('portal.ninja2020.components.general.card-element-single') -
+
@@ -81,15 +80,6 @@ return card; } - async function createPayment(token) { - - document.getElementById('sourceId').value = token; - document.getElementById('server_response').submit(); - - const errorBody = await paymentResponse.text(); - throw new Error(errorBody); - } - async function tokenize(paymentMethod) { const tokenResult = await paymentMethod.tokenize(); if (tokenResult.status === 'OK') { @@ -154,10 +144,12 @@ // disable the submit button as we await tokenization and make a payment request. cardButton.disabled = true; const token = await tokenize(paymentMethod); - const paymentResults = await createPayment(token); + + document.getElementById('sourceId').value = token; + document.getElementById('server_response').submit(); + displayPaymentResults('SUCCESS'); - console.debug('Payment Success', paymentResults); } catch (e) { cardButton.disabled = false; displayPaymentResults('FAILURE'); From 6cf3ef9b77a5229242f3aa94a415230cd5bf00ff Mon Sep 17 00:00:00 2001 From: = Date: Sat, 14 Aug 2021 22:17:35 +1000 Subject: [PATCH 8/8] Square authorize --- app/PaymentDrivers/Square/CreditCard.php | 26 ++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/app/PaymentDrivers/Square/CreditCard.php b/app/PaymentDrivers/Square/CreditCard.php index 052480e1eff4..76b3ca63ad5e 100644 --- a/app/PaymentDrivers/Square/CreditCard.php +++ b/app/PaymentDrivers/Square/CreditCard.php @@ -50,6 +50,8 @@ class CreditCard public function authorizeResponse($request) { + $payment = false; + $amount_money = new \Square\Models\Money(); $amount_money->setAmount(100); //amount in cents $amount_money->setCurrency($this->square_driver->client->currency()->code); @@ -67,8 +69,11 @@ class CreditCard $api_response = $this->square_driver->square->getPaymentsApi()->createPayment($body); if ($api_response->isSuccess()) { - $result = $api_response->getResult(); - nlog($result); + // $result = $api_response->getResult(); + + $result = $api_response->getBody(); + $payment = json_decode($result); + } else { $errors = $api_response->getErrors(); nlog($errors); @@ -183,7 +188,7 @@ Success response looks like this: $body = new \Square\Models\CreateCardRequest( Str::random(32), - $request->sourceId, + $payment->payment->id, $card ); @@ -194,8 +199,13 @@ Success response looks like this: if ($api_response->isSuccess()) { $result = $api_response->getResult(); + nlog($result->getBody()); + nlog("ressy"); + nlog($result); } else { $errors = $api_response->getErrors(); + nlog("i got errors"); + nlog($errors); } /** @@ -229,14 +239,14 @@ Success response looks like this: */ $cgt = []; - $cgt['token'] = $result->getCard()->getId(); + $cgt['token'] = $result->getId(); $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; $payment_meta = new \stdClass; - $payment_meta->exp_month = $result->getCard()->getExpMonth(); - $payment_meta->exp_year = $result->getCard()->getExpYear(); - $payment_meta->brand = $result->getCard()->getCardBrand(); - $payment_meta->last4 = $result->getCard()->getLast4(); + $payment_meta->exp_month = $result->getExpMonth(); + $payment_meta->exp_year = $result->getExpYear(); + $payment_meta->brand = $result->getCardBrand(); + $payment_meta->last4 = $result->getLast4(); $payment_meta->type = GatewayType::CREDIT_CARD; $cgt['payment_meta'] = $payment_meta;