Implement coupons for the other gateways.
This commit is contained in:
parent
bad9d0ec12
commit
24ce267962
6 changed files with 78 additions and 70 deletions
|
@ -9,10 +9,12 @@ use App\Models\PartnerDiscount;
|
|||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\User;
|
||||
use App\Models\Coupon;
|
||||
use App\Traits\Coupon as CouponTrait;
|
||||
use App\Events\CouponUsedEvent;
|
||||
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;
|
||||
|
@ -23,6 +25,8 @@ use Illuminate\Support\Facades\Http;
|
|||
*/
|
||||
class MollieExtension extends AbstractExtension
|
||||
{
|
||||
use CouponTrait;
|
||||
|
||||
public static function getConfig(): array
|
||||
{
|
||||
return [
|
||||
|
@ -33,7 +37,7 @@ class MollieExtension extends AbstractExtension
|
|||
];
|
||||
}
|
||||
|
||||
static function pay(Request $request): void
|
||||
public function pay(Request $request): void
|
||||
{
|
||||
$url = 'https://api.mollie.com/v2/payments';
|
||||
$settings = new MollieSettings();
|
||||
|
@ -41,6 +45,18 @@ class MollieExtension extends AbstractExtension
|
|||
$user = Auth::user();
|
||||
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
|
||||
$discount = PartnerDiscount::getDiscount();
|
||||
$couponCode = $request->input('couponCode');
|
||||
$isValidCoupon = $this->validateCoupon($request->user(), $couponCode, $request->shopProduct);
|
||||
$price = $shopProduct->price;
|
||||
|
||||
// Coupon Discount.
|
||||
if ($isValidCoupon->getStatusCode() == 200) {
|
||||
$price = $this->calcDiscount($price, $isValidCoupon->getData());
|
||||
}
|
||||
|
||||
// Partner Discount.
|
||||
$price = $price - ($price * $discount / 100);
|
||||
$price = number_format($price, 2, thousands_separator: '');
|
||||
|
||||
// create a new payment
|
||||
$payment = Payment::create([
|
||||
|
@ -50,7 +66,7 @@ class MollieExtension extends AbstractExtension
|
|||
'type' => $shopProduct->type,
|
||||
'status' => 'open',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
|
||||
'price' => $price,
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
|
@ -65,10 +81,10 @@ class MollieExtension extends AbstractExtension
|
|||
])->post($url, [
|
||||
'amount' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'value' => number_format($shopProduct->getTotalPrice(), 2, '.', ''),
|
||||
'value' => $price,
|
||||
],
|
||||
'description' => "Order #{$payment->id} - " . $shopProduct->name,
|
||||
'redirectUrl' => route('payment.MollieSuccess'),
|
||||
'redirectUrl' => route('payment.MollieSuccess', ['couponCode' => $couponCode]),
|
||||
'cancelUrl' => route('payment.Cancel'),
|
||||
'webhookUrl' => url('/extensions/payment/MollieWebhook'),
|
||||
'metadata' => [
|
||||
|
@ -103,6 +119,15 @@ class MollieExtension extends AbstractExtension
|
|||
{
|
||||
$payment = Payment::findOrFail($request->input('payment'));
|
||||
$payment->status = 'pending';
|
||||
$coupon_code = $request->input('couponCode');
|
||||
|
||||
// increase the use of the coupon when the payment is confirmed.
|
||||
if ($coupon_code) {
|
||||
$coupon = new Coupon;
|
||||
$coupon->incrementUses($coupon_code);
|
||||
|
||||
event(new CouponUsedEvent($coupon));
|
||||
}
|
||||
|
||||
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
|
||||
return;
|
||||
|
|
|
@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Route;
|
|||
use App\Extensions\PaymentGateways\Mollie\MollieExtension;
|
||||
|
||||
Route::middleware(['web', 'auth'])->group(function () {
|
||||
Route::get('payment/MolliePay/{shopProduct}', function () {
|
||||
MollieExtension::pay(request());
|
||||
Route::get('payment/MolliePay/{shopProduct}', function (MollieExtension $mollieExtension) {
|
||||
$mollieExtension->pay(request());
|
||||
})->name('payment.MolliePay');
|
||||
|
||||
Route::get(
|
||||
|
|
|
@ -4,12 +4,15 @@ namespace App\Extensions\PaymentGateways\Stripe;
|
|||
|
||||
use App\Helpers\AbstractExtension;
|
||||
use App\Events\PaymentEvent;
|
||||
use App\Events\CouponUsedEvent;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Extensions\PaymentGateways\Stripe\StripeSettings;
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\User;
|
||||
use App\Models\Coupon;
|
||||
use App\Traits\Coupon as CouponTrait;
|
||||
use App\Notifications\ConfirmPaymentNotification;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
|
@ -21,6 +24,8 @@ use Stripe\StripeClient;
|
|||
|
||||
class StripeExtension extends AbstractExtension
|
||||
{
|
||||
use CouponTrait;
|
||||
|
||||
public static function getConfig(): array
|
||||
{
|
||||
return [
|
||||
|
@ -35,10 +40,14 @@ class StripeExtension extends AbstractExtension
|
|||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
*/
|
||||
public static function StripePay(Request $request)
|
||||
public function StripePay(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
|
||||
$discount = PartnerDiscount::getDiscount();
|
||||
$couponCode = $request->input('couponCode');
|
||||
$isValidCoupon = $this->validateCoupon($request->user(), $couponCode, $request->shopProduct);
|
||||
$price = $shopProduct->price;
|
||||
|
||||
// check if the price is valid for stripe
|
||||
if (!self::checkPriceAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), 'stripe')) {
|
||||
|
@ -46,7 +55,14 @@ class StripeExtension extends AbstractExtension
|
|||
return;
|
||||
}
|
||||
|
||||
$discount = PartnerDiscount::getDiscount();
|
||||
// Coupon Discount.
|
||||
if ($isValidCoupon->getStatusCode() == 200) {
|
||||
$price = $this->calcDiscount($price, $isValidCoupon->getData());
|
||||
}
|
||||
|
||||
// Partner Discount.
|
||||
$price = $price - ($price * $discount / 100);
|
||||
$price = number_format($price, 2);
|
||||
|
||||
|
||||
// create payment
|
||||
|
@ -57,7 +73,7 @@ class StripeExtension extends AbstractExtension
|
|||
'type' => $shopProduct->type,
|
||||
'status' => 'open',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
|
||||
'price' => $price,
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
|
@ -75,7 +91,7 @@ class StripeExtension extends AbstractExtension
|
|||
'name' => $shopProduct->display . ($discount ? (' (' . __('Discount') . ' ' . $discount . '%)') : ''),
|
||||
'description' => $shopProduct->description,
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
|
||||
'unit_amount_decimal' => $price,
|
||||
],
|
||||
'quantity' => 1,
|
||||
],
|
||||
|
@ -93,7 +109,7 @@ class StripeExtension extends AbstractExtension
|
|||
],
|
||||
|
||||
'mode' => 'payment',
|
||||
'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}',
|
||||
'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id, 'couponCode' => $couponCode]) . '&session_id={CHECKOUT_SESSION_ID}',
|
||||
'cancel_url' => route('payment.Cancel'),
|
||||
'payment_intent_data' => [
|
||||
'metadata' => [
|
||||
|
@ -114,7 +130,7 @@ class StripeExtension extends AbstractExtension
|
|||
$user = User::findOrFail($user->id);
|
||||
$payment = Payment::findOrFail($request->input('payment'));
|
||||
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
|
||||
|
||||
$couponCode = $request->input('couponCode');
|
||||
|
||||
Redirect::route('home')->with('success', 'Please wait for success')->send();
|
||||
|
||||
|
@ -136,6 +152,14 @@ class StripeExtension extends AbstractExtension
|
|||
'status' => 'paid',
|
||||
]);
|
||||
|
||||
// increase the use of the coupon when the payment is confirmed.
|
||||
if ($couponCode) {
|
||||
$coupon = new Coupon;
|
||||
$coupon->incrementUses($couponCode);
|
||||
|
||||
event(new CouponUsedEvent($coupon));
|
||||
}
|
||||
|
||||
//payment notification
|
||||
$user->notify(new ConfirmPaymentNotification($payment));
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Route;
|
|||
use App\Extensions\PaymentGateways\Stripe\StripeExtension;
|
||||
|
||||
Route::middleware(['web', 'auth'])->group(function () {
|
||||
Route::get('payment/StripePay/{shopProduct}', function () {
|
||||
StripeExtension::StripePay(request());
|
||||
Route::get('payment/StripePay/{shopProduct}', function (StripeExtension $stripeExtension) {
|
||||
$stripeExtension->StripePay(request());
|
||||
})->name('payment.StripePay');
|
||||
|
||||
Route::get(
|
||||
|
|
|
@ -4,11 +4,21 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Coupon extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use HasFactory, LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnlyDirty()
|
||||
->logOnly(['*'])
|
||||
->dontSubmitEmptyLogs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
|
@ -97,67 +107,16 @@ class Coupon extends Model
|
|||
return $coupons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standardize queries into one single function.
|
||||
*
|
||||
* @param string $code Coupon Code.
|
||||
* @param array $attributes Attributes to be returned.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getQueryData(string $code, array $attributes): mixed
|
||||
{
|
||||
$query = (Coupon::where('code', $code)
|
||||
->where('expires_at', '>', Carbon::now())
|
||||
->whereColumn('uses', '<=', 'max_uses')
|
||||
->get($attributes)->toArray()
|
||||
);
|
||||
|
||||
// When there are results, it comes nested arrays, idk why. This is the solution for now.
|
||||
$results = count($query) > 0 ? $query[0] : $query;
|
||||
|
||||
if (empty($results)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data from a coupon.
|
||||
*
|
||||
* @param string $code Coupon Code.
|
||||
* @param array $attributes Attributes of a coupon.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCoupon(string $code, array $attributes = ['percentage']): mixed
|
||||
{
|
||||
$coupon = $this->getQueryData($code, $attributes);
|
||||
|
||||
if (is_null($coupon)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $coupon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the use of a coupon.
|
||||
*
|
||||
* @param string $code Coupon Code.
|
||||
* @param int $amount Amount to increment.
|
||||
*
|
||||
* @return null|bool
|
||||
* @return bool
|
||||
*/
|
||||
public function incrementUses(string $code, int $amount = 1): null|bool
|
||||
public function incrementUses(string $code, int $amount = 1): bool
|
||||
{
|
||||
$coupon = $this->getQueryData($code, ['uses', 'max_uses']);
|
||||
|
||||
if (empty($coupon) || $coupon['uses'] == $coupon['max_uses']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->where('code', $code)->increment('uses', $amount);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -43,7 +43,7 @@ class CouponSettings extends Settings
|
|||
'description' => 'Maximum number of uses that a user can make of the same coupon.'
|
||||
],
|
||||
'delete_coupon_on_expires' => [
|
||||
'label' => 'Delete Coupon On Expires',
|
||||
'label' => 'Auto Delete Expired Coupons',
|
||||
'type' => 'boolean',
|
||||
'description' => 'Automatically deletes the coupon if it expires.'
|
||||
],
|
||||
|
|
Loading…
Add table
Reference in a new issue