<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjStripe extends pjStripeAppController
{
    protected static $logPrefix = "Payments | pjStripe plugin<br>";
    
    protected static $paymentMethod = 'stripe';
    
    public static function getPaymentLocale($localeId = null)
    {
        $locale = 'en'; // English (default)

        if ($localeId && $locale_arr = pjLocaleModel::factory()->select('language_iso')->find($localeId)->getData())
        {
            $lang = strtok($locale_arr['language_iso'], '-');
            if (strpos($locale_arr['language_iso'], '-FI'))
            {
                $lang = 'fi';
            }
            elseif (strpos($locale_arr['language_iso'], '-NO') || in_array($locale_arr['language_iso'], array('nb', 'nn')))
            {
                $lang = 'no';
            }
            elseif (strpos($locale_arr['language_iso'], '-SE'))
            {
                $lang = 'sv';
            }

            $locales = array(
                'zh' => 'zh', // Simplified Chinese
                'da' => 'da', // Danish
                'nl' => 'nl', // Dutch
                'fi' => 'fi', // Finnish
                'fr' => 'fr', // French
                'de' => 'de', // German
                'it' => 'it', // Italian
                'ja' => 'ja', // Japanese
                'no' => 'no', // Norwegian
                'es' => 'es', // Spanish
                'sv' => 'sv', // Swedish
            );

            if (array_key_exists($lang, $locales))
            {
                $locale = $locales[$lang];
            }
        }

        return $locale;
    }

	public function pjActionForm()
	{
		$this->setLayout('pjActionEmpty');

		$params = $this->getParams();
		
		$cancel_url = "{$params['notify_url']}&cancel_hash={$params['cancel_hash']}";
		
		$data = array(
			'payment_method_types' => array('card'),
			'line_items' => array(
				array(
					'price_data' => array(
						'currency' => strtolower($params['currency_code']),
						'product_data' => array(
							'name' => @$params['item_name'],
							'description' => @$params['item_name'],
						),
						'unit_amount' => $params['amount'] * 100, // convert to cents
					),
					'quantity' => 1,
				)
			),
			'mode' => 'payment',
			'locale' => self::getPaymentLocale($params['locale_id']),
			'success_url' => @$params['notify_url'] . '&id=' . @$params['custom'] .'&stripesessid={CHECKOUT_SESSION_ID}',
			'cancel_url' => $cancel_url . '&id=' . @$params['custom'] .'&stripesessid={CHECKOUT_SESSION_ID}',
		);

		$sdk = new pjStripeSDK(null, $params['public_key'], $params['private_key']);
		
		try {
			$result = $sdk->createSession($data);
			
			if (isset($result['id']))
			{
				$this->set('session_id', $result['id']);
			}
		} catch (Exception $e) {
			echo $e->getMessage();
		}
		
		$this->set('arr', $params);
	}

    public function pjActionConfirm()
    {
        $params = $this->getParams();
        $request = $params['request'];

        if (!isset($params['key']) || $params['key'] != md5($this->option_arr['private_key'] . PJ_SALT))
        {
            $this->log(self::$logPrefix . "Missing or invalid 'key' parameter.");
            return FALSE;
        }

        $response = array('status' => 'FAIL', 'redirect' => true);
        if (isset($request['cancel_hash']) && $request['cancel_hash'] == $params['cancel_hash'])
        {
            $this->log(self::$logPrefix . "Payment was cancelled.");
            $response['status'] = 'CANCEL';
            return $response;
        }

        $options = $this->option_arr;

        $_response = $this->requestAction(array(
            'controller' => 'pjStripe',
            'action' => 'pjActionProcess',
            'params' => array(
                'key' => md5($this->option_arr['private_key'] . PJ_SALT),
            	'public_key' => $options['o_stripe_public_key'],
            	'private_key' => $options['o_stripe_private_key'],
                'amount' => $params['amount'] * 100,
                'currency' => $this->option_arr['o_currency'],
                'description' => pjSanitize::html(@$params['uuid']),
                'foreign_id' => $params['order_id'],
            	'session_id' => $request['stripesessid'], // Stripe session_id
            )
        ), array('return'));
        
        if ($_response['status'] == 'OK')
        {
            $response['status'] = 'OK';
            $response['txn_id'] = @$_response['result']['data']['object']['payment_intent'];
        }

        return $response;
    }

	public function pjActionProcess()
	{
		$params = $this->getParams();
		if (!isset($params['key']) || $params['key'] != md5($this->option_arr['private_key'] . PJ_SALT))
		{
            $this->log(self::$logPrefix . "Missing or invalid key parameter.");
            return array('status' => 'ERR', 'code' => 100, 'text' => 'Missing or invalid key parameter');
		}
		
		if (!(isset($params['session_id'], $params['private_key'], $params['amount'], $params['currency'])))
		{
            $this->log(self::$logPrefix . "Missing, empty or invalid parameters.");
            return array('status' => 'ERR', 'code' => 101, 'text' => 'Missing, empty or invalid parameters.');
		}
		
		$sdk = new pjStripeSDK(null, $params['public_key'], $params['private_key']);
		
		try {
			$events = $sdk->getEvents();
			
		} catch (Exception $e) {
			
			$this->log(self::$logPrefix . $e->getMessage());
			return array('status' => 'ERR', 'code' => 102, 'text' => $e->getMessage());
		}
		
		# Handle post-payment fulfillment
		$found = false;
		$completed = false;
		$event_id = NULL;
		$payment_id = NULL;
		$result = NULL;
		foreach ($events['data'] as $item)
		{
			if ($item['data']['object']['id'] == $params['session_id'] && $item['data']['object']['object'] == 'checkout.session')
			{
				$found = true;
				if ($item['type'] == 'checkout.session.completed')
				{
				    $event_id = $item['id'];
				    $payment_id = $item['data']['object']['payment_intent'];
				    $result = $item;
				    
					$completed = true;
					if (isset($params['foreign_id']))
					{
						$data = array_merge($params, array(
							'stripe_id' => $item['id'],
							'created' => $item['created']
						));
						self::pjActionSavePayment($params['foreign_id'], $data);
					}
				}
				break;
			}
		}
		
		if (!$found)
		{
			$this->log(self::$logPrefix . "Payment not found.");
			return array('status' => 'ERR', 'code' => 104, 'text' => 'Payment still not found.', 'result' => $events);
		}
		
		if (!$completed)
		{
			$this->log(self::$logPrefix . "Payment failed.");
			return array('status' => 'ERR', 'code' => 105, 'text' => 'Payment failed.', 'result' => $events);
		}
		
		$this->log(self::$logPrefix . "Payment completed. Event ID: {$event_id}. Payment ID: {$payment_id}");
		return array('status' => 'OK', 'code' => 200, 'text' => 'Payment completed.', 'result' => $result);
	}
	
	private static function pjActionSavePayment($foreign_id, $data)
	{
		return pjStripeModel::factory()
			->setAttributes(array(
				'foreign_id' => $foreign_id,
				'stripe_id' => @$data['stripe_id'],
				'token' => @$data['token'],
				'amount' => @$data['amount']/100,
				'currency' => @$data['currency'],
				'description' => @$data['item_name'],
				'created' => preg_match('|^\d{10}$|', @$data['created']) ? sprintf(':FROM_UNIXTIME(%u)', @$data['created']) : @$data['created']
			))
			->insert()
			->getInsertId();
	}
}
?>
