feat: ✨ Create Mollie payment gateway extension
This commit is contained in:
parent
59ed6e51c1
commit
c95cde5cde
6 changed files with 220 additions and 1 deletions
app
Extensions/PaymentGateways/Mollie
Listeners
public/images/Extensions/PaymentGateways
146
app/Extensions/PaymentGateways/Mollie/MollieExtension.php
Normal file
146
app/Extensions/PaymentGateways/Mollie/MollieExtension.php
Normal 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]);
|
||||
}
|
||||
}
|
36
app/Extensions/PaymentGateways/Mollie/MollieSettings.php
Normal file
36
app/Extensions/PaymentGateways/Mollie/MollieSettings.php
Normal 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',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
|
@ -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');
|
||||
}
|
||||
}
|
17
app/Extensions/PaymentGateways/Mollie/web_routes.php
Normal file
17
app/Extensions/PaymentGateways/Mollie/web_routes.php
Normal 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');
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
public/images/Extensions/PaymentGateways/mollie_logo.png
Normal file
BIN
public/images/Extensions/PaymentGateways/mollie_logo.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 45 KiB |
Loading…
Add table
Reference in a new issue