HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/topswtw.komma.pro/app/KommaApp/Shop/Checkout/Payment/PaymentService.php
<?php


namespace KommaApp\Shop\Checkout\Payment;

use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use KommaApp\Shop\Modules\Kiyoh\KiyohService;
use KommaApp\Shop\Orders\Order;
use KommaApp\Shop\Orders\OrderTransaction;
use KommaApp\Shop\Orders\OrderRepository;
use KommaApp\Shop\FormValidation\CompletePendingPaymentForm;
use Sokil\IsoCodes\Database\Subdivisions\Subdivision;

class PaymentService
{
    /**
     * @var ShaSign
     */
    private $shaSign;
    /**
     * @var Order
     */
    private $orderModel;

    /**
     * @var IngenicoService
     */
    private $ingenicoService;
    /**
     * @var OrderTransaction
     */
    private $orderTransaction;
    /**
     * @var OrderRepository
     */
    private $orderRepository;
    /**
     * @var CompletePendingPaymentForm
     */
    private $completePendingPaymentForm;
    /**
     * @var KiyohService
     */
    private $kiyohService;

    /**
     * @param ShaSign                    $shaSign
     * @param IngenicoService            $ingenicoService
     * @param Order                      $orderModel
     * @param OrderTransaction           $orderTransaction
     * @param OrderRepository            $orderRepository
     * @param CompletePendingPaymentForm $completePendingPaymentForm
     * @param KiyohService               $kiyohService
     */
    public function __construct(
        ShaSign $shaSign,
        IngenicoService $ingenicoService,
        Order $orderModel,
        OrderTransaction $orderTransaction,
        OrderRepository $orderRepository,
        CompletePendingPaymentForm $completePendingPaymentForm,
        KiyohService $kiyohService)
    {
        $this->shaSign = $shaSign;
        $this->ingenicoService = $ingenicoService;
        $this->orderModel = $orderModel;
        $this->orderTransaction = $orderTransaction;
        $this->orderRepository = $orderRepository;
        $this->completePendingPaymentForm = $completePendingPaymentForm;
        $this->kiyohService = $kiyohService;
    }

    public function ingenicoService()
    {
        return $this->ingenicoService;
    }

    /**
     * Create a form for Ingenico with all the order data
     * @param $data
     * @return \View
     */
    public function form($data)
    {
        // Create a new transaction for the Order with id: $data['orderId']
        /** @var Order $order */
        $order = $this->orderModel->find($data['orderId']);
        $transaction = $order->createNewTransaction();
        $data['orderId'] = $transaction->custom_identifier;

        // Url for redirect
        $paymentUrl = \Config::get('komma/ingenico.paymentUrl');

        // Default form data
        $default = $this->ingenicoService->defaultFormData($order->order_token);

        if($data['pm'] == 'CreditCard') {
            //It now is required to add the operation field for two stage creditcard payments.
            $data['operation'] = 'SAL'; //SAL: request for sale (payment), RES: request for authorization, PAU: Request for pre-authorization
        }

        //Gather data for paypal seller protection
        if($data['pm'] == "PAYPAL") {
            $data['ECOM_SHIPTO_POSTAL_NAME_FIRST'] = $order->shipping_first_name;
            $data['ECOM_SHIPTO_POSTAL_NAME_LAST'] = $order->shipping_last_name;
            $data['ECOM_SHIPTO_POSTAL_STREET_LINE1'] = $order->shipping_street;
            $data['ECOM_SHIPTO_POSTAL_STREET_LINE2'] = implode(' ',[$order->shipping_house_number, $order->shipping_house_number_suffix]);

            $data['ECOM_SHIPTO_POSTAL_COUNTRYCODE'] = $order->shipping_country; //Two letter country code. Like NL, EN
            $data['ECOM_SHIPTO_POSTAL_CITY'] = $order->shipping_city;
            $data['ECOM_SHIPTO_POSTAL_POSTALCODE'] = $order->shipping_postal;
            //$data['ECOM_SHIPTO_POSTAL_STATE'] //Is already included
        }

//        dd($data);
        // Create the shaSign from all the $data for the Ingenico security check
        $default['shaSign'] = $this->shaSign->create(array_merge($data, $default));

        if (isset($data['issuerId']) && !empty($data['issuerId'])) {
            $transaction->payment_issuer_id = $data['issuerId'];
        }

        $transaction->payment_method = $data['brand'];
        $transaction->save();

        // Return View
        return \View::make('checkout.payment.ingenico.paymentForm')->with([
            'data' => $data,
            'default' => $default,
            'url' => $paymentUrl
        ]);
    }

    /*
     * Process the form
     */
    public function processPaymentProviderResponse()
    {
        $paymentData = \Input::all();
        //\Input::except trows an error, so use all and unset SHASIGN
        unset($paymentData['SHASIGN']);

        // Todo: technical error page
        if ($this->shaSign->create($paymentData) != \Input::get('SHASIGN'))
            return ['paymentData' => 'unvalid!'];

        // Get order by transaction id
        if (!$order = $this->orderModel->findByCustomTransactionIdentifier($paymentData['orderID'])) {
            return ['paymentData' => 'unvalid!'];
        }

        // Make sure array keys are upper case
        $paymentData = array_change_key_case($paymentData, CASE_UPPER);

        // Update payment in database
        $this->updatePaymentInDatabase($paymentData);

        return ['paymentData' => $paymentData, 'order' => $order];
    }

    /*
     * Process complete pending payment
     */
    public function processPending()
    {
        // Because this route isn't in the database we manually need to boot the languageService
        \Shop::getLanguageService()->bootFromUri(\Shop::getId());

        // Get form data
        $inputData = \Input::all();

        // Validate fom data
        if (!$this->completePendingPaymentForm->isValid($inputData)) {
            return \Redirect::back()
                ->withErrors($this->completePendingPaymentForm->errorMessages());
        }

        // Validate form
        // Get Payment method and brand
        $token = \Input::get('token');
        $paymentData = $this->ingenicoService->paymentData($inputData);

        // Get Form data (name, address etc.)
        $order = $this->orderRepository->getOrderFromToken($token);
        $formData = $this->ingenicoService->formData($order->toArray());

        // Set data for form
        $data = array_merge(['orderId' => $order->id], $paymentData, $formData);

        return $this->form($data);
    }

    /**
     * Update payment fields in database
     * @param (upper case keys) $paymentData
     */
    protected function updatePaymentInDatabase($paymentData)
    {
        // Fill data and save order
        $data = [];

        // Translate DB_TABLE_NAME => ARRAY_KEY
        $translateArray = [
            'payment_method' => 'PM',
            'payment_date' => 'TRXDATE',
            'payment_status' => 'STATUS',
            'payment_currency' => 'CURRENCY',
            'payment_acceptance' => 'ACCEPTANCE',
            'payment_card_number' => 'CARDNO',
            'payment_cardholder_name' => 'CN',
            'payment_provider_id' => 'PAYID',
            'payment_error_code' => 'NCERROR',
            'payment_card_brand' => 'BRAND',
            'payment_ip' => 'IP',
            'payment_issuer_id' => 'ISSUERID'
        ];
        foreach ($translateArray as $databaseField => $providerField) {
            if ($databaseField == 'payment_date')
                $paymentData[$providerField] = $this->convertPaymentDate($paymentData[$providerField]);

            if (isset($paymentData[$providerField])) $data[$databaseField] = mb_convert_encoding($paymentData[$providerField],'utf-8');
        }

        // Find order and update data
        $orderTransaction = $this->orderTransaction->where('custom_identifier', $paymentData['ORDERID'])->first();
        if (!$orderTransaction
            ->fill($data)
            ->save()
        ) ;
    }

    /**
     * @param $dateString
     * @return static
     */
    protected function convertPaymentDate($dateString)
    {
        $temp = explode('/', $dateString);
        if (count($temp) == 3) {
            $year = (int)'20' . $temp[2];
            $month = (int)$temp[0];
            $day = (int)$temp[1];

            return Carbon::createFromDate($year, $month, $day);
        }
        return null;
    }

    /*
     * Get optional payment methods
     * @return Array
     */
    public function getPaymentMethods()
    {
        $methods['default'] = [
            'iDeal',
            'bancontactMisterCash',
            'sofort_de',
            'masterCard',
            'maestro',
            'visa',
            'ingHomePay',
            'belfius',
            'giropay',
            'cbcOnline',
            'kbcOnline',
            'bankTransfer_nl',
            'bankTransfer_de',
        ];
        //methods / shopCountry
        $methods['NL'] = [
            'iDeal',
            'bancontactMisterCash',
            'visa',
            'masterCard',
            'maestro',
            'payPal',
            'ingHomePay',
            'belfius',
            'cbcOnline',
            'kbcOnline',
            'bankTransfer_nl'
        ];

        $methods['BE'] = [
            'bancontactMisterCash',
            'visa',
            'masterCard',
            'maestro',
            'payPal',
            'ingHomePay',
            'belfius',
            'cbcOnline',
            'kbcOnline',
            'iDeal',
            'bankTransfer_nl'
        ];

        $methods['DE'] = [
            'sofort_de',
            'payPal',
            'giropay',
            'masterCard',
            'maestro',
            'visa',
            'bancontactMisterCash',
            'belfius',
            'cbcOnline',
            'kbcOnline',
            'bankTransfer_de'
        ];

        $methods['AT'] = [
            'sofort_de',
            'payPal',
            'giropay',
            'masterCard',
            'maestro',
            'visa',
            'bancontactMisterCash',
            'belfius',
            'cbcOnline',
            'kbcOnline',
            'bankTransfer_de'
        ];
        $methods['GB'] = [
            'masterCard',
            'visa',
            'payPal',
            'maestro',
            'sofort_de',
            'iDeal',
            'bancontactMisterCash',
            'giropay',
            'bankTransfer_nl',
        ];

        // Select methods based on the country of the domain
        $country_iso = \Shop::getDomainCountry();
        isset($methods[$country_iso]) ? $paymentMethods = $methods[$country_iso] : $paymentMethods = $methods['default'];

        // Generate array
        $list = [];
        $first = true;
        foreach ($paymentMethods as $paymentMethod) {

            //Check if the payment exist in the config
            if (!\Config::has('komma/ingenico.paymentMethods.' . $paymentMethod)) continue;

            //Set the payment from the config
            $payment = \Config::get('komma/ingenico.paymentMethods.' . $paymentMethod);

            //Check if there is an translation for this payment
            if (\Lang::has('checkout/payment.' . $paymentMethod)) {
                //if so merge this with the current payment
                $payment = array_merge($payment, \Lang::get('checkout/payment.' . $paymentMethod));
            }
            //If this isnt the first run set the streamer to null
            if (!$first) $payment['streamer'] = null;
            //set first to false
            $first = false;
            //add the payment to the list
            $list[$paymentMethod] = $payment;
        }
        return $list;
    }

    public function paymentLink($orderId)
    {
        //return url() . '/' . \Shop::getPageService()->page('pendingPayment')->route . '?token=' .$token;
    }

    /**
     * @param $paymentData
     * @return mixed
     */
    public function redirectUsingStatus($paymentData, $order)
    {

        // Token
        $withToken = '?token=' . $order->order_token;

        // Routes
        $paymentCancelRoute = \Shop::getPageService()->page('paymentToCancel')->route;
        $paymentFailedRoute = \Shop::getPageService()->page('paymentFailed')->route;
        $checkoutThanksRoute = \Shop::getPageService()->page('checkoutThanks')->route;
        $waitingRoute = \Shop::getPageService()->page('waiting')->route;

        $status = (int)$paymentData['STATUS'];
        switch ($status) {
            // 0: Incomplete or invalid
            case 0:

                // 1: Cancelled by client
            case 1:
                return \Redirect::to($paymentCancelRoute . $withToken);
                // 2: Payment Failed
            case 2:
                return \Redirect::to($paymentFailedRoute . $withToken);

            // Waiting on client payment (F.e. BankTransfer)
            case 41:
                return \Redirect::to($waitingRoute . $withToken);

            // 9: Payment requested
            case 9:

                return \Redirect::to($checkoutThanksRoute . $withToken);

            // No status: redirect to payment failed
            default:
                return \Redirect::to($paymentFailedRoute . $withToken);

        }
    }

    /**
     * The method that will change the order status.
     */
    public function changeOrderStatus($paymentData, $order)
    {

        $status = (int)$paymentData['STATUS'];
        switch ($status) {
            // 0: Incomplete or invalid
            case 0:

                // 1: Cancelled by client
            case 1:
            case 2:
                break;

            // Waiting on client payment (F.e. BankTransfer)
            case 41:
                break;

            // 9: Payment requested
            case 9:

                if ($order->status != Order::OPEN) {
                    return 'Status is already changed';
                }

                $order->status = Order::PAYED;

                $order->save();

                //todo: Het mailen zou eigenlijk via CustomerMailer moeten lopen
                // Dit wil TOPS voorlopig handmatig doen
                //$this->kiyohService->sendReviewEmailToCustomer($order);

                $data = $order->toArray();
                $data['order'] = $order;


                //send mail with the customerMailer

                $customerMailer = \App::make('KommaApp\Shop\Mailers\CustomerMailer');


                $customerMailer->sendOrderPayed($order);


                break;

            // No status: redirect to payment failed
            default:
                break;

        }
        return 'Status changed';
    }


    /***
     * This method will search for the order by token.
     * And set the status of the order to CANCELLED
     *
     * @param $token
     * @return bool
     */
    public function cancelOrderWithToken($token){

        if(!$order = $this->orderRepository->getOrderFromToken($token)){
            return false;
        }
        $order->status = Order::CANCELLED;
        $order->save();

        return true;
    }

}