diff --git a/app/Exceptions/PaymentRefundFailed.php b/app/Exceptions/PaymentRefundFailed.php new file mode 100644 index 000000000000..e74c362da7b7 --- /dev/null +++ b/app/Exceptions/PaymentRefundFailed.php @@ -0,0 +1,31 @@ +json([ + 'message' => 'Unable to refund the transaction' + ], 401); + } +} diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index 0560c7c47b36..9511dce9c179 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -72,7 +72,7 @@ class PaymentController extends Controller public function process() { $invoices = Invoice::whereIn('id', $this->transformKeys(request()->invoices)) - ->whereClientId(auth('contact')->user()->company()->id) + ->where('company_id', auth('contact')->user()->company->id) ->get(); $amount = $invoices->sum('balance'); diff --git a/app/PaymentDrivers/PayPalExpressPaymentDriver.php b/app/PaymentDrivers/PayPalExpressPaymentDriver.php index f13b57e54c37..82b7ea5d6786 100644 --- a/app/PaymentDrivers/PayPalExpressPaymentDriver.php +++ b/app/PaymentDrivers/PayPalExpressPaymentDriver.php @@ -1,4 +1,5 @@ $response->getData(), - 'data' => $data - ], + 'server_response' => $response->getData(), + 'data' => $data + ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYPAL, @@ -131,20 +131,20 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver } elseif ($response->isSuccessful()) { SystemLogger::dispatch( [ - 'server_response' => $response->getData(), - 'data' => $request->all() - ], + 'server_response' => $response->getData(), + 'data' => $request->all() + ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_PAYPAL, $this->client ); - } elseif (! $response->isSuccessful()) { + } elseif (!$response->isSuccessful()) { SystemLogger::dispatch( [ - 'data' => $request->all(), - 'server_response' => $response->getData() - ], + 'data' => $request->all(), + 'server_response' => $response->getData() + ], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYPAL, @@ -159,13 +159,13 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver $this->attachInvoices($payment, $request->input('hashed_ids')); $payment->service()->UpdateInvoicePayment(); - + event(new PaymentWasCreated($payment, $payment->company)); - return redirect()->route('client.payments.show', ['payment'=>$this->encodePrimaryKey($payment->id)]); + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); } - protected function paymentDetails($input) :array + protected function paymentDetails($input): array { $data = parent::paymentDetails($input); @@ -182,41 +182,41 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver return $data; } - private function buildReturnUrl($input) : string + private function buildReturnUrl($input): string { $url = $this->client->company->domain() . "/client/payments/process/response"; - $url .= "?company_gateway_id={$this->company_gateway->id}&gateway_type_id=".GatewayType::PAYPAL; + $url .= "?company_gateway_id={$this->company_gateway->id}&gateway_type_id=" . GatewayType::PAYPAL; $url .= "&hashed_ids=" . implode(",", $input['hashed_ids']); - $url .= "&amount=".$input['amount']; - $url .= "&fee=".$input['fee']; + $url .= "&amount=" . $input['amount']; + $url .= "&fee=" . $input['fee']; return $url; } - private function buildCancelUrl($input) : string + private function buildCancelUrl($input): string { $url = $this->client->company->domain() . '/client/invoices'; return $url; } - private function buildDescription($input) : string + private function buildDescription($input): string { $invoice_numbers = ""; foreach ($input['invoices'] as $invoice) { - $invoice_numbers .= $invoice->number." "; + $invoice_numbers .= $invoice->number . " "; } - return ctrans('texts.invoice_number'). ": {$invoice_numbers}"; + return ctrans('texts.invoice_number') . ": {$invoice_numbers}"; } - private function buildTransactionId($input) : string + private function buildTransactionId($input): string { return implode(",", $input['hashed_ids']); } - private function paymentItems($input) : array + private function paymentItems($input): array { $items = []; $total = 0; @@ -255,7 +255,7 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver return $items; } - public function createPayment($data) : Payment + public function createPayment($data): Payment { $payment = parent::createPayment($data); @@ -270,4 +270,41 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver return $payment; } + + public function refund(Payment $payment, $amount = null) + { + $this->gateway(); + + $response = $this->gateway + ->refund(['transactionReference' => $payment->transaction_reference, 'amount' => $amount ?? $payment->amount]) + ->send(); + + if ($response->isSuccessful()) { + SystemLogger::dispatch( + [ + 'server_response' => $response->getMessage(), + 'data' => request()->all(), + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_PAYPAL, + $this->client + ); + + return true; + } + + SystemLogger::dispatch( + [ + 'server_response' => $response->getMessage(), + 'data' => request()->all(), + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_PAYPAL, + $this->client + ); + + return false; + } } diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 4f119ceca86b..037cb3b6046f 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -471,6 +471,42 @@ class StripePaymentDriver extends BasePaymentDriver return $customer; } + public function refund(Payment $payment, $amount = null) + { + $this->gateway(); + + $response = $this->gateway + ->refund(['transactionReference' => $payment->transaction_reference, 'amount' => $amount ?? $payment->amount]) + ->send(); + + if ($response->isSuccessful()) { + SystemLogger::dispatch( + [ + 'server_response' => $response->getMessage(), + 'data' => request()->all(), + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_PAYPAL, + $this->client + ); + + return true; + } + + SystemLogger::dispatch( + [ + 'server_response' => $response->getMessage(), + 'data' => request()->all(), + ], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_PAYPAL, + $this->client + ); + + return false; + } /************************************** Omnipay API methods **********************************************************/ } diff --git a/app/Utils/Traits/Payment/Refundable.php b/app/Utils/Traits/Payment/Refundable.php index 6dc81d47613e..1ece7ac11fed 100644 --- a/app/Utils/Traits/Payment/Refundable.php +++ b/app/Utils/Traits/Payment/Refundable.php @@ -11,9 +11,11 @@ namespace App\Utils\Traits\Payment; +use App\Exceptions\PaymentRefundFailed; use App\Factory\CreditFactory; use App\Factory\InvoiceItemFactory; use App\Models\Activity; +use App\Models\CompanyGateway; use App\Models\Credit; use App\Models\Invoice; use App\Models\Payment; @@ -163,11 +165,18 @@ trait Refundable $credit_note->number = $this->client->getNextCreditNumber($this->client); $credit_note->save(); - //determine if we need to refund via gateway if ($data['gateway_refund'] !== false) { - //todo process gateway refund, on success, reduce the credit note balance to 0 - } + $gateway = CompanyGateway::find($this->company_gateway_id); + if ($gateway) { + $amount = request()->has('amount') ? request()->amount : null; + $response = $gateway->driver($this->client)->refund($this, $amount); + + if (!$response) { + throw new PaymentRefundFailed(); + } + } + } if ($total_refund > 0) { $this->refunded += $total_refund; diff --git a/resources/views/portal/ninja2020/payments/show.blade.php b/resources/views/portal/ninja2020/payments/show.blade.php index 4891729a408b..59ff02732874 100644 --- a/resources/views/portal/ninja2020/payments/show.blade.php +++ b/resources/views/portal/ninja2020/payments/show.blade.php @@ -78,6 +78,7 @@ href="{{ route('client.invoice.show', ['invoice' => $invoice->hashed_id])}}"> {{ $invoice->number }} + Payment: {{ $payment->hashed_id }} Invoice: {{ $invoice->hashed_id }} Amount: {{ $payment->amount }} @endforeach diff --git a/routes/web.php b/routes/web.php index b60cd41920ab..715474d059a9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,6 +3,8 @@ * Signup Routes */ +use Omnipay\Omnipay; + Route::get('/', 'BaseController@flutterRoute')->middleware('guest'); Route::get('setup', 'SetupController@index')->middleware('guest'); Route::post('setup/check_db', 'SetupController@checkDB')->middleware('guest');