<?php

namespace App\Core\Service;

use App\Core\Repository\PaymentType\PaymentTypeRepository;
use App\Core\Repository\PaymentTransaction\PaymentTransactionRepository;
use App\Core\Repository\PropertyPaymentMapping\PropertyPaymentMappingRepository;
use App\Core\Repository\PropertyPaymentInstallment\PropertyPaymentInstallmentRepository;
use App\Core\Repository\PaymentBinNumber\PaymentBinNumberRepository;
use App\Core\Repository\CurrencyRates\CurrencyRatesRepository;
use App\Core\Validator\PropertyPaymentMapping\PropertyPaymentMappingCreateValidator;
use App\Core\Validator\PropertyPaymentMapping\PropertyPaymentMappingUpdateValidator;
use App\Core\Validator\PropertyPaymentMapping\PropertyPaymentMappingStatusUpdateValidator;
use App\Core\Validator\PropertyPaymentMapping\PropertyPaymentMappingSetDefaultValidator;
use App\Core\Validator\PropertyPaymentMapping\PropertyPaymentInstallmentsUpdateValidator;
use App\Core\Validator\PropertyPayment\PropertyPaymentTransactionCreateValidator;
use App\Core\Validator\PropertyPayment\PropertyPaymentTransactionUpdateValidator;

use App;
use App\Exceptions\ApiError;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Facades\DB;

class PropertyPaymentService
{

    private $paymentTypeRepository;
    private $propertyPaymentMappingCreateValidator;
    private $propertyPaymentMappingUpdateValidator;
    private $propertyPaymentMappingStatusUpdateValidator;
    private $propertyPaymentMappingSetDefaultValidator;
    private $propertyPaymentInstallmentsUpdateValidator;
    private $currencyService;
    private $propertyPaymentTransactionCreateValidator;
    private $propertyPaymentTransactionUpdateValidator;


    public function __construct(
        Request                                     $request,
        PaymentTypeRepository                       $paymentTypeRepository,
        PaymentTransactionRepository                $paymentTransactionRepository,
        PropertyPaymentMappingRepository            $propertyPaymentMappingRepository,
        PropertyPaymentInstallmentRepository        $propertyPaymentInstallmentRepository,
        PaymentBinNumberRepository                  $paymentBinNumberRepository,
        PropertyPaymentMappingCreateValidator       $propertyPaymentMappingCreateValidator,
        PropertyPaymentMappingUpdateValidator       $propertyPaymentMappingUpdateValidator,
        PropertyPaymentMappingStatusUpdateValidator $propertyPaymentMappingStatusUpdateValidator,
        PropertyPaymentMappingSetDefaultValidator   $propertyPaymentMappingSetDefaultValidator,
        PropertyPaymentInstallmentsUpdateValidator  $propertyPaymentInstallmentsUpdateValidator,
        PropertyPaymentTransactionCreateValidator   $propertyPaymentTransactionCreateValidator,
        CurrencyService                             $currencyService,
        PropertyPaymentTransactionUpdateValidator   $propertyPaymentTransactionUpdateValidator,
        CurrencyRatesRepository                     $currencyRatesRepository

    )
    {

        $this->request = $request;
        $this->paymentTypeRepository = $paymentTypeRepository;
        $this->paymentTransactionRepository = $paymentTransactionRepository;
        $this->propertyPaymentMappingRepository = $propertyPaymentMappingRepository;
        $this->propertyPaymentInstallmentRepository = $propertyPaymentInstallmentRepository;
        $this->paymentBinNumberRepository = $paymentBinNumberRepository;
        $this->currencyRatesRepository = $currencyRatesRepository;
        $this->propertyPaymentMappingCreateValidator = $propertyPaymentMappingCreateValidator;
        $this->propertyPaymentMappingUpdateValidator = $propertyPaymentMappingUpdateValidator;
        $this->propertyPaymentMappingStatusUpdateValidator = $propertyPaymentMappingStatusUpdateValidator;
        $this->propertyPaymentMappingSetDefaultValidator = $propertyPaymentMappingSetDefaultValidator;
        $this->propertyPaymentInstallmentsUpdateValidator = $propertyPaymentInstallmentsUpdateValidator;
        $this->currencyService = $currencyService;
        $this->propertyPaymentTransactionCreateValidator = $propertyPaymentTransactionCreateValidator;
        $this->propertyPaymentTransactionUpdateValidator = $propertyPaymentTransactionUpdateValidator;

    }

    public function getExchangeRates()
    {

        $exchangeRate = [];

        $exchangeRatesDailyLastParam = [
            'criteria' => [],
            'orderBy' => [["field" => "date", "value" => "DESC"]],
            'firstRow' => true
        ];

        $exchangeRatesDailyLast = $this->currencyRatesRepository->findByCriteria($exchangeRatesDailyLastParam);


        if (isset($exchangeRatesDailyLast['date'])) {
            $exchangeRatesDailyParam = [
                'criteria' => [
                    ['field' => 'date', 'condition' => '=', 'value' => $exchangeRatesDailyLast['date']]
                ]
            ];

            $exchangeRatesDaily = $this->currencyRatesRepository->findByCriteria($exchangeRatesDailyParam);

            foreach ($exchangeRatesDaily as $rate) {
                $exchangeRate[$rate['currency_code'] . $rate['exc_currency_code']] = $rate['rate'];
            }
        }


        return $exchangeRate;
    }

    public function getPaymentTransactionDetail($paymentCode)
    {

        $response = ['status' => false, 'message' => ''];
        try {

            $paymentTransactionParam = [
                'criteria' => [
                    ['field' => 'code', 'condition' => '=', 'value' => $paymentCode]
                ],
                'with' => ['paymentTypeMapping.paymentType', 'property'],
                'firstRow' => true
            ];

            $paymentTransaction = $this->paymentTransactionRepository->findByCriteria($paymentTransactionParam);

            if (empty($paymentTransaction)) {
                throw new ApiErrorException(lang('Payment Transaction is not found.'));
            }

            $response = [
                'status' => true,
                'data' => $paymentTransaction,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return $response;

    }

    public function getPaymentTypeMapping($propertyId, $currency, $creditCardNumber)
    {

        $paymentTypeAndInstallment['propertyPaymentMappingId'] = null;
        $paymentTypeAndInstallment['propertyPaymentMappingInstallment'] = [];
        $paymentTypeAndInstallment['propertyPaymentMappingCurrency'] = null;
        $propertyPaymentMappingInstallment = [];

        $preferredBankPos = null;

        $creditCardNumber = substr($creditCardNumber, 0, 6);


        $paymentBinNumberParam = [
            'criteria' => [
                ['field' => 'bin_number', 'condition' => '=', 'value' => $creditCardNumber]
            ],
            'firstRow' => true
        ];

        $paymentBinNumber = $this->paymentBinNumberRepository->findByCriteria($paymentBinNumberParam);

        if (!empty($paymentBinNumber)) {
            $preferredBankPos = $paymentBinNumber['payment_type_id'];
        }

        $propertyPaymentMappingParam = [
            'criteria' => [
                ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                ['field' => 'status', 'condition' => '<>', 'value' => 0],
            ],
            'with' => ['paymentType']
        ];

        $propertyPaymentMapping = $this->propertyPaymentMappingRepository->findByCriteria($propertyPaymentMappingParam);
        $propertyPaymentMappingCollect = collect($propertyPaymentMapping);


        if (empty($propertyPaymentMapping)) {
            throw new ApiErrorException(lang('Payment Type Mapping not found'));
        }

        //Eğer aynı banka ve aynı currency ve taksit var ise
        $propertyPaymentMappingSelect = $propertyPaymentMappingCollect->where('currency_code', $currency)->where('payment_type_id', $preferredBankPos)->where('installment', 1)->sortByDesc('id')->first();
        if (!is_null($propertyPaymentMappingSelect)) {

            $paymentMappingInstallmentParam = [
                'criteria' => [
                    ['field' => 'property_payment_mapping_id', 'condition' => '=', 'value' => $propertyPaymentMappingSelect['id']],
                    ['field' => 'status', 'condition' => '<>', 'value' => 0],

                ],
                'orderBy' => [["field" => "installment", "value" => "ASC"]],
            ];

            $propertyPaymentMappingInstallment = $this->propertyPaymentInstallmentRepository->findByCriteria($paymentMappingInstallmentParam, ['installment', 'commission']);

            $paymentTypeAndInstallment['propertyPaymentMappingId'] = $propertyPaymentMappingSelect['id'];
            $paymentTypeAndInstallment['propertyPaymentMappingCurrency'] = $propertyPaymentMappingSelect['currency_code'];
            $paymentTypeAndInstallment['propertyPaymentMappingInstallment'] = $propertyPaymentMappingInstallment;

        }

        //Eğer aynı currency ve banka olmayıp taksit var ise
        if (is_null($paymentTypeAndInstallment['propertyPaymentMappingId'])) {
            $propertyPaymentMappingSelect = $propertyPaymentMappingCollect->where('currency_code', $currency)->where('installment', 1)->where('payment_type.pos_code', '<>', 'POS')->sortByDesc('id')->first();
            if (!is_null($propertyPaymentMappingSelect)) {

                $paymentMappingInstallmentParam = [
                    'criteria' => [
                        ['field' => 'property_payment_mapping_id', 'condition' => '=', 'value' => $propertyPaymentMappingSelect['id']],
                        ['field' => 'status', 'condition' => '<>', 'value' => 0],
                    ],
                    'orderBy' => [["field" => "installment", "value" => "ASC"]],
                ];

                $propertyPaymentMappingInstallment = $this->propertyPaymentInstallmentRepository->findByCriteria($paymentMappingInstallmentParam, ['installment', 'commission']);

                $paymentTypeAndInstallment['propertyPaymentMappingId'] = $propertyPaymentMappingSelect['id'];
                $paymentTypeAndInstallment['propertyPaymentMappingCurrency'] = $propertyPaymentMappingSelect['currency_code'];
                $paymentTypeAndInstallment['propertyPaymentMappingInstallment'] = $propertyPaymentMappingInstallment;

            }
        }

        //Eğer aynı currency ise
        if (is_null($paymentTypeAndInstallment['propertyPaymentMappingId'])) {
            $propertyPaymentMappingSelect = $propertyPaymentMappingCollect->where('currency_code', $currency)->sortByDesc('id')->first();
            if (!is_null($propertyPaymentMappingSelect)) {
                $paymentTypeAndInstallment['propertyPaymentMappingId'] = $propertyPaymentMappingSelect['id'];
                $paymentTypeAndInstallment['propertyPaymentMappingCurrency'] = $propertyPaymentMappingSelect['currency_code'];
            }
        }


        //Eğer hiç bişey yok ise default
        if (is_null($paymentTypeAndInstallment['propertyPaymentMappingId'])) {
            $propertyPaymentMappingSelect = $propertyPaymentMappingCollect->where('is_default', 1)->sortByDesc('id')->first();
            if (!is_null($propertyPaymentMappingSelect)) {
                $paymentTypeAndInstallment['propertyPaymentMappingId'] = $propertyPaymentMappingSelect['id'];
                $paymentTypeAndInstallment['propertyPaymentMappingCurrency'] = $propertyPaymentMappingSelect['currency_code'];


                if (!is_null($paymentTypeAndInstallment['propertyPaymentMappingCurrency']) && !is_null($preferredBankPos) && $propertyPaymentMappingSelect['payment_type_id'] == $preferredBankPos) {

                    $paymentMappingInstallmentParam = [
                        'criteria' => [
                            ['field' => 'property_payment_mapping_id', 'condition' => '=', 'value' => $propertyPaymentMappingSelect['id']],
                            ['field' => 'status', 'condition' => '<>', 'value' => 0],
                        ],
                        'orderBy' => [["field" => "installment", "value" => "ASC"]],
                    ];

                    $propertyPaymentMappingInstallment = $this->propertyPaymentInstallmentRepository->findByCriteria($paymentMappingInstallmentParam, ['installment', 'commission']);

                    $paymentTypeAndInstallment['propertyPaymentMappingInstallment'] = $propertyPaymentMappingInstallment;

                } else if ($propertyPaymentMappingCollect->whereIn('payment_type.pos_code', ['MOK', 'SPY'])->isNotEmpty()) {
                    $paymentMappingInstallmentParam = [
                        'criteria' => [
                            ['field' => 'property_payment_mapping_id', 'condition' => '=', 'value' => $propertyPaymentMappingSelect['id']],
                            ['field' => 'status', 'condition' => '<>', 'value' => 0],
                        ],
                        'orderBy' => [["field" => "installment", "value" => "ASC"]],
                    ];

                    $propertyPaymentMappingInstallment = $this->propertyPaymentInstallmentRepository->findByCriteria($paymentMappingInstallmentParam, ['installment', 'commission']);

                    $paymentTypeAndInstallment['propertyPaymentMappingInstallment'] = $propertyPaymentMappingInstallment;
                }


            }

        }

        //FOR Turkish credit cards are forced TRY currency via TRY POS
        if (!empty($paymentBinNumber)) {
            if ($paymentTypeAndInstallment['propertyPaymentMappingCurrency'] != 'TRY') {

                $propertyPaymentMappingSelect = $propertyPaymentMappingCollect
                    ->where('currency_code', 'TRY')
                    ->sortByDesc('id')->first();

                if (!is_null($propertyPaymentMappingSelect)) {

                    $paymentMappingInstallmentParam = [
                        'criteria' => [
                            ['field' => 'property_payment_mapping_id', 'condition' => '=', 'value' => $propertyPaymentMappingSelect['id']],
                            ['field' => 'status', 'condition' => '<>', 'value' => 0],
                        ],
                        'orderBy' => [["field" => "installment", "value" => "ASC"]],
                    ];


                    $propertyPaymentMappingInstallment = $this->propertyPaymentInstallmentRepository->findByCriteria($paymentMappingInstallmentParam, ['installment', 'commission']);


                    $paymentTypeAndInstallment['propertyPaymentMappingId'] = $propertyPaymentMappingSelect['id'];
                    $paymentTypeAndInstallment['propertyPaymentMappingCurrency'] = $propertyPaymentMappingSelect['currency_code'];
                    $paymentTypeAndInstallment['propertyPaymentMappingInstallment'] = $propertyPaymentMappingInstallment;
                }
            }
        }

        return $paymentTypeAndInstallment;

    }

    public function initializePayment($params = [])
    {
        $response = ['status' => false, 'message' => ''];
        try {

            $exchangeRateStore = 1;
            $paymentCode = getPaymentGenerate(fillOnUndefined($params, 'type'));
            $ipAddress = $this->request->getClientIp() == '127.0.0.1' ? '185.137.215.118' : $this->request->getClientIp();
            $paymentCheckUrl = Config::get('app.url') . '/paymentCheck/' . $paymentCode;

            if (isset($params['preferredPaymentTypeId'])) {

                $propertyPaymentMappingParam = [
                    'criteria' => [
                        ['field' => 'id', 'condition' => '=', 'value' => $params['preferredPaymentTypeId']],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['propertyId']],
                        ['field' => 'status', 'condition' => '<>', 'value' => 0],
                    ],
                    'firstRow' => true,
                    'with' => ['paymentType']
                ];

                $propertyPaymentMapping = $this->propertyPaymentMappingRepository->findByCriteria($propertyPaymentMappingParam);

                if (empty($propertyPaymentMapping)) {
                    throw new ApiErrorException(lang('Payment Type not found'));
                }

                $paymentTypeMapping = [
                    "propertyPaymentMappingId" => $propertyPaymentMapping['id'],
                    'propertyPaymentMappingInstallment' => [],
                    'propertyPaymentMappingCurrency' => $propertyPaymentMapping['currency_code'],
                ];


            } else {

                $paymentTypeMapping = $this->getPaymentTypeMapping($params['propertyId'], $params['currency'], $params['creditCard']['number']);

                if (is_null($paymentTypeMapping['propertyPaymentMappingId'])) {
                    throw new ApiErrorException(lang('Payment Type not found'));
                }
            }

            $installmentRate = [];
            if ($params['installment'] > 0) {

                if (empty($paymentTypeMapping['propertyPaymentMappingInstallment'])) {
                    throw new ApiErrorException(lang('Pos not available installment'));
                }

                $propertyPaymentMappingInstallment = collect($paymentTypeMapping['propertyPaymentMappingInstallment']);

                $installmentRate = $propertyPaymentMappingInstallment->where('installment', $params['installment'])->first();

                if (empty($propertyPaymentMappingInstallment->where('installment', $params['installment'])->first())) {
                    throw new ApiErrorException(lang('Pos not available this installment number'));
                }

            }


            $paymentTypeMappingId = $paymentTypeMapping['propertyPaymentMappingId'];

            $paymentTypeParam = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $paymentTypeMappingId]
                ],
                'with' => ['paymentType'],
                'firstRow' => true
            ];

            $paymentType = $this->propertyPaymentMappingRepository->findByCriteria($paymentTypeParam);

            $params['amount'] = moneyDoubleFormatDecimal($params['amount']);
            $params['base_amount'] = moneyDoubleFormatDecimal($params['amount']);
            $params['base_currency'] = $params['currency'];


            //Eğer istenen döviz tipi postan farklı ise convert edilecek
            if ($params['currency'] != $paymentType['currency_code']) {

                $exchangeRate = $this->getExchangeRates();

                if (!isset($exchangeRate[$params['currency'] . $paymentType['currency_code']])) {
                    throw new ApiErrorException(lang('Currency exchange value not found.'));
                }

                $exchangeRateStore = $exchangeRate[$params['currency'] . $paymentType['currency_code']];

                $params['amount'] = moneyDoubleFormatDecimal($params['amount'] * $exchangeRateStore);
                $params['currency'] = $paymentType['currency_code'];

            }

            if ($params['installment'] > 0 && !empty($installmentRate)) {
                $params['amount'] = moneyDoubleFormatDecimal($params['amount'] + ($params['amount'] * $installmentRate['commission'] / 100));
                $params['installmentRate'] = $installmentRate;
            }

            $paymentParam = [];

            //TODO: PaymentFactory
            if ($paymentType['payment_type']['pos_code'] == 'POS') {

                $posAccount = [];
                $posAccount['bank'] = $paymentType['payment_type']['bank_code'];
                $posAccount['model'] = $paymentType['payment_type']['threed_model'];
                $posAccount['env'] = $paymentType['status'] == 1 ? 'production' : 'test';

                foreach ($paymentType['paramsArray'] as $paramKey => $param) {

                    if (isset($paymentType['payment_type']['paramsArray'][$paramKey])) {
                        $posAccount[$paymentType['payment_type']['paramsArray'][$paramKey]['key']] = $param;
                    }
                }

                $POS = new \App\Core\Payment\Pos\Pos($posAccount);

                $params['installment'] = $params['installment'] == 1 ? 0 : $params['installment'];

                $orderParam = [
                    'id' => $paymentCode,
                    'email' => '',
                    'name' => $params['creditCard']['name'],
                    'amount' => (double)$params['amount'],
                    'installment' => $params['installment'],
                    'currency' => $paymentType['currency_code'],
                    'ip' => $ipAddress,
                    'success_url' => $paymentCheckUrl,
                    'fail_url' => $paymentCheckUrl,
                    'transaction' => 'pay', // pay => Auth, pre PreAuth
                    'lang' => 'tr',
                    'rand' => microtime()
                ];

                $params['orderParam'] = $orderParam;


                $creditCard = [
                    'name' => $params['creditCard']['name'],
                    //'type' => 'visa',
                    'number' => $params['creditCard']['number'],
                    'month' => $params['creditCard']['month'],
                    'year' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv']
                ];

                //dd($creditCard, $orderParam);

                $POS->prepare($orderParam, $creditCard);
                $paymentParam = $POS->get3dFormData();

                if (empty($paymentParam)) {
                    throw new ApiErrorException(lang('Failed to create 3D Form data.'));
                }

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'STR') {


                try {

                    //Secret key
                    $secretKey = $paymentType['paramsArray']['secretKey'];
                    $stripe = new \Stripe\StripeClient($secretKey);

                    $token = $stripe->tokens->create([
                        'card' => [
                            'number' => $params['creditCard']['number'],
                            'exp_month' => $params['creditCard']['month'],
                            'exp_year' => $params['creditCard']['year'],
                            'cvc' => $params['creditCard']['cvv']
                        ],
                    ]);


                    $source = $stripe->sources->create([
                        'currency' => $params['currency'],
                        'amount' => ($params['amount'] * 100),
                        'type' => 'three_d_secure',
                        'three_d_secure' => [
                            'card' => $token->card->id,
                        ],
                        'redirect' => [
                            'return_url' => $paymentCheckUrl
                        ],
                    ]);

                    //Pending, 3DSecure
                    if ($source['status'] == 'failed') {

                        //Direct Payment
                        $charge = $stripe->charges->create([
                            'card' => $token->id,
                            'currency' => $params['currency'],
                            'amount' => ($params['amount'] * 100),
                            'description' => $paymentCode,
                        ]);

                        if ($charge['status'] == 'succeeded') {

                            $response = [
                                'status' => true,
                                'data' => [
                                    'paymentCode' => $paymentCode
                                ],
                            ];

                        }

                    } else {
                        //Aksi tüm durumlarda 3dSecure devam et
                        //} elseif (in_array($source['status'], ['pending', 'chargeable'])) {

                        $response = [
                            'status' => true,
                            'data' => [
                                'paymentCode' => $paymentCode,
                                'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                            ],
                        ];

                    }

                } catch (Exception $e) {
                    $response['message'] = $e->getMessage();
                }


                $paymentTransactionStatus = 0;
                if ($response['status']) {

                    $paymentTransactionStatus = 1;

                    if (isset($response['data']['redirectUrl'])) {
                        $paymentTransactionStatus = 2;
                    }
                }

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'bank_order_id' => isset($charge) ? $charge->id : null,
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => isset($source) ? json_encode($source) : null,
                    'response' => isset($charge) ? json_encode($charge) : null,
                    'message' => fillOnUndefined($response, 'message'),
                    'status' => $paymentTransactionStatus,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                //STRIPE END


            } elseif ($paymentType['payment_type']['pos_code'] == 'ENW') {


                try {

                    //Secret key
                    $secretKey = config('app.stripeENWKey');
                    $stripe = new \Stripe\StripeClient($secretKey);

                    $token = $stripe->tokens->create([
                        'card' => [
                            'number' => $params['creditCard']['number'],
                            'exp_month' => $params['creditCard']['month'],
                            'exp_year' => $params['creditCard']['year'],
                            'cvc' => $params['creditCard']['cvv']
                        ],
                    ]);


                    $source = $stripe->sources->create([
                        'currency' => $params['currency'],
                        'amount' => ($params['amount'] * 100),
                        'type' => 'three_d_secure',
                        'three_d_secure' => [
                            'card' => $token->card->id,
                        ],
                        'redirect' => [
                            'return_url' => $paymentCheckUrl
                        ],
                    ]);

                    //Pending, 3DSecure
                    if ($source['status'] == 'failed') {

                        //Direct Payment
                        $charge = $stripe->charges->create([
                            'card' => $token->id,
                            'currency' => $params['currency'],
                            'amount' => ($params['amount'] * 100),
                            'description' => $paymentCode,
                        ]);

                        if ($charge['status'] == 'succeeded') {

                            $response = [
                                'status' => true,
                                'data' => [
                                    'paymentCode' => $paymentCode
                                ],
                            ];

                        }

                    } else {
                        //Aksi tüm durumlarda 3dSecure devam et
                        //} elseif (in_array($source['status'], ['pending', 'chargeable'])) {

                        $response = [
                            'status' => true,
                            'data' => [
                                'paymentCode' => $paymentCode,
                                'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                            ],
                        ];

                    }

                } catch (Exception $e) {
                    $response['message'] = $e->getMessage();
                }


                $paymentTransactionStatus = 0;
                if ($response['status']) {

                    $paymentTransactionStatus = 1;

                    if (isset($response['data']['redirectUrl'])) {
                        $paymentTransactionStatus = 2;
                    }
                }

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'bank_order_id' => isset($charge) ? $charge->id : null,
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => isset($source) ? json_encode($source) : null,
                    'response' => isset($charge) ? json_encode($charge) : null,
                    'message' => fillOnUndefined($response, 'message'),
                    'status' => $paymentTransactionStatus,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                //STRIPE ENW END


            } elseif ($paymentType['payment_type']['pos_code'] == 'SPY') {


                $paymentInitializeParam = [
                    'merchantId' => $paymentType['paramsArray']['merchantId'],
                    'merchantKey' => $paymentType['paramsArray']['merchantKey'],
                    'appKey' => $paymentType['paramsArray']['appKey'],
                    'appSecret' => $paymentType['paramsArray']['appSecret'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];


                $sipayService = new App\Core\Payment\Sipay\Sipay($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $paymentParam = $sipayService->paySmart3D($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }

                $paymentParam = $paymentParam['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'MOK') {

                $paymentInitializeParam = [
                    'userName' => $paymentType['paramsArray']['userName'],
                    'password' => $paymentType['paramsArray']['password'],
                    'dealerCode' => $paymentType['paramsArray']['dealerCode'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];


                $mokaService = new App\Core\Payment\Moka\Moka($paymentInitializeParam);

                $params['currency'] = $params['currency'] == 'TRY' ? 'TL' : $params['currency'];

                $paymentCreateParam = [
                    'key' => $params['orderId'],
                    'CardHolderFullName' => $params['creditCard']['name'],
                    'CardNumber' => $params['creditCard']['number'],
                    'ExpMonth' => $params['creditCard']['month'],
                    'ExpYear' => $params['creditCard']['year'],
                    'CvcNumber' => $params['creditCard']['cvv'],
                    'Currency' => $params['currency'],
                    'Amount' => (double)$params['amount'],//10.50
                    'InstallmentNumber' => isset($params['installment']) ? $params['installment'] : 1,
                    'OtherTrxCode' => $params['orderId'],
                    'Description' => fillOnUndefined($params, 'description'),
                    'RedirectUrl' => $paymentCheckUrl,
                    'IsPreAuth' => 0, //0: Direct Provision 1: PreProvision
                    'ClientIP' => config('app.env') == 'local' ? '185.137.215.118' : $ipAddress
                ];

                $paymentParam = $mokaService->DoDirectPaymentThreeD($paymentCreateParam);


                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }

                $paymentParam = $paymentParam['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'BOG') {


                $paymentInitializeParam = [
                    'clientId' => $paymentType['paramsArray']['clientId'],
                    'secretKey' => $paymentType['paramsArray']['secretKey'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $bankOfGeorgiaService = new App\Core\Payment\BankOfGeorgia\Payriff($paymentInitializeParam);


                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                if ($creditPaymentParam['currencyCode'] != 'GEL') {
                    throw new ApiErrorException(lang('This payment method only support GEL.'));
                }

                $paymentParam = $bankOfGeorgiaService->paymentInitialize($creditPaymentParam);


                if (!$paymentParam['status']) {
                    throw new ApiErrorException('Payment Initialize is not started.');
                }

                $paymentParam = $paymentParam['data'];

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'TBC') {


                $paymentInitializeParam = [
                    'clientId' => $paymentType['paramsArray']['clientId'],
                    'clientSecret' => $paymentType['paramsArray']['clientSecret'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $tbcBankService = new App\Core\Payment\TBCBankGeorgia\TBCBankGeorgia($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl,
                    'ipAddress' => $ipAddress
                ];

                $paymentParam = $tbcBankService->paymentInitialize($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException('Payment Initialize is not started.');
                }

                $paymentParam = $paymentParam['data'];

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'QNB') {


                $paymentInitializeParam = [
                    'merchantId' => $paymentType['paramsArray']['merchantId'],
                    'merchantKey' => $paymentType['paramsArray']['merchantKey'],
                    'appKey' => $paymentType['paramsArray']['appKey'],
                    'appSecret' => $paymentType['paramsArray']['appSecret'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $qnbPayService = new App\Core\Payment\QNBPay\QNBPay($paymentInitializeParam);


                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $paymentParam = $qnbPayService->paySmart3D($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }

                $paymentParam = $paymentParam['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'TBC') {


                $paymentInitializeParam = [
                    'clientId' => $paymentType['paramsArray']['clientId'],
                    'clientSecret' => $paymentType['paramsArray']['clientSecret'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $tbcBankService = new App\Core\Payment\TBCBankGeorgia\TBCBankGeorgia($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl,
                    'ipAddress' => $ipAddress
                ];

                $paymentParam = $tbcBankService->paymentInitialize($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException('Payment Initialize is not started.');
                }

                $paymentParam = $paymentParam['data'];

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'WEE') {


                $paymentInitializeParam = [
                    'merchantId' => $paymentType['paramsArray']['merchantId'],
                    'apiKey' => $paymentType['paramsArray']['apiKey'],
                    'secretKey' => $paymentType['paramsArray']['secretKey'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                    'ipAddress' => $ipAddress
                ];

                $weePayService = new App\Core\Payment\WeePay\WeePay($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $paymentParam = $weePayService->paySmart3D($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }

                $paymentParam = $paymentParam['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'HLK') {


                $paymentInitializeParam = [
                    'merchantId' => $paymentType['paramsArray']['merchantId'],
                    'merchantKey' => $paymentType['paramsArray']['merchantKey'],
                    'appKey' => $paymentType['paramsArray']['appKey'],
                    'appSecret' => $paymentType['paramsArray']['appSecret'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $paymentTypeService = new App\Core\Payment\HalkOde\HalkOde($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $paymentParam = $paymentTypeService->paySmart3D($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }

                $paymentParam = $paymentParam['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'ESN') {


                $paymentInitializeParam = [
                    'merchant' => $paymentType['paramsArray']['merchant'],
                    'merchantKey' => $paymentType['paramsArray']['merchantKey'],
                    'contactMail' => $paymentType['paramsArray']['contactMail'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $esnekPosService = new App\Core\Payment\Esnekpos\Esnekpos($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $paymentRequest = $esnekPosService->EYV3DPay($creditPaymentParam);

                if (!$paymentRequest['status']) {
                    throw new ApiErrorException($paymentRequest['message']);
                }

                $paymentRequest = $paymentRequest['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentRequest),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'KVY') {

                $paymentInitializeParam = [
                    'customerId' => $paymentType['paramsArray']['customerId'],
                    'merchantId' => $paymentType['paramsArray']['merchantId'],
                    'userName' => $paymentType['paramsArray']['userName'],
                    'password' => $paymentType['paramsArray']['password'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $paymentTypeService = new App\Core\Payment\KuveytTurk\KuveytTurk($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $paymentParam = $paymentTypeService->threeDModelPayGate($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }

                $paymentParam = $paymentParam['data'];

                $params['creditCard']['number'] = creditCardMask($params['creditCard']['number']);

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => $paymentParam,
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'RTL') {


                $paymentInitializeParam = [
                    'userName' => $paymentType['paramsArray']['userName'],
                    'password' => $paymentType['paramsArray']['password'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                    'ipAddress' => $ipAddress
                ];

                $retailPayService = new App\Core\Payment\RetailPay\RetailPay($paymentInitializeParam);

                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                $creditPaymentParam['creditCard'] = [
                    'holderName' => $params['creditCard']['name'],
                    'number' => $params['creditCard']['number'],
                    'expiryMonth' => $params['creditCard']['month'],
                    'expiryYear' => $params['creditCard']['year'],
                    'cvv' => $params['creditCard']['cvv'],
                    'installment' => $params['installment'],
                ];


                $creditPaymentParam['client'] = [
                    'name' => isset($params['client']['name']) ? $params['client']['name'] : 'Extranetwork',
                    'email' => isset($params['client']['email']) ? $params['client']['email'] : 'info@extranetwork.com',
                    'phone' => isset($params['client']['phone']) ? $params['client']['phone'] : '+908508886428',
                ];


                $paymentParam = $retailPayService->ordersAuthorize($creditPaymentParam);


                if (!$paymentParam['status']) {
                    throw new ApiErrorException(lang('3D Form data not generated.'));
                }


                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam['data']),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } elseif ($paymentType['payment_type']['pos_code'] == 'PYR') {


                $paymentInitializeParam = [
                    'secretKey' => $paymentType['paramsArray']['secretKey'],
                    'env' => $paymentType['status'] == 1 ? 'production' : 'test',
                ];

                $payriffService = new App\Core\Payment\Payriff\Payriff($paymentInitializeParam);


                $creditPaymentParam = [
                    'amount' => (double)$params['amount'],
                    'orderId' => $paymentCode,
                    'orderCode' => $params['orderId'],
                    'currencyCode' => $params['currency'],
                    'paymentCheckUrl' => $paymentCheckUrl
                ];

                if ($creditPaymentParam['currencyCode'] != 'AZN') {
                    throw new ApiErrorException(lang('This payment method only support AZN.'));
                }

                $paymentParam = $payriffService->paymentInitialize($creditPaymentParam);

                if (!$paymentParam['status']) {
                    throw new ApiErrorException('Payment Initialize is not started.');
                }

                $paymentParam = $paymentParam['data'];

                $paymentTransactionParam = [
                    'property_id' => $params['propertyId'],
                    'code' => $paymentCode,
                    'order_id' => $params['orderId'],
                    'transaction_type' => fillOnUndefined($params, 'type', 'BKG'),
                    'payment_type_mapping_id' => $paymentTypeMappingId,
                    'base_amount' => $params['base_amount'],
                    'base_currency' => $params['base_currency'],
                    'exchange_rate' => $exchangeRateStore,
                    'amount' => $params['amount'],
                    'currency' => $paymentType['currency_code'],
                    'installment' => $params['installment'],
                    'params' => json_encode($params),
                    'extra_params' => json_encode($paymentParam),
                    'status' => 2,
                ];

                $paymentTransactionCreate = $this->paymentTransactionRepository->create($paymentTransactionParam);

                if ($paymentTransactionCreate['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                $response = [
                    'status' => true,
                    'data' => [
                        'paymentCode' => $paymentCode,
                        'redirectUrl' => Config::get('app.url') . '/paymentRedirect/' . $paymentCode
                    ],
                ];

            } else {
                throw new ApiErrorException(lang('Payment Type not found'));
            }


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return $response;
    }

    public function checkPayment($paymentCode, $params = [])
    {
        $response = ['status' => false, 'message' => '', 'data' => []];
        try {

            //dd(Input::All());
            $bankOrderId = null;

            $paymentTransactionDetail = $this->getPaymentTransactionDetail($paymentCode);
            if (!$paymentTransactionDetail['status']) {
                throw new ApiErrorException(lang('Payment Transaction not found.'));
            }

            $paymentTransactionDetail = $paymentTransactionDetail['data'];

            $responseUrl = $paymentTransactionDetail['paramsArray']['responseUrl'];
            $response['data']['responseUrl'] = $responseUrl;
            $response['data']['paymentCode'] = $paymentCode;

            if ($paymentTransactionDetail['status'] != 3) {
                Log::error($paymentCode);
                Log::error($params);
                throw new Exception('A previously terminated transaction.');
            }


            if ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'POS') {

                $posAccount = [];
                $posAccount['bank'] = $paymentTransactionDetail['payment_type_mapping']['payment_type']['bank_code'];
                $posAccount['model'] = $paymentTransactionDetail['payment_type_mapping']['payment_type']['threed_model'];
                $posAccount['env'] = $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test';


                foreach ($paymentTransactionDetail['payment_type_mapping']['paramsArray'] as $paramKey => $param) {

                    if (isset($paymentTransactionDetail['payment_type_mapping']['payment_type']['paramsArray'][$paramKey])) {
                        $posAccount[$paymentTransactionDetail['payment_type_mapping']['payment_type']['paramsArray'][$paramKey]['key']] = $param;
                    }
                }

                $POS = new \App\Core\Payment\Pos\Pos($posAccount);

                if (isset($paymentTransactionDetail['paramsArray']['creditCard'])) {
                    $paymentTransactionDetail['paramsArray']['orderParam']['creditCardMonth'] = $paymentTransactionDetail['paramsArray']['creditCard']['month'];
                    $paymentTransactionDetail['paramsArray']['orderParam']['creditCardYear'] = $paymentTransactionDetail['paramsArray']['creditCard']['year'];
                    $paymentTransactionDetail['paramsArray']['orderParam']['creditCardYearCvv'] = $paymentTransactionDetail['paramsArray']['creditCard']['cvv'];
                }

                $POS->prepare($paymentTransactionDetail['paramsArray']['orderParam']);

                $payment = $POS->payment();

                if ($payment->isSuccess()) {

                    $bankOrderId = $payment->response->trans_id;

                    $updateParam = [
                        'bank_order_id' => $bankOrderId,
                        'status' => 1,
                        'message' => null,
                        'response' => json_encode($payment->response),
                    ];
                    $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);
                    if ($paymentTransactionUpdateResult['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }


                } else {

                    $errorMessage = null;


                    if (!empty($payment->response->error_message)) {
                        $errorMessage = $payment->response->error_message;
                    }

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => json_encode($payment->response),
                    ];
                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);
                    if ($updateResult['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }

                    throw new ApiErrorException($payment->response->error_message);
                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'STR') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $secretKey = $paymentTransactionDetail['payment_type_mapping']['paramsArray']['secretKey'];
                        $stripe = new \Stripe\StripeClient($secretKey);

                        $charge = $stripe->charges->create([
                            'currency' => $paymentTransactionDetail['currency'],
                            'amount' => ($paymentTransactionDetail['amount'] * 100),
                            'source' => $params['source'],
                            'description' => $paymentTransactionDetail['code']
                        ]);

                        Log::debug($charge);

                        if ($charge['status'] == 'succeeded') {

                            $bankOrderId = $charge->id;

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($charge),
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new Exception('api-unknown_error');
                            }

                        }


                    } catch (Exception $e) {
                        $errorMessage = $e->getMessage();
                    }
                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($charge) ? json_encode($charge) : null,
                    ];
                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);
                    if ($updateResult['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }

                    throw new ApiErrorException($errorMessage);

                }


            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'ENW') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $secretKey = config('app.stripeENWKey');
                        $stripe = new \Stripe\StripeClient($secretKey);

                        $charge = $stripe->charges->create([
                            'currency' => $paymentTransactionDetail['currency'],
                            'amount' => ($paymentTransactionDetail['amount'] * 100),
                            'source' => $params['source'],
                            'description' => $paymentTransactionDetail['code'] . ' - ' . $paymentTransactionDetail['property_id'] . ' - ' . $paymentTransactionDetail['property']['name']
                        ]);

                        Log::debug($charge);

                        if ($charge['status'] == 'succeeded') {

                            $bankOrderId = $charge->id;

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($charge),
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new Exception('api-unknown_error');
                            }

                        }


                    } catch (Exception $e) {

                        $errorMessage = $e->getMessage();
                    }
                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($charge) ? json_encode($charge) : null,
                    ];
                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);
                    if ($updateResult['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }

                    throw new ApiErrorException($errorMessage);

                }


            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'SPY') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'merchantId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantId'],
                            'merchantKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantKey'],
                            'appKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['appKey'],
                            'appSecret' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['appSecret'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $sipayService = new App\Core\Payment\Sipay\Sipay($paymentInitializeParam);

                        $checkPaymentStatus = $sipayService->checkPaymentStatus($paymentCode);

                        if (isset($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                                throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }

                        if ($params['sipay_status'] == 1 && $checkPaymentStatus['status']) {

                            $bankOrderId = $checkPaymentStatus['data']['order_id'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($params['status_description']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }


            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'MOK') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'userName' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['userName'],
                            'password' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['password'],
                            'dealerCode' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['dealerCode'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $mokaService = new App\Core\Payment\Moka\Moka($paymentInitializeParam);

                        $paramPaymentDetail = [
                            //'PaymentId' => fillOnUndefined($param,'OtherTrxCode'),
                            'OtherTrxCode' => $paymentTransactionDetail['order_id'],
                        ];

                        $getPaymentDetail = $mokaService->getPaymentDetail($paramPaymentDetail);

                        if (!$getPaymentDetail['status']) {
                            throw new ApiErrorException($getPaymentDetail['message']);
                        }

                        if (floatval($paymentTransactionDetail['amount']) != floatval($getPaymentDetail['data']['PaymentDetail']['Amount'])) {
                            throw new Exception('Payment received, but amounts do not match!');
                        }

                        if ($getPaymentDetail['data']['IsSuccessful'] && $getPaymentDetail['data']['PaymentDetail']['TrxStatus'] == 1) {

                            $bankOrderId = $getPaymentDetail['data']['PaymentDetail']['DealerPaymentId'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($getPaymentDetail)
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new Exception('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException(reset($getPaymentDetail['data']['PaymentTrxDetailList'])['ResultMessage']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($getPaymentDetail) ? json_encode($getPaymentDetail) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }


            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'BOG') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {


                        $paymentInitializeParam = [
                            'clientId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['clientId'],
                            'secretKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['secretKey'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $bankOfGeorgiaService = new App\Core\Payment\BankOfGeorgia\Payriff($paymentInitializeParam);


                        $checkoutOrderInfo = $bankOfGeorgiaService->checkoutOrderInfo($paymentTransactionDetail['extraParamsArray']['order_id']);


                        if (!$checkoutOrderInfo['status']) {
                            throw new ApiErrorException($checkoutOrderInfo['message']);
                        }

                        if (floatval($paymentTransactionDetail['amount']) != floatval($checkoutOrderInfo['data']['purchaseUnit']['amount']['value'])) {
                            throw new Exception('Payment received, but amounts do not match!');
                        }


                        if ($checkoutOrderInfo['data']['status'] == 'PERFORMED') {

                            $bankOrderId = $checkoutOrderInfo['data']['id'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkoutOrderInfo)
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new Exception('api-unknown_error');
                            }

                        } else {

                            $errorMessage = $checkoutOrderInfo['data']['message'];

                            $updateParam = [
                                'status' => 0,
                                'message' => $errorMessage,
                                'response' => isset($checkoutOrderInfo) ? json_encode($checkoutOrderInfo) : null,
                            ];

                            $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            throw new ApiErrorException($checkoutOrderInfo['data']['message']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkoutOrderInfo) ? json_encode($checkoutOrderInfo) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }


            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'TBC') {

                $bankOrderId = null;
                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    $paymentInitializeParam = [
                        'clientId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['clientId'],
                        'clientSecret' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['clientSecret'],
                        'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                    ];

                    $tbcBankService = new App\Core\Payment\TBCBankGeorgia\TBCBankGeorgia($paymentInitializeParam);

                    $checkoutOrderInfo = $tbcBankService->checkoutOrderInfo($paymentTransactionDetail['extraParamsArray']['payId']);

                    if (!$checkoutOrderInfo['status']) {
                        //throw new ApiErrorException($checkoutOrderInfo['message']);
                        $errorMessage = $checkoutOrderInfo['message'];
                    }

                    if (floatval($paymentTransactionDetail['amount']) != floatval($checkoutOrderInfo['data']['confirmedAmount'])) {
                        //throw new Exception('Payment received, but amounts do not match!');
                        $errorMessage = 'Payment received, but amounts do not match!';
                    }

                    if (empty($errorMessage)) {

                        $bankOrderId = $checkoutOrderInfo['data']['payId'];

                        if ($checkoutOrderInfo['data']['status'] == 'Succeeded') {

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkoutOrderInfo)
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                //throw new Exception('api-unknown_error');
                                $errorMessage = 'api-unknown_error';
                            }

                        } else {

                            $errorMessage = $checkoutOrderInfo['data']['userMessage'];

                            $updateParam = [
                                'status' => 0,
                                'message' => $errorMessage,
                                'response' => isset($checkoutOrderInfo) ? json_encode($checkoutOrderInfo) : null,
                            ];

                            $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                        }

                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'bank_order_id' => $bankOrderId,
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkoutOrderInfo) ? json_encode($checkoutOrderInfo) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                    throw new ApiErrorException($errorMessage);

                }


            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'QNB') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'merchantId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantId'],
                            'merchantKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantKey'],
                            'appKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['appKey'],
                            'appSecret' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['appSecret'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $qnbPayService = new App\Core\Payment\QNBPay\QNBPay($paymentInitializeParam);

                        $checkPaymentStatus = $qnbPayService->checkPaymentStatus($paymentCode);

                        if (isset($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                                //throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }

                        if ($params['payment_status'] == 1 && $checkPaymentStatus['status']) {

                            $bankOrderId = $checkPaymentStatus['data']['order_id'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($params['status_description']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'WEE') {

                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'merchantId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantId'],
                            'apiKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['apiKey'],
                            'secretKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['secretKey'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $weePayService = new App\Core\Payment\WeePay\WeePay($paymentInitializeParam);

                        $checkPaymentStatus = $weePayService->checkPaymentStatus($paymentCode);

                        if (isset($checkPaymentStatus['data']['price'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['data']['price'])) {
                                throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }

                        if ($params['status'] == 'success' && $checkPaymentStatus['status']) {

                            $bankOrderId = $checkPaymentStatus['data']['paymentId'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($checkPaymentStatus['message']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'HLK') {

                $errorMessage = null;


                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'merchantId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantId'],
                            'merchantKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantKey'],
                            'appKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['appKey'],
                            'appSecret' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['appSecret'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $qnbPayService = new App\Core\Payment\HalkOde\HalkOde($paymentInitializeParam);

                        $checkPaymentStatus = $qnbPayService->checkPaymentStatus($paymentCode);

                        if (isset($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                                //throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }

                        if ($params['payment_status'] == 1 && $checkPaymentStatus['status']) {

                            $bankOrderId = $checkPaymentStatus['data']['order_id'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($params['status_description']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'ESN') {

                $errorMessage = null;


                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'merchant' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchant'],
                            'merchantKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantKey'],
                            'contactMail' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['contactMail'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $esnekPosService = new App\Core\Payment\Esnekpos\Esnekpos($paymentInitializeParam);

                        $checkPaymentStatus = $esnekPosService->checkPaymentStatus($paymentCode);

                        if (isset($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                                //throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }

                        if ($params['RETURN_CODE'] == 0 && $checkPaymentStatus['status']) {

                            $bankOrderId = $checkPaymentStatus['data']['REFNO'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($checkPaymentStatus['message']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'KVY') {

                $errorMessage = null;


                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {

                        $paymentInitializeParam = [
                            'customerId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['customerId'],
                            'merchantId' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['merchantId'],
                            'userName' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['userName'],
                            'password' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['password'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $posService = new App\Core\Payment\KuveytTurk\KuveytTurk($paymentInitializeParam);

                        $checkPaymentStatus = $posService->checkPaymentStatus($paymentCode, $params);

                        //dd($paymentTransactionDetail, $params, $checkPaymentStatus);

                        if (isset($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['serviceResponse']['transaction_amount'])) {
                                //throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }

                        if ($checkPaymentStatus['status']) {

                            $bankOrderId = isset($checkPaymentStatus['data']['ProvisionNumber']) ? $checkPaymentStatus['data']['ProvisionNumber'] : null;

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($checkPaymentStatus['message']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }

                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'RTL') {

                $bankOrderId = null;
                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {


                        $paymentInitializeParam = [
                            'userName' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['userName'],
                            'password' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['password'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $retailPayService = new App\Core\Payment\RetailPay\RetailPay($paymentInitializeParam);

                        if (!isset($params['order_id'])) {
                            throw new ApiErrorException('order_id not found!');
                        }


                        $orderCharge = $retailPayService->orderCharge($params['order_id']);

                        if (!$orderCharge['status']) {
                            throw new ApiErrorException($orderCharge['message']);
                        }

                        $checkPaymentStatus = $retailPayService->checkPaymentStatus($params['order_id']);

                        /*if (isset($checkPaymentStatus['data']['price'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['data']['price'])) {
                                throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }*/


                        if ($checkPaymentStatus['status']) {

                            $bankOrderId = $checkPaymentStatus['data']['id'];

                            $updateParam = [
                                'bank_order_id' => $bankOrderId,
                                'status' => 1,
                                'message' => null,
                                'response' => json_encode($checkPaymentStatus['serviceResponse'])
                            ];
                            $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                            if ($paymentTransactionUpdateResult['status'] != 'success') {
                                throw new ApiErrorException('api-unknown_error');
                            }

                        } else {

                            throw new ApiErrorException($checkPaymentStatus['message']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }


                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($checkPaymentStatus['serviceResponse']) ? json_encode($checkPaymentStatus['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            } elseif ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'PYR') {

                $bankOrderId = null;
                $errorMessage = null;

                if ($paymentTransactionDetail['status'] == 1) {

                    $bankOrderId = $paymentTransactionDetail['bank_order_id'];

                } else {

                    try {


                        $paymentInitializeParam = [
                            'secretKey' => $paymentTransactionDetail['payment_type_mapping']['paramsArray']['secretKey'],
                            'env' => $paymentTransactionDetail['payment_type_mapping']['status'] == 1 ? 'production' : 'test',
                        ];

                        $payriffService = new App\Core\Payment\Payriff\Payriff($paymentInitializeParam);

                        if (!isset($paymentTransactionDetail['extraParamsArray']['payload']['orderId'])) {
                            throw new ApiErrorException('order_id not found!');
                        }


                        $orderInformation = $payriffService->orderInformation($paymentTransactionDetail['extraParamsArray']['payload']['orderId']);

                        if (!$orderInformation['status']) {
                            throw new ApiErrorException($orderInformation['message']);
                        }

                        /*if (isset($checkPaymentStatus['data']['price'])) {
                            if (floatval($paymentTransactionDetail['amount']) != floatval($checkPaymentStatus['data']['price'])) {
                                throw new ApiErrorException('Payment received, but amounts do not match!');
                            }
                        }*/


                        if ($orderInformation['status']) {

                            if ($orderInformation['serviceResponse']['payload']['paymentStatus'] == 'APPROVED') {
                                $bankOrderId = $orderInformation['serviceResponse']['payload']['orderId'];

                                $updateParam = [
                                    'bank_order_id' => $bankOrderId,
                                    'status' => 1,
                                    'message' => null,
                                    'response' => json_encode($orderInformation['serviceResponse'])
                                ];
                                $paymentTransactionUpdateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                                if ($paymentTransactionUpdateResult['status'] != 'success') {
                                    throw new ApiErrorException('api-unknown_error');
                                }

                            } else {

                                throw new ApiErrorException('Payment not confirmed!');
                            }


                        } else {

                            throw new ApiErrorException($orderInformation['message']);

                        }

                    } catch (ApiErrorException $e) {

                        $errorMessage = $e->getMessage();
                    }

                }


                if (!empty($errorMessage)) {

                    $updateParam = [
                        'status' => 0,
                        'message' => $errorMessage,
                        'response' => isset($orderInformation['serviceResponse']) ? json_encode($orderInformation['serviceResponse']) : null,
                    ];

                    $updateResult = $this->paymentTransactionRepository->update($paymentTransactionDetail['id'], $updateParam);

                }

            }

            $response['status'] = true;
            $response['data']['bankOrderId'] = $bankOrderId;


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        //Mask CreditCard Number
        if ($paymentTransactionDetail['payment_type_mapping']['payment_type']['pos_code'] == 'POS') {

            if (isset($paymentTransactionDetail['extraParamsArray']['inputs']['Pan'])) {
                $paymentTransactionDetail['extraParamsArray']['inputs']['Pan'] = creditCardMask($paymentTransactionDetail['extraParamsArray']['inputs']['Pan']);
            } elseif (isset($paymentTransactionDetail['extraParamsArray']['inputs']['pan'])) {
                $paymentTransactionDetail['extraParamsArray']['inputs']['pan'] = creditCardMask($paymentTransactionDetail['extraParamsArray']['inputs']['pan']);
            } elseif (isset($paymentTransactionDetail['extraParamsArray']['inputs']['cardnumber'])) {
                $paymentTransactionDetail['extraParamsArray']['inputs']['cardnumber'] = creditCardMask($paymentTransactionDetail['extraParamsArray']['inputs']['cardnumber']);
            }

            $this->updatePaymentTransaction($paymentTransactionDetail['id'], ['extra_params' => json_encode($paymentTransactionDetail['extraParamsArray'])]);
        }

        $paymentTransactionDetail = $this->getPaymentTransactionDetail($paymentCode);
        $response['data']['paymentTransactionDetail'] = $paymentTransactionDetail['data'];

        return $response;
    }


    /***/

    public function selectPaymentTransaction($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->paymentTransactionRepository->findByCriteria($param, $column);

            $response = [
                'status' => true,
                'data' => $data,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function updatePaymentTransaction($id, $param = [])
    {


        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $updateResult = $this->paymentTransactionRepository->update($id, $param);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $updateData = $updateResult["data"];
            $response = [
                'status' => true,
                'data' => $updateData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function getPaymentTypeList($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $paymentRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
            ];

            $paymentResponse = $this->paymentTypeRepository->findByCriteria($paymentRequest);

            $paymentMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
            ];

            $paymentMappingResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentMappingRequest);
            $paymentMapping = collect($paymentMappingResponse);
            $paymentList = collect($paymentResponse)->map(function ($value) use ($paymentMapping) {
                $hasMapping = $paymentMapping->where("payment_type_id", "=", $value['id'])
                    ->where("status", "!=", 0)
                    ->first();
                return [
                    'id' => $value['id'],
                    'pos_code' => $value['pos_code'],
                    'bank_code' => $value['bank_code'],
                    'threed_model' => $value['threed_model'],
                    'name' => $value['name'],
                    'installment' => $value['installment'],
                    'icon' => $value['icon'],
                    'status' => $value['status'],
                    'bank_params' => $value['paramsArray'],
                    "has_setup" => isset($hasMapping)
                ];


            })->values()->all();


            $response = [
                'status' => true,
                'data' => $paymentList,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function getPaymentMappingList($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $paymentMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['paymentType', 'propertyPaymentMappingInstallments'],
                'orderBy' => [
                    ['field' => 'payment_type_id', 'value' => 'ASC']
                ]
            ];

            if (isset($params['property_payment_mapping_id'])) {
                $paymentMappingRequest['criteria'][] = ['field' => 'id', 'condition' => '=', 'value' => $params['property_payment_mapping_id']];
            }

            $paymentMappingResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentMappingRequest);
            $paymentMappingList = collect($paymentMappingResponse)->map(function ($value) {

                $fieldKeys = $value['paramsArray'];
                $fieldsValues = collect($value['payment_type']['paramsArray'])->map(function ($value, $key) use ($fieldKeys) {
                    $return = $value;
                    $return['value'] = isset($fieldKeys[$key]) ? $fieldKeys[$key] : null;
                    return $return;
                });

                return [
                    'id' => $value['id'],
                    'property_id' => $value['property_id'],
                    'payment_type_id' => $value['payment_type_id'],
                    'payment_type_status' => $value['payment_type']['status'],
                    'currency_code' => $value['currency_code'],
                    'is_default' => $value['is_default'],
                    'pos_code' => $value['payment_type']['pos_code'],
                    'bank_code' => $value['payment_type']['bank_code'],
                    'threed_model' => $value['payment_type']['threed_model'],
                    'name' => $value['payment_type']['name'],
                    'payment_installment' => $value['payment_type']['installment'],
                    'status' => $value['status'],
                    'icon' => $value['payment_type']['icon'],
                    'payment_params_array' => $fieldsValues,
                    'fields' => $fieldKeys,
                    'has_installments' => $value['property_payment_mapping_installments'] ? true : false,
                    'installments' => $value['property_payment_mapping_installments'],
                ];
            })->values();

            $paymentMappingList = isset($params['property_payment_mapping_id']) ? $paymentMappingList->first() : $paymentMappingList->all();


            $response = [
                'status' => true,
                'data' => $paymentMappingList,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function createPaymentMapping($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {
            DB::beginTransaction();

            $validationResult = $this->propertyPaymentMappingCreateValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $paymentType = $this->paymentTypeRepository->find($params['payment_type_id']);
            $paymentMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['paymentType']
            ];
            $oldPaymentResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentMappingRequest);
            $oldPayments = collect($oldPaymentResponse)->map(function ($value) {
                $return = $value;
                $return['pos_code'] = $value['payment_type']['pos_code'];
                return $return;
            });

            $activeMappings = $oldPayments->where('status', '=', 1)->all();
            if ($activeMappings) {
                $isDefault = $params['is_default'];
            } else {
                $isDefault = 1;
            }


            $fields = $params['fields'];
            $fieldsJson = json_encode($fields);

            $insertMapping = [
                'property_id' => $params['property_id'],
                'payment_type_id' => $params['payment_type_id'],
                'params' => $fieldsJson,
                'installment' => $paymentType['installment'] ? $paymentType['installment'] : 0,
                'currency_code' => $params['currency'],
                'is_default' => $isDefault,
                'status' => 1,
                'created_by' => fillOnUndefined($params, "user_id", 0),
                'updated_by' => fillOnUndefined($params, "user_id", 0),
                'created_at' => Carbon::now()->timestamp,
                'updated_at' => Carbon::now()->timestamp,
            ];

            if ($paymentType['pos_code'] == 'POS') {
                if ($params['currency'] == 'TRY') {
                    $hasMapping = $oldPayments->where('currency_code', '=', $params['currency'])
                        ->where('payment_type_id', '=', $params['payment_type_id'])
                        ->first();

                    if (!$hasMapping) {
                        $hasMapping = $oldPayments->where('currency_code', '=', $params['currency'])
                            ->where('pos_code', '!=', 'POS')
                            ->where('status', '=', 1)
                            ->first();
                    }
                } else {
                    $hasMapping = $oldPayments
                        ->where('currency_code', '=', $params['currency'])
                        ->where('status', '=', 1)
                        ->first();
                }
            } else {

                $hasMapping = $oldPayments->where('currency_code', '=', $params['currency'])
                    ->where('status', '=', 1)
                    ->where('pos_code', '!=', 'POS')
                    ->first();
            }

            if ($hasMapping) {
                throw new ApiErrorException('payment mapping error');
            }

            $insertPaymentMapping = $this->propertyPaymentMappingRepository->create($insertMapping);

            if ($insertPaymentMapping['status'] != 'success') {
                throw new ApiErrorException($insertPaymentMapping['message']);
            }
            $insertPaymentMappingData = $insertPaymentMapping['data'];

            if ($params['is_default'] == 1) {
                $updateThisIds = $oldPayments->where('is_default', '=', 1)->keyBy('id')->keys()->all();

                $updateUseMappingData = [
                    "is_default" => 0,
                    "updated_by" => $params['user_id'],
                    'updated_at' => time()
                ];

                $updateResult = $this->propertyPaymentMappingRepository->updateWhereIn($updateThisIds, $updateUseMappingData);
                if ($updateResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }

            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
            DB::rollBack();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            DB::rollBack();
        }

        return output($response);

    }

    public function updatePaymentMappingStatus($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            DB::beginTransaction();

            $validationResult = $this->propertyPaymentMappingStatusUpdateValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }


            $paymentMapping = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['paymentType']
            ];

            $oldPaymentResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentMapping);
            $oldPayments = collect($oldPaymentResponse)->map(function ($value) {
                $return = $value;
                $return['pos_code'] = $value['payment_type']['pos_code'];
                return $return;
            });


            $thisPaymentMapping = $oldPayments->where('id', '=', $params['property_payment_mapping_id'])->first();
            if (!$thisPaymentMapping) {
                throw new Exception('api-unknown_error');
            }
            $hasMapping = null;

            if ($params['set_status'] == 1) {
                if ($thisPaymentMapping['pos_code'] == 'POS') {
                    if ($thisPaymentMapping['currency_code'] == 'TRY') {
                        $hasMapping = $oldPayments
                            ->where('currency_code', '=', $thisPaymentMapping['currency_code'])
                            ->where('payment_type_id', '=', $thisPaymentMapping['payment_type_id'])
                            ->where('id', '!=', $thisPaymentMapping['id'])
                            ->first();

                        if (!$hasMapping) {
                            $hasMapping = $oldPayments->where('currency_code', '=', $thisPaymentMapping['currency_code'])
                                ->where('pos_code', '!=', 'POS')
                                ->where('status', '=', 1)
                                ->first();
                        }
                    } else {
                        $hasMapping = $oldPayments
                            ->where('currency_code', '=', $thisPaymentMapping['currency_code'])
                            ->where('status', '=', 1)
                            ->first();
                    }
                } else {
                    $hasMapping = $oldPayments->where('currency_code', '=', $thisPaymentMapping['currency_code'])
                        ->where('status', '=', 1)
                        ->first();
                }

                if ($hasMapping) {
                    throw new ApiErrorException('payment mapping error');
                }

            }


            $updateMappingCriteria = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_payment_mapping_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];

            $updateUseMappingData = [
                "status" => $params['set_status'],
                "updated_by" => $params['user_id'],
                'updated_at' => time()
            ];

            $updateResult = $this->propertyPaymentMappingRepository->updateWhere($updateMappingCriteria, $updateUseMappingData);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $thisPaymentMapping['status'] = $params['set_status'];

            $response = [
                'status' => true,
                'data' => $thisPaymentMapping,
            ];

            DB::commit();
        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
            DB::rollBack();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            DB::rollBack();
        }

        return output($response);

    }

    public function setPaymentMappingDefault($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            DB::beginTransaction();

            $validationResult = $this->propertyPaymentMappingSetDefaultValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $updateMappingCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'is_default', 'condition' => '=', 'value' => 1],
                ]
            ];

            $updateResult = $this->propertyPaymentMappingRepository->findByCriteria($updateMappingCriteria, ['id']);
            $updateThisIds = collect($updateResult)->keyBy('id')->keys()->all();

            $updateUseMappingData = [
                "is_default" => 0,
                "updated_by" => $params['user_id'],
                'updated_at' => time()
            ];

            $updateResult = $this->propertyPaymentMappingRepository->updateWhereIn($updateThisIds, $updateUseMappingData);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }


            $updateUseMappingData = [
                "is_default" => 1,
                "updated_by" => $params['user_id'],
                'updated_at' => time()
            ];

            $updateResult = $this->propertyPaymentMappingRepository->update($params['property_payment_mapping_id'], $updateUseMappingData);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $response = [
                'status' => true,
                'data' => null,
            ];

            DB::commit();
        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
            DB::rollBack();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            DB::rollBack();
        }

        return output($response);

    }

    public function updatePaymentMapping($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            DB::beginTransaction();

            $validationResult = $this->propertyPaymentMappingUpdateValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $paymentTypeRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_payment_mapping_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['paymentType'],
                'firstRow' => 1
            ];
            $paymentTypeResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentTypeRequest);
            if (!isset($paymentTypeResponse['payment_type']['paramsArray'])) {
                throw new ApiErrorException('payment mapping error');
            }

            $getPaymentParams = $paymentTypeResponse['payment_type']['paramsArray'];
            $fields = $params['fields'];

            foreach ($getPaymentParams as $key => $getPaymentParam) {
                if (!isset($fields[$key])) {
                    throw new ApiErrorException('field error');
                }
            }

            $fieldsJson = json_encode($fields);
            $updateMapping = [
                'params' => $fieldsJson,
                'is_default' => $params['is_default'],
                'updated_by' => fillOnUndefined($params, "user_id", 0),
                'updated_at' => Carbon::now()->timestamp,
            ];

            $updatePaymentMapping = $this->propertyPaymentMappingRepository->update($params['property_payment_mapping_id'], $updateMapping);
            if ($updatePaymentMapping['status'] != 'success') {
                throw new ApiErrorException($updatePaymentMapping['message']);
            }

            if ($params['is_default'] == 1) {
                $oldPaymentMappingRequest = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                        ['field' => 'id', 'condition' => '!=', 'value' => $params['property_payment_mapping_id']],
                    ],
                    'with' => ['paymentType']
                ];
                $oldPaymentResponse = $this->propertyPaymentMappingRepository->findByCriteria($oldPaymentMappingRequest);
                $oldPayments = collect($oldPaymentResponse)
                    ->where('is_default', '=', 1)
                    ->map(function ($value) {
                        $return = $value;
                        $return['pos_code'] = $value['payment_type']['pos_code'];
                        return $return;
                    });

                $updateThisIds = $oldPayments->keyBy('id')->keys()->all();
                $updateUseMappingData = [
                    "is_default" => 0,
                    "updated_by" => $params['user_id'],
                    'updated_at' => time()
                ];

                $updateResult = $this->propertyPaymentMappingRepository->updateWhereIn($updateThisIds, $updateUseMappingData);
                if ($updateResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }

            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
            DB::rollBack();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            DB::rollBack();
        }

        return output($response);

    }

    public function updateInstallments($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            DB::beginTransaction();


            $validationResult = $this->propertyPaymentInstallmentsUpdateValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $updateMapping = [
                'installment' => $params['has_installments'] ? 1 : 0,
                'updated_by' => fillOnUndefined($params, "user_id", 0),
                'updated_at' => Carbon::now()->timestamp,
            ];

            $updatePaymentMapping = $this->propertyPaymentMappingRepository->update($params['property_payment_mapping_id'], $updateMapping);
            if ($updatePaymentMapping['status'] != 'success') {
                throw new ApiErrorException($updatePaymentMapping['message']);
            }

            $paymentTypeRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_payment_mapping_id']],
                ],
                'with' => ['paymentType', 'propertyPaymentMappingInstallments'],
                'firstRow' => 1
            ];
            $paymentTypeResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentTypeRequest);

            if (!isset($paymentTypeResponse['payment_type']['paramsArray'])) {
                throw new ApiErrorException('payment mapping error');
            }


            if ($paymentTypeResponse['payment_type']['installment'] != 1) {
                throw new ApiErrorException('installments access error');
            }
            $oldInstallments = $paymentTypeResponse['property_payment_mapping_installments'];
            $oldInstallments = collect($oldInstallments);

            $installmentArray = [];
            foreach ($params['installments'] as $installment) {

                $checkHasInstallment = $oldInstallments->where('installment', '=', $installment['installment'])->first();

                if ($checkHasInstallment) {
                    $updateInstallmentData = [
                        'commission' => fillOnUndefinedAndEmpty($installment, 'commission', 0),
                        'updated_by' => fillOnUndefined($params, "user_id", 0),
                        'updated_at' => Carbon::now()->timestamp,
                    ];

                    $updateInstallment = $this->propertyPaymentInstallmentRepository->update($checkHasInstallment['id'], $updateInstallmentData);
                    if ($updateInstallment['status'] != 'success') {
                        throw new ApiErrorException($updateInstallment['message']);
                    }

                } else {
                    $installmentArray[] = [
                        'property_id' => $params['property_id'],
                        'property_payment_mapping_id' => $params['property_payment_mapping_id'],
                        'installment' => $installment['installment'],
                        'commission' => fillOnUndefinedAndEmpty($installment, 'commission', 0),
                        'status' => 1,
                        'created_by' => fillOnUndefined($params, "user_id", 0),
                        'updated_by' => fillOnUndefined($params, "user_id", 0),
                        'created_at' => Carbon::now()->timestamp,
                        'updated_at' => Carbon::now()->timestamp,
                    ];
                }
            }

            if ($installmentArray) {
                $insertPaymentMapping = $this->propertyPaymentInstallmentRepository->insert($installmentArray);
                if ($insertPaymentMapping['status'] != 'success') {
                    throw new ApiErrorException($insertPaymentMapping['message']);
                }
            }

            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
            DB::rollBack();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            DB::rollBack();
        }

        return output($response);

    }

    public function updatePaymentInstallmentStatus($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $paymentInstallmentRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['installment_id']],
                    ['field' => 'property_payment_mapping_id', 'condition' => '=', 'value' => $params['property_payment_mapping_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'firstRow' => 1
            ];
            $installmentResponse = $this->propertyPaymentInstallmentRepository->findByCriteria($paymentInstallmentRequest);

            if (!$installmentResponse) {
                throw new Exception('api-unknown_error');
            }

            $updateInstallmentData = [
                'status' => fillOnUndefinedAndEmpty($params, 'set_status', 0),
                'updated_by' => fillOnUndefined($params, "user_id", 0),
                'updated_at' => Carbon::now()->timestamp,
            ];

            $updateInstallment = $this->propertyPaymentInstallmentRepository->update($installmentResponse['id'], $updateInstallmentData);
            if ($updateInstallment['status'] != 'success') {
                throw new ApiErrorException($updateInstallment['message']);
            }

            $response = [
                'status' => true,
                'data' => null,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function getPaymentType($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $paymentRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['payment_type_id']],
                ],
                'firstRow' => 1
            ];

            $paymentResponse = $this->paymentTypeRepository->findByCriteria($paymentRequest);
            if (!$paymentResponse) {
                throw new Exception('api-unknown_error');
            }

            $paymentMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'payment_type_id', 'condition' => '=', 'value' => $params['payment_type_id']],
                ],
                'with' => ['paymentType', 'propertyPaymentMappingInstallments'],
                'orderBy' => [
                    ['field' => 'payment_type_id', 'value' => 'ASC']
                ]
            ];
            $paymentMappingResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentMappingRequest);
            $paymentMappingResponse = collect($paymentMappingResponse);

            $currencyList = $this->currencyService->getCurrencyList();
            if ($currencyList['status'] != 'success') {
                throw new Exception($currencyList['message']);
            }

            $currencyList = collect($currencyList['data'])->map(function ($value) use ($paymentMappingResponse, $paymentResponse) {
                $thisMapping = $paymentMappingResponse->where('currency_code', '=', $value['code'])->first();

                $installments = collect(isset($thisMapping) ? $thisMapping['property_payment_mapping_installments'] : []);
                $installmentArray = [];
                for ($i = 1; $i <= 12; $i++) {
                    $installment = $installments->where('installment', '=', $i)->first();
                    $installmentArray[] = [
                        "installment_id" => isset($installment) ? $installment['id'] : null,
                        "installment" => $i,
                        "commission" => isset($installment) ? $installment['commission'] : null,
                        "has_installments" => isset($installment),
                        "status" => $installment['status'] ? $installment['status'] : 0,
                    ];
                }

                return [
                    'code' => $value['code'],
                    'name' => $value['name'],
                    'id' => isset($thisMapping) ? $thisMapping['id'] : null,
                    'bank_params' => isset($paymentResponse) ? $paymentResponse['paramsArray'] : null,
                    'language_key' => $value['language_key'],
                    'fields' => isset($thisMapping) ? $thisMapping['paramsArray'] : null,
                    'has_installments' => isset($thisMapping) ? $thisMapping['installment'] : 0,
                    'status' => isset($thisMapping) && $thisMapping['status'] == 1 ? 1 : 0,
                    'is_default' => isset($thisMapping) ? $thisMapping['is_default'] : null,
                    'installments' => isset($thisMapping['installment']) && $thisMapping['installment'] ? $installmentArray : []
                ];
            })->values()->all();

            $getPayment = [
                'id' => $paymentResponse['id'],
                'pos_code' => $paymentResponse['pos_code'],
                'bank_code' => $paymentResponse['bank_code'],
                'threed_model' => $paymentResponse['threed_model'],
                'name' => $paymentResponse['name'],
                'installment' => $paymentResponse['installment'],
                'icon' => $paymentResponse['icon'],
                'status' => $paymentResponse['status'],
                'currencies' => $currencyList,
            ];

            $response = [
                'status' => true,
                'data' => $getPayment,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function createManualPayment($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            if ($params['payment_type_mapping_id']) {
                $paymentRequest = [
                    'criteria' => [
                        ['field' => 'status', 'condition' => '!=', 'value' => 0],
                        ['field' => 'id', 'condition' => '=', 'value' => $params['payment_type_mapping_id']],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ],
                    'firstRow' => 1
                ];
                $paymentResponse = $this->propertyPaymentMappingRepository->findByCriteria($paymentRequest);
                if (!$paymentResponse) {
                    throw new Exception('api-unknown_error');
                }
            }

            $validationResult = $this->propertyPaymentTransactionCreateValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $orderId = getCodeGenerate('LNK');
            $baseAmount = fillOnUndefined($params, 'base_amount');
            $commission = fillOnUndefined($params, 'commission');
            $amount = $baseAmount + (($baseAmount * $commission) / 100);

            $paramsColumn = [
                "title" => fillOnUndefined($params, 'title'),
                "description" => fillOnUndefined($params, 'description'),
                "email" => fillOnUndefined($params, 'email'),
                "base_amount" => $baseAmount,
                "commission" => $commission,
                "amount" => $amount

            ];

            $insertData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'payment_type_mapping_id' => fillOnUndefined($params, 'payment_type_mapping_id'),
                    'code' => null,
                    'order_id' => $orderId,
                    'transaction_type' => 'LNK',
                    'bank_order_id' => null,
                    'base_amount' => $amount,
                    'base_currency' => fillOnUndefined($params, 'currency'),
                    'exchange_rate' => 1,
                    'amount' => $amount,
                    'currency' => fillOnUndefined($params, 'currency'),
                    'installment' => 0,
                    'params' => json_encode($paramsColumn),
                    "status" => fillOnUndefined($params, "status", 5),
                    "created_by" => fillOnUndefined($params, "user_id", null),
                ];


            $userCreateResult = $this->paymentTransactionRepository->create($insertData);


            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $userCreateResult["data"];

            $userData['payment_link'] = Config::get('app.paymentFormLink') . $userData['order_id'];

            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function updateManualPayment($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $validationResult = $this->propertyPaymentTransactionUpdateValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $paymentRequest = [
                'criteria' => [
                    ['field' => 'order_id', 'condition' => '=', 'value' => $params['order_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];
            $paymentResponse = $this->paymentTransactionRepository->findByCriteria($paymentRequest);
            if (!$paymentResponse) {
                throw new Exception('api-unknown_error');
            }

            $paymentTransactions = collect($paymentResponse);

            $hasSuccessTransaction = $paymentTransactions->whereNotIn('status', [0, 5])->count();

            if ($hasSuccessTransaction) {
                throw new Exception('enw-payment-payment_link-paid_payment-message');
            }

            $updateMe = $paymentTransactions->where('status', '=', 5)->first();
            $paymentTransactionId = $updateMe['id'];

            $baseAmount = fillOnUndefined($params, 'base_amount');
            $commission = fillOnUndefined($params, 'commission');
            $amount = $baseAmount + (($baseAmount * $commission) / 100);

            $paramsColumn = [
                "title" => fillOnUndefined($params, 'title'),
                "description" => fillOnUndefined($params, 'description'),
                "email" => fillOnUndefined($params, 'email'),
                "base_amount" => $baseAmount,
                "commission" => $commission,
                "amount" => $amount

            ];

            $updateData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'payment_type_mapping_id' => fillOnUndefined($params, 'payment_type_mapping_id'),
                    'base_amount' => $amount,
                    'base_currency' => fillOnUndefined($params, 'currency'),
                    'exchange_rate' => 1,
                    'amount' => $amount,
                    'currency' => fillOnUndefined($params, 'currency'),
                    'params' => json_encode($paramsColumn),
                ];


            $userCreateResult = $this->paymentTransactionRepository->update($paymentTransactionId, $updateData);

            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $userCreateResult["data"];

            $userData['payment_link'] = Config::get('app.paymentFormLink') . $userData['order_id'];

            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function createManualPaymentForm($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $currencyList = $this->currencyService->getCurrencyList();
            if ($currencyList['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData['currency_list'] = $currencyList['data'];

            $paymentMappingList = $this->getPaymentMappingList($params);
            if ($paymentMappingList['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $userData['payment_mapping_list'] = $paymentMappingList['data'];


            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function editManualPaymentForm($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $currencyList = $this->currencyService->getCurrencyList();
            if ($currencyList['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData['currency_list'] = $currencyList['data'];

            $paymentMappingList = $this->getPaymentMappingList($params);
            if ($paymentMappingList['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $userData['payment_mapping_list'] = $paymentMappingList['data'];


            $paymentRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['payment_transaction_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];
            $paymentResponse = $this->paymentTransactionRepository->findByCriteria($paymentRequest);
            if (!$paymentResponse) {
                throw new Exception('api-unknown_error');
            }

            $paymentTransactions = collect($paymentResponse);

            $hasSuccessTransaction = $paymentTransactions->whereNotIn('status', [0, 5])->count();

            if ($hasSuccessTransaction) {
                throw new Exception('api-unknown_error');
            }

            $updateMe = $paymentTransactions->where('status', '=', 5)->first();

            $userData['manual_payment_data'] = $updateMe;

            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

    public function getManualPayment($params)
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $paymentRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['payment_transaction_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['relatedTransactions'],
                'firstRow' => 1
            ];
            $paymentResponse = $this->paymentTransactionRepository->findByCriteria($paymentRequest);
            if (!$paymentResponse) {
                throw new ApiErrorException('api-unknown_error');
            }

            $paymentResponse['payment_link'] = $paymentResponse['status'] == 5 && $paymentResponse['transaction_type'] != 'BKG' ? Config::get('app.paymentFormLink') . $paymentResponse['order_id'] : null;

            $response = [
                'status' => true,
                'data' => $paymentResponse,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);

    }

}
