400 lines
9.7 KiB
PHP
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;
|
|
}
|
|
}
|
|
}
|