690 lines
18 KiB
PHP
690 lines
18 KiB
PHP
<?php
|
|
|
|
namespace App\Core\Payment\Pos;
|
|
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use App\Core\Payment\Pos\Exceptions\UnsupportedPaymentModelException;
|
|
use App\Core\Payment\Pos\Exceptions\UnsupportedTransactionTypeException;
|
|
use App\Core\Payment\Pos\PosHelpersTrait;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Exception;
|
|
|
|
/**
|
|
* Class VkfPOS
|
|
* @package Mews\Pos
|
|
*/
|
|
class VkfPos implements PosInterface
|
|
{
|
|
use PosHelpersTrait;
|
|
|
|
/**
|
|
* @const string
|
|
*/
|
|
public const NAME = 'VPos';
|
|
|
|
/**
|
|
* API URL
|
|
*
|
|
* @var string
|
|
*/
|
|
public $url;
|
|
|
|
/**
|
|
* 3D Pay Gateway URL
|
|
*
|
|
* @var string
|
|
*/
|
|
public $gateway;
|
|
|
|
/**
|
|
* Response Codes
|
|
*
|
|
* @var array
|
|
*/
|
|
public $codes = [
|
|
'00' => 'approved',
|
|
'01' => 'bank_call',
|
|
'02' => 'bank_call',
|
|
'05' => 'reject',
|
|
'09' => 'try_again',
|
|
'12' => 'invalid_transaction',
|
|
'28' => 'reject',
|
|
'51' => 'insufficient_balance',
|
|
'54' => 'expired_card',
|
|
'57' => 'does_not_allow_card_holder',
|
|
'62' => 'restricted_card',
|
|
'77' => 'request_rejected',
|
|
'99' => 'general_error',
|
|
];
|
|
|
|
/**
|
|
* Transaction Types
|
|
*
|
|
* @var array
|
|
*/
|
|
public $types = [
|
|
'pay' => 'Auth',
|
|
'pre' => 'PreAuth',
|
|
'post' => 'PostAuth',
|
|
];
|
|
|
|
/**
|
|
* Currencies
|
|
*
|
|
* @var array
|
|
*/
|
|
public $currencies = [];
|
|
|
|
/**
|
|
* Transaction Type
|
|
*
|
|
* @var string
|
|
*/
|
|
public $type;
|
|
|
|
/**
|
|
* API Account
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $account = [];
|
|
|
|
/**
|
|
* Order Details
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $order = [];
|
|
|
|
/**
|
|
* Credit Card
|
|
*
|
|
* @var object
|
|
*/
|
|
protected $card;
|
|
|
|
/**
|
|
* Request
|
|
*
|
|
* @var Request
|
|
*/
|
|
protected $request;
|
|
|
|
/**
|
|
* Response Raw Data
|
|
*
|
|
* @var object
|
|
*/
|
|
protected $data;
|
|
|
|
/**
|
|
* Processed Response Data
|
|
*
|
|
* @var mixed
|
|
*/
|
|
public $response;
|
|
|
|
/**
|
|
* Configuration
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $config = [];
|
|
|
|
/**
|
|
* Processed Response Data
|
|
*
|
|
* @var mixed
|
|
*/
|
|
public $client;
|
|
|
|
/**
|
|
* EstPos constructor.
|
|
*
|
|
* @param array $config
|
|
* @param mixed $account
|
|
* @param array $currencies
|
|
*/
|
|
public function __construct($config, $account, array $currencies)
|
|
{
|
|
$client = new Client();
|
|
$this->client = $client;
|
|
$this->config = $config;
|
|
$this->account = $account;
|
|
$this->currencies = $currencies;
|
|
|
|
$this->url = isset($this->config['urls'][$this->account->env]) ?
|
|
$this->config['urls'][$this->account->env] :
|
|
$this->config['urls']['production'];
|
|
|
|
$this->gateway = isset($this->config['urls']['gateway'][$this->account->env]) ?
|
|
$this->config['urls']['gateway'][$this->account->env] :
|
|
$this->config['urls']['gateway']['production'];
|
|
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Create Regular Payment XML
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function createRegularPaymentXML()
|
|
{
|
|
$nodes = [
|
|
'CC5Request' => [
|
|
'Name' => $this->account->username,
|
|
'Password' => $this->account->password,
|
|
'ClientId' => $this->account->client_id,
|
|
'Type' => $this->type,
|
|
'IPAddress' => $this->order->ip,
|
|
'Email' => $this->order->email,
|
|
'OrderId' => $this->order->id,
|
|
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
|
|
'Total' => $this->order->amount,
|
|
'Currency' => $this->order->currency,
|
|
'Taksit' => $this->order->installment,
|
|
'CardType' => isset($this->card->type) ? $this->card->type : null,
|
|
'Number' => $this->card->number,
|
|
'Expires' => $this->card->month . '/' . $this->card->year,
|
|
'Cvv2Val' => $this->card->cvv,
|
|
'Mode' => 'P',
|
|
'GroupId' => '',
|
|
'TransId' => '',
|
|
'BillTo' => [
|
|
'Name' => $this->order->name ? $this->order->name : null,
|
|
]
|
|
]
|
|
];
|
|
|
|
return $this->createXML($nodes, 'ISO-8859-9');
|
|
}
|
|
|
|
/**
|
|
* Create Regular Payment Post XML
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function createRegularPostXML()
|
|
{
|
|
$nodes = [
|
|
'CC5Request' => [
|
|
'Name' => $this->account->username,
|
|
'Password' => $this->account->password,
|
|
'ClientId' => $this->account->client_id,
|
|
'Type' => $this->types[$this->order->transaction],
|
|
'OrderId' => $this->order->id,
|
|
]
|
|
];
|
|
|
|
return $this->createXML($nodes, 'ISO-8859-9');
|
|
}
|
|
|
|
/**
|
|
* Create 3D Payment XML
|
|
* @return string
|
|
*/
|
|
protected function create3DPaymentXML()
|
|
{
|
|
$nodes = [
|
|
'CC5Request' => [
|
|
'Name' => $this->account->username,
|
|
'Password' => $this->account->password,
|
|
'ClientId' => $this->account->client_id,
|
|
'Type' => $this->type,
|
|
'IPAddress' => $this->order->ip,
|
|
'Email' => $this->order->email,
|
|
'OrderId' => $this->order->id,
|
|
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
|
|
'Total' => $this->order->amount,
|
|
'Currency' => $this->order->currency,
|
|
'Taksit' => $this->order->installment,
|
|
'Number' => $this->request->get('md'),
|
|
'Expires' => '',
|
|
'Cvv2Val' => '',
|
|
'PayerTxnId' => $this->request->get('xid'),
|
|
'PayerSecurityLevel' => $this->request->get('eci'),
|
|
'PayerAuthenticationCode' => $this->request->get('cavv'),
|
|
'CardholderPresentCode' => '13',
|
|
'Mode' => 'P',
|
|
'GroupId' => '',
|
|
'TransId' => '',
|
|
]
|
|
];
|
|
|
|
if ($this->order->name) {
|
|
$nodes['BillTo'] = [
|
|
'Name' => $this->order->name,
|
|
];
|
|
}
|
|
|
|
return $this->createXML($nodes, 'ISO-8859-9');
|
|
}
|
|
|
|
/**
|
|
* Get ProcReturnCode
|
|
*
|
|
* @return string|null
|
|
*/
|
|
protected function getProcReturnCode()
|
|
{
|
|
return isset($this->data->ProcReturnCode) ? (string)$this->data->ProcReturnCode : null;
|
|
}
|
|
|
|
/**
|
|
* Get Status Detail Text
|
|
*
|
|
* @return string|null
|
|
*/
|
|
protected function getStatusDetail()
|
|
{
|
|
$proc_return_code = $this->getProcReturnCode();
|
|
|
|
return $proc_return_code ? (isset($this->codes[$proc_return_code]) ? (string)$this->codes[$proc_return_code] : null) : null;
|
|
}
|
|
|
|
/**
|
|
* Create 3D Hash
|
|
*
|
|
* @return string
|
|
*/
|
|
public function create3DHash()
|
|
{
|
|
$hash_str = '';
|
|
$hash_str = $this->order->id . $this->order->amount . $this->order->success_url . $this->order->fail_url . $this->type . $this->order->installment . $this->order->rand . $this->account->merchant_pass;
|
|
|
|
return base64_encode(pack('H*', sha1($hash_str)));
|
|
}
|
|
|
|
/**
|
|
* Check 3D Hash
|
|
*
|
|
* @param array $data
|
|
* @return bool
|
|
*/
|
|
public function check3DHash($data)
|
|
{
|
|
$return = false;
|
|
$responseHash = $data['ResponseHash'];
|
|
|
|
//MerchantID + MerchantPass + OrderId + AuthCode + ProcReturnCode + 3DStatus + ResponseRnd + UserCode
|
|
$generatedHash = $this->account->merchant_id . $this->account->merchant_pass . $data['OrderId'] . $data['AuthCode'] . $data['ProcReturnCode'] . $data['3DStatus'] . $data['ResponseRnd'] . $this->account->user_code;
|
|
$generatedHash = base64_encode(pack('H*', sha1($generatedHash)));
|
|
|
|
if ($generatedHash == $responseHash) {
|
|
$return = true;
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Regular Payment
|
|
*
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function makeRegularPayment()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Make 3D Payment
|
|
*
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function make3DPayment()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Make 3D Pay Payment
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function make3DPayPayment()
|
|
{
|
|
$this->request = Request::createFromGlobals();
|
|
$requestAll = $this->request->request->all();
|
|
$ipAddress = $this->request->getClientIp();
|
|
|
|
/*echo "<pre>";
|
|
print_r($this->order);
|
|
die();*/
|
|
|
|
$paymentCheck = null;
|
|
$status = 'declined';
|
|
$transaction_security = 'MPI fallback';
|
|
$errorMessage = null;
|
|
|
|
try {
|
|
|
|
$requestParam = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><VposRequest></VposRequest>');
|
|
|
|
$requestParam->addChild('MerchantId', $this->account->merchant_id);
|
|
$requestParam->addChild('Password', $this->account->merchant_password);
|
|
$requestParam->addChild('TerminalNo', $this->account->terminal_no);
|
|
$requestParam->addChild('TransactionType', 'Sale');
|
|
$requestParam->addChild('OrderId', $this->order->id);
|
|
$requestParam->addChild('CurrencyAmount', number_format(($requestAll['PurchAmount'] / 100), 2, '.', ''));
|
|
$requestParam->addChild('CurrencyCode', $requestAll['PurchCurrency']);
|
|
$requestParam->addChild('Pan', $requestAll['Pan']);
|
|
$requestParam->addChild('Expiry', $this->order->creditCardYear . $this->order->creditCardMonth);
|
|
$requestParam->addChild('Cvv', $this->order->creditCardYearCvv);
|
|
$requestParam->addChild('ECI', $requestAll['Eci']);
|
|
$requestParam->addChild('CAVV', $requestAll['Cavv']);
|
|
$requestParam->addChild('MpiTransactionId', $requestAll['VerifyEnrollmentRequestId']);
|
|
$requestParam->addChild('ClientIp', $ipAddress);
|
|
$requestParam->addChild('TransactionDeviceSource', 0);
|
|
|
|
if (!empty($requestAll['InstallmentCount'])) {
|
|
$requestParam->addChild('NumberOfInstallments', $requestAll['InstallmentCount']);
|
|
}
|
|
|
|
$payment = $this->client->request('POST', $this->url, [
|
|
'form_params' => ['prmstr' => $requestParam->asXML()]
|
|
]);
|
|
|
|
$paymentCheck = $this->XMLStringToObject($payment->getBody()->getContents());
|
|
|
|
if ($paymentCheck->ResultCode == '0000') {
|
|
$status = 'approved';
|
|
} else {
|
|
$errorMessage = $paymentCheck->ResultDetail;
|
|
}
|
|
|
|
if ($paymentCheck->ThreeDSecureType == '2') {
|
|
$transaction_security = 'Full 3D Secure';
|
|
} elseif ($paymentCheck->ThreeDSecureType == '3') {
|
|
$transaction_security = 'Half 3D Secure';
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
Log::error($this->account->bank . ' Error!');
|
|
Log::error($e->getMessage());
|
|
}
|
|
|
|
|
|
|
|
$this->response = (object)[
|
|
'id' => isset($paymentCheck->TransactionId) ? (string)$paymentCheck->TransactionId : null,
|
|
'trans_id' => isset($paymentCheck->TransactionId) ? (string)$paymentCheck->TransactionId : null,
|
|
'auth_code' => isset($paymentCheck->AuthCode) ? (string)$paymentCheck->AuthCode : null,
|
|
'host_ref_num' => isset($paymentCheck->TransactionId) ? (string)$paymentCheck->TransactionId : null,
|
|
'order_id' => isset($paymentCheck->TransactionId) ? (string)$paymentCheck->TransactionId : null,
|
|
'status' => $status,
|
|
'response' => $paymentCheck,
|
|
'transaction_security' => $transaction_security,
|
|
'error_code' => isset($paymentCheck->ResultCode) ? (string)$paymentCheck->ResultCode : null,
|
|
'error_message' => $errorMessage,
|
|
'all' => $paymentCheck
|
|
];
|
|
|
|
/*echo "<pre>";
|
|
print_r($this->response);
|
|
die();*/
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get 3d Form Data
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get3DFormData()
|
|
{
|
|
$threeDFormData = [];
|
|
|
|
try {
|
|
|
|
if ($this->order) {
|
|
|
|
$threeDCheckParam = [
|
|
'Pan' => $this->card->number,
|
|
'ExpiryDate' => $this->getCardExpDate(),
|
|
'PurchaseAmount' => number_format(($this->order->amount * 100 / 100), 2, '.', ''),
|
|
'Currency' => $this->order->currency,
|
|
'BrandName' => null,
|
|
'VerifyEnrollmentRequestId' => $this->order->id,
|
|
'MerchantId' => $this->account->merchant_id,
|
|
'MerchantPassword' => $this->account->merchant_password,
|
|
'SuccessUrl' => $this->order->success_url,
|
|
'FailUrl' => $this->order->success_url,
|
|
];
|
|
|
|
$response = $this->client->request('POST', $this->gateway, [
|
|
'form_params' => $threeDCheckParam
|
|
]);
|
|
|
|
$threeDCheck = $this->XMLStringToObject($response->getBody()->getContents());
|
|
|
|
if ($threeDCheck->MessageErrorCode != 200) {
|
|
throw new Exception($threeDCheck->MessageErrorCode . ' - ' . $threeDCheck->ErrorMessage);
|
|
}
|
|
|
|
$threeDFormData = [
|
|
'status' => $threeDCheck->Message->VERes->Status,
|
|
'gateway' => $threeDCheck->Message->VERes->ACSUrl,
|
|
'success_url' => $this->order->success_url,
|
|
'fail_url' => $this->order->success_url,
|
|
'inputs' => [
|
|
'PaReq' => $threeDCheck->Message->VERes->PaReq,
|
|
'TermUrl' => $threeDCheck->Message->VERes->TermUrl,
|
|
'MD' => $threeDCheck->Message->VERes->MD
|
|
]
|
|
];
|
|
|
|
if ($threeDFormData['status'] != 'Y') {
|
|
throw new Exception('3D Secure is not supported for this card.');
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
Log::error($this->account->bank . ' Error!');
|
|
Log::error($e->getMessage());
|
|
$threeDFormData = [];
|
|
}
|
|
|
|
return $threeDFormData;
|
|
}
|
|
|
|
/**
|
|
* Send contents to WebService
|
|
*
|
|
* @param $contents
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function send($contents)
|
|
{
|
|
$client = new Client();
|
|
|
|
$response = $client->request('POST', $this->url, [
|
|
'body' => $contents
|
|
]);
|
|
|
|
$this->data = $this->XMLStringToObject($response->getBody()->getContents());
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Prepare Order
|
|
*
|
|
* @param object $order
|
|
* @param object null $card
|
|
* @return mixed
|
|
* @throws UnsupportedTransactionTypeException
|
|
*/
|
|
public function prepare($order, $card = null)
|
|
{
|
|
$this->type = $this->types['pay'];
|
|
if (isset($order->transaction)) {
|
|
if (array_key_exists($order->transaction, $this->types)) {
|
|
$this->type = $this->types[$order->transaction];
|
|
} else {
|
|
throw new UnsupportedTransactionTypeException('Unsupported transaction type!');
|
|
}
|
|
}
|
|
|
|
$this->order = $order;
|
|
$this->card = $card;
|
|
|
|
$this->order->installment = $this->order->installment == 0 ? 0 : $this->order->installment;
|
|
}
|
|
|
|
/**
|
|
* Make Payment
|
|
*
|
|
* @param object $card
|
|
* @return mixed
|
|
* @throws UnsupportedPaymentModelException
|
|
* @throws GuzzleException
|
|
*/
|
|
public function payment($card)
|
|
{
|
|
$this->card = $card;
|
|
|
|
$model = 'regular';
|
|
if (isset($this->account->model) && $this->account->model) {
|
|
$model = $this->account->model;
|
|
}
|
|
|
|
if ($model == 'regular') {
|
|
$this->makeRegularPayment();
|
|
} elseif ($model == '3d') {
|
|
$this->make3DPayment();
|
|
} elseif ($model == '3d_pay') {
|
|
$this->make3DPayPayment();
|
|
} else {
|
|
throw new UnsupportedPaymentModelException();
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Refund Order
|
|
*
|
|
* @param array $meta
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function refund(array $meta)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Cancel Order
|
|
*
|
|
* @param array $meta
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function cancel(array $meta)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Order Status
|
|
*
|
|
* @param array $meta
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function status(array $meta)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Order History
|
|
*
|
|
* @param array $meta
|
|
* @return $this
|
|
* @throws GuzzleException
|
|
*/
|
|
public function history(array $meta)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getConfig()
|
|
{
|
|
return $this->config;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getAccount()
|
|
{
|
|
return $this->account;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getCurrencies()
|
|
{
|
|
return $this->currencies;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getOrder()
|
|
{
|
|
return $this->order;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getCard()
|
|
{
|
|
return $this->card;
|
|
}
|
|
|
|
/**
|
|
* @return string|null
|
|
*/
|
|
public function getCardCode()
|
|
{
|
|
$card_type = null;
|
|
if (isset($this->card->type)) {
|
|
if ($this->card->type == 'visa') {
|
|
$card_type = '0';
|
|
} elseif ($this->card->type == 'master') {
|
|
$card_type = '1';
|
|
} elseif ($this->card->type == '1' || $this->card->type == '2') {
|
|
$card_type = $this->card->type;
|
|
}
|
|
}
|
|
return $card_type;
|
|
}
|
|
|
|
protected function getCardExpDate()
|
|
{
|
|
$year = (string)substr($this->card->year, 2, 2);
|
|
$month = (string)substr($this->card->month, 0, 2);
|
|
|
|
return (string)$year . $month;
|
|
}
|
|
|
|
|
|
}
|