Current File : /home/tradevaly/vendor/sowrensen/laravel-shurjopay/src/ShurjoPayService.php
<?php

namespace Sowren\ShurjoPay;


use GuzzleHttp\Client;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Request;
use GuzzleHttp\Exception\GuzzleException;

class ShurjoPayService
{
    private const SERVER_URL_TEST = 'https://shurjotest.com';
    private const SERVER_URL_PROD = 'https://shurjopay.com';

    /**
     * Amount to pay.
     *
     * @var float
     */
    protected $amount;

    /**
     * URL to return after a successful transaction.
     *
     * @var string
     */
    protected $successUrl;

    /**
     * ShurjoPay server URL.
     *
     * @var string
     */
    protected $serverUrl;

    /**
     * ShurjoPay merchant username.
     *
     * @var string
     */
    protected $merchantUsername;

    /**
     * ShurjoPay merchant password.
     *
     * @var string
     */
    protected $merchantPassword;

    /**
     * ShurjoPay merchant key prefix.
     *
     * @var string
     */
    protected $merchantKeyPrefix;

    /**
     * Requesting IP address.
     *
     * @var string
     */
    protected $clientIp;

    /**
     * An unique transaction ID.
     *
     * @var string
     */
    protected $txnId;

    /**
     * Whether or not to use cURL.
     *
     * @var bool
     */
    protected $useCurl;

    /**
     * ShurjoPay response handler URL.
     *
     * @var string
     */
    protected $responseHandler;

    /**
     * XML data required by ShurjoPay.
     *
     * @var string
     */
    protected $xmlData;

    /**
     * ShurjoPayService constructor.
     * @param  float  $amount  Amount to pay
     * @param  string  $successUrl  URL to return after a successful transaction
     * @param  string|null  $serverUrl  Server URL provided by ShurjoPay
     * @param  string|null  $merchantUsername  Merchant username provided by ShurjoPay
     * @param  string|null  $merchantPassword  Merchant password provided by ShurjoPay
     * @param  string|null  $merchantKeyPrefix  Merchant key prefix provided by ShurjoPay
     * @param  bool  $useCurl  If false, cURL will be used instead of Guzzle
     * @param  string|null  $responseHandler  Custom ShurjoPay response handler URL
     */
    public function __construct(
        float $amount,
        string $successUrl,
        string $serverUrl = null,
        string $merchantUsername = null,
        string $merchantPassword = null,
        string $merchantKeyPrefix = null,
        bool $useCurl = false,
        string $responseHandler = null
    ) {
        $this->amount = $amount;
        $this->successUrl = $successUrl;
        $this->serverUrl = $serverUrl ?? config('shurjopay.server_url');
        $this->merchantUsername = $merchantUsername ?? config('shurjopay.merchant_username');
        $this->merchantPassword = $merchantPassword ?? config('shurjopay.merchant_password');
        $this->merchantKeyPrefix = $merchantKeyPrefix ?? config('shurjopay.merchant_key_prefix');
        $this->clientIp = Request::ip();
        $this->useCurl = $useCurl;
        $this->responseHandler = $responseHandler;
    }

    /**
     * Generate an unique transaction ID for current transaction.
     *
     * @param  string|null  $uniqueId
     * @return string
     */
    public function generateTxnId(string $uniqueId = null)
    {
        $this->txnId = $uniqueId
            ? $this->merchantKeyPrefix.$uniqueId : $this->merchantKeyPrefix.uniqid();
        return $this->txnId;
    }

    /**
     * Guzzle client post request options.
     *
     * @return array
     */
    private function postOptions()
    {
        return [
            'form_params' => [
                'spdata' => $this->xmlData
            ],
            'verify' => false,
            'timeout' => 3,
            'curl' => [
                CURLOPT_RETURNTRANSFER => true
            ]
        ];
    }

    /**
     * Prepare XML data to send.
     *
     * @return void
     */
    private function setXmlData()
    {
        $default = '<?xml version="1.0" encoding="utf-8"?>'.
            '<shurjoPay><merchantName>'.$this->merchantUsername.'</merchantName>'.
            '<merchantPass>'.$this->merchantPassword.'</merchantPass>'.
            '<userIP>'.$this->clientIp.'</userIP>'.
            '<uniqID>'.$this->txnId.'</uniqID>'.
            '<totalAmount>'.$this->amount.'</totalAmount>'.
            '<paymentOption>shurjopay</paymentOption>'.
            '<returnURL>'.$this->returnUrl().'</returnURL></shurjoPay>';

        $this->xmlData = $this->useCurl ? 'spdata='.$default : $default;
    }

    /**
     * Get return URL.
     *
     * @return string
     */
    private function returnUrl()
    {
        $returnUrl = $this->responseHandler ?? route('shurjopay.response');
        $returnUrl .= "?success_url={$this->successUrl}";
        return $returnUrl;
    }

    /**
     * Get request URL.
     *
     * @return string
     */
    private function requestUrl()
    {
        return Str::endsWith($this->serverUrl, '/')
            ? $this->serverUrl.'sp-data.php'
            : $this->serverUrl.'/sp-data.php';
    }

    /**
     * Attempt a payment via ShurjoPay payment gateway.
     *
     * @throws GuzzleException
     */
    public function makePayment()
    {
        $this->setXmlData();
        return $this->useCurl ? $this->sendRequestCurl() : $this->sendRequest();
    }

    /**
     * Send a HTTP request using Guzzle to ShurjoPay.
     *
     * @return \Psr\Http\Message\StreamInterface
     * @throws GuzzleException
     */
    private function sendRequest()
    {
        try {
            $client = new Client();
            $response = $client->request('POST', $this->requestUrl(), $this->postOptions());
            return $response->getBody();
        } catch (GuzzleException $exception) {
            throw $exception;
        }
    }

    /**
     * Send a payment request using cURL to ShurjoPay payment gateway.
     *
     * @return string|true
     */
    private function sendRequestCurl()
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->requestUrl());
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->xmlData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        $response = curl_exec($ch);
        curl_close($ch);
        return print_r($response);
    }

    /**
     * Decrypt ShurjoPay response.
     *
     * @param  string  $data
     * @return \SimpleXMLElement
     * @throws GuzzleException
     * @throws \Exception
     */
    public static function decryptResponse(string $data)
    {
        try {
            $client = new Client();
            $decryptionServerUrl = self::getDecryptionServerUrl();
            $response = $client->get("{$decryptionServerUrl}/merchant/decrypt.php?data={$data}");
            return simplexml_load_string($response->getBody()->getContents());
        } catch (GuzzleException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            throw $exception;
        }
    }

    /**
     * Determine the decryption URL based on application environment.
     *
     * @return string
     */
    private static function getDecryptionServerUrl()
    {
        return app()->environment('local') ? self::SERVER_URL_TEST : self::SERVER_URL_PROD;
    }
}