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(''); $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; } }