diff --git a/app/PaymentDrivers/Mollie/Bancontact.php b/app/PaymentDrivers/Mollie/Bancontact.php index 38dc27ce39..53199e8eee 100644 --- a/app/PaymentDrivers/Mollie/Bancontact.php +++ b/app/PaymentDrivers/Mollie/Bancontact.php @@ -12,8 +12,15 @@ namespace App\PaymentDrivers\Mollie; +use App\Exceptions\PaymentFailed; use App\Http\Requests\Request; use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; +use App\Jobs\Mail\PaymentFailureMailer; +use App\Jobs\Util\SystemLogger; +use App\Models\GatewayType; +use App\Models\Payment; +use App\Models\PaymentType; +use App\Models\SystemLog; use App\PaymentDrivers\Common\MethodInterface; use App\PaymentDrivers\MolliePaymentDriver; use Illuminate\Http\RedirectResponse; @@ -52,7 +59,158 @@ class Bancontact implements MethodInterface return redirect()->route('client.payment_methods.index'); } - public function paymentView(array $data) { } + /** + * Show the payment page for Bancontact. + * + * @param array $data + * @return Redirector|RedirectResponse + */ + public function paymentView(array $data) + { + $this->mollie->payment_hash + ->withData('gateway_type_id', GatewayType::BANCONTACT) + ->withData('client_id', $this->mollie->client->id); - public function paymentResponse(PaymentResponseRequest $request) { } + try { + $payment = $this->mollie->gateway->payments->create([ + 'method' => 'bancontact', + 'amount' => [ + 'currency' => $this->mollie->client->currency()->code, + 'value' => $this->mollie->convertToMollieAmount((float) $this->mollie->payment_hash->data->amount_with_fee), + ], + 'description' => \sprintf('Invoices: %s', collect($data['invoices'])->pluck('invoice_number')), + 'redirectUrl' => route('client.payments.response', [ + 'company_gateway_id' => $this->mollie->company_gateway->id, + 'payment_hash' => $this->mollie->payment_hash->hash, + 'payment_method_id' => GatewayType::BANCONTACT, + ]), + 'webhookUrl' => $this->mollie->company_gateway->webhookUrl(), + 'metadata' => [ + 'client_id' => $this->mollie->client->hashed_id, + ], + ]); + + $this->mollie->payment_hash->withData('payment_id', $payment->id); + + return redirect( + $payment->getCheckoutUrl() + ); + } catch (\Mollie\Api\Exceptions\ApiException | \Exception $exception) { + return $this->processUnsuccessfulPayment($exception); + } + } + + /** + * Handle unsuccessful payment. + * + * @param Exception $exception + * @throws PaymentFailed + * @return void + */ + public function processUnsuccessfulPayment(\Exception $exception): void + { + PaymentFailureMailer::dispatch( + $this->mollie->client, + $exception->getMessage(), + $this->mollie->client->company, + $this->mollie->payment_hash->data->amount_with_fee + ); + + SystemLogger::dispatch( + $exception->getMessage(), + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_MOLLIE, + $this->mollie->client, + $this->mollie->client->company, + ); + + throw new PaymentFailed($exception->getMessage(), $exception->getCode()); + } + + + /** + * Handle the payments for the KBC. + * + * @param PaymentResponseRequest $request + * @return mixed + */ + public function paymentResponse(PaymentResponseRequest $request) + { + if (!\property_exists($this->mollie->payment_hash->data, 'payment_id')) { + return $this->processUnsuccessfulPayment( + new PaymentFailed('Whoops, something went wrong. Missing required [payment_id] parameter. Please contact administrator. Reference hash: ' . $this->mollie->payment_hash->hash) + ); + } + + try { + $payment = $this->mollie->gateway->payments->get( + $this->mollie->payment_hash->data->payment_id + ); + + if ($payment->status === 'paid') { + return $this->processSuccessfulPayment($payment); + } + + if ($payment->status === 'open') { + return $this->processOpenPayment($payment); + } + + if ($payment->status === 'failed') { + return $this->processUnsuccessfulPayment( + new PaymentFailed(ctrans('texts.status_failed')) + ); + } + + return $this->processUnsuccessfulPayment( + new PaymentFailed(ctrans('texts.status_voided')) + ); + } catch (\Mollie\Api\Exceptions\ApiException | \Exception $exception) { + return $this->processUnsuccessfulPayment($exception); + } + } + + /** + * Handle the successful payment for Bancontact. + * + * @param string $status + * @param ResourcesPayment $payment + * @return RedirectResponse + */ + public function processSuccessfulPayment(\Mollie\Api\Resources\Payment $payment, string $status = 'paid'): RedirectResponse + { + $data = [ + 'gateway_type_id' => GatewayType::BANCONTACT, + 'amount' => array_sum(array_column($this->mollie->payment_hash->invoices(), 'amount')) + $this->mollie->payment_hash->fee_total, + 'payment_type' => PaymentType::BANCONTACT, + 'transaction_reference' => $payment->id, + ]; + + $payment_record = $this->mollie->createPayment( + $data, + $status === 'paid' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING + ); + + SystemLogger::dispatch( + ['response' => $payment, 'data' => $data], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_MOLLIE, + $this->mollie->client, + $this->mollie->client->company, + ); + + return redirect()->route('client.payments.show', ['payment' => $this->mollie->encodePrimaryKey($payment_record->id)]); + } + + /** + * Handle 'open' payment status for Bancontact. + * + * @param ResourcesPayment $payment + * @return RedirectResponse + */ + public function processOpenPayment(\Mollie\Api\Resources\Payment $payment): RedirectResponse + { + return $this->processSuccessfulPayment($payment, 'open'); + } }