| Server IP : 138.197.107.151 / Your IP : 216.73.217.7 Web Server : Apache/2.4.58 (Ubuntu) System : Linux BloxBy-Builder 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64 User : wpbetasites_mrakzqskir ( 1022) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/shark/app/Http/Controllers/ |
Upload File : |
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Stripe\Stripe;
use Stripe\Checkout\Session;
use App\Models\PricingPlan;
use App\Models\Order;
use App\Models\Payment;
use App\Models\Website;
use Stripe\Webhook;
use Stripe\Subscription;
use Stripe\Invoice;
use Carbon\Carbon;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use App\Helpers\EncryptionHelper;
use Mail;
class PaymentController extends Controller
{
public function createCheckoutSession(Request $request, $website_id, $plan_id)
{
//$plan_id = $request->plan_id;
if(@env("disable_payments")==1){
die;
}
if(auth()->user() && auth()->user()->email_verified_at==null){
return back()->with('error', 'Please verify your email to process your payments.');
die;
}
$plan = PricingPlan::where("id", $plan_id)->first();
if($plan){
$order = Order::create([
"user_id" => auth()->user()->id,
"name" => auth()->user()->name,
"pricing_plan_id" => $plan->id,
"order_total" => $plan->price,
"type" => $plan->type,
"status"=>"pending",
"website_id"=>$website_id
]);
if($order){
Stripe::setApiKey(env('STRIPE_SECRET'));
$session = Session::create([
'payment_method_types' => ['card'],
'mode' => $plan->type == "one-time" ? 'payment' : "subscription",
'line_items' => [[
'price' => $plan->stripe_pricing_id, // Replace with your Price ID
'quantity' => 1,
]],
'metadata' => [
'order_id' => $order->id,
'user_id' => auth()->id(),
'type' => $order->type
],
'success_url' => route('payment.success',["website_id"=>$website_id]),
'cancel_url' => route('payment.cancel',["website_id"=>$website_id]),
'consent_collection' => [
'terms_of_service' => 'required',
],
]);
$order->update([
'stripe_session_id' => $session->id,
]);
return redirect($session->url);
}
}
}
public function success(Request $request)
{
$website = null;
if($request->website_id){
$website = Website::where("id",$request->website_id)->first();
}
return view('payments.success')->with(["website"=>$website]); // create this view
}
public function cancel(Request $request)
{
$website = null;
if($request->website_id){
$website = Website::where("id",$request->website_id)->first();
}
return view('payments.cancel')->with(["website"=>$website]); // create this view
}
public function handleCheckoutSessionWebhook(Request $request)
{
Stripe::setApiKey(env('STRIPE_SECRET'));
$endpointSecret = env('STRIPE_CHECKOUT_SESSION_WEBHOOK_SECRET'); // from Stripe Dashboard
$payload = $request->getContent();
$sigHeader = $request->server('HTTP_STRIPE_SIGNATURE');
$event = null;
/*try {
// Verify signature automatically
$event = \Stripe\Webhook::constructEvent(
$payload,
$sigHeader,
$endpointSecret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}*/
$stripe_date = json_decode($payload, true);
$payment_type = "one-time";
$subscription = null;
if($stripe_date["type"] == "checkout.session.completed"){
$webhook = $stripe_date["data"]["object"];
if($webhook["status"]=="complete" && $webhook["payment_status"]=="paid"){
$orderId = $webhook["metadata"]["order_id"] ?? null;
$paymentIntent = isset($webhook["payment_intent"]) ? $webhook["payment_intent"] : (isset($webhook["subscription"]) ? $webhook["subscription"] : null) ;
$amountTotal = $webhook["amount_total"];
$currency = $webhook["currency"];
$invoice_id = isset($webhook["invoice"]) ? $webhook["invoice"] :null;
$payment = null;
if ($orderId) {
$order = Order::find($orderId);
$website = Website::find($order->website_id);
if ($order && $order->status !== 'paid') {
$order->status = 'paid';
$order->save();
// Optionally log a payment
$payment = Payment::create([
'user_id' => $order->user_id,
'website_title' => $website ? $website->title :"Website",
'order_id' => $order->id,
'stripe_transaction_id' => $paymentIntent,
'status' => 'succeeded',
'invoice_total' => $amountTotal,
'currency' => $currency,
'paid_at' => now(),
]);
}
if($website){
$website->active_plan_id = $order->pricing_plan_id;
$website->last_payment_date = date("Y-m-d H:i:s");
$transaction_id = null;
$paidAt = null;
if(isset($webhook["subscription"])){
$website->stripe_subscription_id = $webhook["subscription"];
$subscription = Subscription::retrieve( $webhook["subscription"]); // your Stripe subscription ID
if($subscription){
$current_period_end = null;
if($subscription->items){
if($subscription->items->data){
foreach($subscription->items->data as $plan){
$current_period_end = $plan->current_period_end;
}
}
}
$nextPayment = $current_period_end
? Carbon::createFromTimestamp($current_period_end)->toDateTimeString()
: null;
$website->next_payment_date = $nextPayment;
$invoice_id = $subscription->latest_invoice;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.stripe.com/v1/invoices/'.$invoice_id.'?expand[]=payments',
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 => array(
'Authorization: Bearer '.env('STRIPE_SECRET')
),
));
$response = curl_exec($curl);
curl_close($curl);
if($response){
$invoice = json_decode($response, true);
if($invoice && isset($invoice['payments']) && isset($invoice['payments']['data']) && sizeof($invoice['payments']['data'])>0){
$payment_stripe = $invoice['payments']['data'][0];
if($payment_stripe && isset($payment_stripe['payment'])){
$paymentIntentId = isset($payment_stripe['payment']['payment_intent']) ? $payment_stripe['payment']['payment_intent'] : null;
if($paymentIntentId){
$paymentIntent = \Stripe\PaymentIntent::retrieve($paymentIntentId);
if($paymentIntent){
$chargeId = $paymentIntent->latest_charge;
$charge = \Stripe\Charge::retrieve($chargeId);
if($charge){
$transaction_id = $charge->balance_transaction;
$paidAt = Carbon::createFromTimestamp($charge->created)->toDateTimeString();
}
}
}
}
}
}
}
$payment_type = "recurring";
} else {
$website->is_zip_enabled = 1;
$paymentIntentId = $paymentIntent;
$paymentIntent = \Stripe\PaymentIntent::retrieve($paymentIntentId);
if($paymentIntent && $paymentIntent->latest_charge)
{
$charge = \Stripe\Charge::retrieve($paymentIntent->latest_charge);
if($charge){
$transaction_id = $charge->balance_transaction;
$paidAt = Carbon::createFromTimestamp($charge->created)->toDateTimeString();
}
}
//return $paymentIntent;
//dd($transaction_id);
}
$website->save();
if($payment){
$payment = Payment::where("id",$payment->id)->first();
$payment->website_id = $website->id;
$payment->stripe_transaction_id = $transaction_id;
$payment->paid_at = $paidAt ?? $payment->paid_at;
$payment->stripe_invoice_id = $invoice_id;
$payment->save();
// dd($payment);
$this->changeRole($website,"bloxby-user");
if($payment_type=="one-time"){
$this->sendOneTimePaymentEmail($payment->user, $website, $payment);
} else {
$this->sendFirstRecurringPaymentEmail($payment->user, $website, $payment);
}
}
}
}
}
}
return response(["message"=>'Webhook received', "payload"=>$payload, "subscription"=>$subscription ], 200);
}
public function changeRole($website, $role){
if($website){
$user = $website->user;
$server_meta = json_decode($website->server_meta, true);
$process = new Process([
'sudo',
'/var/bloxbycommands/changeinrole.sh',
'/var/www/'.$server_meta["folder"].'/'.$server_meta["sftp_user"]."/public_html",
$user->email,
$role
]);
$process->setTimeout(300); // Increase for long tasks
$process->run();
if (!$process->isSuccessful()) {
return response()->json(['status' => 'error', 'message' => $process->getErrorOutput()], 500);
}
}
}
function generateSecureUniqueId($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
$charactersLength = strlen($characters);
$uniqueId = '';
for ($i = 0; $i < $length; $i++) {
$uniqueId .= $characters[random_int(0, $charactersLength - 1)];
}
return $uniqueId;
}
public function changeSFTPPassword($website){
if($website){
$user = $website->user;
$server_meta = json_decode($website->server_meta, true);
$password = $this->generateSecureUniqueId(10);
$process = new Process([
'sudo',
'/var/bloxbycommands/change_sftp_password.sh',
$server_meta["sftp_user"],
$password
]);
$process->setTimeout(300); // Increase for long tasks
$process->run();
$server_meta["sftp_pass"] = EncryptionHelper::secret_encrypt($password, env("SODIUM_KEY"));
$website->server_meta = json_encode($server_meta);
$website->save();
if (!$process->isSuccessful()) {
//return response()->json(['status' => 'error', 'message' => $process->getErrorOutput()], 500);
}
}
}
public function removeDomain($website){
if($website){
$server_meta = json_decode($website->server_meta, true);
$process = new Process([
'sudo',
'/var/bloxbycommands/remove_domain.sh',
$website->domain,
$server_meta["domain"].".bloxby.io",
"/var/www/".$server_meta["folder"]."/".$server_meta["sftp_user"]."/public_html"
]);
$process->setTimeout(300); // Increase for long tasks
$process->run();
if (!$process->isSuccessful()) {
//return redirect()->back()->with([ 'errors' =>[ $process->getErrorOutput()]]);
}
$website->domain= null;
$website->domain_status= 'pending';
$website->domain_error= null;
$website->save();
}
}
public function list(Request $request){
$payments = Payment::where("user_id", auth()->user()->id);
$title = "Payments list";
$col = "payments.created_at";
if($request->col){
$col = $request->col;
}
$dir = $request->get('dir', 'desc');
$payments = $payments->orderBy($col, $dir);
$payments = $payments->paginate(20); // 10 users per page
return view('payments.list', compact('payments','title','col','dir'));
}
public function handlePaymentSuccess(Request $request)
{
Stripe::setApiKey(env('STRIPE_SECRET'));
$endpointSecret = env('STRIPE_INVOICE_SUCCESS_WEBHOOK_SECRET'); // from Stripe Dashboard
$payload = $request->getContent();
$sigHeader = $request->server('HTTP_STRIPE_SIGNATURE');
$event = null;
try {
// Verify signature automatically
$event = \Stripe\Webhook::constructEvent(
$payload,
$sigHeader,
$endpointSecret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
$paidAt = null;
$stripe_data = json_decode($payload, true);
if(isset($stripe_data["data"])){
if(isset($stripe_data["data"]["object"])){
$payment = $stripe_data["data"]["object"];
if($payment["billing_reason"]=="subscription_cycle"){
$subscription = null;
$current_period_end = null;
$amount = $payment["amount_paid"];
$currency = $payment["currency"];
foreach($payment["lines"]["data"] as $line){
$subscription = $line["parent"]["subscription_item_details"]["subscription"];
$current_period_end = $line["period"]["end"];
$amount = $line["amount"];
$currency = $line["currency"];
}
if($subscription){
$stripe_subscription = \Stripe\Subscription::retrieve($subscription);
$transaction_id = null;
if($stripe_subscription){
$invoice_id = $stripe_subscription->latest_invoice;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.stripe.com/v1/invoices/'.$invoice_id.'?expand[]=payments',
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 => array(
'Authorization: Bearer '.env('STRIPE_SECRET')
),
));
$response = curl_exec($curl);
curl_close($curl);
if($response){
$invoice = json_decode($response, true);
if($invoice && isset($invoice['payments']) && isset($invoice['payments']['data']) && sizeof($invoice['payments']['data'])>0){
$payment_stripe = $invoice['payments']['data'][0];
if($payment_stripe && isset($payment_stripe['payment'])){
$paymentIntentId = isset($payment_stripe['payment']['payment_intent']) ? $payment_stripe['payment']['payment_intent'] : null;
if($paymentIntentId){
$paymentIntent = \Stripe\PaymentIntent::retrieve($paymentIntentId);
if($paymentIntent){
$chargeId = $paymentIntent->latest_charge;
$charge = \Stripe\Charge::retrieve($chargeId);
if($charge){
$transaction_id = $charge->balance_transaction;
$paidAt = \Carbon\Carbon::createFromTimestamp($charge->created)->toDateTimeString();
}
}
}
}
}
}
}
$website = Website::where("stripe_subscription_id", $subscription)->first();
if($website){
$website->reminder_email_sent = 0;
$nextPayment = $current_period_end
? Carbon::createFromTimestamp($current_period_end)->toDateTimeString()
: null;
$website->next_payment_date = $nextPayment;
$website->last_payment_date = date("Y-m-d H:i:s");
$website->save();
$payment_db = Payment::create([
'user_id' => $website->user_id,
'website_id' => $website->id,
'website_title' => $website ? $website->title :"Website",
'order_id' => null,
'stripe_transaction_id' => $transaction_id,
'status' => 'succeeded',
'invoice_total' => $amount,
'currency' => $currency,
'paid_at' => $paidAt ?? now(),
'stripe_invoice_id' => isset($invoice_id) && $invoice_id!=null ? $invoice_id : null
]);
$payment_save = Payment::where("id",$payment_db->id)->first();
if($payment_save && $payment_save->user){
$this->sendFollowRecurringPaymentEmail($payment_save->user, $website, $payment_save);
}
}
}
}
}
}
return response(["message"=>'Webhook received', "payload"=>$payload], 200);
}
public function handleSubscriptionDeleted(Request $request)
{
Stripe::setApiKey(env('STRIPE_SECRET'));
$endpointSecret = env('STRIPE_SUBSCRIPTION_DELETE_WEBHOOK_SECRET'); // from Stripe Dashboard
$payload = $request->getContent();
$sigHeader = $request->server('HTTP_STRIPE_SIGNATURE');
$event = null;
try {
// Verify signature automatically
$event = \Stripe\Webhook::constructEvent(
$payload,
$sigHeader,
$endpointSecret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
$stripe_data = json_decode($payload, true);
if(isset($stripe_data["data"]) && $stripe_data["type"]=="customer.subscription.deleted"){
if(isset($stripe_data["data"]["object"])){
$subscription = $stripe_data["data"]["object"];
if( $subscription["status"]=="canceled"){
$website = Website::where("stripe_subscription_id", $subscription["id"])->first();
$website->is_cancellation_requested = 0;
$website->cancelled_stripe_subscription_id = $subscription["id"];
$website->stripe_subscription_id = null;
$website->active_plan_id = null;
$website->save();
$this->changeRole($website,"editor");
$this->changeSFTPPassword($website);
if($website->domain){
$this->removeDomain($website);
}
}
}
}
return response(["message"=>'Webhook received', "payload"=>$payload], 200);
}
public function sendOneTimePaymentEmail($user, $website, $payment){
Mail::send('emails.onetime_payment_success', [
'user' => $user,
'website' => $website,
'plan' => $website->plan,
'payment' => $payment
], function ($message) use ($user, $website) {
$message->to($user->email);
$message->subject('Payment Successful – '.($website->plan ? $website->plan->title : "Hosted with Bloxby" ));
});
}
public function sendFirstRecurringPaymentEmail($user, $website, $payment){
Mail::send('emails.first_recurring_payment_success', [
'user' => $user,
'website' => $website,
'plan' => $website->plan,
'payment' => $payment,
], function ($message) use ($user, $website) {
$message->to($user->email);
$message->subject('Payment Successful – '.(($website && $website->plan)? $website->plan->title : "Monthly").' Plan');
});
}
public function sendFollowRecurringPaymentEmail($user, $website, $payment){
Mail::send('emails.recurring_payment_success', [
'user' => $user,
'website' => $website,
'plan' => $website->plan,
'payment' => $payment
], function ($message) use ($user, $website) {
$message->to($user->email);
$message->subject('Payment Successful – '.(($website && $website->plan)? $website->plan->title : "Monthly").' Plan');
});
}
}