Files
law-api/app/Http/Controllers/api/SubscribePlanController.php

334 lines
13 KiB
PHP

<?php
namespace App\Http\Controllers\api;
use App\Http\Controllers\Controller;
use App\Models\PaymentTransaction;
use App\Models\SubscribePlan;
use App\Models\UserSubscriber;
use App\Services\AppMarketPurchaseVerifier;
use App\Traits\BaseApiResponse;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Shetabit\Multipay\Invoice;
use Shetabit\Payment\Facade\Payment;
class SubscribePlanController extends Controller
{
use BaseApiResponse;
public function __construct(private AppMarketPurchaseVerifier $marketVerifier)
{
}
public function index()
{
$subscribePlans = SubscribePlan::query()->where('is_active', true)->get()->map(function ($q) {
if ($q->is_free) {
if (auth()->user()->subscribePlans()->first() !== null) {
return null;
}
}
return [
'id' => $q->id,
'name' => $q->name,
'price' => $q->price,
'expired_day' => $q->expired_day,
'is_free' => $q->is_free == 1 ? true : false,
'type' => $q->type,
'transaction' => $q->transaction
];
})->filter(function ($q) {
return $q != null;
});
return $this->success(array_values($subscribePlans->toArray()), 'Subscribe Plan', 'Subscribe Plan List');
}
public function subscribe(Request $request)
{
$request->validate([
'subscribe_plan_id' => 'required|exists:subscribe_plans,id',
]);
$subscribePlan = SubscribePlan::findOrFail($request->subscribe_plan_id);
$user = auth()->user();
$activeSubscription = $user->userSubscribers()
->where('expired_at', '>', now())
->first();
if ($activeSubscription && !$activeSubscription?->subscribe?->is_free && !$subscribePlan->is_free) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'You already have an active subscription. Please wait until it expires.']);
}
if ($subscribePlan->is_free) {
$hasUsedFreePlan = $user->userSubscribers()
->whereHas('subscribe', function ($query) {
$query->where('is_free', true);
})->exists();
if ($hasUsedFreePlan) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'You have already used the free plan.']);
}
$expiredAt = now()->addDays($subscribePlan->expired_day + 1);
$user->userSubscribers()->create([
'subscribe_plan_id' => $subscribePlan->id,
'expired_at' => $expiredAt,
]);
return $this->success(null, 'Subscribe Plan', 'Free Subscribe Plan Successfully Activated');
}
try {
$invoice = (new Invoice)->amount($subscribePlan->price);
$callback = 'https://ghaafapp.ir';
$payment = Payment::callbackUrl($callback)
->purchase($invoice, function ($driver, $transaction_id) use ($subscribePlan) {
PaymentTransaction::create([
'user_id' => auth()->user()->id,
'subscribe_plan_id' => $subscribePlan->id,
'transaction_id' => $transaction_id,
'amount' => $subscribePlan->price,
'status' => 'pending',
]);
})
->pay();
return $this->success(['url' => $payment]);
} catch (\Exception $e) {
Log::error('Payment initiation failed: ' . $e->getMessage());
return $this->failed(null, 'درگاه پرداخت در دسترس نیست');
}
}
public function subscribe_new(Request $request)
{
$request->validate([
'subscribe_plan_id' => 'required|exists:subscribe_plans,id',
'subscription_id' => 'nullable',
'purchase_token' => 'nullable'
]);
$subscribePlan = SubscribePlan::findOrFail($request->subscribe_plan_id);
$user = auth()->user();
$activeSubscription = $user->userSubscribers()
->where('expired_at', '>', now())
->latest('expired_at')
->first();
if ($subscribePlan->is_free) {
$hasUsedFreePlan = $user->userSubscribers()
->whereHas('subscribe', function ($query) {
$query->where('is_free', true);
})
->exists();
if ($hasUsedFreePlan) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'You have already used the free plan.']);
}
$expiredAt = $activeSubscription ? $activeSubscription->expired_at->addDays($subscribePlan->expired_day) : now()->addDays($subscribePlan->expired_day);
$user->userSubscribers()->create([
'subscribe_plan_id' => $subscribePlan->id,
'expired_at' => $expiredAt,
'is_free' => true
]);
return $this->success(null, 'Subscribe Plan', 'Free Subscribe Plan Successfully Activated');
}
$subscription_id = $request->input('subscription_id');
$purchase_token = $request->input('purchase_token');
if (!$subscription_id || !$purchase_token) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Invalid subscription details.']);
}
try {
$bazaarExpiredAt = $this->marketVerifier->verifyBazaarSubscription($subscription_id, $purchase_token);
if (!$bazaarExpiredAt) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Invalid or expired subscription.']);
}
$expiredAt = $activeSubscription ? $activeSubscription->expired_at->addDays($subscribePlan->expired_day) : $bazaarExpiredAt;
$user->userSubscribers()->whereHas('subscribe', function ($query) {
$query->where('is_free', true);
})
->update(['expired_at' => now()]);
$user->userSubscribers()->create([
'subscribe_plan_id' => $subscribePlan->id,
'expired_at' => $expiredAt,
'subscription_id' => $subscription_id,
'purchase_token' => $purchase_token,
'market_provider' => 'bazaar',
'last_verified_at' => now(),
'is_free' => false
]);
return $this->success(null, 'Subscribe Plan', 'Subscription successfully activated.');
} catch (\Exception $e) {
Log::error('Error in subscription', ['Error' => $e->getMessage()]);
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Failed to verify subscription.']);
}
}
public function subscribeMyket(Request $request)
{
$request->validate([
'subscribe_plan_id' => 'required|exists:subscribe_plans,id',
'sku_id' => 'required|string',
'token' => 'required_without_all:tokenId,token_id,purchase_token|string',
'tokenId' => 'required_without_all:token,token_id,purchase_token|string',
'token_id' => 'required_without_all:token,tokenId,purchase_token|string',
'purchase_token' => 'required_without_all:token,tokenId,token_id|string',
]);
$subscribePlan = SubscribePlan::findOrFail($request->subscribe_plan_id);
$user = auth()->user();
$token = $request->input('token')
?? $request->input('tokenId')
?? $request->input('token_id')
?? $request->input('purchase_token');
if ($subscribePlan->is_free) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Invalid subscription details.']);
}
try {
$purchase = $this->marketVerifier->verifyMyketProduct($request->sku_id, $token);
if (!$purchase) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Invalid or failed Myket purchase.']);
}
$expiredAt = $purchase['purchased_at']->copy()->addDays($subscribePlan->expired_day);
if ($expiredAt->lessThan(now())) {
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Invalid or expired subscription.']);
}
$user->userSubscribers()->whereHas('subscribe', function ($query) {
$query->where('is_free', true);
})->update(['expired_at' => now()]);
$user->userSubscribers()->updateOrCreate(
[
'market_provider' => 'myket',
'purchase_token' => $token,
],
[
'subscribe_plan_id' => $subscribePlan->id,
'expired_at' => $expiredAt,
'subscription_id' => $request->sku_id,
'product_id' => $request->sku_id,
'purchased_at' => $purchase['purchased_at'],
'last_verified_at' => now(),
'is_free' => false,
]
);
return $this->success(null, 'Subscribe Plan', 'Myket subscription successfully activated.');
} catch (\Exception $e) {
Log::error('Error in Myket subscription', ['Error' => $e->getMessage()]);
return $this->failed(null, ['title' => 'Subscribe Plan', 'message' => 'Failed to verify Myket subscription.']);
}
}
public function paymentCallback(Request $request)
{
try {
$url = 'http://bitpay.ir/payment/gateway-result-second';
$api = '066fd-d622e-690a9-be618-ddf02bc6059bbbd67c317bb340d1';
$trans_id = $request->input('trans_id');
$id_get = $request->input('id_get');
$result = $this->get($url, $api, $trans_id, $id_get);
$parseDecode = json_decode($result);
if ($parseDecode->status == 1) {
$transaction = PaymentTransaction::where('transaction_id', $id_get)->firstOrFail();
$transaction->update([
'status' => 'success',
]);
$expiredAt = now()->addDays($transaction->subscribePlan->expired_day);
UserSubscriber::where('user_id', $transaction->user_id)->delete();
$transaction->user->userSubscribers()->create([
'subscribe_plan_id' => $transaction->subscribe_plan_id,
'expired_at' => $expiredAt,
]);
return $this->success([], 'Payment Successful', 'Subscription successfully activated.');
}
return $this->failed([], ['title' => 'Payment Failed', 'message' => 'Payment verification failed.']);
} catch (\Exception $e) {
return $this->failed([], ['title' => 'Payment Failed', 'message' => 'Payment verification failed.']);
}
}
public function current()
{
$user = auth()->user();
$subscribePlans = UserSubscriber::where('user_id', $user->id)
->where('expired_at', '>', now())
->orderBy('expired_at', 'desc')
->get();
if ($subscribePlans->isNotEmpty()) {
$totalExpiredDays = $subscribePlans->sum('expired_day');
$latestPlan = $subscribePlans->first();
$subscribePlanData = [
'id' => $latestPlan->id,
'name' => $latestPlan->subscribe->name,
'price' => $latestPlan->subscribe->price,
'expired_day' => $totalExpiredDays,
'is_free' => $latestPlan->subscribe->is_free == 1,
'expired_at' => Carbon::now()->addDays($totalExpiredDays)->format('Y-m-d'),
];
return $this->success($subscribePlanData, 'Subscribe Plan', 'Current Subscribe Plan');
}
return $this->success(null, 'Subscribe Plan', 'No Subscribe Plan');
}
private function send($url, $api, $amount, $redirect, $factorId, $name, $email, $description)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, "api=$api&amount=$amount&redirect=$redirect&factorId=$factorId&name=$name&email=$email&description=$description");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
return $res;
}
private function get($url, $api, $trans_id, $id_get)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, "api=$api&id_get=$id_get&trans_id=$trans_id&json=1");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
return $res;
}
}