Файловый менеджер - Редактировать - /home/clickysoft/public_html/charliapp-v2.clickysoft.net/app/Http/Controllers/SubscriptionController.php
Назад
<?php namespace App\Http\Controllers; use Laravel\Sanctum\PersonalAccessToken; use App\Models\Package; use App\Models\PackageOption; use App\Models\Coupon; use App\Models\DiscountPlan; use App\Models\InAppSubscription; use Carbon\Carbon; use Illuminate\Http\Request; use App\Models\Subscription; use Illuminate\Http\Response; use Imdhemy\Purchases\Facades\Subscription as ReceiptSubscriptionValidate; use Imdhemy\GooglePlay\Subscriptions\SubscriptionPurchase; use \Imdhemy\Purchases\Facades\Product as ReceiptProductValidate; use \Imdhemy\GooglePlay\Products\ProductPurchase; use Google\Client; use Illuminate\Support\Facades\Http; class SubscriptionController extends Controller { const ERROR_HAS_OCCURRED = 'Error has occurred.'; private $paypalEndpoint; protected $paypalController; public function __construct(PayPalController $paypalController) { $this->paypalController = $paypalController; $this->paypalEndpoint = "https://api-m." . (config('paypal.mode') == 'sandbox' ? "sandbox." : "") . "paypal.com/v1"; } public function goto_subscribe($token, $plan_id) { $package = Package::wherePaypalMonthlyPlanId($plan_id)->first(); if (!empty($package)) { $subscriptionType = "monthly"; $interval = "MONTH"; } else { $package = Package::wherePaypalYearlyPlanId($plan_id)->first(); if (!empty($package)) { $subscriptionType = "yearly"; $interval = "YEAR"; } else { abort(404, "Subscription plan does not exists."); } } $packageId = $package->id; $personalAccessToken = PersonalAccessToken::findToken($token); if (empty($personalAccessToken)) { abort(404, "User not found."); } $user = $personalAccessToken->tokenable; auth()->login($user); if (empty(auth()->user())) { abort(404, "User not found."); } $price = $package->{"price_" . $subscriptionType}; if (!empty(request()->input("coupon_code"))) { $coupon = Coupon::whereCouponCode(request()->input("coupon_code"))->whereStatus(1)->first(); if ( !empty($coupon) && (empty($coupon->package_id) || $coupon->package_id == $packageId) && ($coupon->package_type == "Both" || $coupon->package_type == ucfirst($subscriptionType)) && (empty($coupon->number_of_usage) || $coupon->usage_count < $coupon->number_of_usage) && (empty($coupon->date_of_expiry) || date_difference(date("Y-m-d"), $coupon->date_of_expiry) > 0) ) { $price = $package->{"price_" . $subscriptionType}; $discountAmount = $coupon->discount_amount; $discountType = $coupon->discount_type; $discount = $discountType == 1 ? ($price * $discountAmount / 100) : $discountAmount; $finalPrice = fixTowAfterDot($price - $discount); if ($finalPrice > 0) { $discountPlan = DiscountPlan::wherePackageId($packageId)->wherePackageType($subscriptionType)->whereDiscountAmount($finalPrice)->first(); if (empty($discountPlan)) { $data = $this->paypalController->createPlan($package->paypal_product_id, $package->package_name . " - " . $subscriptionType . "-" . $finalPrice, $package->description, $finalPrice, $interval); if ($data["success"]) { $plan_id = $data["paypalPlanId"]; DiscountPlan::create([ "paypal_plan_id" => $plan_id, "package_id" => $packageId, "package_type" => $subscriptionType, "discount_amount" => $finalPrice, ]); } } else { $plan_id = $discountPlan->paypal_plan_id; } } else { return redirect()->route("subscription-complete", [ "token" => $token, "subscription_id" => "noId", "package_id" => $packageId, "subscription_type" => $subscriptionType, "coupon_code" => !empty(request()->input("coupon_code")) ? request()->input("coupon_code") : 'null', "price" => $finalPrice, ]); } } } return view("subscription.subscribe", [ "token" => $token, "plan_id" => $plan_id, "package_id" => $packageId, "subscription_type" => $subscriptionType, "coupon_code" => request()->input("coupon_code"), "price" => $price ]); } public function subscription_complete($token, $subscription_id, $package_id, $subscription_type, $coupon_code = null, $price) { $personalAccessToken = PersonalAccessToken::findToken($token); if (empty($personalAccessToken)) { abort(404, "User not found."); } $user = $personalAccessToken->tokenable; auth()->login($user); if (empty(auth()->user())) { abort(404, "User not found."); } $user = auth()->user(); $user->package_id = $package_id; $user->subscription_id = $subscription_id == "noId" ? null : $subscription_id; $user->subscription_type = $subscription_type; $user->subscribed_with_free_coupon = $subscription_id == "noId" && $coupon_code != 'null' ? 1 : 0; $user->subscription_date = Carbon::now()->toDateString(); $user->subscription_device_type = 'web'; $user->subscription_amount = $price; $user->subscription_expiration_date = Carbon::now()->{"add" . str_replace("ly", "", $subscription_type)}()->toDateString(); $user->save(); if ($coupon_code != 'null') { Coupon::whereCouponCode($coupon_code)->increment("usage_count"); } // return redirect()->route("subscription-success"); return redirect()->to(env("FRONT_APP_URL").'/subscription/success'); } public function subscription_success() { return view("subscription.success"); } public function subscription_detail($json = true) { if (!empty(auth()->user()->package_id)) { $package = auth()->user()->package; $options = []; $allOptions = PackageOption::all(); foreach ($package->options as $package_option) { $options[$package_option->id] = [ "option_limit" => $package_option->pivot->option_limit, "option_title" => $package_option->pivot->option_title ]; } $packageOptions = []; foreach ($allOptions as $package_option) { $packageOptions[] = [ "option_name" => $package_option->option_name . (!empty($options[$package_option->id]["option_limit"]) ? " (" . $options[$package_option->id]["option_limit"] . " " . $options[$package_option->id]["option_title"] . ")" : ""), "slug" => $package_option->slug, "available" => in_array($package_option->id, array_keys($options)) ]; } $subscriptionDetails["package"] = [ "name" => $package->package_name, "description" => $package->description, "price" => $package->{"price_" . auth()->user()->subscription_type}, "options" => $packageOptions, ]; $subscriptionDetails["subscription_type"] = ucfirst(auth()->user()->subscription_type); $inAppSubscriptionDetails = InAppSubscription::where('user_id', auth()->user()->id)->first(); if (!empty(auth()->user()->subscription_id) && $inAppSubscriptionDetails) { $status = ""; $dateDiff = 0; if (!empty(auth()->user()->subscription_expiration_date)) { $expiration_date = Carbon::parse(auth()->user()->subscription_expiration_date); $now = Carbon::now(); $dateDiff = $expiration_date->diffInDays($now); $status = $dateDiff <= 0 ? "Expired" : "ACTIVE"; } $subscriptionDate = !empty(auth()->user()->subscription_date) ? Carbon::createFromFormat("Y-m-d H:i:s", auth()->user()->subscription_date)->format(DATE_ISO8601) : ""; $subscriptionDetails["status"] = $status; $subscriptionDetails["start_time"] = $subscriptionDate; $subscriptionDetails["last_payment"] = [ "amount" => [ "currency_code" => "USD", "value" => auth()->user()->subscription_amount ? auth()->user()->subscription_amount : 0 ], "time" => $subscriptionDate ]; $subscriptionDetails["next_billing_time"] = $dateDiff <= 0 ? "" : Carbon::createFromFormat("Y-m-d H:i:s", auth()->user()->subscription_expiration_date)->format(DATE_ISO8601); $subscriptionDetails["subscription_type"] = ucfirst(auth()->user()->subscription_type); } elseif (!empty(auth()->user()->subscription_id)) { $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => $this->paypalEndpoint . '/billing/subscriptions/' . auth()->user()->subscription_id, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => [ 'PayPal-Request-Id: ' . get_guid(), 'Authorization: Bearer ' . request()->get("paypalToken"), ], ]); $response = json_decode(curl_exec($curl)); $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($httpcode == 200) { $subscriptionDetails["status"] = $response->status; $subscriptionDetails["start_time"] = $response->start_time; $subscriptionDetails["last_payment"] = $response->billing_info->last_payment; $subscriptionDetails["next_billing_time"] = $response->status == "CANCELLED" ? "" : $response->billing_info->next_billing_time; curl_close($curl); } else { return $json ? response()->json( ["success" => false, "message" => "Invalid subscription."] ) : null; } } else { $status = ""; $dateDiff = 0; if (!empty(auth()->user()->subscription_expiration_date)) { $expiration_date = Carbon::parse(auth()->user()->subscription_expiration_date); $now = Carbon::now(); $dateDiff = $expiration_date->diffInDays($now); $status = $dateDiff <= 0 ? "Expired" : "ACTIVE"; } $subscriptionDate = !empty(auth()->user()->subscription_date) ? Carbon::createFromFormat("Y-m-d H:i:s", auth()->user()->subscription_date)->format(DATE_ISO8601) : ""; $subscriptionDetails["status"] = $status; $subscriptionDetails["start_time"] = $subscriptionDate; $subscriptionDetails["last_payment"] = [ "amount" => [ "currency_code" => "USD", "value" => auth()->user()->subscription_amount ? auth()->user()->subscription_amount : 0 ], "time" => $subscriptionDate ]; $subscriptionDetails["next_billing_time"] = $dateDiff <= 0 ? "" : Carbon::createFromFormat("Y-m-d H:i:s", auth()->user()->subscription_expiration_date)->format(DATE_ISO8601); $subscriptionDetails["subscription_type"] = ucfirst(auth()->user()->subscription_type); } return $json ? response()->json( ["success" => true, "subscriptionDetails" => $subscriptionDetails] ) : $subscriptionDetails; } else { return $json ? response()->json( ["success" => false, "message" => "User has not subscribed to any package yet."] ) : null; } } public function cancel_subscription(Request $request) { $request->validate([ 'device_type' => 'required|in:web,android,apple' ]); if (!empty(auth()->user()->package_id) && auth()->user()->subscription_device_type && auth()->user()->subscription_device_type != $request->device_type) { return response()->json(["success" => false, "message" => "You should cancel subscription from ".auth()->user()->subscription_device_type.". Previously you subscribed from ".auth()->user()->subscription_device_type."."]); } if (!empty(auth()->user()->subscription_id) && auth()->user()->subscription_device_type != 'android' && auth()->user()->subscription_device_type != 'apple') { $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => $this->paypalEndpoint . '/billing/subscriptions/' . auth()->user()->subscription_id . '/cancel', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => '{ "reason": "Cancelled by user" }', CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . request()->get("paypalToken"), ], ]); $response = json_encode(curl_exec($curl)); $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); if ((int) $httpcode == 204 || (int) $httpcode == 200) { $user = auth()->user(); $user->package_id = null; $user->subscription_id = null; $user->subscription_type = null; $user->subscription_date = null; $user->subscription_device_type = null; $user->subscription_amount = 0; $user->subscription_expiration_date = null; $user->subscribed_with_free_coupon = 0; $user->save(); return response()->json(["success" => true, "message" => "You have been unsubscribed successfully."]); } else { return response()->json(["success" => true, "message" => "Something went wrong, please try again."]); } } elseif (!empty(auth()->user()->package_id)) { $user = auth()->user(); $user->package_id = null; $user->subscription_id = null; $user->subscription_type = null; $user->subscription_date = null; $user->subscription_device_type = null; $user->subscription_amount = 0; $user->subscription_expiration_date = null; $user->subscribed_with_free_coupon = 0; $user->save(); $inAppSubscriptionDetails = InAppSubscription::where('user_id', auth()->user()->id)->first(); if ($inAppSubscriptionDetails) { InAppSubscription::where('user_id', auth()->user()->id)->delete(); } return response()->json(["success" => true, "message" => "You have been unsubscribed successfully."]); } else { return response()->json(["success" => false, "message" => "You have not subscribed to any package yet."]); } } public function add_subscription_from_app(Request $request) { $request->validate([ 'package_id' => 'required|integer|exists:packages,id', 'subscription_id' => 'required', 'subscription_type' => 'required|in:monthly,yearly', 'device_type' => 'required|in:android,apple', 'amount' => 'required|numeric', 'coupon_code' => 'nullable|exists:coupons,coupon_code', ]); if (empty(auth()->user())) { abort(404, "User not found."); } $user = auth()->user(); $user->package_id = $request->package_id; $user->subscription_id = $request->subscription_id; $user->subscription_type = $request->subscription_type; $user->subscribed_with_free_coupon = !empty($request->coupon_code) ? 1 : 0; $user->subscription_date = Carbon::now()->toDateString(); $user->subscription_device_type = $request->device_type; $user->subscription_amount = $request->amount; $user->subscription_expiration_date = Carbon::now()->{"add" . str_replace("ly", "", $request->subscription_type)}()->toDateString(); $result = $user->save(); if (!empty($request->coupon_code)) { Coupon::whereCouponCode($request->coupon_code)->increment("usage_count"); } if ($result) { return response()->json(["success" => true, "message" => "You have been subscribed successfully."]); } return response()->json(["success" => false, "message" => "Something went wrong, please try again."]); } public function get_discounted_price(Request $request) { $request->validate([ 'package_id' => 'required|integer|exists:packages,id', 'coupon_code' => 'required', 'type' => 'required|in:monthly,yearly' ]); $coupon = Coupon::whereCouponCode(request()->input("coupon_code"))->whereStatus(1)->first(); $package = Package::whereId($request->package_id)->first(); $packageId = $package->id; $price = $package->{"price_" . $request->type}; $discounted_price = $price; if ( !empty($coupon) && (empty($coupon->package_id) || $coupon->package_id == $packageId) && ($coupon->package_type == "Both" || $coupon->package_type == ucfirst($request->type)) && (empty($coupon->number_of_usage) || $coupon->usage_count < $coupon->number_of_usage) && (empty($coupon->date_of_expiry) || date_difference(date("Y-m-d"), $coupon->date_of_expiry) > 0) ) { $discountAmount = $coupon->discount_amount; $discountType = $coupon->discount_type; $discount = $discountType == 1 ? ($price * $discountAmount / 100) : $discountAmount; $discounted_price = fixTowAfterDot($price - $discount); } return response()->json(["success" => true, "message" => "Get discounted price.", "price" => $price, "discounted_price" => $discounted_price]); } public function add_subscription_in_app_purchase(Request $request) { $request->validate([ 'package_name' => 'required', 'subscription_plan_id' => 'required', 'subscription_type' => 'required|in:monthly,yearly', 'device_type' => 'required|in:android,apple', 'amount' => 'required|numeric', 'fee' => 'required|numeric', 'amount_charged' => 'required|numeric', 'product_id' => 'required|string', 'purchase_type' => 'required|in:product,subscription', 'payment_charge_id' => 'nullable|string', 'local_price' => 'required|numeric', 'purchase_object' => 'required|json', 'coupon_code' => 'nullable|exists:coupons,coupon_code', ]); $user = auth()->user(); if (!$user) { return response()->json(["success" => false, "message" => "User not found."], 404); } $package = Package::where('package_name', 'LIKE', "%{$request->package_name}%")->first(); if (!$package) { return response()->json(["success" => false, "message" => "Package not found."], 404); } $user->package_id = $package->id; $user->subscription_id = $request->product_id; $user->subscription_type = $request->subscription_type; $user->subscribed_with_free_coupon = !empty($request->coupon_code) ? 1 : 0; $user->subscription_date = Carbon::now()->toDateString(); $user->subscription_device_type = $request->device_type; $user->subscription_amount = $request->amount; $user->subscription_expiration_date = Carbon::now()->{"add" . str_replace("ly", "", $request->subscription_type)}()->toDateString(); $user->save(); $subscription = InAppSubscription::updateOrCreate( [ 'user_id' => $user->id, 'package_id' => $package->id, ], [ 'subscription_id' => $request->product_id, 'subscription_type' => $request->subscription_type, 'device_type' => $request->device_type, 'amount' => $request->amount, 'fee' => $request->fee, 'amount_charged' => $request->amount_charged, 'subscription_plan_id' => $request->subscription_plan_id, 'purchase_type' => $request->purchase_type, 'payment_charge_id' => $request->payment_charge_id, 'product_id' => $request->product_id, 'local_price' => $request->local_price, 'purchase_object' => json_decode($request->purchase_object, true), 'subscription_date' => Carbon::now()->toDateString(), 'subscription_expiration_date' => Carbon::now()->{"add" . str_replace("ly", "", $request->subscription_type)}()->toDateString(), 'subscribed_with_free_coupon' => !empty($request->coupon_code), ] ); if (!empty($request->coupon_code)) { Coupon::where('coupon_code', $request->coupon_code)->increment("usage_count"); } if ($subscription) { return response()->json(["success" => true, "message" => "Subscription processed successfully.", "subscription" => $subscription]); } return response()->json(["success" => false, "message" => "Something went wrong, please try again."]); } public function getGoogleAccessToken() { $client = new Client(); $client->setAuthConfig(base_path('config/'.env('GOOGLE_APPLICATION_CREDENTIALS'))); $client->addScope('https://www.googleapis.com/auth/androidpublisher'); $accessToken = $client->fetchAccessTokenWithAssertion(); return $accessToken['access_token'] ?? null; } public function validateGoogleReceipt($type, $itemId, $purchaseToken) { try { $user = auth()->user(); $packageName = env('GOOGLE_PLAY_PACKAGE_NAME'); // Validate required parameters $errors = $this->validateRequiredFields(compact('type', 'itemId', 'purchaseToken')); if (!empty($errors)) { return makeJsonResponse('error', self::ERROR_HAS_OCCURRED, Response::HTTP_UNPROCESSABLE_ENTITY, [], $errors); } // Get Google Access Token $accessToken = $this->getGoogleAccessToken(); if (!$accessToken) { return makeJsonResponse('error', 'Failed to get Google Access Token', Response::HTTP_INTERNAL_SERVER_ERROR); } // Update Subscription Expiry if applicable $this->updateSubscriptionExpiration($user); // Validate Subscription or Product Receipt $endpoint = ($type === 'subscription') ? "subscriptions" : "products"; $url = "https://www.googleapis.com/androidpublisher/v3/applications/{$packageName}/purchases/{$endpoint}/{$itemId}/tokens/{$purchaseToken}"; $response = Http::withToken($accessToken)->get($url); $inAppSubscriptionDetails = InAppSubscription::where('user_id', auth()->user()->id)->first(); if ($response->successful()) { $data = []; $data['google_object'] = $response->json(); $data['subscription_details'] = $inAppSubscriptionDetails; return makeJsonResponse('success', 'Google purchase verified.', Response::HTTP_OK, $data); } return $this->handleGoogleApiError($response); } catch (\Exception $e) { return makeJsonResponse('error', self::ERROR_HAS_OCCURRED, Response::HTTP_INTERNAL_SERVER_ERROR, [], [[$e->getMessage()]]); } } /** * Validate required fields. */ private function validateRequiredFields($fields) { $errors = []; foreach ($fields as $key => $value) { if (empty($value)) { $errors[] = [ucfirst($key) . ' should not be empty.']; } } return $errors; } /** * Update subscription expiration date. */ private function updateSubscriptionExpiration($user) { $subscription = InAppSubscription::where('user_id', $user->id)->latest()->first(); if ($subscription && Carbon::parse($subscription->subscription_expiration_date)->isToday()) { $newExpiration = ($subscription->subscription_type === 'monthly') ? Carbon::parse($subscription->subscription_expiration_date)->addMonth() : Carbon::parse($subscription->subscription_expiration_date)->addYear(); $subscription->update(['subscription_expiration_date' => $newExpiration]); } } /** * Handle Google API error response. */ private function handleGoogleApiError($response) { $errorResponse = $response->json(); $errorMessage = $errorResponse['error']['message'] ?? 'Unknown error occurred.'; $errorCode = $errorResponse['error']['code'] ?? Response::HTTP_UNPROCESSABLE_ENTITY; $errorDetails = []; if (!empty($errorResponse['error']['errors'])) { foreach ($errorResponse['error']['errors'] as $error) { $errorDetails[] = [ 'message' => $error['message'] ?? 'Unknown error.', 'reason' => $error['reason'] ?? 'unknown_reason', 'domain' => $error['domain'] ?? 'unknown_domain' ]; } } return makeJsonResponse('error', $errorMessage, $errorCode, [], $errorDetails); } public function validateAppStoreReceipt() { try { $user = auth()->user(); try { $request = request()->all(); if(empty($request['receipt'])) { return makeJsonResponse('error', self::ERROR_HAS_OCCURRED, Response::HTTP_UNPROCESSABLE_ENTITY, [], [['Receipt should not be empty.']]); } $subscription = Subscription::where('user_id', $user->id)->latest()->first(); if(!empty($subscription)) { if(!empty($subscription->purchase_object)) { $decodePurchaseObject = json_decode($subscription->purchase_object); $addDuration = Carbon::parse($subscription->next_billing_date); if($addDuration->isToday()) { if($decodePurchaseObject->productId === 'pawssilver') { $addDuration = $addDuration->addMonth(); } elseif($decodePurchaseObject->productId === 'pawsgold') { $addDuration = $addDuration->addMonths(12); } $subscription->update(['next_billing_date' => $addDuration]); } } } $receiptProductValidate = ReceiptProductValidate::appStore()->receiptData($request['receipt'])->verifyReceipt(); return makeJsonResponse('success', 'App store receipt validate.', Response::HTTP_OK, $receiptProductValidate->toArray(), []); } catch (\Exception $e) { return makeJsonResponse('error', self::ERROR_HAS_OCCURRED, Response::HTTP_UNPROCESSABLE_ENTITY, [], [[$e->getMessage()]]); } } catch (\Exception $e) { return makeJsonResponse('error', self::ERROR_HAS_OCCURRED, Response::HTTP_INTERNAL_SERVER_ERROR, [], [[$e->getMessage()]]); } } }
| ver. 1.4 |
Github
|
.
| PHP 8.1.29 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка