UnknownSec Bypass
403
:
/
mnt
/
lmsestudio-instance-vol002
/
lms_adacfe8c5fb8
/
app
/
Http
/
Controllers
/
Cart
/ [
drwxr-xr-x
]
Menu
Upload
Mass depes
Mass delete
Terminal
Info server
About
name :
PagarMeController.php
<?php namespace EstudioLMS\Http\Controllers\Cart; use Carbon\Carbon; use EstudioLMS\Cart\Cart; use EstudioLMS\Events\PagarMeDone; use EstudioLMS\Exceptions\Handler; use EstudioLMS\Http\Controllers\Controller; use EstudioLMS\Repositories\Auth\CustomerInterface; use EstudioLMS\Repositories\Auth\UserRepository; use EstudioLMS\Repositories\Config\PagarmeRecipientInterface; use EstudioLMS\Repositories\Courses\Course\CourseRepository; use EstudioLMS\Repositories\Environment\HiredCourseRepository; use EstudioLMS\Repositories\Financial\PayableInterface; use EstudioLMS\Repositories\Financial\PostbackInterface; use EstudioLMS\Services\Admin\ConfigurationServices; use EstudioLMS\Services\Hires\HiringServices; use EstudioLMS\Services\PagarMeService; use EstudioLMS\Helpers\Helpers; use Illuminate\Contracts\Auth\Guard; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Class PagarMeController * @package EstudioLMS\Http\Controllers\Cart */ class PagarMeController extends Controller { /** * @var Cart */ private $cart; /** * @var SessionInterface */ private $session; /** * @var PagarMeService */ private $pagarMeService; /** * @var CustomerInterface */ private $customer; /** * @var CourseRepository */ private $course; /** * @var ConfigurationServices */ private $configurationServices; /** * @var UserRepository */ private $user; /** * @var HiringServices */ private $hiringServices; /** * @var PagarmeRecipientInterface */ private $pagarmeRecipient; /** * @var HiredCourseRepository */ private $hiredCourse; /** * @var Guard */ private $auth; /** * @var PayableInterface */ private $payable; /** * @var PostbackInterface */ private $postback; /** * PagarMeController constructor. * @param Cart $cart * @param SessionInterface $session * @param PagarMeService $pagarMeService * @param CustomerInterface $customer * @param CourseRepository $course * @param ConfigurationServices $configurationServices * @param UserRepository $user * @param HiringServices $hiringServices * @param PagarmeRecipientInterface $pagarmeRecipient * @param HiredCourseRepository $hiredCourse * @param Guard $auth * @param PayableInterface $payable * @param PostbackInterface $postback */ public function __construct( Cart $cart, SessionInterface $session, PagarMeService $pagarMeService, CustomerInterface $customer, CourseRepository $course, ConfigurationServices $configurationServices, UserRepository $user, HiringServices $hiringServices, PagarmeRecipientInterface $pagarmeRecipient, HiredCourseRepository $hiredCourse, Guard $auth, PayableInterface $payable, PostbackInterface $postback ) { $this->cart = $cart; $this->session = $session; $this->pagarMeService = $pagarMeService; $this->customer = $customer; $this->course = $course; $this->configurationServices = $configurationServices; $this->user = $user; $this->hiringServices = $hiringServices; $this->pagarmeRecipient = $pagarmeRecipient; $this->hiredCourse = $hiredCourse; $this->auth = $auth; $this->payable = $payable; $this->postback = $postback; } /** * @param Request $request * @return \Illuminate\Http\RedirectResponse */ public function checkoutPagarMe(Request $request) { //try { $config = $this->configurationServices->configuration(); $cart = $this->getCart(); $data = $request->all(); $price = ($cart->getGrossAmount() - $cart->getDiscountAmount()) + $cart->getShippingAmount() + $cart->getInstallmentInterest(); if ($price < 1) { return redirect()->route('checkout.result', 'false') ->with('error', 'Valor não permitido. O gateway não aceita transações menores que R$ 1,00'); } // Buscar usuário com customers e endereço $user = $this->user->with(['customer', 'address'])->find(\Auth::user()->id); // Verificar se existe customer específico para o cartão selecionado $selectedCustomer = null; if (isset($data['card_hash_id']) && $data['card_hash_id']) { $selectedCustomer = $user->customer->where('card_id', $data['card_hash_id'])->first(); } // ROTINA DE SEGURANÇA: Verificar se customer existe na API v5 $customerId = $this->pagarMeService->ensureCustomerExistsV5($user); $boletoUrl = null; $boletoBarCode = null; $error = null; $success = 'false'; if ($data['pay_type'] == 'C') { if (isset($data['card_hash_id']) && $selectedCustomer) { $cardId = $selectedCustomer->card_id; $cvv = \Crypt::decrypt($selectedCustomer->hash); } else { $cardData = [ 'card_number' => $data['card_number'], 'holder_name' => $data['holder_name'], 'exp_month' => $data['exp_month'], 'exp_year' => $data['exp_year'], 'cvv' => $data['cvv'], 'customer_id' => $customerId, //'billing_address_id' => '', // Inserir o id do endereço do cliente existente na base ou 'billing_address' => [ 'street' => $user->address->street ?? '', 'street_number' => $user->address->number ?? '', 'complement' => $user->address->complement ?? '', 'neighborhood' => $user->address->neighborhood ?? '', 'city' => $user->address->city ?? '', 'state' => $user->address->state ?? '', 'zipcode' => $user->address->zip_code ?? '', 'country' => 'BR' ] ]; //dd($cardData); try { $card = $this->pagarMeService->createCard($cardData); // Verificar se o ID do cartão foi retornado if (!isset($card['id']) || empty($card['id'])) { \Log::error('ID do cartão não encontrado na resposta', [ 'card_response' => $card, 'card_data' => $cardData ]); throw new \Exception('ID do cartão não foi retornado pela API'); } $this->customer->setAllDefaultFalse($user->id); $this->customer->create([ 'user_id' => $user->id, 'customer_id' => $customerId, 'card_id' => $card['id'], 'hash' => \Crypt::encrypt($data['cvv']), 'default' => true ]); $cardId = $card['id']; $cvv = $data['cvv']; } catch (\Exception $e) { \Log::error('Erro ao criar cartão: ' . $e->getMessage()); return redirect()->route('checkout.result', 'false') ->with('error', 'Erro ao processar cartão: ' . $e->getMessage()); } } $courseId = $cart->get('course_id'); $course = $this->course->with(['plans', 'plans.duration', 'material'])->find($courseId); $installmentInterest = 0.00; if ($data['pay_installment'] > 1) { $noInterest = $course->gateways[0]->pivot->installments; $cartAmount = (double)$cart->get('price') + (double)$cart->get('extra_amount') + (double)$cart->get('shipping_price'); $cartAmount = $cartAmount - (double)$cart->getDiscountAmount(); $amount = intval($cartAmount * 100); $installments = $this->pagarMeService->installments($amount, $noInterest, 12, 1); $installment = $installments['installments'][$data['pay_installment']]; $instalmentAmount = (double)$installment['amount'] / 100; $cartValue = ($cart->getGrossAmount() - $cart->getDiscountAmount()) + $cart->getShippingAmount(); $installmentInterest = $instalmentAmount - $cartValue; $cart->applyInstallment($installment['installment'], $installmentInterest); } $cart = $this->getCart(); $postBackUrl = null; $softDescriptor = Helpers::sanitizeSoftDescriptor($config->site_name); try { // Verificar se deve usar processamento em tempo real $useRealTime = $this->pagarMeService->shouldUseRealTimeProcessing('credit_card'); \Log::info('Processando cartão de crédito', [ 'real_time' => $useRealTime, 'card_id' => $cardId, 'installments' => $data['pay_installment'] ?? 1 ]); // Usar novo método de processamento em tempo real $result = $this->pagarMeService->createCreditCardOrderRealTime( $cardId, $cart, null, // Não é assinatura $user->id, $softDescriptor, $useRealTime ); if ($result['status'] === 'approved') { $success = 'true'; $error = null; // Buscar dados para email - usar order_id padronizado $orderId = $result['order']['id']; $chargeId = $result['charge']['id']; $hiring = $this->hiringServices->getByPaymentCode($orderId); // Preparar dados para o email com estrutura correta $mailData = [ 'user' => [ 'email' => $user->email, 'name' => $user->name ], 'course' => [ 'name' => $cart->get('name') ], 'hiring' => $hiring, 'payment_method' => 'credit_card', 'payment_code' => $orderId, 'gross_amount' => $cart->getGrossAmount(), 'discount_amount' => $cart->getDiscountAmount(), 'net_amount' => $cart->getGrossAmount() - $cart->getDiscountAmount() ]; \Event::fire(new PagarMeDone('credit_card', $mailData)); \Log::info('Transação cartão aprovada tempo real', ['charge_id' => $chargeId, 'order_id' => $orderId]); } elseif ($result['status'] === 'rejected') { $success = 'false'; $error = $result['message']; $chargeId = $result['charge']['id']; $orderId = $result['order']['id']; \Event::fire(new PagarMeDone('credit_card_refused', $error)); \Log::info('Transação cartão rejeitada tempo real', [ 'reason' => $result['reason'], 'charge_id' => $chargeId, 'order_id' => $orderId ]); } else { // Status intermediário - processar como antes (fallback para postback) $charge = $result['charge']; $order = $result['order']; if ($charge['status'] == 'paid') { $this->hiringTransaction( $order['id'], $charge, $cart, $charge['status'], $cardId, $installmentInterest ); $success = 'true'; $error = null; $orderId = $order['id']; $hiring = $this->hiringServices->getByPaymentCode($orderId); // Preparar dados para o email com estrutura correta $mailData = [ 'user' => [ 'email' => $user->email, 'name' => $user->name ], 'course' => [ 'name' => $cart->get('name') ], 'hiring' => $hiring, 'payment_method' => 'credit_card', 'payment_code' => $orderId, 'gross_amount' => $cart->getGrossAmount(), 'discount_amount' => $cart->getDiscountAmount(), 'net_amount' => $cart->getGrossAmount() - $cart->getDiscountAmount() ]; \Event::fire(new PagarMeDone('credit_card', $mailData)); } else { $success = 'false'; $error = $result['message'] ?? 'Transação não autorizada'; \Event::fire(new PagarMeDone('credit_card_refused', $error)); } \Log::info('Transação cartão processada via fallback', ['status' => $charge['status']]); } } catch (\Exception $e) { app(Handler::class)->report($e); $error = $e->getCode() . ' - ' . $e->getMessage(); $success = 'false'; \Log::error('Erro no processamento cartão: ' . $e->getMessage()); } } else { $postBackUrl = null; try { $orderData = [ 'items' => [ [ 'amount' => intval($price * 100), 'description' => 'Curso ID #' . $cart->get('course_id'), 'quantity' => 1, 'code' => (string)$cart->get('course_id') ] ], 'customer_id' => $customerId, 'payments' => [ [ 'payment_method' => 'boleto', 'boleto' => [ 'instructions' => 'Pagar até a data de vencimento', 'due_at' => Carbon::now()->addDays(3)->format('Y-m-d\TH:i:s') ] ] ], 'metadata' => [ 'user_email' => $user->email, 'user_id' => $user->id, 'instance_email' => $this->session->get('planLimite.email', ''), 'instance_url' => request()->getHost(), 'product_id' => $cart->get('course_id'), 'plan_id' => $cart->get('plan_id') ] ]; // Adicionar dados de faturamento se disponíveis if ($user->address) { // Extrair DDD e número do telefone, se disponível $phone = []; if (isset($user->address->phone) && $user->address->phone) { $phoneNumber = preg_replace('/[^0-9]/', '', $user->address->phone); if (strlen($phoneNumber) >= 10) { $phone = [ 'country_code' => '55', 'area_code' => substr($phoneNumber, 0, 2), 'number' => substr($phoneNumber, 2) ]; } } $orderData['billing'] = [ 'address' => [ 'street' => $user->address->street ?? '', 'number' => $user->address->number ?? '', 'complement' => $user->address->complement ?? '', 'neighborhood' => $user->address->neighborhood ?? '', 'city' => $user->address->city ?? '', 'state' => $user->address->state ?? '', 'zip_code' => $user->address->zip_code ?? '', 'country' => 'BR' ] ]; if (!empty($phone)) { $orderData['billing']['phone'] = $phone; } } $order = $this->pagarMeService->createOrderWithSplitRules($orderData, $price, 'boleto', true); $charge = $order['charges'][0] ?? null; $transaction = $charge['last_transaction'] ?? null; if ($charge && $transaction && isset($transaction['url'])) { $status = $charge['status']; $error = null; $this->hiringTransaction($order['id'], $charge, $cart, $status); $success = 'true'; // Buscar pelo order_id (padronização) $orderId = $order['id']; $hiring = $this->hiringServices->getByPaymentCode($orderId); // Preparar dados para o email com estrutura correta $mailData = [ 'user' => [ 'email' => $user->email, 'name' => $user->name ], 'course' => [ 'name' => $cart->get('name') ], 'hiring' => $hiring, 'payment_method' => 'boleto', 'payment_code' => $orderId, 'gross_amount' => $cart->getGrossAmount(), 'discount_amount' => $cart->getDiscountAmount(), 'net_amount' => $cart->getGrossAmount() - $cart->getDiscountAmount(), 'boleto_url' => $transaction['url'], 'boleto_barcode' => $transaction['line'] ?? '' ]; \Event::fire(new PagarMeDone('boleto', $mailData)); $boletoUrl = $transaction['url']; $boletoBarCode = $transaction['line'] ?? ''; } else { $error = 'Falha ao gerar boleto'; $success = 'false'; // Preparar dados estruturados para o email mesmo em caso de erro $errorMailData = [ 'user' => [ 'email' => $user->email, 'name' => $user->name ], 'course' => [ 'name' => $cart->get('name') ], 'payment_method' => 'boleto', 'error_message' => $error, 'gross_amount' => $cart->getGrossAmount(), 'discount_amount' => $cart->getDiscountAmount() ]; \Event::fire(new PagarMeDone('boleto_refused', $errorMailData)); } } catch (\Exception $e) { app(Handler::class)->report($e); $error = $e->getCode() . ' - ' . $e->getMessage(); $success = 'false'; // Preparar dados estruturados para o email em caso de exceção $exceptionMailData = [ 'user' => [ 'email' => $user->email, 'name' => $user->name ], 'course' => [ 'name' => $cart->get('name') ], 'payment_method' => 'boleto', 'error_message' => $error, 'gross_amount' => $cart->getGrossAmount(), 'discount_amount' => $cart->getDiscountAmount() ]; \Event::fire(new PagarMeDone('boleto_refused', $exceptionMailData)); } } if (!is_null($cart)) { $cart->destroy(); $this->session->set('cart', $cart); } return redirect()->route('checkout.result', $success) ->with('error', $error) ->with('boletoUrl', $boletoUrl); //} catch (\Exception $e) { //app(Handler::class)->report($e); //return redirect()->route('checkout.result', 'false') // ->with('error', 'Erro ao processar pagamento: ' . $e->getMessage()); //} } /** * Pega o carrinho de compras da sessão caso exista, se não cria um novo carrinho * * * @return mixed */ private function getCart() { if ($this->session->has('cart')) { $cart = $this->session->get('cart'); } else { $cart = $this->cart; } return $cart; } /** * @param array $charge Charge da API v5 * @param Cart $cart * @param string $status * @param string|null $cardId * @param float $interestAmount */ public function hiringTransaction( $orderId, $charge, $cart, $status, $cardId = null, $interestAmount = 0.00 ) { $courseId = $cart->get('course_id'); $planId = $cart->get('plan_id'); $course = $this->course->with(['plans', 'plans.duration', 'material'])->find($courseId); $plan = $course['plans']->where('id', (int)$planId)->first(); $totalFeeAmount = 0; $startDate = date('Y-m-d'); $addDate = '+' . $plan['duration']['duration'] . ' months'; $endDate = date('Y-m-d 23:59:59', strtotime($addDate, strtotime($startDate))); $recipientESId = config('pagar_me.PAGAR_ME_RECIPIENT_ID'); if ($status == 'paid') { $payables = $this->pagarMeService->getChargePayables($charge['id']); foreach ($payables as $payable) { if ($payable['recipient_id'] === $recipientESId) { $totalFeeAmount += $payable['amount']; } else { $totalFeeAmount += $payable['fee']; } } $totalFeeAmount = $totalFeeAmount / 100; } $transaction = $charge['last_transaction']; $paymentMethod = $transaction['payment_method'] ?? $charge['payment_method']; if ($paymentMethod == 'boleto') { $installments = 1; } else { $installments = $transaction['installments'] ?? 1; } $grossAmount = $cart->getGrossAmount(); $discountAmount = $cart->getDiscountAmount(); $netAmount = ($grossAmount - ($totalFeeAmount + $discountAmount)) + $interestAmount; $header = [ 'user_id' => $this->auth->user()['id'], 'gateway_id' => 'PagarMe', 'payment_code' => $orderId, // Corrigido: usar order_id ao invés de charge['id'] 'payment_method' => $paymentMethod, 'gross_amount' => $grossAmount, 'discount_amount' => $discountAmount, 'fee_amount' => $totalFeeAmount, 'shipping_amount' => $cart->getShippingAmount(), 'extra_amount' => $cart->getExtraAmount(), 'net_amount' => $netAmount, 'shipping_type' => $cart->getShippingCode(), 'status' => \GatHelper::translateGatewayStatus( 'PagarMe', $status ), 'course_id' => $cart->get('course_id'), 'plan_id' => $planId, 'start' => $startDate, 'end' => $endDate, 'coupon_title' => $cart->get('coupon_name'), 'coupon_code' => $cart->get('coupon_code'), 'coupon_discount' => $cart->get('coupon_discount'), 'installments' => $installments, 'installment_interest' => $interestAmount ]; $createHiring = $this->hiringServices->store($header); /* Cursos contratados do Aluno */ $hiredCourse = [ 'user_id' => $this->auth->user()['id'], 'course_id' => $cart->get('course_id'), 'plan_id' => $cart->get('plan_id'), 'hirings_id' => $createHiring['id'], 'status' => \GatHelper::translateGatewayStatus( 'PagarMe', $status ), 'start' => $startDate, 'end' => $endDate, 'is_free' => false ]; $renew = $this->hiredCourse->findWhere([ ['user_id', '=', $this->auth->user()['id']], ['course_id', '=', $cart->get('course_id')] ])->first(); if ($renew) { $this->hiredCourse->update($hiredCourse, $renew['id']); } else { $this->hiredCourse->create($hiredCourse); } if (!empty($payables)) { $recipient = $this->pagarmeRecipient->firstRecord(); $filterBy = $recipient->pagarme_recipient_id; $recipientPayables = array_filter($payables, function ($payable) use ($filterBy) { return $payable['recipient_id'] == $filterBy; }); foreach ($recipientPayables as $payable) { $sumFeeAmount = $payable['fee'] ?? 0; $netAmount = $payable['amount'] - $sumFeeAmount; $payableStatus = $payable['status']; $paymentDate = isset($payable['payment_date']) ? Carbon::parse($payable['payment_date'])->format('Y-m-d H:i:s') : null; $payableData = [ 'subscription_hash' => $orderId, // Corrigido: usar order_id 'payment_code' => $orderId, // Corrigido: usar order_id 'payment_type' => $paymentMethod, 'payment_date' => $paymentDate, 'card_id' => $cardId, 'gross_amount' => $payable['amount'] / 100, 'discount_amount' => 0, 'fee_amount' => $sumFeeAmount / 100, 'extra_amount' => 0, 'net_amount' => $netAmount / 100, 'payable_status_id' => $payableStatus == 'paid' ? 2 : 1 ]; $existingPayable = $this->payable->findWhere([ ['subscription_hash', '=', $orderId], // Corrigido: usar order_id ['payment_code', '=', $orderId], // Corrigido: usar order_id ['payment_date', '=', $paymentDate], ['payable_status_id', '=', $payableData['payable_status_id']] ])->first(); if ($existingPayable) { $existingPayable->fill($payableData); $existingPayable->save(); } else { $this->payable->create($payableData); } } } } /** * @param Request $request */ public function postback(Request $request) { $this->pagarMeService->postback($request); } }
Copyright © 2026 - UnknownSec