diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index ee38fbb77181..eed243b27d91 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -51,7 +51,7 @@ class NinjaMailerJob implements ShouldQueue public $override; - /** @var \App\Models\Company $company | null **/ + /** @var null|\App\Models\Company $company **/ public ?Company $company; private $mailer; @@ -143,8 +143,6 @@ class NinjaMailerJob implements ShouldQueue LightLogs::create(new EmailSuccess($this->nmo->company->company_key)) ->send(); - $this->nmo = null; - $this->company = null; } catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) { nlog("Mailer failed with a Logic Exception {$e->getMessage()}"); $this->fail(); @@ -195,6 +193,9 @@ class NinjaMailerJob implements ShouldQueue $this->release($this->backoff()[$this->attempts()-1]); } + $this->nmo = null; + $this->company = null; + /*Clean up mailers*/ $this->cleanUpMailers(); } diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index 446d3022c8fe..d40c569ba05b 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -221,6 +221,22 @@ class CompanyGateway extends BaseModel { $this->config = encrypt(json_encode($config)); } + + /** + * setConfigField + * + * @param mixed $field + * @param mixed $value + * @return void + */ + public function setConfigField($field, $value): void + { + $config = $this->getConfig(); + $config->{$field} = $value; + + $this->setConfig($config); + $this->save(); + } /** * @return mixed diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 79677bf45b5c..80c5b391d7c0 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -171,7 +171,7 @@ class Gateway extends StaticModel ]; case 57: return [ - GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => true], //Square + GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], //Square ]; case 52: return [ diff --git a/app/Models/PaymentHash.php b/app/Models/PaymentHash.php index daf6b6197d9f..a870489ce02f 100644 --- a/app/Models/PaymentHash.php +++ b/app/Models/PaymentHash.php @@ -17,7 +17,7 @@ use Illuminate\Database\Eloquent\Model; * App\Models\PaymentHash * * @property int $id - * @property string $hash + * @property string $hash 32 char length AlphaNum * @property float $fee_total * @property int|null $fee_invoice_id * @property \stdClass $data @@ -41,6 +41,7 @@ class PaymentHash extends Model /** * @class \App\Models\PaymentHash $this * @property \App\Models\PaymentHash $data + * @property \App\Modes\PaymentHash $hash 32 char length AlphaNum * @class \stdClass $data * @property string $raw_value */ diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 43290710a70d..940727d9f917 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -263,6 +263,8 @@ class BaseDriver extends AbstractPaymentDriver public function setClient(Client $client) { $this->client = $client; + + return $this; } /************************** Helper methods *************************************/ diff --git a/app/PaymentDrivers/Square/CreditCard.php b/app/PaymentDrivers/Square/CreditCard.php index 9d61f652ffa1..59139361a946 100644 --- a/app/PaymentDrivers/Square/CreditCard.php +++ b/app/PaymentDrivers/Square/CreditCard.php @@ -12,6 +12,7 @@ namespace App\PaymentDrivers\Square; +use App\Models\Invoice; use App\Models\Payment; use App\Models\SystemLog; use Illuminate\View\View; @@ -33,11 +34,8 @@ class CreditCard implements MethodInterface { use MakesHash; - public $square_driver; - - public function __construct(SquarePaymentDriver $square_driver) + public function __construct(public SquarePaymentDriver $square_driver) { - $this->square_driver = $square_driver; $this->square_driver->init(); } @@ -102,28 +100,35 @@ class CreditCard implements MethodInterface ); if ($request->shouldUseToken()) { - /** @var \App\Models\ClientGatewayToken $cgt **/ - $cgt = ClientGatewayToken::where('token', $request->token)->first(); + $cgt = ClientGatewayToken::query()->where('token', $request->token)->first(); $token = $cgt->token; } + $invoice = Invoice::query()->whereIn('id', $this->transformKeys(array_column($this->square_driver->payment_hash->invoices(), 'invoice_id')))->withTrashed()->first(); + + if ($invoice) { + $description = "Invoice {$invoice->number} for {$amount} for client {$this->square_driver->client->present()->name()}"; + } else { + $description = "Payment with no invoice for amount {$amount} for client {$this->square_driver->client->present()->name()}"; + } + $amount_money = new \Square\Models\Money(); $amount_money->setAmount($amount); $amount_money->setCurrency($this->square_driver->client->currency()->code); - $body = new \Square\Models\CreatePaymentRequest($token, $request->idempotencyKey, $amount_money); - + $body = new \Square\Models\CreatePaymentRequest($token, $request->idempotencyKey); + $body->setAmountMoney($amount_money); $body->setAutocomplete(true); $body->setLocationId($this->square_driver->company_gateway->getConfigField('locationId')); - $body->setReferenceId(Str::random(16)); - + $body->setReferenceId($this->square_driver->payment_hash->hash); + $body->setNote($description); + if ($request->shouldUseToken()) { $body->setCustomerId($cgt->gateway_customer_reference); }elseif ($request->has('verificationToken') && $request->input('verificationToken')) { $body->setVerificationToken($request->input('verificationToken')); } - /** @var ApiResponse */ $response = $this->square_driver->square->getPaymentsApi()->createPayment($body); if ($response->isSuccess()) { diff --git a/app/PaymentDrivers/Square/SquareWebhook.php b/app/PaymentDrivers/Square/SquareWebhook.php new file mode 100644 index 000000000000..8e99e160e10a --- /dev/null +++ b/app/PaymentDrivers/Square/SquareWebhook.php @@ -0,0 +1,280 @@ + PaymentType::CREDIT_CARD_OTHER, + 'BANK_ACCOUNT' => PaymentType::ACH, + 'WALLET' => PaymentType::CREDIT_CARD_OTHER, + 'BUY_NOW_PAY_LATER' => PaymentType::CREDIT_CARD_OTHER, + 'SQUARE_ACCOUNT' => PaymentType::CREDIT_CARD_OTHER, + 'CASH' => PaymentType::CASH, + 'EXTERNAL' =>PaymentType::CREDIT_CARD_OTHER + ]; + + public function __construct(public array $webhook_array, public string $company_key, public int $company_gateway_id) + { + } + + +/** + * { + * "merchant_id": "6SSW7HV8K2ST5", + * "type": "payment.created", + * "event_id": "13b867cf-db3d-4b1c-90b6-2f32a9d78124", + * "created_at": "2020-02-06T21:27:30.792Z", + * "data": { + * "type": "payment", + * "id": "KkAkhdMsgzn59SM8A89WgKwekxLZY", + * "object": { + * "payment": { + * "id": "hYy9pRFVxpDsO1FB05SunFWUe9JZY", + * "created_at": "2020-11-22T21:16:51.086Z", + * "updated_at": "2020-11-22T21:16:51.198Z", + * "amount_money": { + * "amount": 100, + * "currency": "USD" + * }, + * "status": "APPROVED", + * "delay_duration": "PT168H", + * "source_type": "CARD", + * "card_details": { + * "status": "AUTHORIZED", + * "card": { + * "card_brand": "MASTERCARD", + * "last_4": "9029", + * "exp_month": 11, + * "exp_year": 2022, + * "fingerprint": "sq-1-Tvruf3vPQxlvI6n0IcKYfBukrcv6IqWr8UyBdViWXU2yzGn5VMJvrsHMKpINMhPmVg", + * "card_type": "CREDIT", + * "prepaid_type": "NOT_PREPAID", + * "bin": "540988" + * }, + * "entry_method": "KEYED", + * "cvv_status": "CVV_ACCEPTED", + * "avs_status": "AVS_ACCEPTED", + * "statement_description": "SQ *DEFAULT TEST ACCOUNT", + * "card_payment_timeline": { + * "authorized_at": "2020-11-22T21:16:51.198Z" + * + */ + public function handle() + { + nlog("Square Webhook"); + + MultiDB::findAndSetDbByCompanyKey($this->company_key); + + $this->company_gateway = CompanyGateway::query()->withTrashed()->find($this->company_gateway_id); + $this->driver = $this->company_gateway->driver()->init(); + $this->square = $this->driver->square; + + $status = $this->webhook_array['data']['object']['payment']['status'] ?? false; + $payment_id = $this->webhook_array['data']['object']['payment']['id'] ?? null; + + $payment_status = false; + + match($status){ + 'APPROVED' => $payment_status = false, + 'COMPLETED' => $payment_status = Payment::STATUS_COMPLETED, + 'PENDING' => $payment_status = Payment::STATUS_PENDING, + 'CANCELED' => $payment_status = Payment::STATUS_CANCELLED, + 'FAILED' => $payment_status = Payment::STATUS_FAILED, + default => $payment_status = false, + }; + + if(!$payment_status){ + nlog("Square Webhook - Payment Status Not Found or not worthy of processing"); + nlog($this->webhook_array); + } + + $payment = $this->retrieveOrCreatePayment($payment_id, $payment_status); + + /** If the status was pending and now is reporting as Failed / Cancelled - process failure path */ + if($payment->status_id == Payment::STATUS_PENDING && in_array($payment_status, [Payment::STATUS_CANCELLED, Payment::STATUS_FAILED])){ + $payment->service()->deletePayment(); + + if ($this->driver->payment_hash) { + $error = ctrans('texts.client_payment_failure_body', [ + 'invoice' => implode(',', $payment->invoices->pluck('number')->toArray()), + 'amount' => array_sum(array_column($this->driver->payment_hash->invoices(), 'amount')) + $this->driver->payment_hash->fee_total, + ]); + } else { + $error = 'Payment for '.$payment->client->present()->name()." for {$payment->amount} failed"; + } + + PaymentFailedMailer::dispatch( + $this->driver->payment_hash, + $this->driver->client->company, + $this->driver->client, + $error + ); + + } + elseif($payment->status_id == Payment::STATUS_PENDING && in_array($payment_status, [Payment::STATUS_COMPLETED, Payment::STATUS_COMPLETED])){ + $payment->status_id = Payment::STATUS_COMPLETED; + $payment->save(); + } + + //toggle pending to completed. + } + + private function retrieveOrCreatePayment(?string $payment_reference, int $payment_status): ?\App\Models\Payment + { + + $payment = Payment::withTrashed()->where('transaction_reference', $payment_reference)->first(); + + if($payment) + return $payment; + + /** Handles the edge case where for some reason the payment has not yet been recorded in Invoice Ninja */ + $apiResponse = $this->square->getPaymentsApi()->getPayment($payment_reference); + +// { +// "payment": { +// "id": "bP9mAsEMYPUGjjGNaNO5ZDVyLhSZY", +// "created_at": "2021-10-13T19:34:33.524Z", +// "updated_at": "2021-10-13T19:34:34.339Z", +// "amount_money": { +// "amount": 555, +// "currency": "USD" +// }, +// "status": "COMPLETED", +// "delay_duration": "PT168H", +// "source_type": "CARD", +// "card_details": { +// "status": "CAPTURED", +// "card": { +// "card_brand": "VISA", +// "last_4": "1111", +// "exp_month": 11, +// "exp_year": 2022, +// "fingerprint": "sq-1-Hxim77tbdcbGejOejnoAklBVJed2YFLTmirfl8Q5XZzObTc8qY_U8RkwzoNL8dCEcQ", +// "card_type": "DEBIT", +// "prepaid_type": "NOT_PREPAID", +// "bin": "411111" +// }, +// "entry_method": "KEYED", +// "cvv_status": "CVV_ACCEPTED", +// "avs_status": "AVS_ACCEPTED", +// "auth_result_code": "2Nkw7q", +// "statement_description": "SQ *EXAMPLE TEST GOSQ.C", +// "card_payment_timeline": { +// "authorized_at": "2021-10-13T19:34:33.680Z", +// "captured_at": "2021-10-13T19:34:34.340Z" +// } +// }, +// "location_id": "L88917AVBK2S5", +// "order_id": "d7eKah653Z579f3gVtjlxpSlmUcZY", +// "processing_fee": [ +// { +// "effective_at": "2021-10-13T21:34:35.000Z", +// "type": "INITIAL", +// "amount_money": { +// "amount": 34, +// "currency": "USD" +// } +// } +// ], +// "note": "Test Note", +// "total_money": { +// "amount": 555, +// "currency": "USD" +// }, +// "approved_money": { +// "amount": 555, +// "currency": "USD" +// }, +// "employee_id": "TMoK_ogh6rH1o4dV", +// "receipt_number": "bP9m", +// "receipt_url": "https://squareup.com/receipt/preview/bP9mAsEMYPUGjjGNaNO5ZDVyLhSZY", +// "delay_action": "CANCEL", +// "delayed_until": "2021-10-20T19:34:33.524Z", +// "team_member_id": "TMoK_ogh6rH1o4dV", +// "application_details": { +// "square_product": "VIRTUAL_TERMINAL", +// "application_id": "sq0ids-Pw67AZAlLVB7hsRmwlJPuA" +// }, +// "version_token": "56pRkL3slrzet2iQrTp9n0bdJVYTB9YEWdTNjQfZOPV6o" +// } +// } + + if($apiResponse->isSuccess()){ + + $payment_hash_id = $apiResponse->getPayment()->getReferenceId() ?? false; + $square_payment = $apiResponse->getPayment()->jsonSerialize(); + $payment_hash = PaymentHash::where('hash', $payment_hash_id)->firstOrFail(); + + $payment_hash->data = array_merge((array) $payment_hash->data, (array)$square_payment); + $payment_hash->save(); + + $this->driver->setPaymentHash($payment_hash); + $this->driver->setClient($payment_hash->fee_invoice->client); + + $data = [ + 'payment_type' => $this->source_type[$square_payment->source_type], + 'amount' => $payment_hash->amount_with_fee, + 'transaction_reference' => $square_payment->id, + 'gateway_type_id' => GatewayType::BANK_TRANSFER, + ]; + + $payment = $this->driver->createPayment($data, $payment_status); + + SystemLogger::dispatch( + ['response' => $this->webhook_array, 'data' => $square_payment], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_SQUARE, + $this->driver->client, + $this->driver->client->company, + ); + + return $payment; + + } + else{ + nlog("Square Webhook - Payment not found: $payment_reference"); + nlog($apiResponse->getErrors()); + return null; + } + } +} \ No newline at end of file diff --git a/app/PaymentDrivers/SquarePaymentDriver.php b/app/PaymentDrivers/SquarePaymentDriver.php index cdae15876a2e..3ff5e09121a3 100644 --- a/app/PaymentDrivers/SquarePaymentDriver.php +++ b/app/PaymentDrivers/SquarePaymentDriver.php @@ -11,18 +11,22 @@ namespace App\PaymentDrivers; -use App\Http\Requests\Payments\PaymentWebhookRequest; -use App\Jobs\Util\SystemLogger; -use App\Models\ClientGatewayToken; -use App\Models\GatewayType; use App\Models\Invoice; use App\Models\Payment; +use App\Models\SystemLog; +use App\Models\GatewayType; use App\Models\PaymentHash; use App\Models\PaymentType; -use App\Models\SystemLog; -use App\PaymentDrivers\Square\CreditCard; +use App\Jobs\Util\SystemLogger; use App\Utils\Traits\MakesHash; -use Square\Http\ApiResponse; +use Square\Utils\WebhooksHelper; +use App\Models\ClientGatewayToken; +use Square\Models\WebhookSubscription; +use App\PaymentDrivers\Square\CreditCard; +use App\PaymentDrivers\Square\SquareWebhook; +use Square\Models\CreateWebhookSubscriptionRequest; +use App\Http\Requests\Payments\PaymentWebhookRequest; +use Square\Models\Builders\RefundPaymentRequestBuilder; class SquarePaymentDriver extends BaseDriver { @@ -96,15 +100,115 @@ class SquarePaymentDriver extends BaseDriver public function refund(Payment $payment, $amount, $return_client_response = false) { $this->init(); + $this->client = $payment->client; $amount_money = new \Square\Models\Money(); $amount_money->setAmount($this->convertAmount($amount)); $amount_money->setCurrency($this->client->currency()->code); - $body = new \Square\Models\RefundPaymentRequest(\Illuminate\Support\Str::random(32), $amount_money, $payment->transaction_reference); + $body = RefundPaymentRequestBuilder::init(\Illuminate\Support\Str::random(32), $amount_money) + ->paymentId($payment->transaction_reference) + ->reason('Refund Request') + ->build(); + + $apiResponse = $this->square->getRefundsApi()->refundPayment($body); + + if ($apiResponse->isSuccess()) { + + $refundPaymentResponse = $apiResponse->getResult(); + + nlog($refundPaymentResponse); + + /** + * - `PENDING` - Awaiting approval. + * - `COMPLETED` - Successfully completed. + * - `REJECTED` - The refund was rejected. + * - `FAILED` - An error occurred. + */ + + $status = $refundPaymentResponse->getRefund()->getStatus(); + + if(in_array($status, ['COMPLETED', 'PENDING'])){ + + $transaction_reference = $refundPaymentResponse->getRefund()->getId(); + + $data = [ + 'transaction_reference' => $transaction_reference, + 'transaction_response' => json_encode($refundPaymentResponse->getRefund()->jsonSerialize()), + 'success' => true, + 'description' => $refundPaymentResponse->getRefund()->getReason(), + 'code' => $refundPaymentResponse->getRefund()->getReason(), + ]; + + SystemLogger::dispatch( + [ + 'server_response' => $data, + 'data' => request()->all() + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_SQUARE, + $this->client, + $this->client->company + ); + + return $data; + } + elseif(in_array($status, ['REJECTED', 'FAILED'])) { + + $transaction_reference = $refundPaymentResponse->getRefund()->getId(); + + $data = [ + 'transaction_reference' => $transaction_reference, + 'transaction_response' => json_encode($refundPaymentResponse->getRefund()->jsonSerialize()), + 'success' => false, + 'description' => $refundPaymentResponse->getRefund()->getReason(), + 'code' => $refundPaymentResponse->getRefund()->getReason(), + ]; + + SystemLogger::dispatch( + [ + 'server_response' => $data, + 'data' => request()->all() + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_SQUARE, + $this->client, + $this->client->company + ); + + return $data; + } + + } else { + + /** @var \Square\Models\Error $error */ + $error = end($apiResponse->getErrors()); + + $data = [ + 'transaction_reference' => $payment->transaction_reference, + 'transaction_response' => $error->jsonSerialize(), + 'success' => false, + 'description' => $error->getDetail(), + 'code' => $error->getCode(), + ]; + + SystemLogger::dispatch( + [ + 'server_response' => $data, + 'data' => request()->all() + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_SQUARE, + $this->client, + $this->client->company + ); + + return $data; + } - /** @var ApiResponse */ - $response = $this->square->getRefundsApi()->refund($body); } public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) @@ -126,10 +230,12 @@ class SquarePaymentDriver extends BaseDriver $amount_money->setAmount($amount); $amount_money->setCurrency($this->client->currency()->code); - $body = new \Square\Models\CreatePaymentRequest($cgt->token, \Illuminate\Support\Str::random(32), $amount_money); + $body = new \Square\Models\CreatePaymentRequest($cgt->token, \Illuminate\Support\Str::random(32)); $body->setCustomerId($cgt->gateway_customer_reference); + $body->setAmountMoney($amount_money); + $body->setReferenceId($payment_hash->hash); + $body->setNote(substr($description,0,500)); - /** @var ApiResponse */ $response = $this->square->getPaymentsApi()->createPayment($body); $body = json_decode($response->getBody()); @@ -177,8 +283,107 @@ class SquarePaymentDriver extends BaseDriver return false; } - public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) + public function checkWebhooks(): bool { + $this->init(); + + $api_response = $this->square->getWebhookSubscriptionsApi()->listWebhookSubscriptions(); + + if ($api_response->isSuccess()) { + + //array of WebhookSubscription objects + foreach($api_response->getResult()->getSubscriptions() as $subscription) + { + if($subscription->getName() == 'Invoice_Ninja_Webhook_Subscription') + return true; + } + + } else { + $errors = $api_response->getErrors(); + nlog($errors); + + } + + return false; + } + + // { + // "subscription": { + // "id": "wbhk_b35f6b3145074cf9ad513610786c19d5", + // "name": "Example Webhook Subscription", + // "enabled": true, + // "event_types": [ + // "payment.created", + // "order.updated", + // "invoice.created" + // ], + // "notification_url": "https://example-webhook-url.com", + // "api_version": "2021-12-15", + // "signature_key": "1k9bIJKCeTmSQwyagtNRLg", + // "created_at": "2022-08-17 23:29:48 +0000 UTC", + // "updated_at": "2022-08-17 23:29:48 +0000 UTC" + // } + // } + public function createWebhooks(): void + { + + if($this->checkWebhooks()) + return; + + $this->init(); + + $event_types = ['payment.created', 'payment.updated']; + $subscription = new WebhookSubscription(); + $subscription->setName('Invoice_Ninja_Webhook_Subscription'); + $subscription->setEventTypes($event_types); + + // $subscription->setNotificationUrl('https://invoicing.co'); + + $subscription->setNotificationUrl($this->company_gateway->webhookUrl()); + // $subscription->setApiVersion('2021-12-15'); + + $body = new CreateWebhookSubscriptionRequest($subscription); + $body->setIdempotencyKey(\Illuminate\Support\Str::uuid()); + + $api_response = $this->square->getWebhookSubscriptionsApi()->createWebhookSubscription($body); + + if ($api_response->isSuccess()) { + $subscription = $api_response->getResult()->getSubscription(); + $signatureKey = $subscription->getSignatureKey(); + + $this->company_gateway->setConfigField('signatureKey', $signatureKey); + + } else { + $errors = $api_response->getErrors(); + nlog($errors); + } + + } + + public function processWebhookRequest(PaymentWebhookRequest $request) + { + + $signature_key = $this->company_gateway->getConfigField('signatureKey'); + $notification_url = $this->company_gateway->webhookUrl(); + + // header('Content-Type: text/plain'); + // $webhook_payload = file_get_contents('php://input'); + + $body = ''; + $handle = fopen('php://input', 'r'); + while(!feof($handle)) { + $body .= fread($handle, 1024); + } + + if (WebhooksHelper::isValidWebhookEventSignature($body, $request->header('x-square-hmacsha256-signature'), $signature_key, $notification_url)) { + SquareWebhook::dispatch($request->all(), $request->company_key, $this->company_gateway->id)->delay(5); + } else { + nlog("Square Hash Mismatch"); + nlog($request->all()); + } + + return response()->json(['success' => true]); + } public function convertAmount($amount) diff --git a/composer.json b/composer.json index 0d071ca1da10..d9bb6348f79c 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ "socialiteproviders/microsoft": "^4.1", "spatie/laravel-data": "^3.5", "sprain/swiss-qr-bill": "^3.2", - "square/square": "13.0.0.20210721", + "square/square": "30.0.0.*", "stripe/stripe-php": "^7.50", "symfony/http-client": "^6.0", "symfony/mailgun-mailer": "^6.1", diff --git a/composer.lock b/composer.lock index 2be5001245e6..31584f8b7590 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": "9d7348352c913eb82fcca2e67670e1f8", + "content-hash": "673ca66ddfdb05c3ea29012594a196d3", "packages": [ { "name": "adrienrn/php-mimetyper", @@ -99,21 +99,121 @@ "time": "2023-05-02T15:11:17+00:00" }, { - "name": "apimatic/jsonmapper", - "version": "v2.0.3", + "name": "apimatic/core", + "version": "0.3.2", "source": { "type": "git", - "url": "https://github.com/apimatic/jsonmapper.git", - "reference": "f7588f1ab692c402a9118e65cb9fd42b74e5e0db" + "url": "https://github.com/apimatic/core-lib-php.git", + "reference": "32238fb83ce9a3ebef38c726b497c0f218d6e6c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/apimatic/jsonmapper/zipball/f7588f1ab692c402a9118e65cb9fd42b74e5e0db", - "reference": "f7588f1ab692c402a9118e65cb9fd42b74e5e0db", + "url": "https://api.github.com/repos/apimatic/core-lib-php/zipball/32238fb83ce9a3ebef38c726b497c0f218d6e6c9", + "reference": "32238fb83ce9a3ebef38c726b497c0f218d6e6c9", "shasum": "" }, + "require": { + "apimatic/core-interfaces": "~0.1.0", + "apimatic/jsonmapper": "^3.1.1", + "ext-curl": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "php": "^7.2 || ^8.0", + "php-jsonpointer/php-jsonpointer": "^3.0.2" + }, "require-dev": { - "phpunit/phpunit": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "phan/phan": "5.4.2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Core\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Core logic and the utilities for the Apimatic's PHP SDK", + "homepage": "https://github.com/apimatic/core-lib-php", + "keywords": [ + "apimatic", + "core", + "corelib", + "php" + ], + "support": { + "issues": "https://github.com/apimatic/core-lib-php/issues", + "source": "https://github.com/apimatic/core-lib-php/tree/0.3.2" + }, + "time": "2023-07-11T09:30:32+00:00" + }, + { + "name": "apimatic/core-interfaces", + "version": "0.1.2", + "source": { + "type": "git", + "url": "https://github.com/apimatic/core-interfaces-php.git", + "reference": "183214195a79784c382a446795c46ca8c1f43cc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/apimatic/core-interfaces-php/zipball/183214195a79784c382a446795c46ca8c1f43cc1", + "reference": "183214195a79784c382a446795c46ca8c1f43cc1", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "CoreInterfaces\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Definition of the behavior of apimatic/core, apimatic/unirest-php and Apimatic's PHP SDK", + "homepage": "https://github.com/apimatic/core-interfaces-php", + "keywords": [ + "apimatic", + "core", + "corelib", + "interface", + "php", + "unirest" + ], + "support": { + "issues": "https://github.com/apimatic/core-interfaces-php/issues", + "source": "https://github.com/apimatic/core-interfaces-php/tree/0.1.2" + }, + "time": "2023-04-04T06:40:52+00:00" + }, + { + "name": "apimatic/jsonmapper", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/apimatic/jsonmapper.git", + "reference": "6673a946c21f2ceeec0cb60d17541c11a22bc79d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/apimatic/jsonmapper/zipball/6673a946c21f2ceeec0cb60d17541c11a22bc79d", + "reference": "6673a946c21f2ceeec0cb60d17541c11a22bc79d", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "squizlabs/php_codesniffer": "^3.0.0" }, "type": "library", @@ -144,37 +244,38 @@ "support": { "email": "mehdi.jaffery@apimatic.io", "issues": "https://github.com/apimatic/jsonmapper/issues", - "source": "https://github.com/apimatic/jsonmapper/tree/v2.0.3" + "source": "https://github.com/apimatic/jsonmapper/tree/3.1.2" }, - "time": "2021-07-16T09:02:23+00:00" + "time": "2023-06-08T04:27:10+00:00" }, { "name": "apimatic/unirest-php", - "version": "2.3.0", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/apimatic/unirest-php.git", - "reference": "52e226fb3b7081dc9ef64aee876142a240a5f0f9" + "reference": "e16754010c16be5473289470f129d87a0f41b55e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/apimatic/unirest-php/zipball/52e226fb3b7081dc9ef64aee876142a240a5f0f9", - "reference": "52e226fb3b7081dc9ef64aee876142a240a5f0f9", + "url": "https://api.github.com/repos/apimatic/unirest-php/zipball/e16754010c16be5473289470f129d87a0f41b55e", + "reference": "e16754010c16be5473289470f129d87a0f41b55e", "shasum": "" }, "require": { + "apimatic/core-interfaces": "^0.1.0", "ext-curl": "*", - "php": ">=5.6.0" + "ext-json": "*", + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^5 || ^6 || ^7 || ^8 || ^9" - }, - "suggest": { - "ext-json": "Allows using JSON Bodies for sending and parsing requests" + "phan/phan": "5.4.2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "autoload": { - "psr-0": { + "psr-4": { "Unirest\\": "src/" } }, @@ -208,9 +309,9 @@ "support": { "email": "opensource@apimatic.io", "issues": "https://github.com/apimatic/unirest-php/issues", - "source": "https://github.com/apimatic/unirest-php/tree/2.3.0" + "source": "https://github.com/apimatic/unirest-php/tree/4.0.5" }, - "time": "2022-06-15T08:29:49+00:00" + "time": "2023-04-25T14:19:45+00:00" }, { "name": "asm/php-ansible", @@ -424,16 +525,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.279.0", + "version": "3.279.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "7b3d38cfccd393add0ea0ce281de91846967c61e" + "reference": "ebd5e47c5be0425bb5cf4f80737850ed74767107" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7b3d38cfccd393add0ea0ce281de91846967c61e", - "reference": "7b3d38cfccd393add0ea0ce281de91846967c61e", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ebd5e47c5be0425bb5cf4f80737850ed74767107", + "reference": "ebd5e47c5be0425bb5cf4f80737850ed74767107", "shasum": "" }, "require": { @@ -513,9 +614,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.279.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.279.2" }, - "time": "2023-08-16T18:18:34+00:00" + "time": "2023-08-18T18:13:09+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1351,16 +1452,16 @@ }, { "name": "doctrine/dbal", - "version": "3.6.5", + "version": "3.6.6", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "96d5a70fd91efdcec81fc46316efc5bf3da17ddf" + "reference": "63646ffd71d1676d2f747f871be31b7e921c7864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/96d5a70fd91efdcec81fc46316efc5bf3da17ddf", - "reference": "96d5a70fd91efdcec81fc46316efc5bf3da17ddf", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/63646ffd71d1676d2f747f871be31b7e921c7864", + "reference": "63646ffd71d1676d2f747f871be31b7e921c7864", "shasum": "" }, "require": { @@ -1376,10 +1477,11 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.21", + "phpstan/phpstan": "1.10.29", "phpstan/phpstan-strict-rules": "^1.5", "phpunit/phpunit": "9.6.9", "psalm/plugin-phpunit": "0.18.4", + "slevomat/coding-standard": "8.13.1", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^5.4|^6.0", "symfony/console": "^4.4|^5.4|^6.0", @@ -1443,7 +1545,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.6.5" + "source": "https://github.com/doctrine/dbal/tree/3.6.6" }, "funding": [ { @@ -1459,7 +1561,7 @@ "type": "tidelift" } ], - "time": "2023-07-17T09:15:50+00:00" + "time": "2023-08-17T05:38:17+00:00" }, { "name": "doctrine/deprecations", @@ -3348,16 +3450,16 @@ }, { "name": "horstoeko/zugferd", - "version": "v1.0.23", + "version": "v1.0.26", "source": { "type": "git", "url": "https://github.com/horstoeko/zugferd.git", - "reference": "bb55417be4c4de8deb0113e832feeaf7b4d3984e" + "reference": "2a7541a35f00499c206391273f30159dc2c7072a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/bb55417be4c4de8deb0113e832feeaf7b4d3984e", - "reference": "bb55417be4c4de8deb0113e832feeaf7b4d3984e", + "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/2a7541a35f00499c206391273f30159dc2c7072a", + "reference": "2a7541a35f00499c206391273f30159dc2c7072a", "shasum": "" }, "require": { @@ -3415,9 +3517,9 @@ ], "support": { "issues": "https://github.com/horstoeko/zugferd/issues", - "source": "https://github.com/horstoeko/zugferd/tree/v1.0.23" + "source": "https://github.com/horstoeko/zugferd/tree/v1.0.26" }, - "time": "2023-08-16T17:39:36+00:00" + "time": "2023-08-18T03:05:43+00:00" }, { "name": "http-interop/http-factory-guzzle", @@ -7664,6 +7766,62 @@ }, "time": "2020-07-07T09:29:14+00:00" }, + { + "name": "php-jsonpointer/php-jsonpointer", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/raphaelstolt/php-jsonpointer.git", + "reference": "4428f86c6f23846e9faa5a420c4ef14e485b3afb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/raphaelstolt/php-jsonpointer/zipball/4428f86c6f23846e9faa5a420c4ef14e485b3afb", + "reference": "4428f86c6f23846e9faa5a420c4ef14e485b3afb", + "shasum": "" + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^1.11", + "phpunit/phpunit": "4.6.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Rs\\Json": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Stolt", + "email": "raphael.stolt@gmail.com", + "homepage": "http://raphaelstolt.blogspot.com/" + } + ], + "description": "Implementation of JSON Pointer (http://tools.ietf.org/html/rfc6901)", + "homepage": "https://github.com/raphaelstolt/php-jsonpointer", + "keywords": [ + "json", + "json pointer", + "json traversal" + ], + "support": { + "issues": "https://github.com/raphaelstolt/php-jsonpointer/issues", + "source": "https://github.com/raphaelstolt/php-jsonpointer/tree/master" + }, + "time": "2016-08-29T08:51:01+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -10037,29 +10195,28 @@ }, { "name": "square/square", - "version": "13.0.0.20210721", + "version": "30.0.0.20230816", "source": { "type": "git", "url": "https://github.com/square/square-php-sdk.git", - "reference": "03d90445854cd3b500f75061a9c63956799b8ecf" + "reference": "fedfea8b6c6f16b6a90ef0d629743ae9ae25e13d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/square/square-php-sdk/zipball/03d90445854cd3b500f75061a9c63956799b8ecf", - "reference": "03d90445854cd3b500f75061a9c63956799b8ecf", + "url": "https://api.github.com/repos/square/square-php-sdk/zipball/fedfea8b6c6f16b6a90ef0d629743ae9ae25e13d", + "reference": "fedfea8b6c6f16b6a90ef0d629743ae9ae25e13d", "shasum": "" }, "require": { - "apimatic/jsonmapper": "^2.0.2", - "apimatic/unirest-php": "^2.0", - "ext-curl": "*", + "apimatic/core": "~0.3.0", + "apimatic/core-interfaces": "~0.1.0", + "apimatic/unirest-php": "^4.0.0", "ext-json": "*", - "ext-mbstring": "*", - "php": ">=7.2" + "php": "^7.2 || ^8.0" }, "require-dev": { - "phan/phan": "^3.0", - "phpunit/phpunit": "^7.5 || ^8.5", + "phan/phan": "5.4.2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -10088,9 +10245,9 @@ ], "support": { "issues": "https://github.com/square/square-php-sdk/issues", - "source": "https://github.com/square/square-php-sdk/tree/13.0.0.20210721" + "source": "https://github.com/square/square-php-sdk/tree/30.0.0.20230816" }, - "time": "2021-07-21T06:43:15+00:00" + "time": "2023-08-15T21:45:55+00:00" }, { "name": "stripe/stripe-php", diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index 4a096febef58..6803c4bf5f54 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -80,7 +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}'], + ['id' => 57, 'name' => 'Square', 'provider' => 'Square', 'is_offsite' => false, 'sort_order' => 21, 'key' => '65faab2ab6e3223dbe848b1686490baz', 'fields' => '{"accessToken":"","applicationId":"","locationId":"","signatureKey":"","testMode":false}'], ['id' => 58, 'name' => 'Razorpay', 'provider' => 'Razorpay', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9', 'fields' => '{"apiKey":"","apiSecret":""}'], ['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'], ['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'], diff --git a/tests/Feature/CompanyGatewayTest.php b/tests/Feature/CompanyGatewayTest.php index 4547ffbbc9af..cefb2baeaf97 100644 --- a/tests/Feature/CompanyGatewayTest.php +++ b/tests/Feature/CompanyGatewayTest.php @@ -47,6 +47,22 @@ class CompanyGatewayTest extends TestCase $this->assertNotNull($company_gateway); } + public function testSetConfigFields() + { + $company_gateway = CompanyGateway::first(); + + $this->assertNotNull($company_gateway->getConfig()); + + $company_gateway->setConfigField('test', 'test'); + + $this->assertEquals('test', $company_gateway->getConfigField('test')); + + $company_gateway->setConfigField('signatureKey', 'hero'); + + $this->assertEquals('hero', $company_gateway->getConfigField('signatureKey')); + + } + public function testFeesAndLimitsExists() { $data = [];