| Server IP : 85.158.181.41 / Your IP : 216.73.217.12 Web Server : Apache System : Linux cloud9-vm129 6.1.178+1-ph #ph SMP PREEMPT_DYNAMIC Wed Jul 29 09:00:54 UTC 2026 x86_64 User : moncbefd ( 1024) PHP Version : 7.3.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/moncbefd/www.moneta.at/GXModules/Gambio/Afterbuy/Classes/ |
Upload File : |
<?php
/* --------------------------------------------------------------
AfterbuyOrderSender.inc.php 2019-08-08
Gambio GmbH
http://www.gambio.de
Copyright (c) 2018 Gambio GmbH
Released under the GNU General Public License (Version 2)
[http://www.gnu.org/licenses/gpl-2.0.html]
--------------------------------------------------------------
*/
class AfterbuyOrderSender
{
const AFTERBUY_URL = 'https://api.afterbuy.de/afterbuy/ShopInterfaceUTF8.aspx';
// Timeout for requests to AFTERBUY_URL
const REQUEST_TIMEOUT = 5;
// 1 = interne products_id (DB-ID)
// andere Werte = Ziffern aus Artikelnummer, products_id als Fallback
const VERWENDE_SHOP_ARTIKELNUMMER = 0;
// 0 = Feedbackdatum setzen und KEINE automatische Erstkontaktmail versenden
// 1 = KEIN Feedbackdatum setzen, aber automatische Erstkontaktmail versenden
// (Achtung: Kunde müsste Feedback durchlaufen wenn die Erstkontakt nicht angepasst wird!)
// 2 = Feedbackdatum setzen und automatische Erstkontaktmail versenden
// (Achtung: Erstkontaktmail muss mit Variablen angepasst werden!)
const FEEDBACKDATUM = '0';
// 1 = Versand aus Shop
// 0 = Versandermittlung durch Afterbuy (nur wenn Stammartikel erkannt wird!)
const VERSANDERMITTLUNG_AB = 1;
// 0 = Standard EbayName (= gesamte Zeile "Benutzername" in dieser Datei)
// 1 = E-Mail
// 2 = EKNummer (wenn im Shop vorhanden!)
const KUNDENERKENNUNG = '1';
// 0 = Product ID (Artikelnummer im Shop muss gleich Product ID Afterbuy sein)
// 1 = Artikelnummer (Artikelnummer im Shop muss gleich Artikelnummer Afterbuy sein)
// 2 = EAN (Artikel-EAN muss gleich EAN Afterbuy sein) (wird nicht unterstützt)
const ARTIKELERKENNUNG = '1';
protected $orderId;
protected $partnerID;
protected $partnerPass;
protected $userID;
protected $orderStatus;
protected $b2bStatusIds;
protected $orderTotalConfiguration;
protected $paymentMapping;
protected $logger;
protected $configuration;
/**
* @var OrderInterface
*/
protected $order;
/**
* AfterbuyOrderSender constructor.
*
* Configuration will fall back on values from the old configuration page if GXModuleConfigurationStorage does not
* contain values from the new configuration.
*
* @param $orderId
*/
public function __construct($orderId)
{
$this->configuration = MainFactory::create('GambioAfterbuyConfigurationStorage');
$this->orderId = (int)$orderId;
$this->partnerID = $this->configuration->get('partner_id');
$this->partnerPass = $this->configuration->get('partner_password');
$this->userID = $this->configuration->get('user_id');
$this->orderStatus = $this->configuration->get('order_status');
$this->b2bStatusIds = [3];
$this->logger = MainFactory::create('AfterbuyLogger');
/** @var OrderReadService $orderService */
$orderReadService = StaticGXCoreLoader::getService('OrderRead');
/** @var OrderInterface $order */
$this->order = $orderReadService->getOrderById(new IdType((int)$this->orderId));
$this->orderTotalConfiguration = [];
$this->addOrderTotalConfiguration('ot_bonus_fee', '99999991', 'Bonuspunkte', -1);
$this->addOrderTotalConfiguration('ot_payment', '99999995', 'Zahlartenrabatt');
$this->addOrderTotalConfiguration('ot_coupon', '99999996', 'Kupon');
$this->addOrderTotalConfiguration('ot_gv', '99999997', 'Gutschein');
$this->addOrderTotalConfiguration('ot_discount', '99999998', 'Rabatt');
$this->addOrderTotalConfiguration('ot_cod_fee', '99999999', 'Nachnahme');
$this->paymentMapping = [];
$this->addPaymentMapping('banktransfer', 'Bankeinzug', '7');
$this->addPaymentMapping('cash', 'Barzahlung', '2');
$this->addPaymentMapping('cod', 'Nachnahme', '4');
$this->addPaymentMapping('invoice', 'Rechnung', '6');
$this->addPaymentMapping('moneyorder', 'Überweisung/Vorkasse', '1');
$this->addPaymentMapping('eustandardtransfer', 'Überweisung/Vorkasse', '1');
$this->addPaymentMapping('moneybookers', 'Moneybookers', '15');
$this->addPaymentMapping('moneybookers_cc', 'Moneybookers CC', '15');
$this->addPaymentMapping('moneybookers_cgb', 'Moneybookers CGB', '15');
$this->addPaymentMapping('moneybookers_csi', 'Moneybookers CSI', '15');
$this->addPaymentMapping('moneybookers_elv', 'Moneybookers ELV', '15');
$this->addPaymentMapping('moneybookers_giropay', 'Moneybookers GIROPAY', '15');
$this->addPaymentMapping('moneybookers_ideal', 'Moneybookers IDEAL', '15');
$this->addPaymentMapping('moneybookers_mae', 'Moneybookers MAE', '15');
$this->addPaymentMapping('moneybookers_netpay', 'Moneybookers NETPAY', '15');
$this->addPaymentMapping('moneybookers_psp', 'Moneybookers PSP', '15');
$this->addPaymentMapping('moneybookers_pwy', 'Moneybookers PWY', '15');
$this->addPaymentMapping('moneybookers_sft', 'Moneybookers SFT', '15');
$this->addPaymentMapping('moneybookers_wlt', 'Moneybookers WLT', '15');
$this->addPaymentMapping('paypal', 'PayPal', '5');
$this->addPaymentMapping('paypalexpress', 'PayPal', '5');
$this->addPaymentMapping('paypal_gambio', 'PayPal', '5');
$this->addPaymentMapping('paypalgambio_alt', 'PayPal', '5');
$this->addPaymentMapping('paypalng', 'PayPal', '5');
$this->addPaymentMapping('paypal3', 'PayPal', '5');
$this->addPaymentMapping('sofortueberweisung', 'Sofortüberweisung', '12');
$this->addPaymentMapping('sofortueberweisungredirect', 'Sofortüberweisung', '12');
$this->addPaymentMapping('sofortueberweisung_direct', 'Sofortüberweisung', '12');
$this->addPaymentMapping('sofortueberweisungvorkasse', 'Sofortüberweisung', '12');
$this->addPaymentMapping('sofort_sofortueberweisung', 'Sofortüberweisung', '12');
$this->addPaymentMapping('billsafe', 'BillSAFE', '18');
$this->addPaymentMapping('ipayment_cc', 'iPayment CC', '99');
$this->addPaymentMapping('ipayment_elv', 'iPayment ELV', '99');
$this->addPaymentMapping('cc', 'Kreditkarte', '99');
$this->addPaymentMapping('amazonadvpay', 'AmazonPay', '99');
$this->addPaymentMapping('default', 'sonstige Zahlungsweise', '99');
}
public function addOrderTotalConfiguration($moduleCode, $artikelNr, $artikelName, $factor = 1, $taxRate = 0)
{
$this->orderTotalConfiguration[$moduleCode] = [
'Artikelnr' => $artikelNr,
'Artikelname' => $artikelName,
'ArtikelMwst' => $taxRate,
'factor' => $factor,
];
}
public function addPaymentMapping($moduleCode, $afterbuyName, $afterbuyId)
{
$this->paymentMapping[$moduleCode] = [
'name' => $afterbuyName,
'id' => $afterbuyId,
];
}
/**
* @throws AfterbuyException
*/
public function processOrder()
{
$this->logger->notice('preparing data for order ' . $this->orderId);
$data = $this->prepareData();
$this->logger->notice('sending order ' . $this->orderId);
$this->sendData($data);
}
public function prepareData()
{
$customerAddress = $this->order->getCustomerAddress();
$billingAddress = $this->order->getBillingAddress();
$deliveryAddress = $this->order->getDeliveryAddress();
$salutations = ['m' => 'Herr', 'f' => 'Frau'];
$customerGender = (string)$billingAddress->getGender();
$isB2B = in_array($this->order->getCustomerStatusInformation()->getStatusId(), $this->b2bStatusIds, true)
|| $customerAddress->getB2BStatus()->getStatus();
$customerStatusId = $this->order->getCustomerStatusInformation()->getStatusId();
$db = StaticGXCoreLoader::getDatabaseQueryBuilder();
/** @var \CI_DB_mysqli_result $customersStatusRow */
$customersStatusRow = $db->where('customers_status_id', $customerStatusId)
->get('customers_status', 1)
->row_array();
$mustAddTax = (bool)$customersStatusRow['customers_status_show_price_tax'] === false
&& (bool)$customersStatusRow['customers_status_add_tax_ot'] === true;
$data = [
'Kundenerkennung' => self::KUNDENERKENNUNG,
'Action' => 'new',
'PartnerID' => $this->partnerID,
'PartnerPass' => $this->partnerPass,
'UserID' => $this->userID,
'Kbenutzername' => $this->order->getCustomerId() . '_XTC_' . $this->order->getOrderId(),
'Kanrede' => array_key_exists($customerGender, $salutations) ? $salutations[$customerGender] : '',
'KFirma' => (string)$billingAddress->getCompany(),
'KVorname' => (string)$billingAddress->getFirstname(),
'KNachname' => (string)$billingAddress->getLastname(),
'KStrasse' => (string)$billingAddress->getStreet(),
'KStrasse2' => (string)$billingAddress->getAdditionalAddressInfo(),
'KPLZ' => (string)$billingAddress->getPostcode(),
'KOrt' => (string)$billingAddress->getCity(),
'KTelefon' => (string)$this->order->getCustomerTelephone(),
'Kfax' => '',
'Kemail' => (string)$this->order->getCustomerEmail(),
'KLand' => (string)$billingAddress->getCountry()->getIso2(),
'Lieferanschrift' => '0',
'UsStID' => (string)$this->order->getVatIdNumber(),
'VID' => (string)$this->order->getOrderId(),
'CheckVID' => (string)$this->order->getOrderId(),
'Haendler' => $isB2B ? '1' : '0',
'Artikelerkennung' => self::ARTIKELERKENNUNG,
'PosAnz' => '0',
'Versandkosten' => '',
'kommentar' => '',
'Versandart' => '',
'NoVersandCalc' => '',
'Zahlart' => '',
'ZFunktionsID' => '',
'Bestandart' => 'shop',
'NoFeedback' => self::FEEDBACKDATUM,
'SoldCurrency' => $this->order->getCurrencyCode()->getCode(),
];
if ($billingAddress != $deliveryAddress) {
$deliveryAddressData = [
'Lieferanschrift' => 1,
'KLFirma' => (string)$deliveryAddress->getCompany(),
'KLVorname' => (string)$deliveryAddress->getFirstname(),
'KLNachname' => (string)$deliveryAddress->getLastname(),
'KLStrasse' => (string)$deliveryAddress->getStreet(),
'KLStrasse2' => (string)$deliveryAddress->getAdditionalAddressInfo(),
'KLPLZ' => (string)$deliveryAddress->getPostcode(),
'KLOrt' => (string)$deliveryAddress->getCity(),
'KLLand' => (string)$deliveryAddress->getCountry()->getIso2(),
];
$data = array_merge($data, $deliveryAddressData);
}
$artikelPos = 0;
/**
* @var int $idx
* @var OrderItem $orderItem
*/
foreach ($this->order->getOrderItems() as $idx => $orderItem) {
$artikelPos++;
$productsId = (int)$orderItem->getAddonValue(new StringType('productId'));
if (self::VERWENDE_SHOP_ARTIKELNUMMER === 1) {
$data['Artikelnr_' . $artikelPos] = (string)$productsId;
if ($data['Artikelnr_' . $artikelPos] === '') {
$data['Artikelnr_' . $artikelPos] = '99999';
}
} else {
$data['Artikelnr_' . $artikelPos] = (string)$orderItem->getProductModel();
$data['Artikelnr_' . $artikelPos] = preg_replace('/\D+/', '', $data['Artikelnr_' . $artikelPos]);
if ($data['Artikelnr_' . $artikelPos] === '') {
$data['Artikelnr_' . $artikelPos] = (string)$productsId;
}
}
if ($GLOBALS['gmSEOBoost']->boost_products) {
$productUrl = xtc_href_link($GLOBALS['gmSEOBoost']->get_boosted_product_url($productsId,
$orderItem->getName()));
} else {
$productUrl = xtc_href_link('product_info.php', xtc_product_link($productsId, $orderItem->getName()));
}
$itemPrice = $orderItem->getPrice();
if ($mustAddTax) {
$this->logger->notice('orderItemTax: ' . $orderItem->getTax());
$itemPrice *= ($orderItem->getTax() + 100) / 100;
}
$data['ArtikelStammID_' . $artikelPos] = $data['Artikelnr_' . $artikelPos];
$data['Artikelname_' . $artikelPos] = $orderItem->getName();
$data['ArtikelEPreis_' . $artikelPos] = $this->convertPrice($itemPrice);
$data['ArtikelMwst_' . $artikelPos] = $this->convertPrice($orderItem->getTax());
$data['ArtikelMenge_' . $artikelPos] = (string)$orderItem->getQuantity();
$data['ArtikelLink_' . $artikelPos] = $productUrl;
$attributesCollection = $orderItem->getAttributes();
if ($attributesCollection->isEmpty() !== true) {
$attributes = [];
/** @var StoredOrderItemAttribute $attribute */
foreach ($attributesCollection->getIterator() as $attribute) {
$attributes[] = $attribute->getName() . ':' . $attribute->getValue();
if ($attribute instanceof OrderItemAttribute) {
$attrModel = $this->getAttributeModel($productsId, $attribute);
if ($attrModel !== '') {
$data['Artikelnr_' . $artikelPos] = $attrModel;
}
}
}
$data['Attribute_' . $artikelPos] = implode('|', $attributes);
}
}
/** @var $orderTotal StoredOrderTotal */
foreach ($this->order->getOrderTotals() as $orderTotal) {
if (array_key_exists($orderTotal->getClass(), $this->orderTotalConfiguration)) {
$otConfiguration = $this->orderTotalConfiguration[$orderTotal->getClass()];
$artikelPos++;
$artikelEPreis = $this->convertPrice($otConfiguration['factor']
* $orderTotal->getValue());
$data['Artikelnr_' . $artikelPos] = $otConfiguration['Artikelnr'];
$data['Artikelname_' . $artikelPos] = $otConfiguration['Artikelname'];
$data['ArtikelEPreis_' . $artikelPos] = $artikelEPreis;
$data['ArtikelMwst_' . $artikelPos] = $this->convertPrice($otConfiguration['ArtikelMwst']);
$data['ArtikelMenge_' . $artikelPos] = '1';
}
if ($orderTotal->getClass() === 'ot_shipping') {
$shippingCost = $orderTotal->getValue();
if ($mustAddTax && MODULE_ORDER_TOTAL_SHIPPING_TAX_CLASS > 0) {
$shippingTaxRate = $this->getTaxRate(MODULE_ORDER_TOTAL_SHIPPING_TAX_CLASS,
$this->order->getBillingAddress()->getCountry(),
$this->order->getBillingAddress()->getCountryZone());
$shippingCost *= ($shippingTaxRate + 100) / 100;
}
$data['Versandkosten'] = $this->convertPrice($shippingCost);
}
}
$data['PosAnz'] = $artikelPos;
$data['kommentar'] = $this->order->getComment();
$data['Versandart'] = preg_replace('/ \(.*?\)/', '', $this->order->getShippingType()->getTitle());
$data['NoVersandCalc'] = self::VERSANDERMITTLUNG_AB;
$data['VID'] = $this->order->getOrderId();
$afterbuyPayment = $this->mapPayment($this->order->getPaymentType()->getModule());
$data['Zahlart'] = $afterbuyPayment['name'];
$data['ZFunktionsID'] = $afterbuyPayment['id'];
if ($this->configuration->get('order_status_paid') === '-1' || $this->orderIsPaid() === true) {
$data['SetPay'] = 1;
}
$data['debug'] = $this->order->getOrderTotals();
return $data;
}
protected function getTaxRate($taxClassId, CustomerCountryInterface $country, CustomerCountryZoneInterface $zone)
{
$db = StaticGXCoreLoader::getDatabaseQueryBuilder();
$taxRateQuery = $db->query("SELECT SUM(tax_rate) AS tax_rate
FROM
tax_rates tr
LEFT JOIN zones_to_geo_zones za ON (tr.tax_zone_id = za.geo_zone_id)
LEFT JOIN geo_zones tz ON (tz.geo_zone_id = tr.tax_zone_id)
WHERE
(za.zone_country_id IS NULL OR
za.zone_country_id = '0' OR
za.zone_country_id = ?) AND
(za.zone_id IS NULL OR
za.zone_id = '0' OR
za.zone_id = ?) AND
tr.tax_class_id = ?
GROUP BY tr.tax_priority",
[$country->getId(), $zone->getId(), (int)$taxClassId]);
$multiplier = 1.0;
foreach ($taxRateQuery->result_array() as $row) {
$multiplier *= ($row['tax_rate'] + 100) / 100;
}
$taxRate = ($multiplier - 1.0) * 100;
return $taxRate;
}
/**
* @param $data
*
* @throws AfterbuyException if sending data fails
*/
protected function sendData($data)
{
$requestData = http_build_query($data);
$this->logger->notice("Request data:\n" . $requestData);
$ch = curl_init();
$curlOptions = [
CURLOPT_URL => self::AFTERBUY_URL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $requestData,
CURLOPT_TIMEOUT => self::REQUEST_TIMEOUT,
];
curl_setopt_array($ch, $curlOptions);
$response = curl_exec($ch);
$curlInfo = curl_getinfo($ch);
$curlErrno = curl_errno($ch);
$curlError = curl_error($ch);
curl_close($ch);
$this->logger->notice("Received response:\n" . $response);
if ($curlErrno !== CURLE_OK) {
throw new AfterbuyException(sprintf('Request failed - %d/%s', $curlErrno, $curlError));
}
$xmlResponse = simplexml_load_string($response);
if ($xmlResponse === false) {
throw new AfterbuyException("Response from Afterbuy could not be parsed:\n===\n" . $response . "\n===\n");
}
if ((string)$xmlResponse->success === '1') {
$kundenNr = (string)$xmlResponse->data->KundenNr;
$this->logger->notice('transmission successful, order_id ' . $this->orderId . ' KundenNr ' . $kundenNr);
$db = StaticGXCoreLoader::getDatabaseQueryBuilder();
$db->set('afterbuy_success', '1')
->set('afterbuy_id', $kundenNr)
->where('orders_id', $this->orderId)
->update('orders');
if ((string)$this->orderStatus !== '') {
/** @var OrderWriteService $orderWriteService */
$orderWriteService = StaticGXCoreLoader::getService('OrderWrite');
$orderWriteService->updateOrderStatus(new IdType((int)$this->orderId),
new IdType((int)$this->orderStatus),
new StringType('Afterbuy KundenNr.: ' . $kundenNr),
new BoolType(false));
}
} else {
/** @var OrderWriteService $orderWriteService */
$orderWriteService = StaticGXCoreLoader::getService('OrderWrite');
$orderWriteService->updateOrderStatus(new IdType((int)$this->orderId),
new IdType($this->order->getStatusId()),
new StringType('Afterbuy Error: '
. (string)$xmlResponse->errorlist->error),
new BoolType(false));
throw new AfterbuyException((string)$xmlResponse->errorlist->error);
}
}
protected function convertPrice($price, $currencyFactor = 1.0)
{
$convertedPrice = (float)$price / $currencyFactor;
$convertedPrice = number_format($convertedPrice, 4, ',', '');
return $convertedPrice;
}
protected function getAttributeModel($productsId, StoredOrderItemAttribute $orderItemAttribute)
{
$db = StaticGXCoreLoader::getDatabaseQueryBuilder();
$attrQueryRow = $db->select('attributes_model')
->from('products_attributes')
->where('products_id', $productsId)
->where('options_id', $orderItemAttribute->getOptionId())
->where('options_values_id', $orderItemAttribute->getOptionValueId())
->get()
->row();
if ($attrQueryRow !== null) {
$attributeModel = $attrQueryRow->attributes_model;
$attributeModel = preg_replace('/\D+/', '', $attributeModel);
} else {
$attributeModel = '';
}
return $attributeModel;
}
protected function mapPayment($paymentCode)
{
if (array_key_exists($paymentCode, $this->paymentMapping)) {
$afterbuyPayment = $this->paymentMapping[$paymentCode];
} else {
$afterbuyPayment = $this->paymentMapping['default'];
}
return $afterbuyPayment;
}
/**
* Checks if the order is to be considered paid in full.
*
* An order is paid if the order status configured as order_status_paid is found in the order’s status history.
*
* @return bool
*/
public function orderIsPaid()
{
$paidOrderStatus = (int)$this->configuration->get('order_status_paid');
$isPaid = false;
/** @var OrderStatusHistoryListItem $statusHistoryItem */
foreach ($this->order->getStatusHistory() as $statusHistoryItem) {
if ($statusHistoryItem->getOrderStatusId() === $paidOrderStatus) {
$isPaid = true;
break;
}
}
return $isPaid;
}
}