first commit
This commit is contained in:
354
class/payments/class.PayU.php
Normal file
354
class/payments/class.PayU.php
Normal file
@@ -0,0 +1,354 @@
|
||||
<?php
|
||||
|
||||
use KupShop\KupShopBundle\Config;
|
||||
|
||||
class PayU extends Payment
|
||||
{
|
||||
public static $name = 'PayU platební brána';
|
||||
|
||||
public $template = 'payment.PayU.tpl';
|
||||
protected $templateCart = 'payment.PayU.cart.tpl';
|
||||
|
||||
public $class = 'PayU';
|
||||
|
||||
public $url = 'https://secure.payu.com/paygw/';
|
||||
|
||||
// Session
|
||||
public $ts;
|
||||
public $session_id;
|
||||
|
||||
public $method;
|
||||
|
||||
protected $pay_method = Payment::METHOD_ONLINE;
|
||||
|
||||
public function setOrder($order)
|
||||
{
|
||||
if (empty($order)) {
|
||||
$this->readParams();
|
||||
|
||||
$order = $this->getOrderId($this->session_id);
|
||||
}
|
||||
|
||||
if (empty($order)) {
|
||||
$payu_response = $this->makeStatusRequest();
|
||||
|
||||
$trans = $this->readResponse($payu_response);
|
||||
|
||||
$result = $this->readStatus($trans);
|
||||
|
||||
logError(__FILE__, __LINE__, 'Not Found: result:'.print_r($result, true));
|
||||
|
||||
if ($result['code'] == 2 || $result['code'] == 1) {
|
||||
// If payment canceled or not paid yet, confirm
|
||||
echo 'OK';
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($result['code'] == 99) {
|
||||
logError(__FILE__, __LINE__, 'Missed payment!! Creating ...');
|
||||
$order = intval($trans->order_id);
|
||||
}
|
||||
|
||||
logError(__FILE__, __LINE__, 'Not Found: payu_response:'.$payu_response);
|
||||
}
|
||||
|
||||
return parent::setOrder($order);
|
||||
}
|
||||
|
||||
public function storePaymentInfo()
|
||||
{
|
||||
$data = parent::storePaymentInfo();
|
||||
|
||||
$data['method'] = explode('-', getVal('payment_id'))[1];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function checkAuth()
|
||||
{
|
||||
$this->readParams();
|
||||
|
||||
if ($this->session_id && !getVal('cf')) {
|
||||
$parts = explode('_', $this->session_id);
|
||||
$_GET['cf'] = getVal(0, $parts);
|
||||
}
|
||||
}
|
||||
|
||||
public function readParams()
|
||||
{
|
||||
$this->session_id = getVal('session_id');
|
||||
$this->ts = time();
|
||||
}
|
||||
|
||||
public function readResponse($payu_response)
|
||||
{
|
||||
$xml = simplexml_load_string($payu_response);
|
||||
|
||||
if (!$xml) {
|
||||
logError(__FILE__, __LINE__, "Chyba parsovani xml: {$payu_response}");
|
||||
}
|
||||
|
||||
if (strval($xml->status) != 'OK') {
|
||||
logError(__FILE__, __LINE__, 'Transakce vratila chybu');
|
||||
}
|
||||
|
||||
return $xml->trans;
|
||||
}
|
||||
|
||||
public function readStatus($trans)
|
||||
{
|
||||
// incorrect POS ID number specified in response
|
||||
if ($trans->pos_id != $this->config['pos']) {
|
||||
return ['code' => false, 'message' => 'incorrect POS number'];
|
||||
}
|
||||
|
||||
// calculating signature for comparison with sig sent by PayU
|
||||
$sig = md5($trans->pos_id.$trans->session_id.$trans->order_id.$trans->status.$trans->amount.$trans->desc.$trans->ts.$this->config['key2']);
|
||||
|
||||
// incorrect signature in response in comparison to locally calculated one
|
||||
if ($trans->sig != $sig) {
|
||||
return ['code' => false, 'message' => 'incorrect signature'];
|
||||
}
|
||||
|
||||
// different messages depending on transaction status. For status description, see documentation
|
||||
switch ($trans->status) {
|
||||
case 1:
|
||||
return ['code' => $trans->status, 'message' => 'new'];
|
||||
case 2:
|
||||
return ['code' => $trans->status, 'message' => 'cancelled'];
|
||||
case 3:
|
||||
return ['code' => $trans->status, 'message' => 'rejected'];
|
||||
case 4:
|
||||
return ['code' => $trans->status, 'message' => 'started'];
|
||||
case 5:
|
||||
return ['code' => $trans->status, 'message' => 'awaiting receipt'];
|
||||
case 6:
|
||||
return ['code' => $trans->status, 'message' => 'no authorization'];
|
||||
case 7:
|
||||
return ['code' => $trans->status, 'message' => 'payment rejected'];
|
||||
case 99:
|
||||
return ['code' => $trans->status, 'message' => 'payment received - ended'];
|
||||
case 888:
|
||||
return ['code' => $trans->status, 'message' => 'incorrect status'];
|
||||
default:
|
||||
return ['code' => false, 'message' => 'no status'];
|
||||
}
|
||||
}
|
||||
|
||||
public function checkReceivedSignature()
|
||||
{
|
||||
// some parameters are missing
|
||||
if (!isset($_POST['pos_id']) || !isset($_POST['session_id']) || !isset($_POST['ts']) || !isset($_POST['sig'])) {
|
||||
logError(__FILE__, __LINE__, 'ERROR: EMPTY PARAMETERS');
|
||||
}
|
||||
|
||||
// received POS ID is different than expected
|
||||
if ($_POST['pos_id'] != $this->config['pos']) {
|
||||
logError(__FILE__, __LINE__, 'ERROR: INCORRECT POS ID');
|
||||
}
|
||||
|
||||
// verification of received signature
|
||||
$sig = md5($_POST['pos_id'].$_POST['session_id'].$_POST['ts'].$this->config['key2']);
|
||||
|
||||
// incorrect signature
|
||||
if ($_POST['sig'] != $sig) {
|
||||
logError(__FILE__, __LINE__, 'ERROR: INCORRECT SIGNATURE');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function makeStatusRequest()
|
||||
{
|
||||
// signature that will be sent to PayU with request
|
||||
$sig = md5($this->config['pos'].$this->session_id.$this->ts.$this->config['key1']);
|
||||
|
||||
// preparing parameters string to be sent to PayU
|
||||
$parameters = 'pos_id='.$this->config['pos'].'&session_id='.$this->session_id.'&ts='.$this->ts.'&sig='.$sig;
|
||||
|
||||
// sending request via CURL
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $this->url.'UTF/Payment/get');
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
|
||||
$payu_response = curl_exec($ch);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
return $payu_response;
|
||||
}
|
||||
|
||||
public function step($index, $message, $data = [])
|
||||
{
|
||||
if ($index == 1) {
|
||||
if (!empty($this->method)) {
|
||||
$data['method'] = $this->method;
|
||||
} else {
|
||||
$data['method'] = getVal('payu_method');
|
||||
}
|
||||
}
|
||||
|
||||
parent::step($index, $message, $data);
|
||||
}
|
||||
|
||||
public function processStep_1()
|
||||
{
|
||||
$this->ts = strval(time());
|
||||
$this->session_id = "{$this->order->getSecurityCode()}_{$this->ts}";
|
||||
$this->method = getVal('method');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function processStep_5()
|
||||
{
|
||||
$this->error('Platba byla zrušena.');
|
||||
}
|
||||
|
||||
public function processStep_6()
|
||||
{
|
||||
$this->updatePaymentStatus();
|
||||
|
||||
if ($this->status == Payment::STATUS_FINISHED) {
|
||||
$this->success('Platba proběhla v pořádku.');
|
||||
} else {
|
||||
$this->step(2, 'Platba byla zaznamenána, čeká se na zaplacení. O přijetí platby Vám zašleme email.');
|
||||
}
|
||||
}
|
||||
|
||||
public function processStep_7()
|
||||
{
|
||||
$this->checkReceivedSignature();
|
||||
|
||||
if ($this->updatePaymentStatus()) {
|
||||
logError(__FILE__, __LINE__, 'PayU step 7 - OK');
|
||||
echo 'OK';
|
||||
} else {
|
||||
logError(__FILE__, __LINE__, 'PayU step 7 - KO');
|
||||
echo 'KO';
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
public function ensurePaymentExists($trans)
|
||||
{
|
||||
if (!$this->getStatus($this->session_id)) {
|
||||
$this->createPayment($this->session_id, intval($trans->amount) / 100, ['id_payu' => $trans->id]);
|
||||
}
|
||||
}
|
||||
|
||||
public function updatePaymentStatus()
|
||||
{
|
||||
$payu_response = $this->makeStatusRequest();
|
||||
|
||||
logError(__FILE__, __LINE__, 'updatePaymentStatus: payu_response:'.$payu_response);
|
||||
|
||||
$trans = $this->readResponse($payu_response);
|
||||
|
||||
$result = $this->readStatus($trans);
|
||||
logError(__FILE__, __LINE__, 'updatePaymentStatus: response:'.print_r($result, true));
|
||||
|
||||
if ($result['code']) {
|
||||
if ($result['code'] == '2') {
|
||||
// transaction canceled
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->ensurePaymentExists($trans);
|
||||
|
||||
// change of transaction status in system of the shop
|
||||
if ($result['code'] == '99') {
|
||||
// payment sucessful so we send back OK
|
||||
if (!$this->setStatus(Payment::STATUS_FINISHED, $this->session_id)) {
|
||||
logError(__FILE__, __LINE__, 'Payment::updatePaymentStatus: setStatus failed!');
|
||||
}
|
||||
|
||||
return true;
|
||||
} elseif ($result['code'] == '4') {
|
||||
// transaction pending
|
||||
if (!$this->setStatus(Payment::STATUS_PENDING, $this->session_id)) {
|
||||
logError(__FILE__, __LINE__, 'Payment::updatePaymentStatus: setStatus failed!');
|
||||
}
|
||||
|
||||
return true;
|
||||
} elseif ($result['code'] == '1') {
|
||||
// transaction started
|
||||
if (!$this->setStatus(Payment::STATUS_CREATED, $this->session_id)) {
|
||||
logError(__FILE__, __LINE__, 'Payment::updatePaymentStatus: setStatus failed!');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
logError(__FILE__, __LINE__, 'updatePaymentStatus: not handled');
|
||||
|
||||
return false;
|
||||
} else {
|
||||
logError(__FILE__, __LINE__, 'updatePaymentStatus: error: code='.$result['code'].' message='.$result['message']."\n{$payu_response}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
$methods = $this->getAvailableMethods();
|
||||
|
||||
return parent::getName().' - '.getVal($this->method, $methods, ['name' => 'Neznámý typ PayU platby'])['name'];
|
||||
}
|
||||
|
||||
public function getAvailableMethods()
|
||||
{
|
||||
if (!($methods = getCache('payu-methods'))) {
|
||||
$methods = $this->fetchAvailableMethods();
|
||||
setCache('payu-methods', $methods);
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
public function fetchAvailableMethods()
|
||||
{
|
||||
$key = substr($this->config['key1'], 0, 2);
|
||||
|
||||
$xml = new SimpleXMLElement($this->url."UTF/xml/{$this->config['pos']}/{$key}/paytype.xml", 0, true);
|
||||
$payTypes = $xml->xpath('//paytype');
|
||||
|
||||
$methods = [];
|
||||
|
||||
foreach ($payTypes as $payment) {
|
||||
$payment = (array) $payment;
|
||||
$payment['enable'] = $payment['enable'] == 'true';
|
||||
$methods[$payment['type']] = $payment;
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
public function requiresEET()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasOnlinePayment()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function isEnabled($className)
|
||||
{
|
||||
$cfg = Config::get();
|
||||
|
||||
if (empty($cfg['Modules']['payments'][$className])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user