252 lines
10 KiB
PHP
252 lines
10 KiB
PHP
<?php
|
|
|
|
use KupShop\KupShopBundle\Config;
|
|
|
|
/**
|
|
* Requires composer packages alcohol/iso3166, alcohol/iso4217 and adamstipak/webpay-php:~1.1.3 (https://github.com/wpj-cz/gp-webpay-php-sdk).
|
|
*/
|
|
class WebPay extends Payment
|
|
{
|
|
public static $name = 'WebPay platební brána';
|
|
|
|
// public $template = 'payment.WebPay.tpl';
|
|
|
|
public $class = 'WebPay';
|
|
|
|
public $tp_id_payment;
|
|
|
|
/** @var \AdamStipak\Webpay\Api */
|
|
public $apiContext;
|
|
|
|
public $method;
|
|
|
|
protected $pay_method = Payment::METHOD_ONLINE;
|
|
|
|
public function getPaymentUrl()
|
|
{
|
|
return $this->getGenericPaymentUrl(1);
|
|
}
|
|
|
|
public function getGatewayUrl()
|
|
{
|
|
return $this->config['webpayUrl'];
|
|
}
|
|
|
|
public function getData(): array
|
|
{
|
|
$request = $this->createPaymentRequest();
|
|
|
|
return $this->getApiContext()->createPaymentParam($request);
|
|
}
|
|
|
|
private function getPayment(bool $alwaysNew = true)
|
|
{
|
|
$kupshopPayment = $this->getPendingPayment();
|
|
if (!$alwaysNew && $kupshopPayment) {
|
|
return $kupshopPayment;
|
|
} else {
|
|
$this->createPayment(
|
|
null,
|
|
$this->order->getRemainingPayment(),
|
|
['paymentClass' => self::class]
|
|
);
|
|
$paymentRow = $this->selectSQL('order_payments', ['id' => $this->paymentId])->fetch();
|
|
$json = json_decode($paymentRow['payment_data'], true);
|
|
$json['session'] = $this->paymentId;
|
|
$paymentRow['payment_data'] = json_encode($json);
|
|
$this->updateSQL('order_payments', $paymentRow, ['id' => $this->paymentId]);
|
|
|
|
$paymentRow['decoded_data'] = $json;
|
|
|
|
return $paymentRow;
|
|
}
|
|
}
|
|
|
|
private function createPaymentRequest(): AdamStipak\Webpay\PaymentRequest
|
|
{
|
|
$iso4217 = new Alcohol\ISO4217();
|
|
if (class_exists('Alcohol\ISO3166\ISO3166')) {
|
|
$iso3166 = new Alcohol\ISO3166\ISO3166();
|
|
}
|
|
|
|
$amount = $this->order->getRemainingPayment();
|
|
if ($amount <= (float) 0) {
|
|
$this->step(-3, 'storno');
|
|
}
|
|
|
|
$addInfo = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><additionalInfoRequest xmlns="http://gpe.cz/gpwebpay/additionalInfo/request" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>');
|
|
$addInfo['version'] = '4.0';
|
|
|
|
$cardHolderInfo = $addInfo->addChild('cardholderInfo');
|
|
$cardHolderDetails = $cardHolderInfo->addChild('cardholderDetails');
|
|
$cardHolderDetails->name = mb_substr($this->order->invoice_name.' '.$this->order->invoice_surname, 0, 255);
|
|
$cardHolderDetails->email = mb_substr($this->order->invoice_email, 0, 255);
|
|
|
|
if (!empty($this->order->invoice_street) && isset($iso3166)
|
|
&& !empty($this->order->invoice_name)
|
|
&& !empty($this->order->invoice_city)
|
|
&& !empty($this->order->invoice_zip)
|
|
&& !empty($this->order->invoice_country)
|
|
&& !empty($this->order->invoice_email)
|
|
) {
|
|
$billingDetails = $cardHolderInfo->addChild('billingDetails');
|
|
$billingDetails->name = mb_substr($this->order->invoice_name.' '.$this->order->invoice_surname, 0, 255);
|
|
$billingDetails->address1 = mb_substr($this->order->invoice_street, 0, 50);
|
|
if (!empty($this->order->invoice_custom_address)) {
|
|
$billingDetails->address2 = mb_substr($this->order->invoice_custom_address, 0, 50);
|
|
}
|
|
$billingDetails->city = mb_substr($this->order->invoice_city, 0, 50);
|
|
$billingDetails->postalCode = mb_substr($this->order->invoice_zip, 0, 16);
|
|
$billingDetails->country = (int) $iso3166->getByAlpha2($this->order->invoice_country)['numeric'];
|
|
// phone has weird validation rules: cvc-pattern-valid: Value '+420777852147' is not facet-valid with respect to pattern '\d{1,15}' for type 'phoneValue'.
|
|
if (!empty($this->order->invoice_phone)) {
|
|
$billingDetails->phone = mb_substr(preg_replace('/([^0-9]+)/', '', $this->order->invoice_phone), 0, 20);
|
|
}
|
|
$billingDetails->email = mb_substr($this->order->invoice_email, 0, 255);
|
|
}
|
|
|
|
if (!empty($this->order->delivery_street) && isset($iso3166)
|
|
&& !empty($this->order->delivery_name)
|
|
&& !empty($this->order->delivery_city)
|
|
&& !empty($this->order->delivery_zip)
|
|
&& !empty($this->order->delivery_country)
|
|
) {
|
|
$shippingDetails = $cardHolderInfo->addChild('shippingDetails');
|
|
$shippingDetails->name = mb_substr($this->order->delivery_name.' '.$this->order->delivery_surname, 0, 255);
|
|
$shippingDetails->address1 = mb_substr($this->order->delivery_street, 0, 50);
|
|
if (!empty($this->order->delivery_custom_address)) {
|
|
$shippingDetails->address2 = mb_substr($this->order->delivery_custom_address, 0, 50);
|
|
}
|
|
$shippingDetails->city = mb_substr($this->order->delivery_city, 0, 50);
|
|
$shippingDetails->postalCode = mb_substr($this->order->delivery_zip, 0, 16);
|
|
$shippingDetails->country = (int) $iso3166->getByAlpha2($this->order->delivery_country)['numeric'];
|
|
// phone has weird validation rules: cvc-pattern-valid: Value '+420777852147' is not facet-valid with respect to pattern '\d{1,15}' for type 'phoneValue'.
|
|
if (!empty($this->order->delivery_phone)) {
|
|
$shippingDetails->phone = mb_substr(preg_replace('/([^0-9]+)/', '', $this->order->delivery_phone), 0, 20);
|
|
}
|
|
}
|
|
|
|
$paymentInfo = $addInfo->addChild('paymentInfo');
|
|
$paymentInfo->transactionType = '01';
|
|
|
|
$shoppingCartInfo = $addInfo->addChild('shoppingCartInfo');
|
|
$shoppingCartItems = $shoppingCartInfo->addChild('shoppingCartItems');
|
|
foreach ($this->order->fetchItems() as $item) {
|
|
if ($item['piece_price']['value_without_vat']->asInteger() < 0) {
|
|
continue; // skip items with negative price (must be unsignedLong - 12 digits max)
|
|
}
|
|
$shoppingCartItem = $shoppingCartItems->addChild('shoppingCartItem');
|
|
if (!empty($item['id_product'])) {
|
|
$itemCodeValue = $item['id_product'].(!empty($item['id_variation']) ? ('_'.$item['id_variation']) : '');
|
|
if (mb_strlen($itemCodeValue) <= 20) {
|
|
$shoppingCartItem->itemCode = $itemCodeValue;
|
|
}
|
|
}
|
|
$shoppingCartItem->itemDescription = mb_substr($item['descr'], 0, 50);
|
|
$shoppingCartItem->itemQuantity = $item['pieces'];
|
|
$shoppingCartItem->itemUnitPrice = $item['piece_price']['value_without_vat']->asInteger();
|
|
}
|
|
|
|
$request = new \AdamStipak\Webpay\PaymentRequest(
|
|
$this->getPayment()['id'],
|
|
$amount,
|
|
(int) $iso4217->getByAlpha3($this->order->currency)['numeric'],
|
|
1,
|
|
$this->getGenericPaymentUrl(5),
|
|
$this->order->id
|
|
);
|
|
|
|
$request->setParam('REFERENCENUMBER', $this->order->order_no);
|
|
$request->setParam('ADDINFO', str_replace(PHP_EOL, '', $addInfo->asXML()));
|
|
|
|
return $request;
|
|
}
|
|
|
|
/* Payment steps */
|
|
public function processStep_1()
|
|
{
|
|
$this->template = 'payment.WebPay.tpl';
|
|
}
|
|
|
|
public function processStep_5()
|
|
{
|
|
$response = new \AdamStipak\Webpay\PaymentResponse(
|
|
$_REQUEST['OPERATION'],
|
|
$_REQUEST['ORDERNUMBER'],
|
|
$_REQUEST['MERORDERNUM'],
|
|
$_REQUEST['PRCODE'],
|
|
$_REQUEST['SRCODE'],
|
|
$_REQUEST['RESULTTEXT'],
|
|
$_REQUEST['DIGEST'],
|
|
$_REQUEST['DIGEST1']
|
|
);
|
|
|
|
try {
|
|
$this->getApiContext()->verifyPaymentResponse($response);
|
|
} catch (\AdamStipak\Webpay\PaymentResponseException $e) {
|
|
// change payment status to finished
|
|
if (!$this->setStatus(Payment::STATUS_STORNO, $_REQUEST['ORDERNUMBER'])) {
|
|
logError(__FILE__, __LINE__, 'WebPay::updatePaymentStatus: setStatus failed!');
|
|
exit;
|
|
}
|
|
if ($_REQUEST['PRCODE'] != 50) { // nejedna se o "Drzitel karty zrusil platbu"
|
|
// PaymentResponseException has $prCode, $srCode for properties for logging GP Webpay response error codes.
|
|
logError(__FILE__, __LINE__, 'WebPay error: '.$_REQUEST['PRCODE'].' - '.$_REQUEST['RESULTTEXT'].', exception:'.$e);
|
|
}
|
|
$this->error(translate('payment_storno', 'payment'));
|
|
} catch (Exception $e) {
|
|
// Digest is not correct.
|
|
logError(__FILE__, __LINE__, 'WebPay exception: '.$e);
|
|
$this->error(translate('payment_storno', 'payment'));
|
|
}
|
|
|
|
if ($_REQUEST['PRCODE'] == 0) {
|
|
$this->status = Payment::STATUS_FINISHED;
|
|
// change payment status to finished
|
|
if (!$this->setStatus(Payment::STATUS_FINISHED, $_REQUEST['ORDERNUMBER'])) {
|
|
logError(__FILE__, __LINE__, 'WebPay::updatePaymentStatus: setStatus failed!');
|
|
exit;
|
|
}
|
|
|
|
$this->success(translate('paymentSuccess', 'payment'));
|
|
}
|
|
}
|
|
|
|
/* Payment methods */
|
|
|
|
public function getApiContext(): AdamStipak\Webpay\Api
|
|
{
|
|
if (!isset($this->apiContext)) {
|
|
$signer = new \AdamStipak\Webpay\Signer(
|
|
$this->config['privateKeyFilepath'],
|
|
$this->config['privateKeyPassword'],
|
|
$this->config['GPpublicKeyFilepath']
|
|
);
|
|
|
|
$this->apiContext = new \AdamStipak\Webpay\Api(
|
|
$this->config['merchantNumber'],
|
|
$this->config['webpayUrl'],
|
|
$signer
|
|
);
|
|
}
|
|
|
|
return $this->apiContext;
|
|
}
|
|
|
|
public function hasOnlinePayment()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public static function isEnabled($className)
|
|
{
|
|
$cfg = Config::get();
|
|
|
|
if (empty($cfg['Modules']['payments'][$className])) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|