• File: UserClientController.php.save.1
  • Full Path: /var/www/sandbox/app/Http/Controllers/UserClientController.php.save.1
  • Date Modified: 09/13/2024 11:49 PM
  • File size: 153.77 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php

namespace App\Http\Controllers;

use App\Bank\MasterAccount;
use App\Bank\Payment;
use App\Classes\GenerateImaliAccount;
use App\Classes\GenerateToken;
use App\Classes\GenerateUserId;
use App\Classes\Kyc;
use App\Classes\PartnerKyc;
use App\Classes\Record;
use App\Classes\SendResponse;
use App\Classes\SendSMS;
use App\Classes\SendSMSSislog;
use App\Classes\SmsManager;
use App\Classes\TransactionGeneration;
use App\Classes\UserKyc;
use App\Credelec;
use App\GeneralAdvice;
use App\Imali\ImaliAccount;
use App\Imali\ImaliAccountConfig;
use App\Imali\MerchantAccount;
use App\Imali\MerchantContract;
use App\Imali\RechargeImaliAccount;
use App\Imali\Transfer;
use App\ImaliSubAccount;
use App\PaymentGeneration;
use App\PhoneValidation;
use App\PurchaseVoucher;
use App\Refund;
use App\Store;
use App\StoreAmountGeneration;
use App\User;
use App\UserClient;
use App\UserMobilePhone;
use App\VoucherType;
use App\Water;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
//use DB;
use SoapClient;
use SoapFault;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Spatie\ArrayToXml\ArrayToXml;

class UserClientController extends Controller
{

    protected $username;
    protected $password;
    protected $topUpUrl;

    protected $client;
    protected $msid;

    protected $request;
    protected $requestRefund;
    protected $requestRefundConfirm;
    protected $token;
    protected $generatedPayment;

    protected SmsManager $smsManager;


    public function __construct()
    {
//        TESTE
        $this->username = "TEST_PAYTEK";
        $this->password = "TESTpassPAYtek";
        $this->topUpUrl = 'https://topupretail.com:18880/Service.asmx?wsdl';

//         PRODUCTION
//        $this->username = "PAYTEK_PROD";
//        $this->password = "fs.S}nf4:IGXT|R";
//        $this->topUpUrl = 'https://topupretail.com:18873/Service.asmx?wsdl';

        $options = array(
//            'cache_wsdl' => 0,
//            'trace' => 1,
            'exceptions' => 1,
            'trace' => true,
            'keep_alive' => false,
            'connection_timeout' => 5000,
            'cache_wsdl' => WSDL_CACHE_NONE,
            'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE,
            'stream_context' => stream_context_create(array(
                'ssl' => array(
                    'verify_peer' => true,
                    'verify_peer_name' => true,
                    'allow_self_signed' => true,
//                    'ciphers'=>'RC4-SHA'
                )
            )));

        // $this->client = new SoapClient($this->topUpUrl, $options);
        // $this->msid = new TransactionGeneration();

        $this->smsManager = new SmsManager();

    }

    public function getLang()
    {
        return response()->json(['message' => trans('not_found_transaction')]);
    }

    public function checkTransactionStatus(Request $request, $transaction)
    {
        $token = str_replace('Bearer ', '', $request->header('authorization'));

        $userClient = UserClient::query()
            ->where('client_key', '=', $token)
            ->first();

	//if(!$userClient){
        //   return response()->json([
        //        'cody' => trans('error')[1]['cody'],
        //        'error' => trans('error')[1]['error'],
        //        'type' => trans('error')[1]['type'],
        //        'message' => "Invalid Client Key",
        //    ], trans('error')[1]['http_code']);
       // }

        $pay = Payment::query()
            ->with(['store', 'customer', 'account'])
            ->where('partner_transaction_id', '=', $transaction)
            ->first();


        if (!$pay) {

            $pay = Payment::query()
                ->with(['store', 'customer', 'account'])
                ->where('transaction_id', '=', $transaction)
                ->first();

            if ($pay) {

                $pay->makeHidden([
                    'id', 'qrcode', 'firebase_token', 'device_name', 'store_id', 'user_client_id', 'updated_at',
                    'imali_account_id', 'merchant_id', 'sender_id', 'store_amount_generation_id', 'category_id',
                    'estado', 'estado_color', 'transaction_id', 'token', 'token_sent', 'used_points', 'received_points',
                    'client_id', 'payment_type', 'amount_debited', 'comissao', 'payment_id'
                ]);

                if ($pay->customer) {
                    $pay->customer->makeHidden(['id', 'status', 'profile', 'email', 'birthday', 'balance_visibility', 'country_code', 'email_verified_at', 'session_status', 'firebase_token', 'user_client_id', 'phone_reference', 'terminalCompanyName', 'terminalChannel', 'terminalID', 'client_id', 'created_at', 'updated_at',
                        'info_status', 'last_name','phone','bi', 'update_info_status', 'user_update_info_status', 'document_id', 'photo', 'user_id']);
                }

                if ($pay->account) {
                    $pay->account->makeHidden(['id', 'status', 'profile', 'email', 'birthday', 'balance_visibility', 'country_code', 'email_verified_at', 'session_status', 'firebase_token', 'user_client_id', 'phone_reference', 'terminalCompanyName', 'terminalChannel', 'terminalID', 'client_id', 'created_at', 'updated_at',
                        'info_status', 'bi', 'update_info_status', 'user_update_info_status', 'document_id', 'photo', 'user_id',
                        'imali_account_config', 'captive_balance', 'balance', 'points', 'reference'
                    ]);
                }

                $pay->store->makeHidden([
                    'id', 'qrcode', 'firebase_token', 'device_name', 'store_id', 'user_client_id', 'created_at', 'updated_at',
                    'updated_at', 'user_id', 'industry_activity', 'merchant_contract_id', 'merchant_account_id',
                    'longitude', 'latitude', 'balance', 'session_status', 'photo', 'logo', 'status', 'email', 'qrcode'
                ]);

                if ($userClient->id != $pay->client_id) {
                 return response()->json(['message' => trans('not_allowed_on_store')], 400);

		//	return response()->json([
                //        'cody' => trans('error')[3]['cody'],
                 //       'error' => trans('error')[3]['error'],
                  //      'type' => trans('error')[3]['type'],
                  //      'message' => "Not allowed to transact in this store",
                  //  ], trans('error')[3]['http_code']);

                } else {
                    return response()->json($pay);

		   // return response()->json([
                   //     'cody' => trans('success')[0]['cody'],
                   //     'success' => trans('success')[0]['success'],
                   //     'type' => trans('success')[0]['type'],
                   //     'data' => $pay,
                   // ], trans('success')[0]['http_code']);
                }
            } else {

                return response()->json(['message' => trans('not_found_transaction')], 400);

		//return response()->json([
                //    'cody' => trans('error')[3]['cody'],
                //    'error' => trans('error')[3]['error'],
                //    'type' => trans('error')[3]['type'],
                //    'message' => "Transaction not found",
               // ], trans('error')[3]['http_code']);
            }

        } else {

            $pay->makeHidden([
                'id', 'qrcode', 'firebase_token', 'device_name', 'store_id', 'user_client_id', 'updated_at',
                'imali_account_id', 'merchant_id', 'sender_id', 'store_amount_generation_id', 'category_id',
                'estado', 'estado_color', 'transaction_id', 'token', 'token_sent', 'used_points', 'received_points',
                'client_id', 'payment_type', 'amount_debited', 'comissao', 'payment_id'
            ]);

            if ($pay->customer) {
                $pay->customer->makeHidden(['id', 'status', 'profile', 'email', 'birthday', 'balance_visibility', 'country_code', 'email_verified_at', 'session_status', 'firebase_token', 'user_client_id', 'phone_reference', 'terminalCompanyName', 'terminalChannel', 'terminalID', 'client_id', 'created_at', 'updated_at',
                    'info_status', 'phone','last_name','bi', 'update_info_status', 'user_update_info_status', 'document_id', 'photo', 'user_id']);
            }

            if ($pay->account) {
                $pay->account->makeHidden(['id', 'status', 'profile', 'email', 'birthday', 'balance_visibility', 'country_code', 'email_verified_at', 'session_status', 'firebase_token', 'user_client_id', 'phone_reference', 'terminalCompanyName', 'terminalChannel', 'terminalID', 'client_id', 'created_at', 'updated_at',
                    'info_status', 'bi', 'update_info_status', 'user_update_info_status', 'document_id', 'photo', 'user_id',
                    'imali_account_config', 'captive_balance', 'balance', 'points', 'reference'
                ]);
            }

            $pay->store->makeHidden([
                'id', 'qrcode', 'firebase_token', 'device_name', 'store_id', 'user_client_id', 'created_at', 'updated_at',
                'updated_at', 'user_id', 'industry_activity', 'merchant_contract_id', 'merchant_account_id',
                'longitude', 'latitude', 'balance', 'session_status', 'photo', 'logo', 'status', 'email', 'qrcode'
            ]);

            if ($userClient->id != $pay->client_id) {
                return response()->json(['message' => trans('not_allowed_on_store')], 400);

	//	return response()->json([
        //            'cody' => trans('error')[3]['cody'],
        //            'error' => trans('error')[3]['error'],
        //            'type' => trans('error')[3]['type'],
        //            'message' => "Not allowed to transact in this store.",
        //        ], trans('error')[3]['http_code']);

            } else {
                return response()->json($pay);

	//	return response()->json([
        //            'cody' => trans('success')[0]['cody'],
        //            'success' => trans('success')[0]['success'],
        //            'type' => trans('success')[0]['type'],
        //            'message' => "Transaction found",
        //            'data' => $pay,
        //        ], trans('success')[0]['http_code']);

            }
        }

    }

    public function getTransaction(Request $request, $transaction)
    {
        $token = str_replace('Bearer ', '', $request->header('authorization'));

        $userClient = UserClient::query()
            ->where('client_key', '=', $token)
            ->first();

        $pay = PaymentGeneration::query()
            ->where('payment_generations.partner_transaction_id', '=', $transaction)
            ->first();

        if (!$pay) {
            return response()->json(['message' => trans('not_found_transaction')], 400);
        } else {

            if ($userClient->id != $pay->user_client_id) {
                return response()->json(['message' => trans('not_allowed_on_store')], 400);
            } else {

                $payment = PaymentGeneration::query()
                    ->with(['store', 'customer'])
                    ->where('payment_generations.partner_transaction_id', '=', $transaction)
                    ->get();

                if ($payment) {

                    $payment->makeHidden([
                        'merchant_id', 'imali_account_id', 'user_id', 'token', 'user_client_id', 'token_sent',
                        'id', 'estado_color', 'sender_id', 'store_id', 'client_id', 'updated_at', 'category_id',
                        'stores.id', 'store.status', 'store.session_status', 'store.firebase_token', 'store.user_client_id', 'store.merchant_account_id', 'store.merchant_contract_id', 'store.industry_activity',
                        'store.user_id', 'store.created_at', 'store.updated_at', 'customer.id', 'customer.profile', 'customer.status', 'customer.email', 'customer.birthday', 'customer.balance_visibility',
                        'customer.country_code', 'customer.email_verified_at', 'customer.firebase_token', 'customer.phone_reference', 'customer.terminalCompanyName', 'customer.terminalChannel', 'customer.terminalID', 'customer.client_id', 'customer.info_status',
                        'customer.update_info_status', 'customer.user_update_info_status', 'customer.document_id', 'customer.created_at', 'customer.updated_at',
                    ]);

                    foreach ($payment as $store) {
                        $store->store->makeHidden(['id', 'status', 'session_status', 'firebase_token', 'user_client_id', 'merchant_account_id', 'merchant_contract_id', 'industry_activity', 'user_id', 'created_at', 'updated_at', 'latitude', 'longitude', 'balance']);
                        $store->customer->makeHidden(['id', 'status', 'profile', 'email', 'birthday', 'balance_visibility', 'country_code', 'email_verified_at', 'session_status', 'firebase_token', 'user_client_id', 'phone_reference', 'terminalCompanyName', 'terminalChannel', 'terminalID', 'client_id', 'created_at', 'updated_at',
                            'info_status', 'update_info_status', 'user_update_info_status', 'document_id', 'photo', 'user_id']);

                        $store->account->makeHidden(['id', 'points', 'balance', 'captive_balance', 'user_id', 'imali_account_config', 'created_at', 'updated_at']);
                    }

                    return response()->json($payment);
                } else {
                    return response()->json(['message' => trans('not_found_transaction')], 400);
                }

            }


        }


    }



	//? Metodos pagamentos de servico em real-time com BIM


    public function ckeckKYC(Request $request, $user, $paramName){

        //? Validacao do KYC
        $kyc = ImaliAccountConfig::query()->where('id', '=', $user->imali_account_config)->first();

        $amount = $request->get($paramName);
        $amount = (double)str_replace(',','.', $amount);
        
        $real_amount = ($amount / 100);
        $total_amount = $real_amount + $user->balance;

        $payments = Payment::query()
            ->join('users', 'users.id', 'payments.sender_id')
            ->join('imali_accounts', 'imali_accounts.user_id', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->select('payments.*')
            ->whereDate('payments.created_at', 'LIKE', "%".date('Y-m-d')."%")
            ->orderByDesc('created_at')
            ->get();

        $payMent = count($payments);

        $credelec = Credelec::query()
            ->join('users', 'users.id', 'credelecs.user_id')
            ->join('imali_accounts', 'imali_accounts.user_id', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->whereDate('credelecs.created_at','LIKE', "%".date('Y-m-d')."%")
            ->select('credelecs.*')
            ->orderByDesc('created_at')
            ->get();

        $credeleCT = count($credelec);

        $transferenc = Transfer::query()
            ->join('users', 'users.id', 'transfers.sender_id')
            ->join('imali_accounts', 'imali_accounts.user_id', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->whereDate('transfers.created_at', 'LIKE', "%".date('Y-m-d')."%")
            ->select('transfers.*')
            ->orderByDesc('created_at')
            ->get();

        $transferT = count($transferenc);


        $water = Water::query()
            ->join('users', 'users.id', 'waters.user_id')
            ->join('imali_accounts', 'imali_accounts.user_id', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->whereDate('waters.created_at', 'LIKE', "%".date('Y-m-d')."%")
            ->select('waters.*')
            ->orderByDesc('created_at')
            ->get();

        $waterT = count($water);


        $voucher = PurchaseVoucher::query()
            ->join('users', 'users.id', 'purchase_vouchers.user_id')
            ->join('imali_accounts', 'imali_accounts.user_id', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->whereDate('purchase_vouchers.created_at', 'LIKE', "%".date('Y-m-d')."%")
            ->select('purchase_vouchers.*')
            ->orderByDesc('created_at')
            ->get();

        $voucherT = count($voucher);


        $rechargeImali = ImaliAccount::query()
            ->join('users', 'users.id', 'imali_accounts.user_id')
            ->join('recharge_imali_accounts', 'recharge_imali_accounts.imali_account_id', 'imali_accounts.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->whereDate('recharge_imali_accounts.created_at', 'LIKE', "%".date('Y-m-d')."%")
            ->select('imali_accounts.*')
            ->orderByDesc('created_at')
            ->get();

        $rechargeT = count($rechargeImali);


        $carrementosAnuais = RechargeImaliAccount::query()
            ->join('imali_accounts', 'imali_accounts.id', 'recharge_imali_accounts.imali_account_id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->whereYear('recharge_imali_accounts.created_at', 'LIKE', "%".date('Y')."%")
            ->select('recharge_imali_accounts.*')
            ->sum('amount');

	$carrementosAnuais+=$real_amount;


        $total_transacoes = $payMent + $waterT + $credeleCT + $transferT + $voucherT + $rechargeT;
            

        //? Validacao do valor maximo por operacao
        if($kyc->max_value_operation < $real_amount) return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Utilizador sem permissão para pagamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->get($paramName), 'estado'=> 'P002']);

        if($kyc->min_value_operation > $real_amount) return response()->json(['msgid'=> 'E007', 'msgtype'=> 'E', 'msg'=> 'Montante Indicado Invalido', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->get($paramName), 'estado'=> 'P002']);

        if($total_amount > $kyc->max_balance) return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Utilizador sem permissão para pagamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->get($paramName), 'estado'=> 'P002']);
        
        if($kyc->nr_transaction <= $total_transacoes) return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Utilizador sem permissão para pagamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->get($paramName), 'estado'=> 'P002']);
                
        //? Validacao do valor maximo do carregamento Anuais
        if($kyc->max_value_year < $carrementosAnuais) return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Utilizador sem permissão para pagamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->get($paramName), 'estado'=> 'P002']);
    
        return false;
    }





    public function checkReference(Request $request)
    {

        try {
            $this->validate($request, [
                'apiKey'=> 'required',
                'codigoEntidade'=> 'required',
                'referenciaDoc'=> 'required',
                'montanteTran'=> 'required'
            ]);

        } catch (\Throwable $th) {
            return response()->json(['msgid'=> 'E005', 'msgtype'=> 'E', 'msg'=> 'Parâmetro de entrada invalido', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->montanteTran, 'estado'=> 'P002'], 400);
        }

        $amount = $request->montanteTran;
        $amount = (double)str_replace(',','.', $amount);
        // return $amount;

        $token = str_replace('Bearer ', '', $request->header('authorization'));

        if(!$token && $request->apiKey) {
            $token = $request->apiKey;
        }

        try {
            $partner = UserClient::query()
            ->where('client_key', '=', $token)
            ->first();
        } catch (\Throwable $th) {

	Log::info('[Error Check API Key]', [
            'content' => $th->getMessage(),
        ]);

            return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Erro interno de processamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);
        }
        

        if(!$partner) return response()->json(['msgid'=> 'E003', 'msgtype'=> 'E', 'msg'=> 'API Key invalida', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);

        if($amount < 20) return response()->json(['msgid'=> 'E007', 'msgtype'=> 'E', 'msg'=> 'Montante Indicado Invalido', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);
        
        //Verificar tamanho da referencia
        if(!is_numeric($request->referenciaDoc) || strlen($request->referenciaDoc) != 11) return response()->json(['msgid'=> 'E004', 'msgtype'=> 'E', 'msg'=> 'A Guia não foi encontrada', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);

        
        try {
            $user = User::query()
            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->select('users.*','imali_accounts.imali_account_config','imali_accounts.balance')
            ->first();
        } catch (\Throwable $th) {
            return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Erro interno de processamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);
        }

	if(!$user) return response()->json(['msgid'=> 'E004', 'msgtype'=> 'E', 'msg'=> 'A Guia não foi encontrada', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);
        
        //? Validacao do KYC
        if($this->ckeckKYC($request, $user,'montanteTran')) return $this->ckeckKYC($request, $user,'montanteTran');

        return response()->json(['msgid'=> 'S001', 'msgtype'=> 'S', 'msg'=> 'Validacao efectuada com sucesso', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $amount, 'estado'=> 'P002']);
    }


    //? Metodo para registar o pagamento real-time com BIM
    public function paymentRegister(Request $request){

        try {
            $this->validate($request, [
                'apiKey'=> 'required',
                'codigoEntidade'=> 'required|integer',
                'referenciaDoc'=> 'required',
                'refbancariatran'=> 'required',
                'datatransaccao'=> 'required',
                'valor'=> 'required'
            ]);

        } catch (\Throwable $th) {
            return response()->json(['msgid'=> 'E005', 'msgtype'=> 'E', 'msg'=> 'Parâmetro de entrada invalido', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->valor, 'estado'=> 'P002']);
        }

        $token = str_replace('Bearer ', '', $request->header('authorization'));

        if(!$token && $request->apiKey) {
            $token = $request->apiKey;
        }

        try {
            $partner = UserClient::query()
            ->where('client_key', '=', $token)
            ->first();
        } catch (\Throwable $th) {

	Log::info('[Error Check API Key Payment]', [
            'content' => $th->getMessage(),
        ]);

            return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Erro interno de processamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->valor, 'estado'=> 'P002']);
        }

        if(!$partner) return response()->json(['msgid'=> 'E003', 'msgtype'=> 'E', 'msg'=> 'API Key invalida', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->valor, 'estado'=> 'P002']);


        //Verificar tamanho da referencia
        if(!is_numeric($request->referenciaDoc) || strlen($request->referenciaDoc) != 11) return response()->json(['msgid'=> 'E004', 'msgtype'=> 'E', 'msg'=> 'A Guia não foi encontrada', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->valor, 'estado'=> 'P002']);

        try {
            $user = User::query()
            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
            ->where('imali_accounts.reference', $request->referenciaDoc)
            ->select('users.*','imali_accounts.imali_account_config','imali_accounts.balance', 'imali_accounts.account_number')
            ->first();
        } catch (\Throwable $th) {
            return response()->json(['msgid'=> 'E002', 'msgtype'=> 'E', 'msg'=> 'Erro interno de processamento', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->valor, 'estado'=> 'P002']);
        }

        if(!$user) return response()->json(['msgid'=> 'E004', 'msgtype'=> 'E', 'msg'=> 'A Guia não foi encontrada', 'datadoc'=> date('Y-m-d H:i:s'), 'valorTotal' => $request->valor, 'estado'=> 'P002']);
        
        
        //? Validacao do KYC
        if($this->ckeckKYC($request, $user,'valor')) return $this->ckeckKYC($request, $user,'valor');
        

        $amount = $request->valor;
        $amount = (double)str_replace(',','.', $amount);
        
        $real_amount = ($amount / 100);

        //?Processo de carregamento

        $imaliAccount = ImaliAccount::query()->where('reference', $request->referenciaDoc)->first();
        $transactionString = new TransactionGeneration();

        if ($imaliAccount) {
            $balanceActual = $imaliAccount->balance + $real_amount;

            $masterAccount = MasterAccount::find(2);
            $recharge = RechargeImaliAccount::create([
                'imali_account_id' => $imaliAccount->id,
                'transaction_id' => $transactionString->generateTransaction(),
                'bank_reference' => $request->refbancariatran,
                'bank_date' => $request->datatransaccao,
                'account_reference' => $request->referenciaDoc,
                'description' => 'Carregamento realtime via BIM',
                'amount' => $real_amount,
                'last_balance' => $imaliAccount->balance,
                'balance' => $balanceActual,
                'recharge_way' => 'MOBILE/INTERNET',
                'estado' => 'sucesso',
                'estado_color' => '#388E3C',
                'master_account_id' => $masterAccount->id
            ]);

            $masterBalance = $masterAccount->balance + $real_amount;

            $masterAccount->update(['balance' => $masterBalance]);

            if ($recharge) {

                $imaliAccount->update(['balance' => $balanceActual]);

                $notification = array(
                    //'icon' => 'ic_i_mali_cover',
		    'icon' => 'ic_imali_logo_verde_01',
                    'title' => 'Carregamento ' . $recharge->amount . ' MT',
                    'body' => 'Parabéns, ' . ' carregaste com ' . $recharge->amount . ' MT ' . ' na sua conta ' . $imaliAccount->account_number,
                    'click_action' => 'com.imali.payapp.payment_RECHARGE_DETAILS',
                    'color' => '#ffffff'
                );

                $data = array(
                    'transaction' => $recharge->transaction_id,
                    'bank_reference' => $request->refbancariatran,
                    'account_reference' => $request->account_reference,
                    'bank_date' => $request->datatransaccao,
                    'description' => $request->description,
                    'name' => $user->name,
                    'amount' => (double)$recharge->amount,
                    'phone' => $user->phone,
                    'reference' => $imaliAccount->reference,
                    'data' => $recharge->created_at,
                    'estado' => $recharge->estado,
		    'route' => 'RECHARGE_DETAILS',
                    'recharge_way' => $recharge->recharge_way,
		    'account_number' => $user->account_number,
                    'terminal' => 'firebase'
                );

                $this->pushNotifification($user->firebase_token, $notification, $data);
                $this->smsManager->sendSMSForUserRecharge($recharge);
            }

            $log = new Record();
            $log->createLog([
                'description' => $imaliAccount->account_number,
                'details' => $user->name . ' ' . $user->last_name,
                'operation' => 'Recharge by Reference',
                'status' => 'success',
                'user_id' => $user->id
            ]);

            if ($recharge) {
                return response()->json(['msgid'=> 'S011', 'msgtype'=> 'S', 'msg'=> 'Pedido processado com sucesso', 'referenciarecibo' => $request->refbancariatran, 'data'=> date('Y-m-d H:i:s')]);
            }
        }


    }



    //? Metodos pagamentos de servico em real-time com BIM





    public function getAccount(Request $request)
    {

        return response()->json($request->user()->makeHidden(['id', 'created_at', 'updated_at', 'email_verified_at', 'session_status', 'url', 'user_type'
            , 'client_key', 'status']));
    }

    public function getVoucherType()
    {
        $data = VoucherType::query()
            ->where('status', 'disponivel')
            ->where('type', 'recarga')
            ->select('name', 'code', 'type', 'logo', 'created_at', 'updated_at')
            ->get();
        return response()->json(['data' => $data], 200);
    }

    public function getUserVoucher(Request $request)
    {

        $this->validate($request, [
            'accountNumber' => 'required|min:9|max:9'
        ]);

        $token = str_replace('Bearer ', '', $request->header('authorization'));
        $clientStore = UserClient::query()->where('client_key', $token)->first();

        $kyc = new PartnerKyc();

        $result = $kyc->checkImaliAccount($request);

        if ($result) {
            return $result;
        } else {
            $user = User::query()
                ->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
                ->where('imali_accounts.account_number', $request->accountNumber)
                ->select('users.*')
                ->first();

            $data = PurchaseVoucher::query()
                ->where('user_id', $user->id)
                ->where('client_id', $clientStore->id)
                ->orderByDesc('created_at')
                ->get();

            $data->makeHidden(['id', 'user_id', 'client_id', 'voucher_list_id', 'comissao', 'transaction', 'price', 'voucherinfo']);

            return response()->json(['data' => $data], 200);
        }


    }

    public function getVoucherList()
    {
        try {
            $msid = new TransactionGeneration();
            $params = array(
                'req' => array(
                    'authCred' => array(
                        'opName' => $this->username,
                        'password' => $this->password
                    ),
                    'msgID' => $msid->generateMSID(),
                    'terminalID' => 'APP',
                    'terminalMsgID' => '202001070006'
                )
            );
            $data = json_decode(json_encode($params), true);
            $client = new SoapClient($this->topUpUrl, ['trace' => true]);
            $response = $client->VoucherList($data);

            return response()->json(['data' => $response->VoucherListResult->voucherlist->VoucherInfo]);

        } catch (SoapFault $fault) {
            echo '<br>' . $fault;
        }
    }

    public function buyVoucher(Request $request)
    {
        $this->validate($request, [
            'pin' => 'required|min:4|max:4',
            'accountNumber' => 'required',
            'voucher' => 'required',
            'transactionID' => 'required',
//            'amount' => 'required',
            'terminalID' => 'required',
            'terminalChannel' => 'required',
            'terminalCompanyName' => 'required'
        ], [
            'pin.required' => 'O Pin é Obrigatório',
            'accountNumber.required' => 'O accountNumber é Obrigatório',
            'voucher.required' => 'O voucher é Obrigatório',
            'terminalCompanyName.required' => 'O campo terminalCompanyName é Obrigatório',
            'terminalID.required' => 'terminalID é Obrigatório',
            'terminalChannel.required' => 'terminalChannel é Obrigatório',
        ]);
        $user = User::query()
            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
            ->where('imali_accounts.account_number', $request->accountNumber)
            ->first();

//        $voucherAmount = intval(preg_replace('/[^0-9]+/', '', $request->voucher), 10);

        try {

            $kyc = new PartnerKyc();

            $result = $kyc->checkPaymentVoucher($request);

            if ($result) {
                return $result;
            } else {
                $msid = new TransactionGeneration();
//                $transaction = $msid->generateMSID();
                $transaction = $this->msid->generateMSID();

                $params = array(
                    'req' => array(
                        'authCred' => array(
                            'opName' => $this->username,
                            'password' => $this->password
                        ),
                        'terminalMsgID' => '202001070006',
//                        'msgID' => $request->transactionID,
                        'msgID' => $transaction,
                        'test' => true,
                        'order' => array(
                            'VoucherOrder' => array(
                                'vouchercode' => $request->voucher,
//                                    'vouchercode' => 'VOM000010',
                                'qty' => 1
                            )
                        ),
                        'receiptFormat' => 'POR_FORMATED_50',
                        'terminalChannel' => $request->terminalChannel,
                        'terminalCompanyName' => $request->terminalCompanyName,
                        'terminalID' => $request->terminalID,
                        'terminalOperator' => 'Operator'
                    )
                );
                $data = json_decode(json_encode($params), true);

                $response = $this->client->PurchaseVoucher($data);


                $res = $response->PurchaseVoucherResult;
                $token = str_replace('Bearer ', '', $request->header('authorization'));
                $clientStore = UserClient::query()->where('client_key', $token)->first();

                if ($response->PurchaseVoucherResult->hasFault === false) {
                    $voucher = $response->PurchaseVoucherResult->vouchers->Voucher;
                    $voucherInfo = $response->PurchaseVoucherResult->vouchers->Voucher->voucherinfo;

                    $recarga = PurchaseVoucher::create([
//                        'transaction' => $response->transaction,
                        'vouchername' => $voucherInfo->vouchername,
                        'vouchercode' => $voucherInfo->vouchercode,
                        'vouchervalue' => $voucherInfo->vouchervalue,
                        'barcode' => $voucherInfo->barcode,
//                            'price' => $voucherInfo->price,
                        'price' => $voucherInfo->vouchervalue,
                        'comissao' => $voucherInfo->vouchervalue - $voucherInfo->price,
                        'reqterminalMsgID' => $res->reqterminalMsgID,
                        'reqterminalID' => $res->reqterminalID,
                        'reqMsgID' => $res->reqMsgID,
                        'respDateTime' => $res->respDateTime,
//                        'voucherinfo' => $voucherInfo,
                        'serial' => $voucher->serial,
                        'pin' => $voucher->pin,
                        'datepurchased' => $voucher->datepurchased,
                        'receiptFormat' => $voucher->receiptFormat,
                        'receipt' => $voucher->receipt,
                        'smsreceipt' => $voucher->smsreceipt,
                        'user_id' => $user->id,
                        'voucher_list_id' => null,
                        'type' => 'recarga',
                        'client_id' => $clientStore->id,
                        'terminalChannel' => $request->terminalChannel,
                        'terminalCompanyName' => $request->terminalCompanyName,
                        'terminalID' => $request->terminalID,
                    ]);

                    $imaliUser = ImaliAccount::query()->where('account_number', $request->accountNumber)->first();

                    $totalAmount = $recarga->vouchervalue + $imaliUser->taxa;

                    DB::table('imali_accounts')->where('user_id', $user->id)->decrement('balance', $totalAmount);

//                        $sms = new SendSMS();
//
//                        $sms->sendSMSPurchaseVoucher($response->PurchaseVoucherResult->vouchers->Voucher, $response->PurchaseVoucherResult->vouchers->Voucher->voucherinfo->vouchername, auth()->user()->phone);

                    $notification = array(
                        //'icon' => 'ic_i_mali_cover',
			'icon' => 'ic_imali_logo_verde_01',
                        'title' => 'iMali recargas',
                        'body' => 'Parabéns, ' . ' comprou recarga ' . $recarga->vouchername . '.' . ' i.Mali é o Futuro',
                        'click_action' => 'com.imali.payapp.payment_RECARGA_NOTIFICATION',
                        'color' => '#ffffff'
                    );

                    $data = array(
                        'reqMsgID' => $recarga->reqMsgID,
                        'vouchername' => $recarga->vouchername,
                        'vouchercode' => (double)$recarga->vouchercode,
                        'data' => $recarga->created_at,
                        'pin' => $recarga->pin,
                        'serial' => $recarga->serial,
                        'price' => $recarga->price,
                        'vouchervalue' => $recarga->vouchervalue,
                        'sms' => $recarga->receipt,
			'route' => 'RECARGA_NOTIFICATION',
                        'terminal' => 'firebase'
                    );
                    $this->pushNotifification($user->firebase_token, $notification, $data);

                    return response()->json([
                        'message' => 'Compra Feita com Sucesso!',
                        'transaction' => $request->transactionID,
//                        'data' => $response->PurchaseVoucherResult,
                        'vouchername' => $voucherInfo->vouchername,
                        'vouchercode' => $voucherInfo->vouchercode,
                        'vouchervalue' => $voucherInfo->vouchervalue,
                        'barcode' => $voucherInfo->barcode,
                        'serial' => $voucher->serial,
                        'pin' => $voucher->pin,
                    ], 200);

                } else {

                    if ($response->PurchaseVoucherResult->fault->mustALR === true) {

                        $imaliUser = ImaliAccount::query()->where('user_id', $user->id)->first();
                        $totalAmount = $request->amount + $imaliUser->taxa;
                        DB::table('imali_accounts')->where('user_id', $user->id)->increment('captive_balance', $totalAmount);

//                        return response()->json(['message' => $response->PurchaseVoucherResult], 405);

                        GeneralAdvice::create([
                            'reqMsgID' => $response->PurchaseVoucherResult->reqMsgID,
                            'reqterminalID' => $response->PurchaseVoucherResult->reqterminalID,
//                            'receiptFormat' => $response->PurchaseVoucherResult->receiptFormat,
                            'receiptFormat' => 'POR_FORMATED_50',
                            'respDateTime' => $response->PurchaseVoucherResult->respDateTime,
                            'faultNumber' => $response->PurchaseVoucherResult->fault->faultnumber,
                            'user_id' => $user->id,
                            'type' => 'direct',
//                            'amount' => $request->voucher . substr(4, 4),
                            'amount' => $request->amount,
                            'message' => $response->PurchaseVoucherResult->fault->POR_operatorMsg,
                            'msno' => $request->voucher,
                            'description' => $request->voucher,
                            'client_id' => $clientStore->id,
                            'terminalChannel' => $request->terminalChannel,
                            'terminalCompanyName' => $request->terminalCompanyName,
                            'terminalID' => $request->terminalID,
                        ]);
                        return response()->json(['message' => $response->PurchaseVoucherResult->fault->POR_operatorMsg], 405);

                    } else {
                        return response()->json(['message' => $response->PurchaseVoucherResult->fault->POR_operatorMsg], 400);
                    }

                }


            }
        } catch (SoapFault $fault) {
            echo '<br>' . $fault;
        }
    }

    public function getUserInfo($accountNumber, Request $request)
    {
        $user = User::query()
            ->join('imali_accounts', 'users.id', '=', 'imali_accounts.user_id')
            ->where('account_number', $accountNumber)
            ->first();

        $user->makeHidden(['id', 'user_id', 'client_id', 'profile', 'status', 'birthday', 'bi', 'terminalID', 'terminalChannel', 'terminalCompanyName', 'email_verified_at',
            'firebase_token', 'phone_reference', 'created_at', 'updated_at', 'imali_account_config', 'captive_balance', 'country_code', 'photo', 'email', 'points', 'phone', 'balance_visibility',
            'update_info_status', 'user_update_info_status', 'document_id', 'info_status'
        ]);
//        $token = str_replace('Bearer ', '', $request->header('authorization'));
//        $clientStore = UserClient::query()->where('client_key', $token)->first();

        $kyc = new PartnerKyc();

        $result = $kyc->checkImaliAccount($request);

        if ($result) {
            return $result;
        } else {
            return response()->json($user);
        }
    }

    public function IntegrateImaliAccount(Request $request)
    {
        $this->validate($request, [
            'accountNumber' => 'required|min:9|max:9',
            'pin' => 'required|min:4|max:4',
        ]);

        $user = User::query()
            ->join('imali_accounts', 'users.id', '=', 'imali_accounts.user_id')
            ->where('account_number', $request->accountNumber)
            ->first();

        if ($user) {
            if (Hash::check($request->pin, $user->pin)) {
                return response()->json(['message' => 'Conta verificada']);
            } else {
                return response()->json(['message' => 'Pin incorrecto'], 405);
            }
        } else {
            return response()->json(['message' => 'Conta inválida'], 400);
        }

    }

    function saveClientIntegrator(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|min:3|max:50',
            'institution' => 'required|unique:user_clients|min:3',
            'phone' => 'required|unique:user_clients|min:9|integer',
            'email' => 'required|email|unique:user_clients,email',
            'nuit' => 'required|min:9|integer',
            'description' => 'required',
        ], [
            'email.required' => 'O Campo Email é de carácter Obrigatório',
            'email.unique' => 'Este Email já está em uso',
            'phone.required' => 'O Número do celular é obrigatório',
            'phone.unique' => 'O Número do celular já está em uso',
            'phone.min' => 'O Campo Celular deve ter 9 dígitos',
            'name.required' => 'O Campo Nome é obrigatório',
            'institution.required' => 'O Campo Institution é obrigatório',
            'nuit.required' => 'O campo Nuit é Obrigatório',
            'nuit.min' => 'O campo nuit ter 9 dígitos',
            'description.required' => 'O campo descricao é obrigatório',
        ]);


        $client = UserClient::create([
            'name' => $request->name,
            'email' => $request->email,
            'phone' => $request->phone,
            'description' => $request->description,
            'institution' => $request->institution,
            'password' => Hash::make('12345678'),
            'nuit' => $request->nuit,
            'user_type' => $request->user_type
        ]);


        $token = $client->createToken('api_token')->plainTextToken;

        $client->update(['client_key' => $token]);

//        Mail::to($client->email)->send(new ImaliIntegration($client));

        return response()->json(['message' => 'Cliente Integrador Adicionado com Sucesso', 'api_token' => $token]);

    }

    public function saveToken(Request $request)
    {

        $this->validate($request, [
            'client_id' => 'required'
        ]);
        $client = UserClient::find($request->client_id);

        if ($client) {

            $token = $client->createToken('api_token')->plainTextToken;

            UserClient::query()
                ->where('id', '=', $request->client_id)
                ->update(['client_key' => $token]);

            return response()->json(['api_token' => $token]);
        } else {
            return response()->json(['message' => 'Client Not Found'], 400);
        }

    }

    public function getClients()
    {
        $users = UserClient::query()->with(['stores'=>function($query){
            return $query->leftJoin('admins', 'admins.id', '=', 'stores.user_id')
            ->leftJoin('ramo_activities', 'ramo_activities.id', '=', 'stores.industry_activity')
            ->leftJoin('merchant_contracts', 'stores.merchant_contract_id', '=', 'merchant_contracts.id')
            ->leftJoin('merchant_accounts', 'stores.merchant_account_id', '=', 'merchant_accounts.id')
		->select('stores.*', 
		'admins.name as username', 
		'ramo_activities.nome as industry', 
		'merchant_contracts.*', 
		'merchant_accounts.name as merchant_name', 
		'stores.name as store_name','stores.id as id_store');
        }])->select('user_clients.*','user_clients.Institution as institution')->get();

        return response()->json($users);
    }

    public function getStoreQrcode(Request $request, $accountNumber)
    {
        $kyc = new PartnerKyc();
        $checkKyc = $kyc->checkGetTransactions($request, $accountNumber);

        if ($checkKyc) {
            return $checkKyc;
        } else {
            $store = Store::query()
                ->where('account_number', $accountNumber)
                ->select('qrcode', 'public_id')
                ->first();
            return response()->json(['qrcode_url' => $store->qrcode, 'store_reference' => $store->public_id], 200);
        }
    }

    public function QrcodeTransaction(Request $request)
    {
        $this->validate($request, [
            'amount' => 'required',
            'accountNumber' => 'required',
            'transactionID' => 'required|min:12',
            'terminalID' => 'required',
            'terminalChannel' => 'required',
            'terminalCompanyName' => 'required'
        ], [
            'accountNumber.required' => 'O Campo accountNumber é Obrigatório',
            'transactionID.required' => 'O Campo transactionId é Obrigatório',
            'amount.required' => 'O Campo amount é Obrigatório',
            'terminalCompanyName.required' => 'O campo terminalCompanyName é Obrigatório',
            'terminalID.required' => 'terminalID é Obrigatório',
            'terminalChannel.required' => 'terminalChannel é Obrigatório',
        ]);

        $kyc = new PartnerKyc();

        $result = $kyc->checkIntegrador($request);

        if ($result) {
            $log = new Record();
            $log->createLog([
                'description' => 'Gerar Qrcode Partner',
                'details' => $request,
                'operation' => 'Falha',
                'properties' => json_encode($request->all()),
                'origin_request' => $request->url(),
                'origin_ip' => $request->ip(),
                'status' => 'error',
                'user_id' => $request->user()->id
            ]);
            return $result;
        } else {
            $checkStore = Store::query()
                ->join('merchant_accounts', 'merchant_accounts.id', '=', 'stores.merchant_account_id')
                ->where('stores.account_number', $request->accountNumber)
                ->select('stores.*', 'merchant_accounts.institution')
                ->first();
            $token = str_replace('Bearer ', '', $request->header('authorization'));
            $userClient = UserClient::query()->where('client_key', $token)->first();

            if ($checkStore) {
                if (is_numeric($request->amount)) {
                    $res = StoreAmountGeneration::create([
                        'transaction' => \Ramsey\Uuid\Uuid::uuid4(),
                        'partner_transaction_id' => $request->transactionID,
                        'amount' => $request->amount,
                        'store_id' => $checkStore->id,
                        'firebase_token' => $request->firebase_token,
                        'terminalID' => $request->terminalID,
                        'terminalChannel' => $request->terminalChannel,
                        'terminalCompanyName' => $request->terminalCompanyName,
                        'user_client_id' => $userClient->id
                    ]);
                    return response()->json(['message' => 'Transacção Gerada com Sucesso',
                        'amount' => $res->amount,
                        'transaction' => $res->transaction,
//                        'transaction' => $res->partner_transaction_id,
                        'account_number' => $checkStore->account_number,
                        'address_store' => $checkStore->address,
//                        'duration' => $res->duration,
//                        'status' => $res->status,
                        'institution' => $checkStore->institution,
                        'promo' => 'Compra Recargas com Zero Taxas no i.Mali'], 201);
                } else {
                    return response()->json(['message' => 'Introduza um montante válido'], 407);
                }
            } else
                return response()->json(['message' => 'Loja Inválida'], 404);
        }

    }

    public function Qrcode(Request $request)
    {

	try {
            $this->validate($request, [
                'amount' => 'required',
                'accountNumber' => 'required',
                'transactionID' => 'required|min:12',
                'terminalID' => 'required',
                'terminalChannel' => 'required',
                'terminalCompanyName' => 'required'
            ]);
        } catch (\Throwable $th) {
            return response()->json([
                'cody' => trans('error')[0]['cody'],
                'error' => trans('error')[0]['error'],
                'type' => trans('error')[0]['type'],
                'message' => $th->getMessage(),
            ], trans('error')[0]['http_code']);
        }

//        $this->validate($request, [
//            'amount' => 'required',
//            'accountNumber' => 'required',
//            'transactionID' => 'required|min:12',
//            'terminalID' => 'required',
//            'terminalChannel' => 'required',
//            'terminalCompanyName' => 'required'
//        ], [
//            'accountNumber.required' => 'O Campo accountNumber é Obrigatório',
//            'transactionID.required' => 'O Campo transactionId é Obrigatório',
//            'amount.required' => 'O Campo amount é Obrigatório',
//            'terminalCompanyName.required' => 'O campo terminalCompanyName é Obrigatório',
//            'terminalID.required' => 'terminalID é Obrigatório',
//            'terminalChannel.required' => 'terminalChannel é Obrigatório',
//        ]);

        $kyc = new PartnerKyc();

        $result = $kyc->checkIntegrador($request);

        if ($result) {
            $log = new Record();
            $log->createLog([
                'description' => 'Gerar Qrcode Partner',
                'details' => $request,
                'operation' => 'Falha',
                'properties' => json_encode($request->all()),
                'origin_request' => $request->url(),
                'origin_ip' => $request->ip(),
                'status' => 'error',
                'user_id' => $request->user()->id
            ]);
            return $result;
        } else {
            $checkStore = Store::query()
                ->join('merchant_accounts', 'merchant_accounts.id', '=', 'stores.merchant_account_id')
                ->where('stores.account_number', '=', $request->accountNumber)
                ->select('stores.*', 'merchant_accounts.institution')
                ->first();

            $token = str_replace('Bearer ', '', $request->header('authorization'));
            $userClient = UserClient::query()->where('client_key', $token)->first();

            if ($checkStore) {
                if (is_numeric($request->amount)) {
                    $res = Payment::create([
//                        'transaction_id' => \Ramsey\Uuid\Uuid::uuid4(),
                        'transaction_id' => $request->transactionID,
                        'partner_transaction_id' => $request->transactionID,
                        'amount' => $request->amount,
                        'store_id' => $checkStore->id,
                        'status' => 'pending',
                        'estado' => 'pending',
                        'firebase_token' => $request->firebase_token,
                        'terminalID' => $request->terminalID,
                        'terminalChannel' => $request->terminalChannel,
                        'terminalCompanyName' => $request->terminalCompanyName,
                        'client_id' => $userClient->id
                    ]);

		   return response()->json([
                        'cody' => trans('success')[1]['cody'],
                        'success' => trans('success')[1]['success'],
                        'type' => trans('success')[1]['type'],
                        'message' => "Transaction created successfully",
                        'amount' => $res->amount,
                        'transaction' => $res->transaction_id,
                        'account_number' => $checkStore->account_number,
                        'address_store' => $checkStore->address,
                        'institution' => $checkStore->institution,
                    ], trans('success')[1]['http_code']);

//                    return response()->json([
//                        'message' => trans('transaction_generated'),
//                        'amount' => $res->amount,
//                        'transaction' => $res->transaction_id,
//                        'transaction' => $res->partner_transaction_id,
//                        'account_number' => $checkStore->account_number,
//                        'address_store' => $checkStore->address,
//                        'duration' => $res->duration,
//                        'status' => $res->status,
//                        'institution' => $checkStore->institution,
//                        'promo' => trans('promo')], 201);


                } else {
//                    return response()->json(['message' => trans('insert_valid_amount')], 407);

		    return response()->json([
                        'cody' => trans('error')[0]['cody'],
                        'error' => trans('error')[0]['error'],
                        'type' => trans('error')[0]['type'],
                        'message' => "Insert a valid amont",
                    ], trans('error')[0]['http_code']);
                }
            } else
//                return response()->json(['message' => trans('invalid_store')], 404);

		return response()->json([
                    'cody' => trans('error')[3]['cody'],
                    'error' => trans('error')[3]['error'],
                    'type' => trans('error')[3]['type'],
                    'message' => "Store account number not found",
                ], trans('error')[3]['http_code']);
        }

    }

    public function getBalance($account_number)
    {
        if (is_numeric($account_number)) {
            $userBalance = ImaliAccount::query()
                ->where('account_number', $account_number)
                ->select('balance')
                ->first();

            if ($userBalance) {
                return response()->json($userBalance);
            } else {
                return response()->json(['message' => 'Conta inválida'], 400);
            }
        } else {
            return response()->json(['message' => 'Conta i.Mali contém apenas dígitos numéricos'], 400);
        }

    }

    public function addStoreToUserClient(Request $request)
    {
        $this->validate($request, [
            'store_account_number' => 'required',
            'user_client_id' => 'required',
//            'id' => 'required',
        ], [
            'account_number.required' => 'campo store_account_number é de carácter obrigatório',
//            'id.required' => 'Campo id é obrigatório',
            'user_client_id.required' => 'Campo user_client_id é obrigatório',
        ]);
        $store = Store::query()
            ->where('account_number', $request->store_account_number)
//            ->where('account_number', $request->account_number)
//            ->where('id', $request->id)
            ->first();

        $checkIntegration = Store::query()
            ->where('account_number', $request->store_account_number)
            ->where('user_client_id', $request->user_client_id)
            ->where('id', $request->id)
            ->first();

        if ($checkIntegration) {
            return response()->json(['message' => 'Está integração já foi feita!'], 400);
        } else {

            if ($store) {
                $store->update([
                    'user_client_id' => $request->user_client_id
                ]);

                return response()->json(['message' => 'Lojá integrada com Sucesso'], 200);
            } else {
                return response()->json(['message' => 'Lojá inválida'], 400);
            }

        }


    }

    public function sendToken(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'phone' => 'required|unique:users|min:9',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8',
            'password_confirmation' => 'required|min:8',
            'terminalID' => 'required',
//            'country_code' => 'required',
            'terminalChannel' => 'required',
            'terminalCompanyName' => 'required',
        ], [
            'email.required' => 'O Campo Email é de carácter Obrigatório',
            'email.unique' => 'Este Email já está em uso',
            'phone.required' => 'O Número do celular é obrigatório',
            'phone.unique' => 'O Número do celular já está em uso',
            'phone.min' => 'O Campo Celular deve ter 9 dígitos',
            'name.required' => 'O Campo Nome é obrigatório',
//            'bi.required' => 'O campo Bi é Obrigatório',
//            'bi.min' => 'O campo Bi ter 13 dígitos',
            'password.required' => 'O Campo Senha é obrigatório',
            'password.confirmed' => 'Senhas incompatíveis',
            'password.min' => 'A senha deve ter 8 digitos no mínimo',
            'terminalChannel.required' => 'terminalChannel é Obrigatório',
            'terminalID.required' => 'terminalID é Obrigatório',
            'terminalCompanyName.required' => 'terminalCompanyName é Obrigatório',
//            'country_code.required' => 'country_code é Obrigatório'
        ]);

        $token = new GenerateToken();
        $data = ['phone' => $request->country_code . $request->phone, 'codigo' => $token->generatePhoneNumberCode()];
//        $sms = new  SendSMS();
//        $sent = $sms->verifyUser($data);
//        $sislog = new SendSMSSislog();
//        $sent = $sislog->smsVerifyUser($data);

//        if ($sent) {

        $validate = PhoneValidation::query()->where('phone', $request->phone)->count();

        if ($validate === 0) {
            $save = PhoneValidation::create([
                'phone' => $request->phone,
//                'country_code' => $request->country_code,
                'country_code' => +258,
                'expire_at' => now(),
                'duration' => 5,
                'codigo' => $data['codigo'],
                'is_Validated' => 0
            ]);
            if ($save) {
                return response()->json(['codigo' => $data['codigo'], 'message' => 'Codigo de Verificação enviado com sucesso!'], 200);
            }
        } else {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->first();
            $save = $validate->update(['codigo' => $data['codigo']]);
            if ($save) {
                return response()->json(['message' => 'Codigo de Verificação enviado com sucesso!', 'codigo' => $data['codigo']], 200);
            }
        }

//        }

    }

    public function checkCodigo(Request $request)
    {
        $this->validate($request, [
            'codigo' => 'required',
            'phone' => 'required',
        ], [
//            'codigo.required' => 'O Campo Email é de carácter Obrigatório',
//            'phone.required' => 'O Número do celular é obrigatório',
        ]);

        try {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->where('codigo', $request->codigo)->count();
            $getPhone = PhoneValidation::query()->where('phone', $request->phone)->where('codigo', $request->codigo)->first();
            if ($validate > 0) {

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone,
                    'details' => 'Celular Verificado com Successo!',
                    'operation' => 'Check Phone Validation',
                    'status' => 'Success',
                    'user_id' => 1
                ]);
                $getPhone->update(['is_Validated' => 1]);
                return response()->json(['message' => 'Celular Verificado com Successo!'], 200);
            } else {

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone,
                    'details' => 'Código inválido',
                    'operation' => 'Check Phone Validation',
                    'status' => 'Error',
                    'user_id' => 1
                ]);

                return response()->json(['message' => 'Código inválido'], 400);
            }
        } catch (Exception $exception) {
            return response()->json($exception);
        }
    }

    public function registerUser(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'phone' => 'required|unique:users|min:9',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|max:8',
            'pin' => 'required|min:4|max:4',
            'terminalID' => 'required',
            'terminalChannel' => 'required',
//            'description' => 'required',
            'terminalCompanyName' => 'required',
//            'bi' => 'required|min:13'
        ], [
            'email.required' => 'O Campo Email é de carácter Obrigatório',
            'email.unique' => 'Este Email já está em uso',
            'phone.required' => 'O Número do celular é obrigatório',
            'phone.unique' => 'O Número do celular já está em uso',
            'phone.min' => 'O Campo Celular deve ter 9 dígitos',
            'name.required' => 'O Campo Nome é obrigatório',
            'bi.required' => 'O campo Bi é Obrigatório',
            'bi.min' => 'O campo Bi ter 13 dígitos',
            'password.required' => 'O Campo Senha é obrigatório',
            'password.confirmed' => 'Senhas incompatíveis',
            'password.min' => 'A senha deve ter 8 digitos no mínimo',
            'terminalChannel.required' => 'terminalChannel é Obrigatório'
        ]);

        $getPhone = PhoneValidation::query()
            ->where('phone', $request->phone)
            ->where('is_Validated', '=', 1)
            ->first();

        if (!$getPhone) {
            return response()->json(['message' => 'O Nr do Celular não confere ou Nr não validado.'], 401);
        }


        $generate = new GenerateUserId();
        $randomString = $generate->generatedUserId(30);


        $user = User::create([
            'firebase_token' => request('firebase_token'),
            'mobile_reference' => request('mobile_reference'),
            'name' => request('name'),
            'email' => request('email'),
            'phone' => request('phone'),
//            'bi' => request('bi'),
            'pin' => Hash::make(request('pin')),
            'user_id' => $randomString,
            'password' => bcrypt(request('password')),
        ]);

        $mobile = UserMobilePhone::query()
            ->where('user_id', $request->user()->id)
            ->where('firebase_token', $request->firebase_token)
            ->where('mobile_reference', $request->mobile_reference)
            ->first();

//        if (!$mobile) {
//            $mobile->create([
//                'firebase_token' => $request->firebase_token,
//                'mobile_reference' => $request->mobile_reference,
//                'user_id' => $user->id
//            ]);
//        } else {
////            $mobile->create([
////                'firebase_token' => $request->firebase_token,
////                'mobile_reference' => $request->mobile_reference,
////                'user_id' => $user->id
////            ]);
//        }

        $imali = new GenerateImaliAccount();
        $generateImaliAcount = $imali->GenerateImaliAccountNumberAndStore();
        $account = '';
        if ($generateImaliAcount) {
//            $imaliConfig = ImaliAccountConfig::find(4);
            $imaliConfig = ImaliAccountConfig::query()->first();
            $account = $user->imaliAccount()->create([
                'points' => 0,
                'user_id' => $user->id,
                'imali_account_config' => $imaliConfig->id,
                'account_number' => $generateImaliAcount,
                'reference' => $imali->generateReference(),
                'balance' => 0
            ]);
        }
        return response()->json(['message' => 'Conta Criada com Sucesso', 'accountNumber' => $account->account_number]);
    }

    public function getGeneratedPayments(Request $request, $accountNumber)
    {

        $kyc = new PartnerKyc();
        $checkKyc = $kyc->checkGetTransactions($request, $accountNumber);

        if ($checkKyc) {
            return $checkKyc;
        } else {

            $payments = Payment::query()
                ->join('stores', 'stores.id', '=', 'payments.store_id')
                ->orderByDesc('created_at')
                ->where('stores.account_number', '=', $accountNumber)
                ->whereDate('payments.created_at', '=', date('Y-m-d'))
                ->select('payments.*', 'stores.account_number as store_account_number')
                ->get();


            $payments->makeHidden([
                'id', 'user_id', 'imali_account_id', 'user_client_id', 'merchant_id',
                'store_id', 'token', 'token_sent', 'duration', 'updated_at', 'transaction_id'
            ]);

            return response()->json(['data' => $payments]);
        }

    }

    public function getStorePayments(Request $request, $accountNumber)
    {

        $kyc = new PartnerKyc();
        $checkKyc = $kyc->checkGetTransactions($request, $accountNumber);

        if ($checkKyc) {
            return $checkKyc;
        } else {

            $payment = Payment::query()
                ->join('stores', 'stores.id', '=', 'payments.store_id')
                ->join('users', 'users.id', '=', 'payments.sender_id')
                ->join('imali_accounts', 'imali_accounts.user_id', '=', 'payments.sender_id')
                ->where('payments.client_id', '=', $request->user()->id)
                ->whereDate('payments.created_at', date('Y-m-d'))
                ->orderByDesc('payments.created_at')
                ->select('payments.*', 'stores.name as store_name', 'stores.account_number as store_account_number', 'imali_accounts.account_number as imali_account', 'users.name as imali_username')
                ->get();
            $payment->makeHidden([
                'id', 'comissao', 'sender_id', 'store_id', 'client_id', 'category_id', 'estado_color', 'updated_at', 'used_points',
                'received_points'
            ]);

            return response()->json(['data' => $payment]);
        }

    }

    public function getRefunds(Request $request, $accountNumber)
    {
        $kyc = new PartnerKyc();
        $checkKyc = $kyc->checkGetTransactions($request, $accountNumber);

        if ($checkKyc) {
            return $checkKyc;
        } else {

            $payment = Payment::query()
                ->join('stores', 'stores.id', '=', 'payments.store_id')
                ->join('users', 'users.id', '=', 'payments.sender_id')
                ->join('imali_accounts', 'imali_accounts.user_id', '=', 'payments.sender_id')
                ->where('payments.client_id', '=', $request->user()->id)
                ->where('stores.account_number', '=', $accountNumber)
                ->whereDate('payments.created_at', '=', date('Y-m-d'))
                ->where('payments.payment_type', '=', 'refund')
                ->orderByDesc('payments.created_at')
                ->select('payments.*', 'stores.name as store_name', 'stores.account_number as store_account_number', 'imali_accounts.account_number as imali_account', 'users.name as imali_username', 'payments.transaction_id as payment_tarnsaction')
//                ->paginate(25)
                ->get();

            $payment->makeHidden([
                'id', 'comissao', 'sender_id', 'store_id', 'client_id', 'updated_at',
                'merchant_id', 'imali_user_id', 'user_client_id', 'payment_id', 'estado_color', 'token',
                'account_number', 'transaction_id', 'received_points', 'used_points', 'amount_credited', 'amount_debited',
                'token_sent', 'estado', 'duration', 'firebase_token', 'qrcode', 'device_name',
                'imali_account_id', 'store_amount_generation_id', 'category_id', 'payment_tarnsaction'
            ]);

            return response()->json(['data' => $payment]);
        }


    }

    public function generatePayment(Request $request)
    {
        $this->validate($request, [
            'storeAccountNumber' => 'required|min:9',
            'clientAccountNumber' => 'required|min:9',
            'transactionID' => 'required',
            'amount' => 'required',
            'terminalID' => 'required',
            'terminalChannel' => 'required',
            'description' => 'required',
            'terminalCompanyName' => 'required',
        ], [
        ]);


        $trasactionGeneration = new TransactionGeneration();
        $kyc = new PartnerKyc();
//        $checkKyc = $kyc->checkPaymentCliente($request);
        $checkKyc = $kyc->checkPaymentGeneration($request);

        $tokenGeral = '';

        if ($checkKyc) {
            return $checkKyc;
        } else {
            $this->request = $request;

            DB::transaction(function () {

                $store = DB::table('stores')->where('account_number', '=', $this->request->storeAccountNumber)->first();
                $imali = DB::table('imali_accounts')->where('account_number', '=', $this->request->clientAccountNumber)->first();
                $payerUser = DB::table('users')->where('id', $imali->user_id)->first();
                $token = str_replace('Bearer ', '', $this->request->header('authorization'));
                $clientStore = DB::table('user_clients')->where('client_key', $token)->first();

                $user = DB::table('users')->where('id', '=', $imali->user_id)->first();

                $merchant = MerchantAccount::find($store->merchant_account_id);


                $trasactionGeneration = new GenerateToken();
                $tra = new TransactionGeneration();

                $generatedToken = $trasactionGeneration->generatePhoneNumberCode();

                DB::table('payments')->insert([
//                    'transaction_id' => $tra->generateTransaction(),
                    'transaction_id' => $this->request->transactionID,
                    'partner_transaction_id' => $this->request->transactionID,
//                    'store_account_number' => $this->request->storeAccountNumber,
//                    'customer_account_number' => $this->request->clientAccountNumber,
                    'amount' => $this->request->amount,
                    'estado' => 'pending',
                    'status' => 'pending',
                    'description' => $this->request->description,
                    'token' => $generatedToken,
                    'terminalID' => $this->request->terminalID,
                    'terminalChannel' => $this->request->terminalChannel,
                    'terminalCompanyName' => $this->request->terminalCompanyName,
                    'store_id' => $store->id,
                    'merchant_id' => $merchant->id,
                    'client_id' => $clientStore->id,
                    'imali_account_id' => $imali->id,
                    'sender_id' => $imali->user_id,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);

                $data = ['phone' => $payerUser->phone, 'token' => $generatedToken];

                $this->token = $generatedToken;

                $this->smsManager->tokenPayment($data);
            });

            return response()->json(['message' => trans('otp_sent'), 'otp' => $this->token]);
        }

    }

    //? Gerar um pedido de pagamento 
    //? atraves da notificacao via PUSH

	public function generatePaymentPush(Request $request)
    {
        try {
            $this->validate($request, [
                'storeAccountNumber' => 'required',
                'clientAccountNumber' => 'required',
                'transactionID' => 'required',
                'amount' => 'required',
                'description' => 'required',
                'terminalID' => 'required',
                'terminalChannel' => 'required',
                'terminalCompanyName' => 'required',
            ],
            [
                'storeAccountNumber.required' => 'storeAccountNumber is required',

                'clientAccountNumber.required' => 'clientAccountNumber is required',

                'transactionID.required' => 'transactionID is required',
                'amount.required' => 'amount is required',
                'description.required' => 'description is required',
                'terminalID.required' => 'terminalID is required',
                'terminalChannel.required' => 'terminalChannel is required',
                'terminalCompanyName.required' => 'terminalCompanyName is required'
            ]);
        } catch (\Throwable $th) {
            //return response()->json(['error'=> $th->getMessage()], 400);
		return response()->json([
                'cody' => trans('error')[0]['cody'],
                'error' => trans('error')[0]['error'],
                'type' => trans('error')[0]['type'],
                'message' => $th->getMessage(),
            ], trans('error')[0]['http_code']);
        }

        if(!is_numeric($request->storeAccountNumber))
       // return response()->json(['error'=> 'storeAccountNumber is numeric'], 400);
	return response()->json([
            'cody' => trans('error')[0]['cody'],
            'error' => trans('error')[0]['error'],
            'type' => trans('error')[0]['type'],
            'message' => 'storeAccountNumber is numeric',
        ], trans('error')[0]['http_code']);

        if(strlen($request->storeAccountNumber) != 9) 
        //return response()->json(['error'=> 'storeAccountNumber min length is 9'], 400);
	return response()->json([
            'cody' => trans('error')[0]['cody'],
            'error' => trans('error')[0]['error'],
            'type' => trans('error')[0]['type'],
            'message' => 'storeAccountNumber min length is 9',
        ], trans('error')[0]['http_code']);

        if(!is_numeric($request->clientAccountNumber)) 
        //return response()->json(['error'=> 'clientAccountNumber is numeric'], 400);
	return response()->json([
            'cody' => trans('error')[0]['cody'],
            'error' => trans('error')[0]['error'],
            'type' => trans('error')[0]['type'],
            'message' => 'clientAccountNumber is numeric',
        ], trans('error')[0]['http_code']);

        if(strlen($request->clientAccountNumber) != 9) 
	//return response()->json(['error'=> 'clientAccountNumber min length is 9'], 400);
	return response()->json([
            'cody' => trans('error')[0]['cody'],
            'error' => trans('error')[0]['error'],
            'type' => trans('error')[0]['type'],
            'message' => 'clientAccountNumber min length is 9',
        ], trans('error')[0]['http_code']);

	$this->request =$request;
        //? Validacoes
        $token = str_replace('Bearer ', '', $this->request->header('authorization'));
        $clientStore = UserClient::query()->where('client_key', $token)->first();
        if(!$clientStore) 
	//return response()->json(['message'=> 'Invalid Client Key', 'error_code'=> 403], 403);
	return response()->json([
            'cody' => trans('error')[2]['cody'],
            'error' => trans('error')[2]['error'],
            'type' => trans('error')[2]['type'],
            'message' => 'Invalid Client Key',
        ], trans('error')[2]['http_code']);

        $store = Store::query()->where('account_number', '=', $this->request->storeAccountNumber)->first();
        if(!$store) 
	//return response()->json(['message'=> 'Store not found', 'error_code'=> 404], 404);
	return response()->json([
            'cody' => trans('error')[3]['cody'],
            'error' => trans('error')[3]['error'],
            'type' => trans('error')[3]['type'],
            'message' => 'Store not found',
        ], trans('error')[3]['http_code']);

         //? fazer a verificacao aqui...
         $imali = ImaliAccount::query()
         ->join('users', 'users.id', 'imali_accounts.user_id')
         ->where('imali_accounts.account_number', '=', $this->request->clientAccountNumber)
         ->orWhere('users.phone', '=', $this->request->clientAccountNumber)
         ->select('imali_accounts.*', 'users.phone as phone', 'users.firebase_token','users.name as nome', 'imali_accounts.user_id as user_id')
         ->first();

     if(!$imali) 
     //return response()->json(['message'=> 'invalid iMali account or phone number', 'error_code'=> 404], 404);
	return response()->json([
            'cody' => trans('error')[3]['cody'],
            'error' => trans('error')[3]['error'],
            'type' => trans('error')[3]['type'],
            'message' => 'invalid iMali account or phone number',
        ], trans('error')[3]['http_code']);	

     //? verificar auth
     if(!$imali->firebase_token) 
     //return response()->json(['message'=> 'Unauthenticated, firebase token NULL', 'error_code'=> 403], 403);
	return response()->json([
            'cody' => trans('error')[2]['cody'],
            'error' => trans('error')[2]['error'],
            'type' => trans('error')[2]['type'],
            'message' => 'Unauthenticated, firebase token NULL',
        ], trans('error')[2]['http_code']);

     $trasactionGeneration = new TransactionGeneration();
     $kyc = new PartnerKyc();
//        $checkKyc = $kyc->checkPaymentCliente($request);
     $checkKyc = $kyc->checkPaymentGeneration($request);

     $tokenGeral = '';

	if ($checkKyc) {
         return $checkKyc;
     } else {
         $this->request = $request;

         // DB::transaction(function () {

             // $client = User::query()->where('phone', $this->request->clientAccountNumber)->first();

             // $payerUser = DB::table('users')->where('id', $imali->user_id)->first();


             // $user = DB::table('users')->where('id', '=', $imali->user_id)->first();

             $merchant = MerchantAccount::find($store->merchant_account_id);


             // $trasactionGeneration = new GenerateToken();
             // $tra = new TransactionGeneration();

	DB::table('payments')->insert([
                'transaction_id' => $this->request->transactionID,
                'partner_transaction_id' => $this->request->transactionID,
                'amount' => $this->request->amount,
                'estado' => 'pending',
                'status' => 'pending',
                'description' => $this->request->description,
                'terminalID' => $this->request->terminalID,
                'terminalChannel' => $this->request->terminalChannel,
                'terminalCompanyName' => $this->request->terminalCompanyName,
                'store_id' => $store->id,
                'merchant_id' => $merchant->id,
                'client_id' => $clientStore->id,
                'imali_account_id' => $imali->id,
                'sender_id' => $imali->user_id,
                'created_at' => now(),
                'updated_at' => now(),
            ]);


            $paymentStore = Store::query()
                ->join('payments', 'payments.store_id', '=', 'stores.id')
                ->join('ramo_activities', 'ramo_activities.id', '=', 'stores.industry_activity')
                ->where('payments.transaction_id', '=', $this->request->transactionID)
                ->select('stores.name', 'stores.logo', 'stores.mobile_phone', 'stores.account_number as storeAccountNumber', 'stores.address', 'payments.transaction_id as transaction',
                'payments.amount', 'ramo_activities.nome as category', 'ramo_activities.logo as logo_category')
                ->first();


                // return $payment;
	$notification = array(
                    //'icon' => 'ic_i_mali_cover',
		    'icon' => 'ic_imali_logo_verde_01',
                    'title' => 'Pagamento iMali : ' . $this->request->transactionID,
                    'body' => $this->request->user()->name . ' gerou um pagamento de ' . $this->request->amount . ' MT',
                    'click_action' => 'com.imali.payapp.payment_PUSH_NOTIFICATION',
                    'color' => '#008577'
                );

                $data = array(
                    'transaction' => $request->transactionID,
                    'amount' => $request->amount,
                    // 'account_number' => $request->clientAccountNumber,
                    'account_number' => $paymentStore->storeAccountNumber,
                    'name' => $paymentStore->name,
                    'address' => $paymentStore->address,
                    'mobile_phone' => $paymentStore->mobile_phone,
                    //'store_account_number' => $paymentStore->storeAccountNumber,
                    'logo' => $paymentStore->logo,
                    'logo_category' => $paymentStore->logo_category,
                    'category' => $paymentStore->category,
                    'description' => $request->description,
		    'route' => 'PUSH_NOTIFICATION',
                    'created_at' => now()
                );


                $pushNotifi =  $this->pushNotifification($imali->firebase_token, $notification, $data);


                if((int)$pushNotifi['success'] === 1){
		$payment = $this->checkTransactionStatus($request, $request->transactionID);

                   $paymentStatus = $this->checkSuccessPayment($request, $payment);

                   if($paymentStatus === 'success'){

                    $payment = $this->checkTransactionStatus($request, $request->transactionID);
                    $formatedPayment = array(
                        "partnerTransactionID" => $payment->getData()->partner_transaction_id,
                        "storeAccountNumber" => $request->storeAccountNumber,
                        "customerAccountNumber" => $request->clientAccountNumber,
                        "amount" => $payment->getData()->amount,
                        "status" => $payment->getData()->status,
                        "description" => $payment->getData()->description,
                        "terminalID" => $payment->getData()->terminalID,
                        "terminalChannel" => $payment->getData()->terminalChannel,
                        "terminalCompanyName" => $payment->getData()->terminalCompanyName,
                        "createdAt" => $payment->getData()->created_at
                    );

                    //return response()->json(['message' => trans('payment_done'), 'status'=> 200, 'data'=> $formatedPayment]);
			return response()->json([
                        'cody' => trans('success')[0]['cody'],
                        'error' => trans('success')[0]['success'],
                        'type' => trans('success')[0]['type'],
                        'message' => 'Payment made successfully',
                        'data'=> $formatedPayment
                    ], trans('success')[0]['http_code']);	

                };

                if($paymentStatus === 'rejected'){
		$payment = $this->checkTransactionStatus($request, $request->transactionID);
                    $formatedPayment = array(
                        "partnerTransactionID" => $payment->getData()->partner_transaction_id,
                        "storeAccountNumber" => $request->storeAccountNumber,
                        "customerAccountNumber" => $request->clientAccountNumber,
                        "amount" => $payment->getData()->amount,
                        "status" => $payment->getData()->status,
                        "description" => $payment->getData()->description,
                        "terminalID" => $payment->getData()->terminalID,
                        "terminalChannel" => $payment->getData()->terminalChannel,
                        "terminalCompanyName" => $payment->getData()->terminalCompanyName,
                        "createdAt" => $payment->getData()->created_at
                    );

                    //return response()->json(['message' => trans('payment_rejected'), 'status'=> 401, 'data'=> $formatedPayment], 406);
			return response()->json([
                        'cody' => trans('error')[7]['cody'],
                        'error' => trans('error')[7]['error'],
                        'type' => trans('error')[7]['type'],
                        'message' => 'Payment Rejected by User',
                        'data'=> $formatedPayment
                    ], trans('error')[7]['http_code']);
                }

                if($paymentStatus === 'expired'){

                    $payment = $this->checkTransactionStatus($request, $request->transactionID);
                    $formatedPayment = array(
                        "partnerTransactionID" => $payment->getData()->partner_transaction_id,
                        "storeAccountNumber" => $request->storeAccountNumber,
                        "customerAccountNumber" => $request->clientAccountNumber,
                        "amount" => $payment->getData()->amount,
                        "status" => $payment->getData()->status,
                        "description" => $payment->getData()->description,
                        "terminalID" => $payment->getData()->terminalID,
                        "terminalChannel" => $payment->getData()->terminalChannel,
                        "terminalCompanyName" => $payment->getData()->terminalCompanyName,
                        "createdAt" => $payment->getData()->created_at
                    );

		$clientUser = User::find($request->user()->id);

                    $this->sendPush($clientUser->firebase_token, $data);

                    //return response()->json(['message' => trans('payment_expired'), 'status'=> 401, 'data'=> $formatedPayment], 408);
			return response()->json([
                        'cody' => trans('error')[4]['cody'],
                        'error' => trans('error')[4]['error'],
                        'type' => trans('error')[4]['type'],
                        'message' => 'Expired Payment',
                        'data'=> $formatedPayment
                    ], trans('error')[4]['http_code']);
                }


            } else if((int)$pushNotifi['failure'] === 1){

                //return response()->json(['message' => 'Erro ao tentar enviar push de pagamento', 'status'=> 500]);
		return response()->json([
                    'cody' => trans('warning')[0]['cody'],
                    'error' => trans('warning')[0]['warning'],
                    'type' => trans('warning')[0]['type'],
                    'message' => 'Error when trying to send payment push',
                ], trans('warning')[0]['http_code']);

                //? Colocar aqui uma mensagem a informar que o utilizador deve se autenticar na APP
            } else {
                //return response()->json(['message' => 'Erro desconhecido', 'status'=> 500]);
		return response()->json([
                    'cody' => trans('warning')[0]['cody'],
                    'error' => trans('warning')[0]['warning'],
                    'type' => trans('warning')[0]['type'],
                    'message' => 'Unknown error',
                ], trans('warning')[0]['http_code']);

            }
    	}

      }	




    public function sendPush($firebase_token, $data){
        $notification = array(
            //'icon' => 'ic_i_mali_cover',
	    'icon' => 'ic_imali_logo_verde_01',
            // 'title' => 'Pagamento de ' . $this->request->transactionID . ' pendente',
            'title' => 'Pagamento iMali : ',
            'body' =>  ' gerou um pagamento de MT',
            'click_action' => 'com.imali.payapp.payment_TARGET_NOTIFICATION',
            'color' => '#008577'
        );


        $this->pushNotifification($firebase_token, $notification, $data);
    }


    //? Recusar pagamento por push

    public function denyPaymentPush(Request $request){


            $this->validate($request, [
                'transaction' => 'required',
            ]);

            $imali = ImaliAccount::query()
            ->where('user_id', $request->user()->id)
            ->first();

                // $PayTransaction = DB::table('payments')->where('partner_transaction_id', $request->transaction)->get();

                $payTransaction = Payment::query()->where('partner_transaction_id', $request->transaction)->first();

                if(($payTransaction && $payTransaction->status === 'rejected') || ($payTransaction && $payTransaction->status === 'expired') || ($payTransaction && $payTransaction->status === 'success')){

                    //return response()->json(['message' => trans('payment_invalid'), 'status'=> 401], 406);
		    return response()->json([
                        'cody' => trans('error')[0]['cody'],
                        'error' => trans('error')[0]['error'],
                        'type' => trans('error')[0]['type'],
                        'message' => trans('payment_invalid'),
                    ], trans('error')[0]['http_code']);
                }

                if($payTransaction){
                    $payTransaction->update([
                        'estado' => 'rejected',
                        'status' => 'rejected',
                        'description' => 'Pagamento rejeitado por ' . $request->user()->name,
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);
                

            $notification = array(
//                'icon' => 'ic_i_mali_cover',
                'icon' => 'ic_imali_logo_verde_01',
                'title' => 'Pedido Recusado',
                'body' => $request->user()->name . ' rejeitou pagamento de ' . $payTransaction->amount . ' MT',
//                'click_action' => 'com.imali.payapp.payment_TARGET_NOTIFICATION',
                'click_action' => 'com.imali.payapp.payment_NOTICIA',
//                'color' => '#008577'
                'color' => '#fff'
            );


            $data = array(
                'id' => $payTransaction->id,
                'name' => $request->user()->name,
                'client_id' => $payTransaction->client_id,
                'user_id' => $request->user()->id,
                'amount' => $payTransaction->amount,
                'account_number' => $imali->account_number,
                'sms' => $request->user()->name . ' rejeitou pagamento de ' . $payTransaction->amount . ' MT',
                'phone' => $request->user()->phone,
                'description' => $payTransaction->description,
		'route' => 'NOTICIA',
                'terminal' => 'firebase'
            );


            $clientUser = User::find($request->user()->id);

            $this->pushNotifification($clientUser->firebase_token, $notification, $data);

           //return response()->json(['message' => trans('payment_rejected'), 'status'=> 200]);
	    return response()->json([
                'cody' => trans('success')[0]['cody'],
                'error' => trans('success')[0]['success'],
                'type' => trans('success')[0]['type'],
                'message' => trans('payment_rejected'),
            ], trans('success')[0]['http_code']);
        }
    }


    public function checkSuccessPayment($request, $payment){
        
        $payment = $this->checkTransactionStatus($request, $request->transactionID);

        $payTransaction2 = Payment::query()->where('partner_transaction_id', $request->transactionID)->first();

            if($payment->getData()->status === "pending"){
            
               $diffTime = (int) (time() - strtotime($payment->getData()->created_at));

               // Delay da transacao 40 secundos
               if($diffTime >= 40){
                    $payTransaction2->update([
                        'estado' => 'expired',
                        'status' => 'expired',
                        'description' => 'Pagamento expirado',
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);
               }

            return $this->checkSuccessPayment($request, $payment);
            } else if($payment->getData()->status === "rejected"){
                return "rejected";
            } if($payment->getData()->status === "expired"){
                return "expired";
            } else {
                return "success";
            }
    }

    public function makePayment(Request $request)
    {
        $this->validate($request, [
            'token' => 'required|min:6',
            'partner_transaction_id' => 'required',
        ], [
            'token.required' => trans('token_required'),
            'partner_transaction_id.required' => trans('partner_transaction_id_required'),
        ]);

        $kyc = new PartnerKyc();
        $checkKyc = $kyc->confirmPayment($request);

        if ($checkKyc) {
            return $checkKyc;
        } else {
            $generatedPayment = Payment::query()->where('partner_transaction_id', '=', $request->partner_transaction_id)->first();

            $this->generatedPayment = $generatedPayment;
            $this->request = $request;

            if ($generatedPayment) {

                DB::transaction(function () {

                    $store = DB::table('stores')->where('id', $this->generatedPayment->store_id)->first();
                    $imali = DB::table('imali_accounts')->where('user_id', $this->generatedPayment->sender_id)->first();
                    $imaliConfig = DB::table('imali_account_configs')->where('id', $imali->imali_account_config)->first();

                    $valorAPagar = $this->generatedPayment->amount + $imaliConfig->taxa;
                    $points = round($valorAPagar);

                    // Payer or Sender Section
                    DB::table('imali_accounts')->where('user_id', $this->generatedPayment->user_id)->decrement('balance', $valorAPagar);
                    DB::table('imali_accounts')->where('user_id', $this->generatedPayment->user_id)->increment('points', $points);

                    $contractoComerciante = DB::table('merchant_contracts')->where('store_id', $this->generatedPayment->store_id)->first();

                    $taxaDesconto = $valorAPagar * ($contractoComerciante->taxa) / 100;

                    $valorMin = $contractoComerciante->min_amount;
                    $valorMax = $contractoComerciante->max_amount;

                    if ($taxaDesconto < $valorMin) {
                        $taxaDesconto = $valorMin;
                    }
                    if ($taxaDesconto > $valorMax) {
                        $taxaDesconto = $valorMax;
                    }

                    $valorFinal = $valorAPagar - $taxaDesconto;

                    // Recever User Merchante
                    DB::table('stores')->where('account_number', $this->generatedPayment->store_account_number)->increment('balance', $valorFinal);


//                    DB::table('payments')->insert([
//                        'transaction_id' => $this->generatedPayment->transaction_id,
//                        'partner_transaction_id' => $this->generatedPayment->partner_transaction_id,
//                        'sender_id' => $this->generatedPayment->user_id,
//                        'store_id' => $this->generatedPayment->store_id,
//                        'client_id' => $this->generatedPayment->user_client_id,
//                        'received_points' => $this->generatedPayment->amount,
//                        'amount' => $this->generatedPayment->amount,
//                        'amount_credited' => $valorFinal,
//                        'comissao' => $taxaDesconto,
//                        'description' => $this->generatedPayment->description,
//                        'used_points' => 0,
//                        'estado' => 'pago',
//                        'estado_color' => '#388E3C',
//                        'payment_type' => 'directo',
//                        'terminalID' => $this->generatedPayment->terminalID,
//                        'terminalChannel' => $this->generatedPayment->terminalChannel,
//                        'terminalCompanyName' => $this->generatedPayment->terminalCompanyName,
//                        'created_at' => now(),
//                        'updated_at' => now()
//                    ]);

                    DB::table('payments')
                        ->where('partner_transaction_id', $this->request->partner_transaction_id)
                        ->update([
                            'received_points' => $this->generatedPayment->amount,
                            'amount_credited' => $this->generatedPayment->amount - $taxaDesconto,
                            'amount_debited' => $valorAPagar,
                            'comissao' => $taxaDesconto,
                            'description' => $this->generatedPayment->description,
                            'used_points' => 0,
                            'estado' => 'success',
                            'status' => 'success',
                            'estado_color' => '#388E3C',
                            'payment_type' => 'directo',
                            'updated_at' => now()
                        ]);

                    $payerUser = DB::table('users')->where('id', $imali->user_id)->first();

                    $trasactionGeneration = new TransactionGeneration();
                    $transaction = $trasactionGeneration->generateTransaction();

                    $actualPoints = $imali->points + $points;

                    $createTransaction = DB::table('payments')->where('transaction_id', $this->generatedPayment->transaction_id)->first();

                    DB::table('history_payments')->insert([
                        'sender_account' => $imali->account_number,
                        'sender_name' => $payerUser->name,
                        'amount_credited' => $valorFinal,
                        'status_user' => 'sender',
                        'status' => 'done',
                        'comissao' => $taxaDesconto,
                        'amount' => $valorAPagar,
                        'user_id' => $payerUser->id,
                        'actual_points' => $actualPoints,
                        'last_points' => $imali->points,
                        'win_points' => $points,
                        'transaction_id' => $transaction,
                        'payment_id' => $createTransaction->id,
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);

                    DB::table('profits')->insert([
                        'payer_id' => $payerUser->id,
                        'payer_account' => $store->account_number,
                        'amount' => $valorAPagar,
                        'amount_credited' => $valorFinal,
                        'comissao' => $taxaDesconto,
                        'profit_id' => $trasactionGeneration->generateTransaction(),
                        'payment_id' => $createTransaction->id,
                        'profit_payer_id' => $createTransaction->store_id,
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);

                    DB::table('payment_generations')
                        ->where('transaction_id', $this->generatedPayment->transaction_id)
                        ->update(['status' => 'success', 'updated_at' => now()]);

                    DB::table('payment_generation_confirmations')->insert([
                        'payment_generation_id' => $this->generatedPayment->id,
                        'payment_id' => $createTransaction->id,
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);

                    $result = json_decode(json_encode($createTransaction), true);
                    $this->smsManager->sendMessageToClientePayment($result);

//                        $sms->sendMessageToComerciante($createTransaction);
//                    $sms->sendMessageToClientePayment($payerUser);
//                        Mail::to($store->email)->send(new PagamentoConfirmado($createTransaction));
//                        Mail::to($payerUser->email)->send(new Pagamento($createTransaction));

                    $log = new Record();

                    $log->createLog([
                        'description' => 'Pagamento na loja do comerciante',
                        'details' => 'Pagamento Feito com Sucesso',
                        'operation' => 'Payment',
                        'properties' => json_encode($createTransaction),
                        'status' => 'Success',
                        'user_id' => $this->generatedPayment->user_id
                    ]);

                }, 5);

            }

        }

        return response()->json(['message' => trans('payment_done')]);
    }

    public function makePaymentOlD(Request $request)
    {
        $this->validate($request, [
            'storeAccountNumber' => 'required|min:9',
            'clientAccountNumber' => 'required|min:9',
            'transactionID' => 'required',
            'amount' => 'required',
            'pin' => 'required|min:4|max:4',
//            'apiKey' => 'required',
            'terminalID' => 'required',
            'terminalChannel' => 'required',
            'description' => 'required',
            'terminalCompanyName' => 'required',
            'usedPoints' => 'required'
        ], [
            'clientAccountNumber.required' => 'O Campo clientAccountNumber é de carácter Obrigatório',
            'storeAccountNumber.required' => 'O Campo storeAccountNumber é de carácter Obrigatório',
            'storeAccountNumber.min' => 'O Campo storeAccountNumber deve ter 9 dígitos',
            'clientAccountNumber.min' => 'O Campo clientAccountNumber deve ter 9 dígitos',
            'transactionID.required' => 'O campo transactionID é obrigatório',
            'pin.required' => 'O pin é obrigatório',
            'pin.max' => 'O pin deve ter 4 digitos',
            'pin.min' => 'O pin deve ter 4 digitos',
            'terminalCompanyName.required' => 'O campo terminalCompanyName é Obrigatório',
            'terminalID.required' => 'terminalID é Obrigatório',
            'amount.required' => 'O Campo amount é obrigatório',
            'apiKey.required' => 'apiKey é obrigatória',
            'description.required' => 'Descrição de Pagamento é obrigatória',
            'usedPoints.required' => 'usedPoints é obrigatória'
        ]);

        $trasactionGeneration = new TransactionGeneration();
        $kyc = new PartnerKyc();
        $checkKyc = $kyc->checkPaymentCliente($request);

        if ($checkKyc) {
            return $checkKyc;
        } else {
            $store = Store::query()->where('account_number', '=', $request->storeAccountNumber)->first();
            $imali = ImaliAccount::query()->where('account_number', '=', $request->clientAccountNumber)->first();
            $payerUser = User::query()->where('id', $imali->user_id)->first();
            $store = Store::query()->where('account_number', $request->storeAccountNumber)->first();
            $token = str_replace('Bearer ', '', $request->header('authorization'));
            $clientStore = UserClient::query()->where('client_key', $token)->first();

            $payer_id = $payerUser->id;
            $imali = ImaliAccount::query()->where('user_id', $payer_id)->first();

            $valorAPagar = $request->amount;
            $points = round($valorAPagar);

            // Payer or Sender Section
            DB::table('imali_accounts')->where('user_id', $payer_id)->decrement('balance', $valorAPagar);
            DB::table('imali_accounts')->where('user_id', $payer_id)->increment('points', $points);

            $contractoComerciante = MerchantContract::query()->where('store_id', $store->id)->first();

            $taxaDesconto = $valorAPagar * ($contractoComerciante->taxa) / 100;

            $valorMin = $contractoComerciante->min_amount;
            $valorMax = $contractoComerciante->max_amount;

            if ($taxaDesconto < $valorMin) {
                $taxaDesconto = $valorMin;
            }
            if ($taxaDesconto > $valorMax) {
                $taxaDesconto = $valorMax;
            }

//                $valorFinal = $valorAPagar - $valorAPagar*($contractoComerciante->taxa)/100;
            $valorFinal = $valorAPagar - $taxaDesconto;

            // Recever User Merchante
            DB::table('stores')->where('account_number', $store->account_number)->increment('balance', $valorFinal);

//                $profit = $valorAPagar*($contractoComerciante->taxa)/100;

            $transaction = $trasactionGeneration->generateTransaction();

            $createTransaction = Payment::create([
                'transaction_id' => $request->transactionID,
                'sender_id' => $payer_id,
                'store_id' => $store->id,
                'client_id' => $clientStore->id,
                'received_points' => $points,
                'amount' => $valorAPagar,
                'amount_credited' => $valorFinal,
                'comissao' => $taxaDesconto,
                'description' => $request->description,
                'used_points' => $request->usedPoints,
                'estado' => 'pago',
                'estado_color' => '#388E3C',
                'terminalID' => $request->terminalID,
                'terminalChannel' => $request->terminalChannel,
                'terminalCompanyName' => $request->terminalCompanyName,
                'created_at' => now(),
                'updated_at' => now()
            ]);

            $actualPoints = $imali->points + $points;
            $createTransaction->paymentHistoric()->create([
                'sender_account' => $imali->account_number,
                'sender_name' => $payerUser->name,
                'amount_credited' => $valorFinal,
                'status_user' => 'sender',
                'status' => 'done',
                'comissao' => $taxaDesconto,
                'amount' => $valorAPagar,
                'user_id' => $payerUser->id,
                'actual_points' => $actualPoints,
                'last_points' => $imali->points,
                'win_points' => $points,
                'transaction_id' => $transaction
            ]);

            $saveProfit = $createTransaction->profit()->create([
                'payer_id' => $payer_id,
                'payer_account' => $store->account_number,
                'amount' => $valorAPagar,
                'amount_credited' => $valorFinal,
                'comissao' => $taxaDesconto,
                'profit_id' => $trasactionGeneration->generateTransaction(),
                'payment_id' => $createTransaction->id,
                'profit_payer_id' => $createTransaction->store_id
            ]);

            $this->smsManager->sendSMSToComerciante($createTransaction);
//                        $sms->sendMessageToComerciante($createTransaction);
//                    $sms->sendMessageToClientePayment($payerUser);
//                        Mail::to($store->email)->send(new PagamentoConfirmado($createTransaction));
//                        Mail::to($payerUser->email)->send(new Pagamento($createTransaction));

            $log = new Record();
            $log->createLog([
                'description' => $imali->account_number . ' - ' . $store->name,
                'details' => 'Pagamento Feito com Sucesso',
                'operation' => 'Payment',
                'status' => 'Success',
                'user_id' => $request->user()->id
            ]);

            return response()->json(['message' => 'Pagamento Feito com Sucesso!',
//                'transaction' => $transaction,
                'transaction' => $createTransaction->transaction_id,
                'amount' => $createTransaction->amount,
                'created_at' => $createTransaction->created_at,
                'duration' => 3000
            ], 200);

        }

    }

    public function makePayment2(Request $request)
    {
//        $user = User::find($request->user()->id);
        $user = User::query()
            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
            ->where('imali_accounts.account_number', '=', $request->account_number)
            ->select('users.*')
            ->first();

        if (Hash::check($request->pin, $user->pin)) {
            $trasactionGeneration = new TransactionGeneration();

//            $payerUser = User::query()->where('user_id', $request->user()->user_id)->first();
            $payerUser = User::query()->where('user_id', $user->user_id)->first();
            $store = Store::query()->where('account_number', $request->store_account_number)->first();
            $payer_id = $payerUser->id;

            $imali = ImaliAccount::query()->where('user_id', $payer_id)->first();
            $kyc = new Kyc();

            $kycCheck = $kyc->checkSenderPayment($request);
            $kyc = new PartnerKyc();
            $checkKYC = $kyc->checkPaymentCliente($request);

            if ($kycCheck) {

                $log = new Record();
                $log->createLog([
                    'description' => $imali->account_number . ' ' . $store->name,
                    'details' => $kycCheck,
                    'operation' => 'Payment',
                    'status' => 'Error',
                    'user_id' => $request->user()->id
                ]);

                return $kycCheck;
            } else {
                if ($payerUser) {
                    if ($imali->balance < $request->amount) {

                        $log = new Record();
                        $log->createLog([
                            'description' => $imali->account_number . ' ' . $store->name,
                            'details' => 'Saldo Insuficiente',
                            'operation' => 'Payment',
                            'status' => 'Error',
                            'user_id' => $request->user()->id
                        ]);

                        return response()->json(['message' => 'Saldo insuficiente', 'class' => 'error'], 402, [], JSON_NUMERIC_CHECK);
                    } else {
                        $valorAPagar = $request->amount;
                        $points = round($valorAPagar);

                        // Payer or Sender Section
                        DB::table('imali_accounts')->where('user_id', $payer_id)->decrement('balance', $valorAPagar);
                        DB::table('imali_accounts')->where('user_id', $payer_id)->increment('points', $points);

                        $contractoComerciante = MerchantContract::query()->where('store_id', $store->id)->first();

                        $taxaDesconto = $valorAPagar * ($contractoComerciante->taxa) / 100;

                        $valorMin = $contractoComerciante->min_amount;
                        $valorMax = $contractoComerciante->max_amount;

                        if ($taxaDesconto < $valorMin) {
                            $taxaDesconto = $valorMin;
                        }
                        if ($taxaDesconto > $valorMax) {
                            $taxaDesconto = $valorMax;
                        }

//                $valorFinal = $valorAPagar - $valorAPagar*($contractoComerciante->taxa)/100;
                        $valorFinal = $valorAPagar - $taxaDesconto;

                        // Recever User Merchante
                        DB::table('stores')->where('account_number', $store->account_number)->increment('balance', $valorFinal);

//                $profit = $valorAPagar*($contractoComerciante->taxa)/100;

                        $transaction = $trasactionGeneration->generateTransaction();

                        $createTransaction = Payment::create([
                            'transaction_id' => $transaction,
                            'sender_id' => $payer_id,
                            'store_id' => $store->id,
                            'received_points' => $points,
                            'amount' => $valorAPagar,
                            'amount_credited' => $valorFinal,
                            'comissao' => $taxaDesconto,
                            'description' => $request->description,
                            'used_points' => $request->used_points,
                            'estado' => 'pago',
                            'estado_color' => '#388E3C',
                            'created_at' => now(),
                            'updated_at' => now()
                        ]);

                        $actualPoints = $imali->points + $points;
                        $createTransaction->paymentHistoric()->create([
                            'sender_account' => $imali->account_number,
                            'sender_name' => $payerUser->name,
                            'amount_credited' => $valorFinal,
                            'status_user' => 'sender',
                            'status' => 'done',
                            'comissao' => $taxaDesconto,
                            'amount' => $valorAPagar,
                            'user_id' => $payerUser->id,
                            'actual_points' => $actualPoints,
                            'last_points' => $imali->points,
                            'win_points' => $points,
                            'transaction_id' => $transaction
                        ]);

                        $saveProfit = $createTransaction->profit()->create([
                            'payer_id' => $payer_id,
                            'payer_account' => $store->account_number,
                            'amount' => $valorAPagar,
                            'amount_credited' => $valorFinal,
                            'comissao' => $taxaDesconto,
                            'profit_id' => $trasactionGeneration->generateTransaction(),
                            'payment_id' => $createTransaction->id,
                            'profit_payer_id' => $createTransaction->store_id
                        ]);
                        if ($saveProfit) {

//                        $sms = new SendSMS();
//                        $sms->sendMessageToClientePayment($createTransaction);
//                        $sms->sendMessageToComerciante($createTransaction);
//                    $sms->sendMessageToClientePayment($payerUser);
//                        Mail::to($store->email)->send(new PagamentoConfirmado($createTransaction));
//                        Mail::to($payerUser->email)->send(new Pagamento($createTransaction));

                            $log = new Record();
                            $log->createLog([
                                'description' => $imali->account_number . ' ' . $store->name,
                                'details' => 'Pagamento Feito com Sucesso',
                                'operation' => 'Payment',
                                'status' => 'Success',
                                'user_id' => $request->user()->id
                            ]);

                            return response()->json(['message' => 'Pagamento Feito com Sucesso!',
                                'transaction' => $transaction,
                                'created_at' => $createTransaction->created_at,
                                'duration' => 3000
                            ], 200);
                        }
                    }
                }
            }
        } else {
            return response()->json(['message' => 'Pin Incorrecto'], 400);
        }
    }

    public function refundCustomerNew(Request $request)
    {

	try {
            $this->validate($request, [
                'amount' => 'required',
                'description' => 'required',
                'customerAccountNumber' => 'required',
                'storeAccountNumber' => 'required',
                'paymentTransaction' => 'required',
                'partnerTransactionID' => 'required|min:12',
                'terminalID' => 'required',
                'terminalChannel' => 'required',
                'terminalCompanyName' => 'required',
            ]);
        } catch (\Throwable $th) {
            return response()->json([
                'cody' => trans('error')[0]['cody'],
                'error' => trans('error')[0]['error'],
                'type' => trans('error')[0]['type'],
                'message' => $th->getMessage(),
            ], trans('error')[0]['http_code']);
        }

//        $this->validate($request, [
//            'amount' => 'required',
//            'description' => 'required',
//            'customerAccountNumber' => 'required',
//            'storeAccountNumber' => 'required',
//            'paymentTransaction' => 'required',
//            'partnerTransactionID' => 'required|min:12',
//            'terminalID' => 'required',
//            'terminalChannel' => 'required',
//            'terminalCompanyName' => 'required',
//        ]);

        $kyc = new PartnerKyc();
        $kycCheck = $kyc->checkMerchantRefund($request);

        if ($kycCheck) {
            return $kycCheck;
        } else {
            $this->requestRefund = $request;

            DB::transaction(function () {

                $imaliUser = DB::table('imali_accounts')
                    ->join('users', 'users.id', '=', 'imali_accounts.user_id')
                    ->where('account_number', $this->requestRefund->customerAccountNumber)
                    ->select('users.*', 'imali_accounts.id as imali_account_id')
                    ->first();

                $merchant = DB::table('merchant_accounts')
                    ->join('stores', 'stores.merchant_account_id', '=', 'merchant_accounts.id')
                    ->where('stores.account_number', $this->requestRefund->storeAccountNumber)
                    ->select('merchant_accounts.*', 'stores.balance as store_balance', 'stores.id as store_id')
                    ->first();

                $imaliConfig = DB::table('imali_account_configs')
                    ->where('id', $merchant->kyc_config_id)
                    ->first();

                $loja = Store::query()->where('account_number', '=', $this->requestRefund->storeAccountNumber)->first();

                $payment = Payment::query()
                    ->where('transaction_id', '=', $this->requestRefund->paymentTransaction)
                    ->first();

                $generation = new GenerateToken();

                $token = $generation->generatePhoneNumberCode();

                DB::table('payments')->insert([
//                    'transaction_id' => $this->msid->generateTransaction(),
                    'transaction_id' => $this->requestRefund->partnerTransactionID,
                    'partner_transaction_id' => $this->requestRefund->partnerTransactionID,
                    'amount' => $this->requestRefund->amount,
                    'comissao' => $imaliConfig->taxa_refund_mechant,
                    'amount_debited' => $this->requestRefund->amount + $imaliConfig->taxa_refund_mechant,
                    'amount_credited' => $this->requestRefund->amount,
//                    'account_number' => $this->requestRefund->customerAccountNumber,
                    'description' => $this->requestRefund->description,
                    'store_id' => $merchant->store_id,
                    'sender_id' => $imaliUser->id,
                    'imali_account_id' => $imaliUser->imali_account_id,
                    'payment_id' => $payment->id,
                    'estado' => 'pending',
                    'status' => 'pending',
                    'payment_type' => 'refund',
                    'token' => $token,
                    'merchant_id' => $merchant->id,
                    'client_id' => $this->requestRefund->user()->id,
                    'terminalCompanyName' => $this->requestRefund->terminalCompanyName,
                    'terminalChannel' => $this->requestRefund->terminalChannel,
                    'terminalID' => $this->requestRefund->terminalID,
                    'created_at' => now(),
                    'updated_at' => now()
                ]);

                $data = ['phone' => $merchant->phone_number, 'token' => $token];

                $this->token = $token;
                $this->smsManager->tokenPayment($data);
            });

//            return response()->json(['message' => trans('otp_sent'), 'token' => $this->token]);

	    return response()->json([
                'cody' => trans('success')[1]['cody'],
                'success' => trans('success')[1]['success'],
                'type' => trans('success')[1]['type'],
                'message' => "OTP successfully sent",
                'token' => $this->token
            ], trans('success')[1]['http_code']);
        }
    }

    public function confirmRefund(Request $request)
    {

	try {
            $this->validate($request, [
                'partner_transaction_id' => 'required|min:12',
                'token_otp' => 'required'
            ]);
        } catch (\Throwable $th) {
            return response()->json([
                'cody' => trans('error')[0]['cody'],
                'error' => trans('error')[0]['error'],
                'type' => trans('error')[0]['type'],
                'message' => $th->getMessage(),
            ], trans('error')[0]['http_code']);
        }

//        $this->validate($request, [
//            'partner_transaction_id' => 'required|min:12',
//            'token_otp' => 'required'
//        ]);

        $kyc = new PartnerKyc();
        $kycCheck = $kyc->checkConfirmRefund($request);

        if ($kycCheck) {
            return $kycCheck;
        } else {

            $this->requestRefundConfirm = $request;
            DB::transaction(function () {

//                $refund = DB::table('refunds')
//                    ->where('partner_transaction_id', $this->requestRefundConfirm->partner_transaction_id)
//                    ->first();

                $refund = DB::table('payments')
                    ->where('partner_transaction_id', $this->requestRefundConfirm->partner_transaction_id)
                    ->first();

//                DB::table('payments')
  //                  ->where('partner_transaction_id', $this->requestRefundConfirm->partner_transaction_id)
    //                ->update([
      //                  'received_points' => 0,
          //              'used_points' => 0,
        //                'estado' => 'success',
            //            'status' => 'success',
              //          'updated_at' => now()
                //    ]);

                $merchant = DB::table('merchant_accounts')
                    ->join('stores', 'stores.merchant_account_id', '=', 'merchant_accounts.id')
                    ->where('stores.id', $refund->store_id)
                    ->select('merchant_accounts.*', 'stores.balance as store_balance')
                    ->first();

                $loja = DB::table('stores')->where('id', '=', $refund->store_id)->first();

                $imaliConfig = ImaliAccountConfig::find($merchant->kyc_config_id);

                $payment = DB::table('payments')->where('id', $refund->payment_id)->first();

                $user = DB::table('users')->where('id', $refund->sender_id)->first();
                $imali = DB::table('imali_accounts')->where('user_id', $refund->sender_id)->first();

                DB::table('imali_accounts')->where('user_id', $refund->sender_id)->increment('balance', $refund->amount);
//                DB::table('merchant_accounts')->where('id', $refund->merchant_id)->increment('balance', $refund->amount + $imaliConfig->taxa_refund_mechant);
                DB::table('merchant_accounts')->where('id', $refund->merchant_id)->decrement('balance', $refund->amount + $imaliConfig->taxa_refund_mechant);


		$imali2 = DB::table('imali_accounts')->where('user_id', $refund->sender_id)->first();

                DB::table('payments')
                    ->where('partner_transaction_id', $this->requestRefundConfirm->partner_transaction_id)
                    ->update([
                        'received_points' => 0,
                        'used_points' => 0,
                        'estado' => 'success',
                        'status' => 'success',
                        'updated_at' => now(),
                        'old_balance' => $imali->balance,
                        'new_balance' => $imali2->balance,
                    ]);


                $tran = new TransactionGeneration();

                DB::table('profits')->insert([
                    'payer_id' => $user->id,
                    'payer_account' => $loja->account_number,
                    'amount' => $refund->amount,
                    'amount_credited' => $refund->amount + $imaliConfig->taxa_refund_mechant,
                    'comissao' => $imaliConfig->taxa_refund_mechant,
                    'profit_id' => $tran->generateTransaction(),
                    'payment_id' => $payment->id,
                    'profit_payer_id' => $payment->store_id,
                    'created_at' => now(),
                    'updated_at' => now()
                ]);

//                DB::table('refunds')
//                    ->where('transaction', $refund->transaction)
//                    ->update(['estado' => 'successo', 'updated_at' => now()]);

                $notification = array(
                    'icon' => 'ic_imali_logo_verde_01',
//                            'icon' => 'ic_i_mali_cover',
                    'title' => 'Recebeste ' . $refund->amount . ' MT',
                    'body' => 'Parabéns, ' . ' recebeste reembolso ' . $refund->amount . ' MT ' . ' da loja ' . $loja->name,
                    'click_action' => 'com.imali.payapp.payment_PAGAR_NOTIFICATION',
//                            'color' => '#008577'
                    'color' => '#ffffff'
                );


                $data = array(
                    'transaction' => $refund->transaction_id,
                    'loja' => $loja->name,
                    'loja_account' => $loja->account_number,
                    'pontos' => $payment->received_points,
                    'pontos_usados' => $payment->used_points,
                    'amount' => (double)$refund->amount,
                    'amount_debited' => (double)$refund->amount,
                    'account_number' => (int)$imali->account_number,
                    'phone' => $user->phone,
                    'descricao' => $refund->description,
                    'data' => $refund->created_at,
                    'estado' => $refund->estado,
                    'comissao' => (double)$refund->comissao,
		    'route' => 'PAGAR_NOTIFICATION',
                    'terminal' => 'firebase'
                );

                $result = json_decode(json_encode($payment), true);

                $this->smsManager->sendMessageToCustomerPayment($data, $result);

                $this->pushNotifification($user->firebase_token, $notification, $data);

            });
//            return response()->json(['message' => trans('refund_done')], 200);


	   return response()->json([
                'cody' => trans('success')[0]['cody'],
                'success' => trans('success')[0]['success'],
                'type' => trans('success')[0]['type'],
                'message' => "Refund successful!"
            ], trans('success')[0]['http_code']);
        }
    }

    public function refundCustomer(Request $request)
    {
        $this->validate($request, [
//            'transaction' => 'required',
            'amount' => 'required',
            'description' => 'required',
            'account_number' => 'required',
            'store_account_number' => 'required',
            'payment_transaction' => 'required',
            'partner_transaction_id' => 'required',
//            'password' => 'required',
            'terminalID' => 'required',
            'terminalChannel' => 'required',
            'terminalCompanyName' => 'required',
        ], [
            'transaction.required' => 'O Campo transaction é de carácter Obrigatório',
            'amount.required' => 'O Campo transaction é de carácter Obrigatório',
            'description.required' => 'O campo description é obrigatório',
            'partner_transaction_id.required' => 'O campo partner_transaction_id é obrigatório',
            'account_number.required' => 'O campo account_number é obrigatório',
            'merchant_id.required' => 'O campo merchant_id é obrigatório',
            'imali_user_id.required' => 'O campo imali_user_id é obrigatório',
            'store_id.required' => 'O campo imali_user_id é obrigatório',
            'user_client_id.required' => 'O campo imali_user_id é obrigatório',
        ]);

        $kyc = new PartnerKyc();
        $kycCheck = $kyc->checkMerchantRefund($request);

        if ($kycCheck) {
            return $kycCheck;
        } else {
            $imaliUser = ImaliAccount::query()
                ->join('users', 'users.id', '=', 'imali_accounts.user_id')
                ->where('account_number', $request->account_number)
                ->select('users.*')
                ->first();


            $merchant = MerchantAccount::query()
                ->join('stores', 'stores.merchant_account_id', '=', 'merchant_accounts.id')
                ->where('stores.account_number', $request->store_account_number)
                ->select('merchant_accounts.*', 'stores.balance as store_balance', 'stores.id as store_id')
                ->first();

            $imaliConfig = ImaliAccountConfig::find($merchant->kyc_config_id);
//            $loja = Store::query()->where('id', '=', $request->store_id)->first();
            $loja = Store::query()->where('account_number', '=', $request->store_account_number)->first();

            $payment = Payment::query()
                ->where('transaction_id', $request->payment_transaction)
                ->first();

            $refund = Refund::create([
                'transaction' => $this->msid->generateTransaction(),
                'amount' => $request->amount,
                'fee' => $imaliConfig->taxa_refund_mechant,
                'amount_debited' => $request->amount + $imaliConfig->taxa_refund_mechant,
                'account_number' => $request->account_number,
                'description' => $request->description,
                'store_id' => $merchant->store_id,
                'imali_user_id' => $imaliUser->id,
                'payment_id' => $payment->id,
//                'estado' => 'Reembolso',
                'estado' => 'pendente',
                'merchant_id' => $merchant->id,
                'user_client_id' => $request->user()->id,
                'terminalCompanyName' => $request->terminalCompanyName,
                'terminalChannel' => $request->terminalChannel,
                'terminalID' => $request->terminalID
            ]);

            $payment = Payment::create([
                'transaction_id' => $refund->transaction,
                'sender_id' => $refund->imali_user_id,
                'store_id' => $refund->store_id,
                'received_points' => 0,
                'amount' => $refund->amount,
                'amount_credited' => $refund->amount,
                'comissao' => $refund->fee,
                'description' => $refund->description,
                'used_points' => 0,
                'estado' => 'pago',
                'client_id' => $request->user()->id,
                'payment_type' => 'reembolso',
                'estado_color' => '#388E3C',
                'created_at' => now(),
                'updated_at' => now()
            ]);

            DB::table('imali_accounts')->where('user_id', $refund->imali_user_id)->increment('balance', $refund->amount);
            DB::table('merchant_accounts')->where('id', $refund->merchant_id)->increment('balance', $refund->amount);

            $notification = array(
                'icon' => 'ic_imali_logo_verde_01',
//                            'icon' => 'ic_i_mali_cover',
                'title' => 'Recebeste ' . $request->amount . ' MT',
                'body' => 'Parabéns, ' . ' recebeste reembolso ' . $request->amount . ' MT ' . ' da loja ' . $loja->name,
                'click_action' => 'com.imali.payapp.payment_PAGAR_NOTIFICATION',
//                            'color' => '#008577'
                'color' => '#ffffff'
            );


            $data = array(
                'transaction' => $refund->transaction,
                'loja' => $loja->name,
                'loja_account' => $loja->account_number,
                'pontos' => $payment->received_points,
                'pontos_usados' => $payment->used_points,
                'amount' => (double)$refund->amount,
                'amount_debited' => (double)$refund->amount,
                'account_number' => (int)$refund->account_number,
                'phone' => $request->user()->phone,
                'descricao' => $refund->description,
                'data' => $refund->created_at,
                'estado' => $refund->estado,
                'comissao' => (double)$refund->comissao,
		'route' => 'PAGAR_NOTIFICATION',
                'terminal' => 'firebase'
            );

            $this->pushNotifification($imaliUser->firebase_token, $notification, $data);

            return response()->json(['message' => 'Reembolso feito com Sucesso!'], 200);
        }
    }


    //? Consultar Saldo da subconta - Check Card Balance
    public function checkCardBalance($card_number)
    {
        if (!$card_number) return response()->json(['message' => 'Número de cartão obrigatório!'], 400);

        $sub_account = ImaliSubAccount::query()->where('card_number', $card_number)->first();

        if (!$sub_account) return response()->json(['message' => 'Cartão invalido!'], 400);
        return response()->json(['balance' => $sub_account->balance], 200);
    }


    //? Refund SubAccount Payment
    public function makePaymentRefund(Request $request)
    {
        $this->validate($request, [
            'transaction_id' => 'required',
            'partner_transaction_id' => 'required',
            'refund_reason' => 'string|max:100',
        ], [
            'transaction_id.required' => 'O campo transaction_id é obrigatório',
            'partner_transaction_id.required' => 'O campo partner_transaction_id é obrigatório',
            'refund_reason.max' => 'O campo Reason deve ter so até 100 caracteres',
        ]);

        // $payment_refund = Payment::query()->where('transaction_id', $request->transaction_id)->where('partner_transaction_id', $request->partner_transaction_id)->where('status', 'success')->first();
        $payment_refund = Payment::query()->where('transaction_id', $request->transaction_id)->where('partner_transaction_id', $request->partner_transaction_id)->first();
        // if (!$payment_refund) return response()->json(['message' => 'Pagamento invalido. Nao pode ser reembolsado'], 400);
        if (!$payment_refund) return response()->json(['message' => 'Pagamento invalido.'], 404);

        if ($payment_refund->status != 'success') return response()->json(['message' => 'Pagamento nao pode ser reembolsado.'], 400);

        $refunded_payment = Payment::query()->where('payment_id', $payment_refund->id)->where('payment_type', 'reembolso')->first();
        if ($refunded_payment) return response()->json(['message' => 'Este pagamento ja foi reembolsado.'], 400);

	$store_old = Store::query()->where('id', $payment_refund->store_id)->first();
        $store = Store::query()->where('id', $payment_refund->store_id)->first();
        if (!$store) return response()->json(['message' => 'Falha de pagamento. Loja nao encontrada.'], 404);

        //if (!($store->balance >= $payment_refund->amount_credited)) return response()->json(['message' => 'Falha de pagamento. Loja nao tem saldo para fazer o reembolso.'], 400);

        // Buscar dados do User que faz a transacao
        //$userPayer = User::getUserDetails($payment_refund->sender_id);

        //$accountPayer = User::getAccount($payment_refund->sender_account_number, $userPayer->id);
        //$accountPayerOld = User::getAccount($payment_refund->sender_account_number, $userPayer->id);

        //$this->msid = new TransactionGeneration();

	//return $userPayer;

        try {

	    // Buscar dados do User que faz a transacao
            $userPayer = User::getUserDetails($payment_refund->sender_id);

           // $accountPayer = User::getAccount($payment_refund->sender_account_number, $userPayer->id);
           // $accountPayerOld = User::getAccount($payment_refund->sender_account_number, $userPayer->id);

	   // Buscar dados da conta do User que faz a transacao
            $accountPayer = User::getAccountByUser($userPayer->id, $userPayer->account_id);
            $accountPayerOld = User::getAccountByUser($userPayer->id, $userPayer->account_id);

	    $accountCardPayer = User::getAccount($payment_refund->sender_card_number);

            if ($accountCardPayer && $accountCardPayer->balance < 0) return SendResponse::errorResp400(
                'Não é possível fazer reembolso com saldo negativo sem cartão',
                'It is not possible to make a refund with a negative balance without card'
            );

            $this->msid = new TransactionGeneration();

            //code...
            DB::beginTransaction();

            $store->balance -= $payment_refund->amount_credited;
            $accountPayer->balance += $payment_refund->amount;
            $store->update();
            $accountPayer->update();

            $payment = Payment::create([
                'transaction_id' => $this->msid->generateTransaction(),
                'partner_transaction_id' => $this->msid->generateTransaction(),
		'terminalID' => $request->terminal_id,
                'sender_id' => $payment_refund->sender_id,
                'store_id' => $payment_refund->store_id,
                'received_points' => 0,
                'amount' => $payment_refund->amount,
                'amount_credited' => $payment_refund->amount,
                'amount_debited' => $payment_refund->amount_credited,
                'payment_id' => $payment_refund->id,

                'sender_name' => $payment_refund->sender_name,
                'sender_account_number' => $payment_refund->sender_account_number,
                'sender_card_number' => $payment_refund->sender_card_number,

                'comissao' => 0,
                'new_balance' => $accountPayer->balance,
                'old_balance' => $accountPayerOld->balance,

		'old_store_balance' => $store_old->balance,
                'new_store_balance' => $store->balance,

                'description' => $payment_refund->description,
                'used_points' => 0,
                'estado' => 'pago',
                'estado_color' => $payment_refund->estado_color,
                'status' => 'success',
                'payment_type' => 'reembolso',

		'transaction_type' => 'credit',
                'transaction_name' => 'Reembolso'
            ]);

            DB::commit();
            return response()->json(['message' => 'Reembolso efectuado com sucesso.', 'transaction_id' => $payment->transaction_id, 'partner_transaction_id' => $payment->partner_transaction_id], 200);
        } catch (\Throwable $th) {
            //throw $th;
            DB::rollback();

            return response()->json(['message' => 'Falha de pagamento.'], 500);
        }

        // return $accountPayer;

        // return response()->json(['message' => 'Pagamento encontrado!'], 200);
    }


    public function pushNotifification($token, $notification = array(), $data = array())
    {
        $apiKey = 'AAAA8zVzEPQ:APA91bHl_DXB6UGb_6gZlmFnaLTQoANtX_OBjvl3nOy2bSlnFhxedvk6EhGj7cZoIvmlbKeCnqGxXbuyMH_rEPuhRXvuitXzo6Pfl2TMXLar1PlifXqEhYq6tS55UMrY2Kffzj-P_UH-';
        $fields = array('to' => $token, 'notification' => $notification, 'data' => $data);
        $headers = array('Authorization: key=' . $apiKey, 'Content-Type: application/json');
        $url = 'https://fcm.googleapis.com/fcm/send';

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
        $result = curl_exec($curl);
        curl_close($curl);


        return json_decode($result, true);

    }

    private function messageJsonToXML($message, $rsCd = 2, $allowPayment = false | 0)
    {
        $jsonResponse = [
            'Document' => [
                'ServiceReq' => [
                    'Hdr' => [
                        'MsgFctn' => env('msgFctn'),
                        'MsgUUID' => Str::orderedUuid(),
                        'PrtcolVrsn' => env('prtcolVrsn'),
                        'RsCd' => $rsCd
                    ],
                    'ResData' => [
                        'AllowPayment' => $allowPayment,
                        'Reason' => $message,
                    ]
                ],
            ],
        ];

        // Converter JSON para XML
        // $xml = ArrayToXml::convert($jsonResponse);
        $xml = ArrayToXml::convert($jsonResponse, [], true, 'UTF-8', '1.0', [], false);

        Log::info('Outgoing Response', [
            'content' => $xml,
        ]);

        return response($xml, 200)->header('Content-Type', 'text/xml');
    }


    private function messageJsonToXMLNotify($message, $rsCd = 2, $allowPayment = false | 0)
    {
        $jsonResponse = [
            'Document' => [
                'ServiceReq' => [
                    'Hdr' => [
                        'MsgFctn' => env('msgFctnNotfy'),
                        'MsgUUID' => Str::orderedUuid(),
                        'PrtcolVrsn' => env('prtcolVrsn'),
                        'RsCd' => $rsCd
                    ],
                    'ResData' => [
                        // 'AllowPayment' => $allowPayment,
                        'Reason' => $message,
                    ]
                ],
            ],
        ];

        // Converter JSON para XML
        $xml = ArrayToXml::convert($jsonResponse, [], true, 'UTF-8', '1.0', [], false);
        // $xml = ArrayToXml::convert($jsonResponse);

        Log::info('Outgoing Response', [
            'content' => $xml,
        ]);

        return response($xml, 200)->header('Content-Type', 'text/xml');
    }

    private function isXML($request)
    {
        $pos=strpos($request->header('Content-Type'),'xml');
        $xml=substr($request->header('Content-Type'),0,$pos+3);

        if ($request->isXmlHttpRequest() || ($xml == 'text/xml') || ($xml == 'application/xml')) return true;
        else return false;
    }


    private function convertXMLToArray($request)
    {

        //NEW
        $fim = strpos($request->getContent(), "?>") + 2;
        $our_header = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>';
        $content = substr($request->getContent(), $fim, strlen($request->getContent()));
        $content = str_replace("code=943", 'code="943"', $content);
        $content = str_replace("<Document xmlns:ren=Renaissance>", "<Document>", $content);

	Log::info('Incoming Request', [
            'content' => $request->getContent(),
        ]);

        // $root_pos = strpos($request->getContent(), "root");
        $root_pos = strpos($content, "root");
        if ($root_pos == false)
            $xmlContent = $our_header . "<root>" . $content . "</root>";
        else
            $xmlContent = $our_header . $content;

        //NEW

        // Carregar dados XML
        $xmlObject = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOCDATA);
        // $xmlObject = simplexml_load_string($xmlContent, 'SimpleXMLElement');

        // Converter para array
        $xmlObj = json_decode(json_encode($xmlObject, JSON_PRETTY_PRINT), true);

        foreach ($xmlObj['Document']['ServiceReq']['Hdr'] as $key => $value) {
            $newArr[$key] = $value;
        }
        foreach ($xmlObj['Document']['ServiceReq']['ReqData'] as $key => $value) {
            $newArr[$key] = $value;
            if ($key === 'Amount')
                $newArr['amountCode'] = (string)$xmlObject->Document->ServiceReq->ReqData->Amount->attributes()->code;
        }

        return new Request($newArr);
    }


    private function validateRequest($request)
    {
        try {
            $this->validate(
                $request,
                [
                    'BillID' => [
                        'required',
                        function ($attribute, $value, $fail) {
                            if ($value != env('BILLID')) {
                                $fail('O valor do parametro ' . $attribute . ' nao esta correcto.');
                            }
                        },
                    ],
                    'amountCode' => [
                        function ($attribute, $value, $fail) {
                            if ($value !== '943') {
                                $fail('Codigo da moeda invalido.');
                            }
                        },
                    ],
                    'EntityID' => 'required',
                    'RefNum' => 'required',
                    'Amount' => 'required'
                ],
                [
                    'BillID' => 'O campo billID informado nao esta correcto',
                    'EntityID' => 'O campo entityID e de caracter obrigatorio',
                    'RefNum' => 'O campo refNum e de caracter obrigatorio',
                    'Amount' => 'O campo amount e de caracter obrigatorio'
                ]
            );

            return response()->json('Done.', 200);
        } catch (\Illuminate\Validation\ValidationException $e) {
            $errors = $e->validator->errors()->getMessages();
            return response()->json(['data' => $errors], 500);
        }
    }

    //? Metodos de Validacao SIMO
    public function validatePayment(Request $request)
    {

        if (!$this->isXML($request)) return $this->messageJsonToXML('requisicao invalida');

        // $request = "<root>". $request->getContent() ."</root>";

        $request = $this->convertXMLToArray($request);

        $respValidation = $this->validateRequest($request);

        if ($respValidation->getStatusCode() != 200) return $this->messageJsonToXML('Erro de parâmetro: ' . json_encode($respValidation->getData()->data));

        $amount = $request->Amount;
        $amount = (float)str_replace(',', '.', $amount);
        $amount = $amount / 100;

        //Verificar tamanho da referencia
        if (!is_numeric($request->RefNum) || strlen($request->RefNum) != 11) return $this->messageJsonToXML('A referencia não foi encontrada.');

        try {
            // Buscar dados do User que faz a transacao
            $account_number = substr($request->RefNum, 0, 9);
            $userAccount = User::getAccount($account_number);

            // return $userAccount;

            // // Verificar se a conta do usuário foi encontrada
            // if (!$userAccount) {
            //     throw new \Exception('Conta do usuário não encontrada');
            // }

            $user = User::getUserDetails($userAccount->user_id);

            if (!$user) return $this->messageJsonToXML('A referencia não foi encontrada');

            //? Validacao do KYC XML
            $kyc = new UserKyc($user);
            $kycResp = $kyc->checkUserKYC($amount);

            if ($kycResp->getStatusCode() != 200) return $this->messageJsonToXML($kycResp->getData()->message);
            return $this->messageJsonToXML('Validacao efetuada com sucesso', 0, true);

            // // Verificar se os detalhes do usuário foram encontrados
            // if (!$user) {
            //     throw new \Exception('Detalhes do usuário não encontrados');
            // }

        } catch (\Throwable $th) {
            // return $this->messageJsonToXML('Erro interno de processamento');
            return $this->messageJsonToXML('A referencia não foi encontrada.');
        }
    }


    public function notifyPayment(Request $request)
    {

        if (!$this->isXML($request)) return $this->messageJsonToXMLNotify('requisicao invalida');

        $request = $this->convertXMLToArray($request);

        $this->validateRequest($request);

        $respValidation = $this->validateRequest($request);

        if ($respValidation->getStatusCode() != 200) return $this->messageJsonToXMLNotify('Erro de parâmetro: ' . json_encode($respValidation->getData()->data));

        //Verificar tamanho da referencia
        if (!is_numeric($request->RefNum) || strlen($request->RefNum) != 11) return $this->messageJsonToXMLNotify('A referencia não foi encontrada.');

        try {
            // Buscar dados do User que faz a transacao
            $account_number = substr($request->RefNum, 0, 9);
            $userAccount = User::getAccount($account_number);
            $user = User::getUserDetails($userAccount->user_id);
            // return $user;

            if (!$user) return $this->messageJsonToXMLNotify('A referencia não foi encontrada');

            $amount = $request->Amount;
            $amount = (float)str_replace(',', '.', $amount);

            $amount = $amount / 100;

            //? Validacao do KYC XML
            $kyc = new UserKyc($user);
            $kycResp = $kyc->checkUserKYC($amount);

            if ($kycResp->getStatusCode() != 200) return $this->messageJsonToXMLNotify($kycResp->getData()->message);
        } catch (\Throwable $th) {
            return $this->messageJsonToXMLNotify('Erro interno de processamento');
        }



        //?Processo de carregamento
        $account_number = substr($request->RefNum, 0, 9);
        $imaliAccount = User::getAccount($account_number);
        // return $userAccount;

        $transactionString = new TransactionGeneration();

        if ($imaliAccount) {
            $balanceActual = $imaliAccount->balance + $amount;

            $masterAccount = MasterAccount::find(2);
            $recharge = RechargeImaliAccount::create([
                'imali_account_id' => $imaliAccount->id,
                'transaction_id' => $transactionString->generateTransaction(),
                // 'bank_reference' => $request->refbancariatran,
                // 'bank_date' => $request->datatransaccao,
                'account_reference' => $imaliAccount->reference,
                'description' => 'Carregamento SIMO',
                'amount' => $amount,
                'last_balance' => $imaliAccount->balance,
                'balance' => $balanceActual,
                'recharge_way' => 'SIMO',
                'estado' => 'sucesso',
                'estado_color' => '#388E3C',
                'master_account_id' => $masterAccount->id
            ]);

            $masterBalance = $masterAccount->balance + $amount;

            $masterAccount->update(['balance' => $masterBalance]);

            if ($recharge) {

                $imaliAccount->update(['balance' => $balanceActual]);

                $notification = array(
                    'icon' => 'ic_imali_logo_verde_01',
                    'title' => 'Carregamento ' . $recharge->amount . ' MT',
                    'body' => 'Parabéns, ' . ' carregaste com ' . $recharge->amount . ' MT ' . ' na tua conta ' . $imaliAccount->account_number,
                    'click_action' => 'com.imali.payapp.payment_RECHARGE_DETAILS',
                    'color' => '#ffffff'
                );

                $data = array(
                    'transaction' => $recharge->transaction_id,
                    // 'bank_reference' => $request->refbancariatran,
                    'account_reference' => $imaliAccount->reference,
                    // 'bank_date' => $request->datatransaccao,
                    'description' => $request->description,
                    'name' => $user->name,
                    'amount' => (float)$recharge->amount,
                    'phone' => $user->phone,
                    'reference' => $imaliAccount->reference,
                    'data' => $recharge->created_at,
                    'estado' => $recharge->estado,
                    'route' => 'RECHARGE_DETAILS',
                    'recharge_way' => $recharge->recharge_way,
                    'account_number' => $user->account_number,
                    'terminal' => 'firebase'
                );

                $this->pushNotifification($user->firebase_token, $notification, $data);
                $this->smsManager->sendSMSForUserRecharge($recharge);
            }

            $log = new Record();
            $log->createLog([
                'description' => $imaliAccount->account_number,
                'details' => $user->name . ' ' . $user->last_name,
                'operation' => 'Recharge by Reference',
                'status' => 'success',
                'user_id' => $user->id
            ]);

            if ($kycResp->getStatusCode() != 200) return $this->messageJsonToXMLNotify($kycResp->getData()->message);
            return $this->messageJsonToXMLNotify('Pedido processado com sucesso', 0, true);
        }
    }


    private function validateCheckDigit($numero)
    {
        // Verifica se o número tem 11 dígitos
        if (strlen($numero) != 11) {
            return false;
        }

        $entity = env('SIMO_ENTITY');
        $ref = (float)substr($numero, 0, 9);
        $cd = (float)substr($numero, 9, 2);

        $check_digit = 98 - (($entity . $ref) * 100) % 97;

        if ($check_digit == $cd) return true;
        return false;
    }

    // GET Payments
    public function getPaymentAccounts()
    {
        // $userPayer = User::getUserDetails(Auth::user()->id);
        return User::getMyAccounts();
        // return User::getAccount($userPayer->account_number);
    }

}