HEX
Server: Apache
System: Linux webm019.cluster128.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: petsclubcc (68997)
PHP: 5.4.45
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/petsclubcc/shop/modules/amazonpay/src/classes/AmazonPayCheckoutSession.php
<?php
/**
 * 2007-2021 patworx.de
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade AmazonPay to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 *  @author    patworx multimedia GmbH <service@patworx.de>
 *  @copyright 2007-2021 patworx multimedia GmbH
 *  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 */

class AmazonPayCheckoutSession
{

    protected $amazon_pay_checkout_session_id = false;
    protected $status = false;
    protected $rawClientResponse;
    protected $client;
    protected $last_message;

    /**
     * AmazonPayCheckoutSession constructor.
     * @param bool $create_if_not_valid
     * @param mixed $manual_id
     * @throws Exception
     */
    public function __construct($create_if_not_valid = true, $manual_id = false)
    {
        $this->client = AmazonPayHelper::getClient();
        if ($manual_id) {
            $this->amazon_pay_checkout_session_id = $manual_id;
        } else {
            if (isset(Context::getContext()->cookie->amazon_pay_checkout_session_id)) {
                if ($this->isValid(Context::getContext()->cookie->amazon_pay_checkout_session_id)) {
                    $this->amazon_pay_checkout_session_id = Context::getContext()->cookie->amazon_pay_checkout_session_id;
                    $this->status = true;
                }
            }
            if (!$this->amazon_pay_checkout_session_id && $create_if_not_valid) {
                $this->status = $this->createNewCheckoutSession();
            }
        }
    }

    /**
     * @return bool
     */
    public function checkStatus()
    {
        return $this->status;
    }

    /**
     * @return json
     */
    public function jsonReturn()
    {
        return $this->rawClientResponse;
    }

    /**
     * @return array
     */
    public function assocReturn()
    {
        return json_decode($this->rawClientResponse, true);
    }

    /**
     * @param bool $returnPayload
     * @return array|bool
     */
    public function createNewCheckoutSession($returnPayload = false)
    {
        $initParams = [];
        if ($returnPayload) {
            $initParams = [
                'decoupled' => '1'
            ];
        }
        $payload = array(
            'webCheckoutDetails' => array(
                'checkoutReviewReturnUrl' => Context::getContext()->link->getModuleLink(
                    'amazonpay',
                    'initcheckout',
                    $initParams
                ),
                'checkoutResultReturnUrl' => Context::getContext()->link->getModuleLink(
                    'amazonpay',
                    'validation'
                )
            ),
            'platformId' => Amazonpay::$pfid,
            'storeId' => Configuration::get('AMAZONPAY_STORE_ID'),
            'paymentDetails' => [
                'presentmentCurrency' => AmazonPayHelper::getCurrentCurrency(),
            ],
        );
        $allowedDestinations = $this->getAllowedDestinations();
        if (sizeof($allowedDestinations) > 0) {
            $payload['deliverySpecifications'] = [
                'addressRestrictions' => [
                    'type' => 'Allowed',
                    'restrictions' => $this->getAllowedDestinations()
                ]
            ];
        }
        if ($returnPayload) {
            return $payload;
        }
        $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
        try {
            $result = $this->client->createCheckoutSession($payload, $headers);
            if ($result['status'] === 201) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $checkoutSessionId = $response['checkoutSessionId'];
                $this->amazon_pay_checkout_session_id = $checkoutSessionId;
                $this->saveSession();
                return true;
            } else {
                $this->logStatusError('createCheckoutSession', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('captureCharge', $e, $result);
            return false;
        }
    }

    /**
     * @return array
     */
    protected function getAllowedDestinations()
    {
        $ret = [];
        $countries = Country::getCountries(
            (int)Context::getContext()->language->id,
            true,
            false,
            false
        );
        foreach ($countries as $country) {
            if (AmazonPayHelper::isValidAmazonDeliveryCountry($country['iso_code'])) {
                if (AmazonPayHelper::hasAtLeastOneCarrier($country)) {
                    $ret[$country['iso_code']] = new ArrayObject();
                }
            }
        }
        return $ret;
    }

    /**
     * @return bool
     */
    public function isCompleted()
    {
        $info = $this->getInformation();
        return $info['statusDetails']['state'] == 'Completed';
    }

    public function isOpenAndInAmazonPayBugWorkarround()
    {
        if (AmazonPayHelper::canHandlePendingAuthorization()) {
            if (AmazonPayHelper::getPaymentIntent() == 'Authorize') {
                return $this->isOpen();
            }
        }
        return false;
    }

    /**
     * @return bool
     */
    public function isOpen()
    {
        $info = $this->getInformation();
        return $info['statusDetails']['state'] == 'Open';
    }

    /**
     * @return array
     */
    public function getCharge()
    {
        $info = $this->getInformation();
        $chargeInfo = array(
            'chargeId' => $info['chargeId'],
            'chargePermissionId' => $info['chargePermissionId'],
            'info' => $this->getChargeInfo($info['chargeId'])
        );
        return $chargeInfo;
    }

    /**
     * @param $refund_id
     * @return array|bool|string
     */
    public function getRefund($refund_id)
    {
        try {
            $result = $this->client->getRefund($refund_id);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                return $response;
            } else {
                $this->logStatusError('getRefund', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('getRefund', $e, $result);
            return false;
        }
    }

    /**
     * @param $charge_id
     * @return bool|mixed
     */
    public function getChargeInfo($charge_id)
    {
        try {
            $result = $this->client->getCharge($charge_id);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                return $response;
            } else {
                $this->logStatusError('getCharge', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('captureCharge', $e, $result);
            return false;
        }
    }

    /**
     * @return bool|mixed
     */
    public function getInformation()
    {
        try {
            $result = $this->client->getCheckoutSession($this->amazon_pay_checkout_session_id);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                return $response;
            } else {
                $this->logStatusError('getCheckoutSession', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('captureCharge', $e, $result);
            return false;
        }
    }

    /**
     * @param Cart $cart
     * @return bool
     * @throws Exception
     */
    public function setPaymentInfo(Cart $cart)
    {
        $payload = array(
            'paymentDetails' => array(
                'paymentIntent' => AmazonPayHelper::getPaymentIntent(),
                'canHandlePendingAuthorization' => AmazonPayHelper::canHandlePendingAuthorization(),
                'chargeAmount' => array(
                    'amount' => (string)Tools::ps_round($cart->getOrderTotal(true, Cart::BOTH), 2),
                    'currencyCode' => AmazonPayHelper::getCurrentCurrency()
                )
            ),
            'merchantMetadata' => array(
                'merchantStoreName' => Tools::substr(Configuration::get('PS_SHOP_NAME'), 0, 49),
                'merchantReferenceId' => AmazonPayHelper::getMerchantReferenceId(),
                'customInformation' => 'Prestashop,Patworx,V2,' . Amazonpay::$plugin_version
            )
        );
        try {
            $result = $this->client->updateCheckoutSession($this->amazon_pay_checkout_session_id, $payload);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $amazonPayRedirectUrl = $response['webCheckoutDetails']['amazonPayRedirectUrl'];
                return $amazonPayRedirectUrl;
            } else {
                $this->logStatusError('updateCheckoutSession', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('captureCharge', $e, $result);
            return false;
        }
    }

    /**
     * @param $chargeId
     * @param $amount
     * @param $currency_code
     * @param string $order_ref
     * @return bool
     */
    public function createCharge($chargePermissionId, $amount, $currency_code, $order_ref = '')
    {
        $payload = array(
            'chargePermissionId' => $chargePermissionId,
            'chargeAmount' => array(
                'amount' => (string)$amount,
                'currencyCode' => $currency_code
            ),
            'captureNow' => true,
            'softDescriptor' => $order_ref
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->createCharge($payload, $headers);
            if ($result['status'] === 201) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $state = $response['statusDetails']['state'];
                AmazonPayTransaction::store(
                    $this->amazon_pay_checkout_session_id,
                    $response['chargeId'],
                    'capture',
                    $amount
                );
                return $state;
            } else {
                $this->logStatusError('createCharge', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('createCharge', $e, $result);
            return false;
        }
    }

    /**
     * @param $chargeId
     * @param $order_ref
     * @return bool
     */
    public function updateOrderReference($chargeId, $order_ref)
    {
        $payload = array(
            'merchantMetadata' => array(
                'merchantReferenceId' => $order_ref
            )
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->updateChargePermission($chargeId, $payload, $headers);
            if ($result['status'] === 200) {
                return true;
            } else {
                $this->logStatusError('updateChargePermission', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('updateChargePermission', $e, $result);
            return false;
        }
    }

    /**
     * @param $chargeId
     * @param $amount
     * @param $currency_code
     * @param string $order_ref
     * @return bool
     */
    public function capture($chargeId, $amount, $currency_code, $order_ref = '')
    {
        $payload = array(
            'captureAmount' => array(
                'amount' => (string)$amount,
                'currencyCode' => $currency_code
            ),
            'softDescriptor' => $order_ref
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->captureCharge($chargeId, $payload, $headers);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $state = $response['statusDetails']['state'];
                AmazonPayTransaction::store(
                    $this->amazon_pay_checkout_session_id,
                    $chargeId,
                    'capture',
                    $amount
                );
                return $state;
            } else {
                $this->logStatusError('captureCharge', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('captureCharge', $e, $result);
            return false;
        }
    }

    /**
     * @param $chargeId
     * @param $amount
     * @param $currency_code
     * @param string $order_ref
     * @return bool
     */
    public function refund($chargeId, $amount, $currency_code, $order_ref = '')
    {
        $payload = array(
            'chargeId' => $chargeId,
            'refundAmount' => array(
                'amount' => (string)$amount,
                'currencyCode' => $currency_code
            ),
            'softDescriptor' => $order_ref
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->createRefund($payload, $headers);
            if ($result['status'] === 201) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $state = $response['statusDetails']['state'];
                AmazonPayTransaction::store(
                    $this->amazon_pay_checkout_session_id,
                    $response['refundId'],
                    'refund_pending',
                    $amount * -1
                );
                return $state;
            } else {
                $this->logStatusError('createRefund', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('createRefund', $e, $result);
            return false;
        }
    }

    /**
     * @param string $chargeId
     * @param string $reason
     * @return bool
     */
    public function cancel($chargeId, $reason)
    {
        $payload = array(
            'cancellationReason' => $reason
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->cancelCharge($chargeId, $payload, $headers);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $state = $response['statusDetails']['state'];
                AmazonPayTransaction::store(
                    $this->amazon_pay_checkout_session_id,
                    $response['chargeId'],
                    'cancel',
                    0
                );
                return $state;
            } else {
                $this->logStatusError('cancelCharge', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('cancelCharge', $e, $result);
            return false;
        }
    }

    /**
     * @param string $chargeId
     * @param string $reason
     * @return bool
     */
    public function close($chargeId, $reason)
    {
        $payload = array(
            'closureReason' => $reason
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->closeChargePermission($chargeId, $payload, $headers);
            if ($result['status'] === 200) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $state = $response['statusDetails']['state'];
                AmazonPayTransaction::store(
                    $this->amazon_pay_checkout_session_id,
                    $response['chargePermissionId'],
                    'close',
                    0
                );
                return $state;
            } else {
                $this->logStatusError('closeChargePermission', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('closeChargePermission', $e, $result);
            return false;
        }
    }

    /**
     * @param $call
     * @param $exception
     * @param $result
     */
    protected function logCallException($call, $exception, $result)
    {
        AmazonPayLogger::getInstance()->addLog(
            'Error API-Call ' . $call,
            3,
            $exception,
            $result
        );
    }

    /**
     * @param $call
     * @param $result
     */
    protected function logStatusError($call, $result)
    {
        $response = json_decode($result['response'], true);
        if (is_array($response) && isset($response['message'])) {
            $this->last_message = $response['message'];
        }
        AmazonPayLogger::getInstance()->addLog(
            'Error API-Call ' . $call,
            3,
            false,
            $result
        );
    }

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

    /**
     * @param $amazon_pay_checkout_session_id
     * @return bool
     */
    public function isValid($amazon_pay_checkout_session_id)
    {
        $result = $this->client->getCheckoutSession(
            $amazon_pay_checkout_session_id
        );
        if ($result['status'] === 200) {
            $this->rawClientResponse = $result['response'];
            return true;
        }
        return false;
    }

    /**
     * @param $amazon_pay_checkout_session_id
     * @return bool
     */
    public function complete($amazon_pay_checkout_session_id, $amount, $currency_code)
    {
        $payload = array(
            'chargeAmount' => array(
                'amount' => (string)$amount,
                'currencyCode' => $currency_code
            )
        );
        try {
            $headers = array('x-amz-pay-Idempotency-Key' => uniqid());
            $result = $this->client->completeCheckoutSession($amazon_pay_checkout_session_id, $payload, $headers);
            if ($result['status'] === 200 || $result['status'] === 202) {
                $this->rawClientResponse = $result['response'];
                $response = json_decode($result['response'], true);
                $state = $response['statusDetails']['state'];
                return $state;
            } else {
                $this->logStatusError('completeCheckoutSession', $result);
                return false;
            }
        } catch (\Exception $e) {
            $this->logCallException('completeCheckoutSession', $e, $result);
            return false;
        }
    }

    /**
     * @param $json
     * @return bool
     */
    public function isInCanceledState($json)
    {
        $response = json_decode($json, true);
        if (isset($response['statusDetails']['state'])) {
            return $response['statusDetails']['state'] == 'Canceled';
        }
        return false;
    }

    /**
     * put session into cookie storage
     */
    public function saveSession()
    {
        Context::getContext()->cookie->amazon_pay_checkout_session_id = $this->amazon_pay_checkout_session_id;
    }

    /**
     * @return bool|string
     */
    public function getAmazonPayCheckoutSessionId()
    {
        return $this->amazon_pay_checkout_session_id;
    }

    /**
     * reset session data in prestashop
     */
    public function reset()
    {
        $this->amazon_pay_checkout_session_id = false;
        unset(Context::getContext()->cookie->amazon_pay_checkout_session_id);
    }
}