Files
grzanieplus.pl/plugins/cvIngPlugin/lib/cvIngService.class.php
2025-03-12 17:06:23 +01:00

400 lines
9.7 KiB
PHP

<?php
require_once(dirname(__FILE__) . '/src/CartData.php');
require_once(dirname(__FILE__) . '/src/Util.php');
class cvIngService
{
public $errors;
public $testModeEnabled;
public $dataDecoded;
public $transactionData;
public $paymentUrl;
public $twistoOrderData;
protected $cfg;
protected $clientId;
protected $shopId;
protected $shopKey;
protected $hashMethod = 'sha256';
public function __construct()
{
$this->cfg = stConfig::getInstance('cvIngBackend');
$this->clientId = $this->cfg->get('client_id');
$this->shopId = $this->cfg->get('shop_id');
$this->shopKey = $this->cfg->get('shop_key');
$this->testModeEnabled = $this->cfg->get('test_mode_enabled');
if($this->testModeEnabled) {
error_reporting(E_ALL);
register_shutdown_function([
'cvIngService',
'handleShutdown',
]);
}
$this->setUrl();
}
protected function setUrl()
{
if($this->testModeEnabled) {
$this->paymentUrl = 'https://sandbox.paywall.imoje.pl/pl/payment';
} else {
$this->paymentUrl = 'https://paywall.imoje.pl/pl/payment';
}
}
public static function validateName($string)
{
return preg_match('/^[^0-9!<>,;?=+()@#"°{}_$%:]+\s[^0-9!<>,;?=+()@#"°{}_$%:]+$/', $string);
}
public static function validateAddress($string)
{
return preg_match('/^[^!<>?=+@{}_$%]+\s[\w\d\/\.\/\s-]+$/', $string);
}
public static function validateTown($string)
{
return preg_match('/^[^!<>;?=+@#"°{}_$%]+$/', $string);
}
public static function validateCode($string)
{
return preg_match('/^[0-9]{2}\-[0-9]{3}$/', $string);
}
public static function validatePhone($string)
{
return preg_match('/^[0-9]{9}$/', $string);
}
public static function validateCountry($string = null)
{
return is_int(intval($string));
}
public static function validateEmail($string)
{
return preg_match('/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i', $string);
}
public static function handleShutdown()
{
$error = error_get_last();
if($error !== null) {
cvIngLog::add("[SHUTDOWN] file:" . $error['file'] . " | ln:" . $error['line'] . " | msg:" . $error['message']);
}
}
/**
* Przygotowanie danych transkcji dla płatności imoje
*
* @param type $order
* @param type $twisto
*
* @return string
*/
public function getTransactionData($order, $twisto = 0)
{
if(!$order) {
return false;
}
$userBilling = $order->getOrderUserDataBilling();
$controller = sfContext::getInstance()->getController();
$data['serviceId'] = $this->shopId;
$data['merchantId'] = $this->clientId;
$data['amount'] = (int) $this->getOrderAmount(stPayment::getUnpayedAmountByOrder($order));
$data['currency'] = $order->getOrderCurrency()->getShortcut();
$data['orderId'] = $order->getId();
$data['customerFirstName'] = $userBilling->getName();
$data['customerLastName'] = $userBilling->getSurname();
$data['customerEmail'] = $order->getGuardUser()->getUsername();
$data['urlReturn'] = $controller->genUrl('cvIngImojeFrontend/return', true);
$data['urlSuccess'] = $controller->genUrl('cvIngImojeFrontend/returnSuccess', true);
$data['urlFailure'] = $controller->genUrl('cvIngImojeFrontend/returnFail', true);
if($twisto) {
$payment = $order->getOrderPayment();
if(!$payment) {
return false;
}
$cartData = $this->getCartData($order);
foreach($this->getPreviousOrders($order->getGuardUser()->getUsername()) as $previousOrder) {
$cartData->addPrevious($previousOrder);
}
$data['cartData'] = $cartData->prepareCartData();
}
$data['signature'] = $this->createSignature($data, $this->shopKey, $this->hashMethod) . ';' . $this->hashMethod;
return $data;
}
protected function getOrderAmount($orderAmountBrutto)
{
return number_format($orderAmountBrutto, 2, '', '');
}
protected function getCartData($order)
{
$cartData = new \Imoje\Payment\CartData();
$cartData->setAmount((int) $this->getOrderAmount(stPayment::getUnpayedAmountByOrder($order)));
$cartData->setCreatedAt(strtotime($order->getCreatedAt()));
foreach($order->getOrderProducts() as $product) {
$quantity = $product->getQuantity();
$cartData->addItem(
$product->getId(),
(int) $product->getVat(),
$product->getName(),
\Imoje\Payment\Util::convertAmountToFractional($product->getTotalAmount(true) / $quantity),
(int) $quantity
);
}
$userBilling = $order->getOrderUserDataBilling();
$cartData->setAddressBilling(
$userBilling->getTown(),
$userBilling->getFullname(),
$userBilling->getPhone(),
$userBilling->getStreet()
. ' '
. $userBilling->getHouse()
. ' '
. $userBilling->getFlat(),
$userBilling->getCountry()->getIsoA2(),
$userBilling->getCode()
);
$userDelivery = $order->getOrderUserDataDelivery();
$cartData->setAddressDelivery(
$userDelivery->getTown(),
$userDelivery->getFullname(),
$userDelivery->getPhone(),
$userDelivery->getStreet()
. ' '
. $userDelivery->getHouse()
. ' '
. $userDelivery->getFlat(),
$userDelivery->getCountry()->getIsoA2(),
$userDelivery->getCode()
);
$shipping = $order->getOrderDelivery();
$cartData->setShipping(
(int) $shipping->getOptTax(),
$shipping->getName(),
\Imoje\Payment\Util::convertAmountToFractional($shipping->getCostBrutto())
);
return $cartData;
}
/**
* @param string $email
*
* @return array
* @throws PropelException
*/
protected function getPreviousOrders($email)
{
$orderPeerCriteria = new Criteria();
$orderPeerCriteria->add(OrderPeer::OPT_CLIENT_EMAIL, $email);
$prevOrders = OrderPeer::doSelect($orderPeerCriteria);
$orders = [];
$iteration = 0;
foreach($prevOrders as $order) {
if($iteration === \Imoje\Payment\CartData::MAX_PREVIOUS_ORDERS) {
break;
}
$orderUserDataBilling = $order->getOrderUserDataDelivery();
$orderUserDataDelivery = $order->getOrderUserDataDelivery();
$orderUserDataBillingFullName = $orderUserDataBilling->getFullName();
$orderUserDataDeliveryFullName = $orderUserDataDelivery->getFullName();
$orderUserDataBillingPhone = $orderUserDataBilling->getPhone();
$orderUserDataDeliveryPhone = $orderUserDataDelivery->getPhone();
if(!$orderUserDataBillingFullName
|| !$orderUserDataDeliveryFullName
|| !$orderUserDataBillingPhone
|| !is_numeric($orderUserDataBillingPhone)
|| !$orderUserDataDeliveryPhone
|| !is_numeric($orderUserDataDeliveryPhone)) {
continue;
}
$total = (int) $this->getOrderAmount(stPayment::getUnpayedAmountByOrder($order));
$calcTotal = 0;
foreach($order->getOrderProducts() as $product) {
$calcTotal += \Imoje\Payment\Util::convertAmountToFractional($product->getTotalAmount(true));
}
$calcTotal += \Imoje\Payment\Util::convertAmountToFractional($order->getOrderDelivery()->getCostBrutto());
if($total != $calcTotal) {
continue;
}
$orders[] = $this->getCartData($order);
$iteration += 1;
}
return $orders;
}
/**
* @param array $orderData
* @param string $serviceKey
* @param string $hashMethod
*
* @return string
*/
protected function createSignature($orderData, $serviceKey, $hashMethod)
{
return hash($hashMethod, $this->prepareData($orderData) . $serviceKey);
}
/**
* @param array $data * @param string $prefix
*
* @return string
*/
protected function prepareData($data, $prefix = '')
{
ksort($data);
$hashData = [];
foreach($data as $key => $value) {
if($prefix) {
$key = $prefix . '[' . $key . ']';
}
if(is_array($value)) {
$hashData[] = prepareData($value, $key);
} else {
$hashData[] = $key . '=' . $value;
}
}
return
implode('&', $hashData);
}
#VALIDATE METHODS
public function verifySignature()
{
$dataEncoded = file_get_contents('php://input');
$this->dataDecoded = json_decode($dataEncoded, 1);
$header = $this->getHeaders();
if(!isset($header['X-Imoje-Signature']) || substr($header['Content-Type'], 0, 16) != 'application/json') {
cvIngLog::add('Wrong headers');
return false;
}
cvIngLog::add($this->dataDecoded);
cvIngLog::add($header);
$headerSignature = $this->parseHeaderValues($header['X-Imoje-Signature']);
$signature = hash($this->hashMethod, $dataEncoded . $this->shopKey);
cvIngLog::add($headerSignature['signature']);
cvIngLog::add($signature);
if($signature === $headerSignature['signature']) {
cvIngLog::add('Correct signature');
return true;
} else {
cvIngLog::add('Wrong signature');
return false;
}
}
protected function getHeaders()
{
foreach($_SERVER as $name => $value) {
if(substr($name, 0, 5) == 'HTTP_') {
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$headers[$name] = $value;
} elseif($name == "CONTENT_TYPE") {
$headers["Content-Type"] = $value;
} elseif($name == "CONTENT_LENGTH") {
$headers["Content-Length"] = $value;
}
}
return $headers;
}
protected function parseHeaderValues($headerValues)
{
$result = [];
$varsets = explode(';', $headerValues);
foreach($varsets as $varset) {
$chunk = explode('=', $varset);
$result[$chunk[0]] = $chunk[1];
}
return $result;
}
public function verifyTransactionData()
{
$result = true;
if(!isset($this->dataDecoded['transaction']) || empty($this->dataDecoded['transaction'])) {
$result = false;
}
if(!isset($this->dataDecoded['transaction']['orderId']) || empty($this->dataDecoded['transaction']['orderId'])) {
$result = false;
}
if(!isset($this->dataDecoded['transaction']['status']) || empty($this->dataDecoded['transaction']['status'])) {
$result = false;
}
if($result) {
$this->transactionData = $this->dataDecoded['transaction'];
cvIngLog::add('Correct transaction data');
return true;
} else {
cvIngLog::add('Wrong transaction data');
return false;
}
}
}