feat: Create Mollie payment gateway extension

This commit is contained in:
IceToast 2023-03-27 00:34:32 +02:00 committed by IceToast
parent 59ed6e51c1
commit c95cde5cde
6 changed files with 220 additions and 1 deletions

View file

@ -0,0 +1,146 @@
<?php
namespace App\Extensions\PaymentGateways\Mollie;
use App\Helpers\AbstractExtension;
use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
use App\Models\PartnerDiscount;
use App\Models\Payment;
use App\Models\ShopProduct;
use App\Models\User;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;
/**
* Summary of PayPalExtension
*/
class MollieExtension extends AbstractExtension
{
public static function getConfig(): array
{
return [
"name" => "Mollie",
"RoutesIgnoreCsrf" => [
"payment/MollieWebhook"
],
];
}
static function pay(Request $request): void
{
$url = 'https://api.mollie.com/v2/payments';
$settings = new MollieSettings();
$user = Auth::user();
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
$discount = PartnerDiscount::getDiscount();
// create a new payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => null,
'payment_method' => 'mollie',
'type' => $shopProduct->type,
'status' => 'open',
'amount' => $shopProduct->quantity,
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
'tax_value' => $shopProduct->getTaxValue(),
'tax_percent' => $shopProduct->getTaxPercent(),
'total_price' => $shopProduct->getTotalPrice(),
'currency_code' => $shopProduct->currency_code,
'shop_item_product_id' => $shopProduct->id,
]);
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $settings->api_key,
])->post($url, [
'amount' => [
'currency' => $shopProduct->currency_code,
'value' => number_format($shopProduct->getTotalPrice(), 2, '.', ''),
],
'description' => "Order #{$payment->id}",
'redirectUrl' => route('payment.mollieSuccess', ['payment' => $payment->id]),
'cancelUrl' => route('payment.cancel'),
'webhookUrl' => url('/extensions/payment/MollieWebhook'),
'metadata' => [
'payment_id' => $payment->id,
],
]);
if ($response->status() != 201) {
Log::error('Mollie Payment: ' . $response->json()['title']);
$payment->delete();
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
return;
}
$payment->update([
'payment_id' => $response->json()['id'],
]);
Redirect::away($response->json()['_links']['checkout']['href'])->send();
return;
} catch (Exception $ex) {
Log::error('Mollie Payment: ' . $ex->getMessage());
$payment->delete();
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
return;
}
}
static function success(Request $request): void
{
$payment = Payment::findOrFail($request->input('payment'));
$payment->status = 'pending';
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
return;
}
static function webhook(Request $request): JsonResponse
{
$url = 'https://api.mollie.com/v2/payments/' . $request->id;
$settings = new MollieSettings();
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $settings->api_key,
])->get($url);
if ($response->status() != 200) {
Log::error('Mollie Payment Webhook: ' . $response->json()['title']);
return response()->json(['success' => false]);
}
$payment = Payment::findOrFail($response->json()['metadata']['payment_id']);
$payment->status->update([
'status' => $response->json()['status'],
]);
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
event(new PaymentEvent($payment, $payment, $shopProduct));
if ($response->json()['status'] == 'paid') {
$user = User::findOrFail($payment->user_id);
event(new UserUpdateCreditsEvent($user));
}
} catch (Exception $ex) {
Log::error('Mollie Payment Webhook: ' . $ex->getMessage());
return response()->json(['success' => false]);
}
// return a 200 status code
return response()->json(['success' => true]);
}
}

View file

@ -0,0 +1,36 @@
<?php
namespace App\Extensions\PaymentGateways\Mollie;
use Spatie\LaravelSettings\Settings;
class MollieSettings extends Settings
{
public bool $enabled = false;
public ?string $api_key;
public static function group(): string
{
return 'mollie';
}
public static function encrypted(): array
{
return [
"api_key",
];
}
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-dollar-sign',
'api_key' => [
'type' => 'string',
'label' => 'API Key',
'description' => 'The API Key of your Mollie App',
]
];
}
}

View file

@ -0,0 +1,18 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
class CreateMollieSettings extends SettingsMigration
{
public function up(): void
{
$this->migrator->addEncrypted('mollie.api_key', null);
$this->migrator->add('mollie.enabled', false);
}
public function down(): void
{
$this->migrator->delete('mollie.api_key');
$this->migrator->delete('mollie.enabled');
}
}

View file

@ -0,0 +1,17 @@
<?php
use App\Extensions\PaymentGateways\Mollie\MollieExtension;
use Illuminate\Support\Facades\Route;
Route::middleware(['web', 'auth'])->group(function () {
Route::get('payment/MolliePay/{shopProduct}', function () {
MollieExtension::pay(request());
})->name('payment.MolliePay');
Route::get(
'payment/PayPalSuccess',
function () {
MollieExtension::success(request());
}
)->name('payment.MollieSuccess');
});

View file

@ -11,6 +11,7 @@ class CreateInvoice
use Invoiceable;
private $invoice_enabled;
private $invoice_settings;
/**
* Create the event listener.
@ -20,6 +21,7 @@ class CreateInvoice
public function __construct(InvoiceSettings $invoice_settings)
{
$this->invoice_enabled = $invoice_settings->enabled;
$this->invoice_settings = $invoice_settings;
}
/**
@ -32,7 +34,7 @@ class CreateInvoice
{
if ($this->invoice_enabled) {
// create invoice using the trait
$this->createInvoice($event->payment, $event->shopProduct);
$this->createInvoice($event->payment, $event->shopProduct, $this->invoice_settings);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB