| 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/system/classes/external/amazon/ |
Upload File : |
<?php
/* --------------------------------------------------------------
AmazonAdvancedPayment.inc.php 2019-11-05
Gambio GmbH
http://www.gambio.de
Copyright (c) 2014 Gambio GmbH
Released under the GNU General Public License (Version 2)
[http://www.gnu.org/licenses/gpl-2.0.html]
--------------------------------------------------------------
*/
class AmazonAdvancedPayment
{
const EP_OAP_DE_SANDBOX = 'https://mws-eu.amazonservices.com/OffAmazonPayments_Sandbox/2013-01-01/';
const EP_OAP_DE_PRODUCTION = 'https://mws-eu.amazonservices.com/OffAmazonPayments/2013-01-01/';
const EP_OAP_UK_SANDBOX = 'https://mws-eu.amazonservices.com/OffAmazonPayments_Sandbox/2013-01-01/';
const EP_OAP_UK_PRODUCTION = 'https://mws-eu.amazonservices.com/OffAmazonPayments/2013-01-01/';
const EP_OAP_US_SANDBOX = 'https://mws.amazonservices.com/OffAmazonPayments_Sandbox/2013-01-01/';
const EP_OAP_US_PRODUCTION = 'https://mws.amazonservices.com/OffAmazonPayments/2013-01-01/';
const URL_WIDGET_DE_SANDBOX = 'https://static-eu.payments-amazon.com/OffAmazonPayments/de/sandbox/js/Widgets.js';
const URL_WIDGET_DE_PRODUCTION = 'https://static-eu.payments-amazon.com/OffAmazonPayments/de/js/Widgets.js';
const URL_WIDGET_UK_SANDBOX = 'https://static-eu.payments-amazon.com/OffAmazonPayments/uk/sandbox/js/Widgets.js';
const URL_WIDGET_UK_PRODUCTION = 'https://static-eu.payments-amazon.com/OffAmazonPayments/uk/js/Widgets.js';
const URL_WIDGET_US_SANDBOX = 'https://static.payments-amazon.com/OffAmazonPayments/sandbox/js/Widgets.js';
const URL_WIDGET_US_PRODUCTION = 'https://static.payments-amazon.com/OffAmazonPayments/js/Widgets.js';
const URL_LPA_WIDGET_DE_SANDBOX = 'https://static-eu.payments-amazon.com/OffAmazonPayments/eur/sandbox/lpa/js/Widgets.js';
const URL_LPA_WIDGET_DE_PRODUCTION = 'https://static-eu.payments-amazon.com/OffAmazonPayments/eur/lpa/js/Widgets.js';
const URL_LPA_WIDGET_UK_SANDBOX = 'https://static-eu.payments-amazon.com/OffAmazonPayments/gbp/sandbox/lpa/js/Widgets.js';
const URL_LPA_WIDGET_UK_PRODUCTION = 'https://static-eu.payments-amazon.com/OffAmazonPayments/gbp/lpa/js/Widgets.js';
const URL_LPA_WIDGET_US_SANDBOX = 'https://static-na.payments-amazon.com/OffAmazonPayments/us/sandbox/js/Widgets.js';
const URL_LPA_WIDGET_US_PRODUCTION = 'https://static-na.payments-amazon.com/OffAmazonPayments/us/js/Widgets.js';
const URL_BUTTON_DE_SANDBOX = 'https://payments-sandbox.amazon.de/gp/widgets/button';
const URL_BUTTON_DE_PRODUCTION = 'https://payments.amazon.de/gp/widgets/button';
const URL_BUTTON_UK_SANDBOX = 'https://payments-sandbox.amazon.co.uk/gp/widgets/button';
const URL_BUTTON_UK_PRODUCTION = 'https://payments.amazon.co.uk/gp/widgets/button';
const URL_BUTTON_US_SANDBOX = 'https://payments-sandbox.amazon.com/gp/widgets/button';
const URL_BUTTON_US_PRODUCTION = 'https://payments.amazon.com/gp/widgets/button';
const MARKETPLACE_DE = 'A1PA6795UKMFR9';
const MARKETPLACE_UK = 'A1F83G8C2ARO7P';
const MARKETPLACE_US = 'ATVPDKIKX0DER';
const CONFIG_PREFIX = 'AMAZONADVPAY_';
const LOGLEVEL_INFO = 0x01;
const LOGLEVEL_WARN = 0x02;
const LOGLEVEL_ERROR = 0x04;
const LOGLEVEL_DEBUG = 0x10;
protected $_configuration;
protected $_txt;
protected $_logger;
protected $_throttle_max_retries = 5;
protected $_retry_delay = 1000; // milliseconds
public function __construct()
{
$this->_logger = new FileLog('payment-amzadvpay', true);
$this->_txt = MainFactory::create_object('LanguageTextManager', array('amazonadvancedpayment', $_SESSION['languages_id']));
$this->_configuration = $this->_load_configuration();
}
protected function _load_configuration()
{
$t_cfg = array(
'location' => 'de', // de|uk|us
'mode' => 'sandbox', // sandbox|production
'seller_id' => '__seller_id',
'aws_access_key' => '__aws_access_key',
'secret_key' => '__secret_key',
'button_color' => 'orange', // orange|tan|dark
'button_size' => 'medium', // medium|large|x-large
'hidden_button' => '0',
'authorization_mode' => 'auto-sync', // auto-sync|auto-async|manual
'capture_mode' => 'manual', // immediate|manual
'erp_mode' => '0', // 0|1
'ipn_enabled' => '1', // 0|1
'orders_status_auth_open' => '0',
'orders_status_auth_declined' => '0',
'orders_status_auth_declined_hard' => '0',
'orders_status_captured' => '0',
'orders_status_capture_failed' => '0',
);
foreach($t_cfg as $cfg_key => $cfg_value)
{
$t_db_cfg_key = self::CONFIG_PREFIX.strtoupper($cfg_key);
$t_db_cfg_value = gm_get_conf($t_db_cfg_key);
if($t_db_cfg_value !== null)
{
$t_cfg[$cfg_key] = $t_db_cfg_value;
}
}
return $t_cfg;
}
protected function _save_configuration($p_key = null)
{
foreach($this->_configuration as $cfg_key => $cfg_value)
{
if($p_key !== null && $cfg_key != $p_key)
{
continue;
}
$t_db_cfg_key = self::CONFIG_PREFIX.strtoupper($cfg_key);
gm_set_conf($t_db_cfg_key, xtc_db_input($cfg_value));
}
}
public function __get($p_varname)
{
$t_value = null;
if(array_key_exists($p_varname, $this->_configuration))
{
$t_value = $this->_configuration[$p_varname];
}
return $t_value;
}
public function __set($p_varname, $p_value)
{
if(array_key_exists($p_varname, $this->_configuration))
{
$this->_configuration[$p_varname] = $p_value;
$this->_save_configuration($p_varname);
}
}
public function __isset($p_varname)
{
$t_isset = false;
if(in_array($p_varname, $this->_configuration))
{
$t_isset = true;
}
return $t_isset;
}
/* ---------------------------------------------------------------------------------------------- */
public function get_authorization_timeout()
{
if($this->authorization_mode === 'auto-async')
{
$t_timeout = 1440;
}
else
{
$t_timeout = 0;
}
return $t_timeout;
}
/* ---------------------------------------------------------------------------------------------- */
public function get_text($placeholder)
{
return $this->_txt->get_text($placeholder);
}
public function replaceLanguagePlaceholders($content)
{
while(preg_match('/##(\w+)\b/', $content, $matches) === 1)
{
$replacement = $this->get_text($matches[1]);
if(empty($replacement))
{
$replacement = $matches[1];
}
$content = preg_replace('/##'.$matches[1].'/', $replacement.'$1', $content, 1);
}
return $content;
}
/* ---------------------------------------------------------------------------------------------- */
public function log($message, $loglevel = self::LOGLEVEL_INFO)
{
if($this->_logger !== false)
{
if($this->_logger instanceof LogControl)
{
switch($loglevel)
{
case self::LOGLEVEL_ERROR:
$this->_logger->error($message, 'payment', 'payment.amazonadvpay');
break;
case self::LOGLEVEL_WARN:
$this->_logger->warning($message, 'payment', 'payment.amazonadvpay');
break;
case self::LOGLEVEL_INFO:
case self::LOGLEVEL_DEBUG:
default:
$this->_logger->notice($message, 'payment', 'payment.amazonadvpay');
break;
}
}
if($this->_logger instanceof FileLog)
{
list($t_millis, $t_secs) = explode(' ', microtime());
$t_timestamp = sprintf('%s.%03d', date('Y-m-d H:i:s', $t_secs), round($t_millis * 1000));
$t_message = $t_timestamp.' | '.$message.PHP_EOL;
$this->_logger->write($t_message);
}
}
}
public function is_enabled()
{
$t_is_enabled = (defined('MODULE_PAYMENT_AMAZONADVPAY_STATUS') && MODULE_PAYMENT_AMAZONADVPAY_STATUS == 'True');
$t_is_enabled = $t_is_enabled && strpos(MODULE_PAYMENT_INSTALLED, 'amazonadvpay.php') !== false;
return $t_is_enabled;
}
public function useDefaultOrdersStatusConfiguration()
{
$LanguageTextManagers = array();
$Language = new language();
foreach($Language->catalog_languages as $lang_iso => $lang_data)
{
$LanguageTextManagers[$lang_iso] = MainFactory::create_object('LanguageTextManager', array('amazonadvancedpayment', $lang_data['id']));
}
$OrdersStatusNames = array(
'orders_status_auth_open' => 'orders_status_name_payment_authorized',
'orders_status_auth_declined' => 'orders_status_name_authorization_declined',
'orders_status_auth_declined_hard' => 'orders_status_name_authorization_declined_hard',
'orders_status_captured' => 'orders_status_name_payment_captured',
'orders_status_capture_failed' => 'orders_status_name_capture_failed',
);
foreach($OrdersStatusNames as $ConfigName => $PhraseLabel)
{
$osm = MainFactory::create_object('OrdersStatusModel');
try {
$osm->loadByName($LanguageTextManagers[DEFAULT_LANGUAGE]->get_text($PhraseLabel));
}
catch(OrdersStatusModelStatusNotFoundException $e)
{
foreach($LanguageTextManagers as $LangISO2 => $LanguageTextManager)
{
$osm->setStatusName($LanguageTextManager->get_text($PhraseLabel), $Language->catalog_languages[$LangISO2]['id']);
$osm->save();
}
}
$this->$ConfigName = $osm->get_('orders_status_id');
}
}
/* ---------------------------------------------------------------------------------------------- */
public function get_amazon_address_book_entry($p_customers_id)
{
$t_address_book_id = false;
// find Amazon address book entry
$t_ab_query =
'SELECT
`address_book_id`
FROM
`address_book`
WHERE
`customers_id` = \':customers_id\' AND
`address_class` = \'amzadvpay_temp\'';
$t_ab_query = strtr($t_ab_query, array(':customers_id' => (int)$p_customers_id));
$t_ab_result = xtc_db_query($t_ab_query, 'db_link', false);
while($t_ab_row = xtc_db_fetch_array($t_ab_result))
{
$t_address_book_id = $t_ab_row['address_book_id'];
}
// create address book entry if necessary
if($t_address_book_id === false)
{
$t_country_and_zone_id = $this->_get_customers_default_country_and_zone_id($p_customers_id);
$t_text_tbd = $this->get_text('ab_entry_to_be_determined');
$t_ab_data = [
'customers_id' => (int)$p_customers_id,
'entry_gender' => '', // N.B.: Amazon does not record customer's gender!
'entry_company' => '',
'entry_firstname' => ' ',
'entry_lastname' => $t_text_tbd,
'entry_street_address' => '',
'entry_postcode' => '',
'entry_city' => '',
'entry_state' => '',
'entry_country_id' => $t_country_and_zone_id['country_id'],
'entry_zone_id' => $t_country_and_zone_id['zone_id'],
'address_date_added' => 'now()',
'address_last_modified' => 'now()',
'address_class' => 'amzadvpay_temp',
];
xtc_db_perform('address_book', $t_ab_data);
$t_address_book_id = xtc_db_insert_id();
}
return $t_address_book_id;
}
public function update_amazon_address_book_entry($p_customers_id, $p_data)
{
$t_address_book_id = $this->get_amazon_address_book_entry($p_customers_id);
if(isset($p_data['country_iso2']))
{
$t_country_and_zone_id = $this->_get_country_and_zone_id_by_iso2($p_data['country_iso2']);
$p_data['entry_country_id'] = $t_country_and_zone_id['country_id'];
$p_data['entry_zone_id'] = $t_country_and_zone_id['zone_id'];
unset($p_data['country_iso2']);
}
$this->log("updating ab entry $t_address_book_id for customer $p_customers_id with data:\n".print_r($p_data, true));
xtc_db_perform('address_book', $p_data, 'update', 'address_book_id = \''.(int)$t_address_book_id.'\'');
return $t_address_book_id;
}
public function delete_amazon_address_book_entries($p_customers_id)
{
$t_query =
'DELETE
FROM `address_book`
WHERE
`customers_id` = \':customers_id\' AND
`address_class` = \'amzadvpay_temp\'';
$t_query = strtr($t_query, array(':customers_id' => (int)$p_customers_id));
xtc_db_query($t_query);
}
protected function _get_customers_default_country_and_zone_id($p_customers_id)
{
$t_query =
'SELECT
`entry_country_id`, `entry_zone_id`
FROM
`address_book` ab
LEFT JOIN `customers` c
ON
`c`.`customers_id` = `ab`.`customers_id` AND
`ab`.`address_book_id` = `c`.`customers_default_address_id`
WHERE
`ab`.`customers_id` = \':customers_id\'';
$t_query = strtr($t_query, array(':customers_id' => (int)$p_customers_id));
$t_result = xtc_db_query($t_query);
$t_country_id = false;
$t_zone_id = false;
while($t_row = xtc_db_fetch_array($t_result))
{
$t_country_id = $t_row['entry_country_id'];
$t_zone_id = $t_row['entry_zone_id'];
}
if($t_country_id === false)
{
$t_result = $this->_get_country_and_zone_id_by_iso2(STORE_COUNTRY);
}
else
{
$t_result = array('country_id' => $t_country_id, 'zone_id' => $t_zone_id);
}
return $t_result;
}
public function get_country_and_zone_id_by_iso2($p_iso2)
{
return $this->_get_country_and_zone_id_by_iso2($p_iso2);
}
protected function _get_country_and_zone_id_by_iso2($p_iso2, $p_zone = '')
{
$this->log("finding country for $p_iso2");
$t_query =
'SELECT
`countries_id`, `zone_id`
FROM
`countries` c
LEFT JOIN `zones` z ON `z`.`zone_country_id` = `c`.`countries_id`
WHERE
`countries_iso_code_2` LIKE \':iso2\'';
if(empty($p_zone) !== true)
{
$t_query .= 'AND (`zone_code` LIKE \':zone\' OR `zone_name` LIKE \':zone\')';
}
$t_query = strtr($t_query, array(':iso2' => xtc_db_input($p_iso2), ':zone' => xtc_db_input($p_zone)));
$t_result = xtc_db_query($t_query);
$t_country_id = false;
$t_zone_id = false;
while($t_row = xtc_db_fetch_array($t_result))
{
$t_country_id = $t_row['countries_id'];
$t_zone_id = $t_row['zone_id'];
}
$t_result = array('country_id' => $t_country_id, 'zone_id' => $t_zone_id);
return $t_result;
}
public function country_is_allowed($p_iso2)
{
$t_query =
'SELECT
`status`
FROM
`countries`
WHERE
`countries_iso_code_2` = \':iso2\'';
$t_query = strtr($t_query, array(':iso2' => xtc_db_input($p_iso2)));
$t_result = xtc_db_query($t_query);
$t_is_allowed = false;
while($t_row = xtc_db_fetch_array($t_result))
{
$t_is_allowed = (int)$t_row['status'] === 1;
}
return $t_is_allowed;
}
public function get_country_name_and_address_format($p_country_iso2)
{
return $this->_get_country_name_and_address_format($p_country_iso2);
}
protected function _get_country_name_and_address_format($p_country_iso2)
{
$t_query =
'SELECT
`countries_name`, `address_format_id`
FROM
`countries`
WHERE
`countries_iso_code_2` LIKE \':iso2\'';
$t_query = strtr($t_query, array(':iso2' => xtc_db_input($p_country_iso2)));
$t_data = array(
'country_name' => '',
'address_format_id' => '0',
);
$t_result = xtc_db_query($t_query);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_data['country_name'] = $t_row['countries_name'];
$t_data['address_format_id'] = $t_row['address_format_id'];
}
return $t_data;
}
/* ---------------------------------------------------------------------------------------------- */
public function get_oap_endpoint()
{
$t_endpoint_identifier = 'self::EP_OAP_'.strtoupper($this->location).'_'.strtoupper($this->mode);
if(defined($t_endpoint_identifier) === false)
{
throw new AmazonAdvancedPaymentException('invalid location or operating mode');
}
$t_endpoint_url = constant($t_endpoint_identifier);
return $t_endpoint_url;
}
public function get_widgets_url()
{
$t_widgets_url_identfier = 'self::URL_WIDGET_'.strtoupper($this->location).'_'.strtoupper($this->mode);
if(defined($t_widgets_url_identfier) === false)
{
throw new AmazonAdvancedPaymentException('invalid location or operating mode');
}
$t_widgets_url = constant($t_widgets_url_identfier);
$t_widgets_url .= '?sellerId='.$this->seller_id;
return $t_widgets_url;
}
public function get_lpa_widgets_url()
{
$t_widgets_url_identfier = 'self::URL_LPA_WIDGET_'.strtoupper($this->location).'_'.strtoupper($this->mode);
if(defined($t_widgets_url_identfier) === false)
{
throw new AmazonAdvancedPaymentException('invalid location or operating mode');
}
$t_widgets_url = constant($t_widgets_url_identfier);
$t_widgets_url .= '?sellerId='.$this->seller_id;
return $t_widgets_url;
}
public function get_button_url()
{
$t_button_url_identfier = 'self::URL_BUTTON_'.strtoupper($this->location).'_'.strtoupper($this->mode);
if(defined($t_button_url_identfier) === false)
{
throw new AmazonAdvancedPaymentException('invalid location or operating mode');
}
$t_button_url = constant($t_button_url_identfier);
$t_button_url .= '?sellerId='.$this->seller_id;
return $t_button_url;
}
public function get_button_element()
{
$t_button_number = uniqid('amzbtn', false);
$t_button_url = $this->get_button_url() .'&size='.$this->button_size.'&color='.$this->button_color;
$t_button_url = str_replace('&', '&', $t_button_url);
$t_style = '';
if((bool)$this->hidden_button === true)
{
$t_style .= 'visibility:hidden;';
}
$useAmazonAddressBook = ($_SESSION['cart']->get_content_type() === 'virtual') ? 'false' : 'true';
$t_element = '<div data-gambio-widget="amazon_payment" data-amazon_payment-seller-id="' . $this->seller_id . '" data-amazon_payment-address-book="' . $useAmazonAddressBook . '" class="paywithamazonbtn" id="paywithamazonbtn_'.$t_button_number.'" style="'.$t_style.'">';
$t_element .= '<img src="'.$t_button_url.'">';
$t_element .= '</div>';
return $t_element;
}
public function get_service_status()
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_service_status_xml = $t_mws_request->proceed('GetServiceStatus');
$t_service_status = simplexml_load_string($t_service_status_xml);
$t_status = (string)$t_service_status->GetServiceStatusResult->Status;
return $t_status;
}
public function check_credentials($seller_id, $aws_access_key, $secret_key)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$aws_access_key,
$secret_key,
$seller_id,
);
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_order_reference_details_xml = $t_mws_request->proceed('GetOrderReferenceDetails', array('AmazonOrderReferenceId' => 'S00-0000000-0000000'));
$t_order_reference_details = simplexml_load_string((string)$t_order_reference_details_xml);
return $t_order_reference_details;
}
public function get_order_reference_details($p_amz_order_reference_id, $p_force_update = false)
{
$t_order_reference_details_xml = false;
$t_from_db = false;
$t_old_state = false;
$t_get_query =
'SELECT
`last_details`, `state`
FROM
`amzadvpay_orders`
WHERE
`order_reference_id` = \':order_reference_id\'';
$t_get_query = strtr($t_get_query, array(':order_reference_id' => $p_amz_order_reference_id));
$t_get_result = xtc_db_query($t_get_query);
while($t_get_row = xtc_db_fetch_array($t_get_result))
{
$t_old_state = $t_get_row['state'];
if($p_force_update === false && !empty($t_get_row['last_details']))
{
$t_order_reference_details_xml = $t_get_row['last_details'];
}
}
if($t_order_reference_details_xml !== false)
{
$t_from_db = true;
$this->log('Retrieved OrderReferenceDetails from database for '.$p_amz_order_reference_id);
}
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
if($p_force_update || $t_order_reference_details_xml === false)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$getOrderReferenceDetailsParameters = [
'AmazonOrderReferenceId' => $p_amz_order_reference_id
];
if(isset($_SESSION['ssoData']['access_token']) && $_SESSION['ssoData']['iss'] === 'amazon.com')
{
$getOrderReferenceDetailsParameters['AddressConsentToken'] = $_SESSION['ssoData']['access_token'];
}
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_order_reference_details_xml = $t_mws_request->proceed(
'GetOrderReferenceDetails',
$getOrderReferenceDetailsParameters
);
$this->log('Received OrderReferenceDetails for '.$p_amz_order_reference_id.":\n".$t_order_reference_details_xml."\n");
}
$t_order_reference_details = simplexml_load_string((string)$t_order_reference_details_xml);
if(isset($t_order_reference_details->Error))
{
$t_error_code = (string)$t_order_reference_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_order_reference_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_order_reference_details->Error->Type.' / '.
(string)$t_order_reference_details->Error->Code.' / '.
(string)$t_order_reference_details->Error->Message;
$this->log('GetOrderReferenceDetails failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
if($t_from_db !== true)
{
// update db with newly acquired data
$t_amzadvpay_orders_id = $this->_find_row_id('amzadvpay_orders', 'order_reference_id', $p_amz_order_reference_id);
$t_order_reference_state = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->OrderReferenceStatus->State;
$t_last_update = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->OrderReferenceStatus->LastUpdateTimestamp;
$t_last_update_datetime = date('Y-m-d H:i:s', strtotime($t_last_update));
$t_query =
'UPDATE
`amzadvpay_orders`
SET
`state` = \':state\',
`last_update` = \':last_update\',
`last_details` = \':last_details\'
WHERE
`amzadvpay_orders_id` = \':amzadvpay_orders_id\'';
$t_query = strtr($t_query, array(
':state' => xtc_db_input($t_order_reference_state),
':last_update' => xtc_db_input($t_last_update_datetime),
':last_details' => xtc_db_input($t_order_reference_details_xml),
':amzadvpay_orders_id' => (int)$t_amzadvpay_orders_id,
));
xtc_db_query($t_query);
// handle state changes
if($t_old_state === 'Suspended' && $t_order_reference_state === 'Open')
{
$this->log('State of order '.$p_amz_order_reference_id.' changed from Suspended to Open');
if($this->authorization_mode !== 'manual')
{
$t_amount = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->OrderTotal->Amount;
$t_currency = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->OrderTotal->CurrencyCode;
$this->log('requesting new authorization of '.$t_amount.' '.$t_currency.' against '.$p_amz_order_reference_id);
$t_capturenow = $this->capture_mode === 'immediate';
$t_authorization_response = $this->authorize_payment($p_amz_order_reference_id, $t_amount, $t_currency, 0, $t_capturenow);
$t_authorization_details = $t_authorization_response->AuthorizeResult->AuthorizationDetails;
$t_state = (string)$t_authorization_details->AuthorizationStatus->State;
$t_orders_id = $this->get_orders_id_for_orders_reference_id($p_amz_order_reference_id);
if($t_state === 'Open')
{
$t_osh_comment = $this->get_text('orderref_state_change_suspended_open_new_auth_open');
$this->_update_orders_status($t_orders_id, $this->orders_status_auth_open, $t_osh_comment);
}
elseif($t_state === 'Closed')
{
// with immediate capture the authorization will be closed immediately with MaxCapturesProcessed
$t_reason_code = (string)$t_authorization_details->AuthorizationStatus->ReasonCode;
$t_osh_comment = $this->get_text('payment_authorized');
$this->_update_orders_status($t_orders_id, $this->orders_status_auth_open, $t_osh_comment);
}
else
{
$t_reason_code = (string)$t_authorization_details->AuthorizationStatus->ReasonCode;
$t_osh_comment = $this->get_text('orderref_state_change_suspended_open_new_auth_fail');
$t_osh_comment .= "\n".$this->get_text('reason').': '.$t_reason_code;
$this->_update_orders_status($t_orders_id, $this->orders_status_auth_declined, $t_osh_comment);
}
}
}
}
return $t_order_reference_details;
}
public function set_order_amount($p_amz_order_reference_id, $p_amount, $p_currency)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_order_reference_details_xml = $t_mws_request->proceed(
'SetOrderReferenceDetails',
array(
'AmazonOrderReferenceId' => $p_amz_order_reference_id,
'OrderReferenceAttributes.OrderTotal.Amount' => sprintf('%.2f', $p_amount),
'OrderReferenceAttributes.OrderTotal.CurrencyCode' => $p_currency,
'OrderReferenceAttributes.SellerOrderAttributes.StoreName' => STORE_NAME,
'OrderReferenceAttributes.PlatformId' => 'AX37G17YUUI1C',
)
);
$this->log('Received OrderReferenceDetails (from SetOrderReferenceDetails) for '.$p_amz_order_reference_id.":\n".$t_order_reference_details_xml."\n");
$t_order_reference_details = simplexml_load_string((string)$t_order_reference_details_xml);
if(isset($t_order_reference_details->Error))
{
$t_error_code = (string)$t_order_reference_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code == 'RequestThrottled')
{
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_order_reference_details->Error->Type.' / '.
(string)$t_order_reference_details->Error->Code.' / '.
(string)$t_order_reference_details->Error->Message;
$this->log('SetOrderReferenceDetails/set_order_amount failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
return $t_order_reference_details;
}
public function set_orders_id($p_amz_order_reference_id, $p_orders_id, $p_amount, $p_currency)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_order_reference_details_xml = $t_mws_request->proceed(
'SetOrderReferenceDetails',
array(
'AmazonOrderReferenceId' => $p_amz_order_reference_id,
'OrderReferenceAttributes.OrderTotal.Amount' => sprintf('%.2f', $p_amount),
'OrderReferenceAttributes.OrderTotal.CurrencyCode' => $p_currency,
'OrderReferenceAttributes.SellerOrderAttributes.SellerOrderId' => $p_orders_id,
)
);
$this->log('set orders_id '.$p_orders_id.' for order with reference id '.$p_amz_order_reference_id);
$t_order_reference_details = simplexml_load_string((string)$t_order_reference_details_xml);
if(isset($t_order_reference_details->Error))
{
$t_error_code = (string)$t_order_reference_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_order_reference_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_order_reference_details->Error->Type.' / '.
(string)$t_order_reference_details->Error->Code.' / '.
(string)$t_order_reference_details->Error->Message;
$this->log('SetOrderReferenceDetails/set_orders_id failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
return $t_order_reference_details;
}
public function cancel_order($p_amz_order_reference_id, $p_reason = '')
{
$this->log(sprintf('cancelling order %s%s', $p_amz_order_reference_id, (!empty($p_reason) ? ' (' . $p_reason . ')' : '')));
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = [
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
];
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
$t_cancel_order_response = null;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_cancel_order_response_xml = $t_mws_request->proceed(
'CancelOrderReference',
array(
'AmazonOrderReferenceId' => $p_amz_order_reference_id,
)
);
$this->log('cancelled order ' . $p_amz_order_reference_id . "\n" . $t_cancel_order_response_xml);
$t_cancel_order_response = simplexml_load_string((string)$t_cancel_order_response_xml);
if(isset($t_confirm_order_response->Error))
{
$t_error_code = (string)$t_cancel_order_response->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_cancel_order_response->Error->Type.' / '.
(string)$t_cancel_order_response->Error->Code.' / '.
(string)$t_cancel_order_response->Error->Message;
$this->log('CancelOrderReference failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
return $t_cancel_order_response;
}
public function confirm_order($p_amz_order_reference_id, $p_orders_id = null, $p_amount = null, $p_currency = null)
{
$t_orders_id = $p_orders_id;
$t_amount = $p_amount;
$t_currency = $p_currency;
$this->log(sprintf("confirming order %d for %s %s", (int)$t_orders_id, (string)$t_amount, (string)$t_currency));
if ($p_orders_id === null) {
throw new Exception('deprecated - orders_id must not be null');
}
$orderReferenceDetails = $this->get_order_reference_details($p_amz_order_reference_id, true);
$oroState = (string)$orderReferenceDetails->GetOrderReferenceDetailsResult->OrderReferenceDetails->OrderReferenceStatus->State;
$this->log("ORO state in confirm_order is {$oroState}");
$db = StaticGXCoreLoader::getDatabaseQueryBuilder();
if ($oroState === 'Draft') {
$this->set_orders_id($p_amz_order_reference_id, $p_orders_id, $p_amount, $p_currency);
$db->insert('amzadvpay_orders',
[
'orders_id' => (int)$t_orders_id,
'state' => 'Draft',
'order_reference_id' => $p_amz_order_reference_id,
]
);
} else {
// re-used ORO (most likely from an InvalidPaymentMethod)
$db->update(
'amzadvpay_orders',
[
'orders_id' => (int)$t_orders_id,
'state' => $oroState,
],
[
'order_reference_id' => $p_amz_order_reference_id,
]
);
}
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = [
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
];
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while ($t_error === true) {
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_confirm_order_response_xml = $t_mws_request->proceed(
'ConfirmOrderReference',
[
'AmazonOrderReferenceId' => $p_amz_order_reference_id,
'SuccessUrl' => xtc_href_link('checkout_process.php', 'amzsca=success', 'SSL', false, false, false, false, true),
'FailureUrl' => xtc_href_link('checkout_process.php', 'amzsca=failure', 'SSL', false, false, false, false, true),
]
);
$this->log('confirmed order ' . $t_orders_id . ' / ' . $p_amz_order_reference_id);
$this->log("ConfirmOrderReference response:\n" . $t_confirm_order_response_xml);
$t_confirm_order_response = simplexml_load_string((string)$t_confirm_order_response_xml);
if (isset($t_confirm_order_response->Error)) {
$t_error_code = (string)$t_confirm_order_response->Error->Code;
if ($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled') {
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying ' . ($t_sleep_time / 1000) . 'ms before retrying');
usleep($t_sleep_time);
} else {
$t_error_message = 'ERROR: ' . (string)$t_confirm_order_response->Error->Type . ' / '
. (string)$t_confirm_order_response->Error->Code . ' / '
. (string)$t_confirm_order_response->Error->Message;
$this->log('ConfirmOrderReference/confirm_order failed, ' . $t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
} else {
$t_error = false;
}
}
if ($p_orders_id !== null) {
/*
$t_orders_query = 'INSERT INTO
`amzadvpay_orders`
SET
`orders_id` = \':orders_id\',
`order_reference_id` = \':order_ref_id\',
`state` = \'Confirmed\'';
$t_orders_query = strtr(
$t_orders_query,
[
':orders_id' => (int)$t_orders_id,
':order_ref_id' => xtc_db_input($p_amz_order_reference_id),
]
);
xtc_db_query($t_orders_query);
*/
$db = StaticGXCoreLoader::getDatabaseQueryBuilder();
$db->update(
'amzadvpay_orders',
['state' => 'Confirmed'],
['orders_id' => (int)$t_orders_id, 'order_reference_id' => $p_amz_order_reference_id]
);
}
return $t_confirm_order_response;
}
public function close_order_reference($p_order_reference_id)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_close_order_details_xml = $t_mws_request->proceed('CloseOrderReference',
array(
'AmazonOrderReferenceId' => $p_order_reference_id,
)
);
$this->log('Closed Order for '.$p_order_reference_id.":\n".$t_close_order_details_xml."\n");
$t_close_order_details = simplexml_load_string((string)$t_close_order_details_xml);
if(isset($t_close_order_details->Error))
{
$t_error_code = (string)$t_close_order_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_close_order_details->Error->Type.' / '.
(string)$t_close_order_details->Error->Code.' / '.
(string)$t_close_order_details->Error->Message;
$this->log('CloseAuthorization failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
return $t_close_order_details;
}
public function update_delivery_address($p_amz_order_reference_id, $p_orders_id, $p_update_customer_data = false)
{
$t_order_reference_details = $this->get_order_reference_details($p_amz_order_reference_id);
if (!isset($t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination)) {
$this->log('not updating delivery address: no delivery address on record, i.e. no physical goods in this order');
return;
}
$t_name = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->Name;
list($t_firstname, $t_lastname) = explode(' ', $t_name, 2);
$t_street1 = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->AddressLine1;
$t_street2 = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->AddressLine2;
$t_street3 = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->AddressLine3;
$t_street = '';
if (!empty($t_street3)) {
$t_street = $t_street3;
$t_company = $t_street2;
} elseif (!empty($t_street2)) {
$t_street = $t_street2;
$t_company = $t_street1;
} else {
$t_street = $t_street1;
$t_company = '';
}
$splitStreet = filter_var(@constant('ACCOUNT_SPLIT_STREET_INFORMATION'), FILTER_VALIDATE_BOOLEAN);
$t_house_number = '';
if (($splitStreet === true) && preg_match('/(.*)\s(\d+.*)/', $t_street, $streetParts) === 1) {
$t_street = $streetParts[1];
$t_house_number = $streetParts[2];
}
$t_postcode = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->PostalCode;
$t_city = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->City;
$t_country_iso2 = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Destination->PhysicalDestination->CountryCode;
$t_country_name_and_address_format = $this->_get_country_name_and_address_format($t_country_iso2);
$t_order_data = [
'delivery_name' => $t_name,
'delivery_firstname' => $t_firstname,
'delivery_lastname' => $t_lastname,
'delivery_company' => $t_company,
'delivery_street_address' => $t_street,
'delivery_house_number' => $t_house_number,
'delivery_city' => $t_city,
'delivery_postcode' => $t_postcode,
'delivery_country' => $t_country_name_and_address_format['country_name'],
'delivery_country_iso_code_2' => $t_country_iso2,
'delivery_address_format_id' => $t_country_name_and_address_format['address_format_id'],
];
if ($p_update_customer_data === true) {
$t_customer_data = [];
if (!empty($t_name)) {
$t_customer_data = [
'customers_name' => $t_name,
'customers_firstname' => $t_firstname,
'customers_lastname' => $t_lastname,
'customers_company' => $t_company,
'customers_street_address' => $t_street,
'customers_house_number' => $t_house_number,
'customers_city' => $t_city,
'customers_postcode' => $t_postcode,
'customers_country' => $t_country_name_and_address_format['country_name'],
'customers_address_format_id' => $t_country_name_and_address_format['address_format_id'],
];
}
$t_email = (string)$t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->Buyer->Email;
if (empty($t_email) !== true) {
$t_customer_data['customers_email_address'] = $t_email;
}
$t_order_data = array_merge($t_order_data, $t_customer_data);
}
xtc_db_perform('orders', $t_order_data, 'update', 'orders_id = \'' . (int)$p_orders_id . '\'');
$this->log(sprintf("updated delivery address for order %d with data:\n%s",
$p_orders_id,
var_export($t_order_data, true)));
}
public function update_billing_address($p_orders_id, $p_billing_address)
{
$this->log('Updating billing address for ' . $p_orders_id);
$this->log("street1: ${p_billing_address['street1']}, street2: ${p_billing_address['street2']}, street3: ${p_billing_address['street3']}");
if (!empty($p_billing_address['street3'])) {
$street = $p_billing_address['street3'];
$company = $p_billing_address['street2'];
} elseif (!empty($p_billing_address['street2'])) {
$street = $p_billing_address['street2'];
$company = $p_billing_address['street1'];
} else {
$street = $p_billing_address['street1'];
$company = '';
}
$house_number = '';
$splitStreet = filter_var(@constant('ACCOUNT_SPLIT_STREET_INFORMATION'), FILTER_VALIDATE_BOOLEAN);
if (($splitStreet === true) && preg_match('/(.*)\s(\d+.*)/', $street, $streetParts) === 1) {
$street = $streetParts[1];
$house_number = $streetParts[2];
}
list($t_firstname, $t_lastname) = explode(' ', $p_billing_address['name'], 2);
$t_country_name_and_address_format = $this->_get_country_name_and_address_format($p_billing_address['country_iso2']);
$t_order_data = [
'billing_name' => $p_billing_address['name'],
'billing_firstname' => $t_firstname,
'billing_lastname' => $t_lastname,
'billing_company' => $company,
'billing_street_address' => $street,
'billing_house_number' => $house_number,
'billing_city' => $p_billing_address['city'],
'billing_postcode' => $p_billing_address['postcode'],
'billing_country' => $t_country_name_and_address_format['country_name'],
'billing_country_iso_code_2' => $p_billing_address['country_iso2'],
'billing_address_format_id' => $t_country_name_and_address_format['address_format_id'],
];
$checkCustomerQuery = 'SELECT customers_name, customers_firstname, customers_lastname, customers_street_address FROM orders WHERE orders_id = "'
. (int)$p_orders_id . '"';
$checkCustomerResult = xtc_db_query($checkCustomerQuery);
while ($checkCustomerRow = xtc_db_fetch_array($checkCustomerResult)) {
if ($checkCustomerRow['customers_name'] === 'Amazon Amazon'
&& $checkCustomerRow['customers_firstname'] === 'Amazon'
&& $checkCustomerRow['customers_lastname'] === 'Amazon'
&& $checkCustomerRow['customers_street_address'] === 'Amazon') {
// replace dummy customer data with billing address; necessary for guest orders of non-physical goods
$t_order_data['customers_name'] = $p_billing_address['name'];
$t_order_data['customers_firstname'] = $t_firstname;
$t_order_data['customers_lastname'] = $t_lastname;
$t_order_data['customers_company'] = $p_billing_address['company'];
$t_order_data['customers_street_address'] = $p_billing_address['street'];
$t_order_data['customers_city'] = $p_billing_address['city'];
$t_order_data['customers_postcode'] = $p_billing_address['postcode'];
$t_order_data['customers_country'] = $t_country_name_and_address_format['country_name'];
$t_order_data['customers_address_format_id'] = $t_country_name_and_address_format['address_format_id'];
}
}
xtc_db_perform('orders', $t_order_data, 'update', 'orders_id = \'' . (int)$p_orders_id . '\'');
}
/** copies the delivery address into the billing address
@param int $orders_id
*/
public function copy_delivery_address_to_billing_address($orders_id)
{
$orders_id = (int)$orders_id;
$copy_query =
'UPDATE
`orders` o
SET
`billing_name` = `delivery_name`,
`billing_firstname` = `delivery_firstname`,
`billing_lastname` = `delivery_lastname`,
`billing_gender` = `delivery_gender`,
`billing_company` = `delivery_company`,
`billing_street_address` = `delivery_street_address`,
`billing_suburb` = `delivery_suburb`,
`billing_city` = `delivery_city`,
`billing_postcode` = `delivery_postcode`,
`billing_state` = `delivery_state`,
`billing_country` = `delivery_country`,
`billing_country_iso_code_2` = `delivery_country_iso_code_2`,
`billing_address_format_id` = `delivery_address_format_id`
WHERE
`orders_id` = \':orders_id\'
';
$copy_query = strtr($copy_query, array(':orders_id' => $orders_id));
xtc_db_query($copy_query);
}
public function authorize_payment($p_amz_order_reference_id, $p_amount, $p_currency, $p_timeout = 1440, $p_capture_now = false, $p_seller_authorization_note = '')
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_auth_ref_id = substr(sha1(uniqid('', true)), 0, 32);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_authorize_params = array(
'AmazonOrderReferenceId' => $p_amz_order_reference_id,
'AuthorizationReferenceId' => $t_auth_ref_id,
'AuthorizationAmount.Amount' => $p_amount,
'AuthorizationAmount.CurrencyCode' => $p_currency,
'TransactionTimeout' => (int)$p_timeout,
'CaptureNow' => $p_capture_now == true ? 'true' : 'false',
);
if(empty($p_seller_authorization_note) !== true)
{
$t_authorize_params['SellerAuthorizationNote'] = $p_seller_authorization_note;
}
$t_authorization_details_xml = $t_mws_request->proceed('Authorize', $t_authorize_params);
$this->log('authorization of '.$p_amount.' '.$p_currency.' against '.$p_amz_order_reference_id.' with AuthRefId '.$t_auth_ref_id);
$this->log("authorization details:\n".$t_authorization_details_xml);
$t_authorization_details = simplexml_load_string((string)$t_authorization_details_xml);
if(isset($t_authorization_details->Error))
{
$t_error_code = (string)$t_authorization_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code == 'RequestThrottled')
{
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_authorization_details->Error->Type.' / '.
(string)$t_authorization_details->Error->Code.' / '.
(string)$t_authorization_details->Error->Message;
$this->log('authorize failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
$t_amazon_authorization_id = (string)$t_authorization_details->AuthorizeResult->AuthorizationDetails->AmazonAuthorizationId;
// keep track of authorizations
$t_orders_id = $this->get_orders_id_for_orders_reference_id($p_amz_order_reference_id);
$this->_insert_authorization($t_orders_id, $p_amz_order_reference_id, $t_amazon_authorization_id);
$t_authorization_state = (string)$t_authorization_details->AuthorizeResult->AuthorizationDetails->AuthorizationStatus->State;
if($p_capture_now === true && $t_authorization_state !== 'Declined')
{
foreach($t_authorization_details->AuthorizeResult->AuthorizationDetails->IdList->member as $t_capture_node)
{
$t_capture_id = (string)$t_capture_node;
$this->_insert_capture($t_orders_id, $p_amz_order_reference_id, $t_amazon_authorization_id, $t_capture_id);
}
}
return $t_authorization_details;
}
protected function _insert_authorization($p_orders_id, $p_order_reference_id, $p_authorization_reference_id)
{
$t_auth_data = array(
'orders_id' => (int)$p_orders_id,
'order_reference_id' => $p_order_reference_id,
'authorization_reference_id' => $p_authorization_reference_id,
);
xtc_db_perform('amzadvpay_authorizations', $t_auth_data, 'insert');
}
public function get_authorization_details($p_authorization_reference_id, $p_order_reference_id, $p_force_update = false)
{
$t_authorization_details_xml = false;
$t_from_db = false;
$t_old_state = false;
$t_get_query =
'SELECT
`last_details`, `state`
FROM
`amzadvpay_authorizations`
WHERE
`authorization_reference_id` = \':authorization_reference_id\'';
$t_get_query = strtr($t_get_query, array(':authorization_reference_id' => $p_authorization_reference_id));
$t_get_result = xtc_db_query($t_get_query);
while($t_get_row = xtc_db_fetch_array($t_get_result))
{
$t_old_state = $t_get_row['state'];
if($p_force_update === false)
{
$t_authorization_details_xml = $t_get_row['last_details'];
}
}
if($t_authorization_details_xml !== false)
{
$t_from_db = true;
$this->log('Retrieved AuthorizationReferenceDetails from database for '.$p_authorization_reference_id);
}
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
if($p_force_update || $t_authorization_details_xml === false)
{
$this->log('Retrieving AuthorizationReferenceDetails from AWS');
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_authorization_details_xml = $t_mws_request->proceed('GetAuthorizationDetails',
array(
'AmazonAuthorizationId' => $p_authorization_reference_id,
)
);
$this->log('Received AuthorizationDetails for '.$p_authorization_reference_id.":\n".$t_authorization_details_xml."\n");
}
$t_authorization_details = simplexml_load_string((string)$t_authorization_details_xml);
if(isset($t_authorization_details->Error))
{
$t_error_code = (string)$t_authorization_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_authorization_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_authorization_details->Error->Type.' / '.
(string)$t_authorization_details->Error->Code.' / '.
(string)$t_authorization_details->Error->Message;
$this->log('GetAuthorizationDetails failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
if($t_from_db !== true)
{
$t_amzadvpay_authorizations_id = $this->_find_row_id('amzadvpay_authorizations', 'authorization_reference_id', $p_authorization_reference_id);
$t_orders_id = $this->get_orders_id_for_orders_reference_id($p_order_reference_id);
if($t_orders_id === false)
{
$this->log("failed to retrieve orders_id for $p_order_reference_id");
}
if($t_amzadvpay_authorizations_id === false)
{
$this->_insert_authorization($t_orders_id, $p_order_reference_id, $p_authorization_reference_id);
$t_old_state = '';
}
$t_authorization_state = (string)$t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->AuthorizationStatus->State;
$t_authorization_last_update = (string)$t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->AuthorizationStatus->LastUpdateTimestamp;
$t_authorization_last_update_datetime = $this->_convert_xml_timestamp_to_datetime($t_authorization_last_update);
$t_query =
'UPDATE
`amzadvpay_authorizations`
SET
`state` = \':state\',
`last_update` = \':last_update\',
`last_details` = \':last_details\'
WHERE
`authorization_reference_id` = \':authorization_reference_id\'';
$t_query = strtr($t_query, array(
':state' => xtc_db_input($t_authorization_state),
':last_update' => xtc_db_input($t_authorization_last_update_datetime),
':last_details' => xtc_db_input($t_authorization_details_xml),
':authorization_reference_id' => xtc_db_input($p_authorization_reference_id),
));
xtc_db_query($t_query);
$this->log("authorization state: $t_old_state => $t_authorization_state");
//if(($t_old_state == 'Pending' || $t_old_state == 'Declined' || $t_old_state == '') && $t_authorization_state == 'Open')
$t_update_billing_address = false;
if($t_old_state !== 'Open' && $t_authorization_state === 'Open')
{
$this->log("transition to Open state detected, updating order's status of $t_orders_id to ".$this->orders_status_auth_open);
$this->_update_orders_status($t_orders_id, $this->orders_status_auth_open);
$t_update_billing_address = true;
}
if($t_old_state !== 'Closed' && $t_authorization_state === 'Closed')
{
$this->log("transition to Closed state detected");
if($this->capture_mode === 'immediate')
{
$t_update_billing_address = true;
}
}
if($t_update_billing_address === true)
{
if(empty($t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->AuthorizationBillingAddress) !== true)
{
$this->log("updating billing address");
$t_billing_address = $t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->AuthorizationBillingAddress;
$t_billing_address_data = array(
'name' => (string)$t_billing_address->Name,
'street1' => (string)$t_billing_address->AddressLine1,
'street2' => (string)$t_billing_address->AddressLine2,
'street3' => (string)$t_billing_address->AddressLine3,
'city' => (string)$t_billing_address->City,
'postcode' => (string)$t_billing_address->PostalCode,
'country_iso2' => (string)$t_billing_address->CountryCode,
);
$this->update_billing_address($t_orders_id, $t_billing_address_data);
}
else
{
// no billing address in authorization details - this happens if Amazon does not have a valid VAT ID on file for the merchant
// As a workaround the delivery address gets copied over.
$this->copy_delivery_address_to_billing_address($t_orders_id);
}
}
if(($t_old_state === 'Pending' || $t_old_state === '') && $t_authorization_state === 'Declined')
{
$t_reason_code = (string)$t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->AuthorizationStatus->ReasonCode;
$t_osh_comment = $this->get_text('reason').': '.$t_reason_code;
if($this->authorization_mode !== 'auto-sync')
{
if($t_reason_code === 'InvalidPaymentMethod')
{
$t_osh_comment .= "\n".$this->get_text('invalid_payment_mail_sent');
$this->log('authorization is reported as Declined/InvalidPaymentMethod, contacting buyer');
$this->_send_invalid_payment_method_notification($t_orders_id);
}
else
{
$t_osh_comment .= "\n".$this->get_text('invalid_payment_mail_sent');
$this->log('authorization is reported as Declined/'.$t_reason_code.', contacting buyer');
$this->_send_invalid_payment_method_notification($t_orders_id, true);
}
}
$this->_update_orders_status($t_orders_id, $this->orders_status_auth_declined, $t_osh_comment);
}
if($t_old_state !== 'Declined' && $t_authorization_state === 'Declined')
{
$t_reason_code = (string)$t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->AuthorizationStatus->ReasonCode;
if($t_reason_code === 'AmazonRejected')
{
$this->log('Authorization declined by Amazon, closing Order Reference');
try
{
$this->close_order_reference($p_order_reference_id);
$t_osh_comment = $this->get_text('order_closed_due_to_rejected_authorization');
$this->_update_orders_status($t_orders_id, $this->orders_status_auth_declined_hard, $t_osh_comment);
}
catch(Exception $e)
{
$this->log('ERROR closing Order Reference: '.$e->getMessage());
}
}
}
}
return $t_authorization_details;
}
protected function _send_invalid_payment_method_notification($p_orders_id, $p_hardfail = false)
{
require_once DIR_FS_CATALOG.'inc/xtc_php_mail.inc.php';
$t_order = new order((int)$p_orders_id);
$t_body_text = $this->get_text('invalid_payment_notification');
$coo_amazonmailcontentview = MainFactory::create_object('AmazonMailContentView');
// ASSIGN VARIABLES
$coo_amazonmailcontentview->set_('language', $_SESSION['language']);
$coo_amazonmailcontentview->set_('language_id', $_SESSION['languages_id']);
$coo_amazonmailcontentview->set_('name', $t_order->customer['name']);
$coo_amazonmailcontentview->set_('orders_id', $p_orders_id);
$coo_amazonmailcontentview->set_('orderdate', $t_order->info['date_purchased']);
// GET E-MAIL LOGO
$t_mail_logo = '';
$t_logo_mail = MainFactory::create_object('GMLogoManager', array("gm_logo_mail"));
if($t_logo_mail->logo_use === '1')
{
$t_mail_logo = $t_logo_mail->get_logo();
}
$coo_amazonmailcontentview->set_('mail_logo', $t_mail_logo);
// GET MAIL CONTENTS ARRAY
$t_mail_content_array = $coo_amazonmailcontentview->get_mail_content_array($p_hardfail);
// GET HTML MAIL CONTENT
$t_html_mail = $t_mail_content_array['html'];
// GET TXT MAIL CONTENT
$t_txt_mail = $t_mail_content_array['txt'];
$t_from_address = EMAIL_BILLING_ADDRESS;
$t_from_name = EMAIL_BILLING_NAME;
$t_to_address = $t_order->customer['email_address'];
$t_to_name = $t_order->customer['name'];
$t_subject = $this->get_text('invalid_payment_notification_subject');
$t_forwarding = '';
$t_reply_address = EMAIL_BILLING_REPLY_ADDRESS;
$t_reply_name = EMAIL_BILLING_REPLY_ADDRESS_NAME;
$t_attachment = '';
$t_attachments = '';
$t_success = xtc_php_mail(
$t_from_address,
$t_from_name,
$t_to_address,
$t_to_name,
$t_forwarding,
$t_reply_address,
$t_reply_name,
$t_attachment,
$t_attachments,
$t_subject,
$t_html_mail,
$t_txt_mail
);
return $t_success;
}
public function close_authorization($p_authorization_reference_id)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_close_authorization_details_xml = $t_mws_request->proceed('CloseAuthorization',
array(
'AmazonAuthorizationId' => $p_authorization_reference_id,
)
);
$this->log('Closed Authorization for '.$p_authorization_reference_id.":\n".$t_close_authorization_details_xml."\n");
$t_close_authorization_details = simplexml_load_string((string)$t_close_authorization_details_xml);
if(isset($t_close_authorization_details->Error))
{
$t_error_code = (string)$t_close_authorization_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_order_reference_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_close_authorization_details->Error->Type.' / '.
(string)$t_close_authorization_details->Error->Code.' / '.
(string)$t_close_authorization_details->Error->Message;
$this->log('CloseAuthorization failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
return $t_close_authorization_details;
}
public function capture_payment($p_auth_ref_id, $p_amount, $p_currency, $p_simulation_string = null)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_capture_ref_id = substr(sha1(uniqid('', true)), 0, 32);
$t_seller_capture_note = '';
if($this->mode === 'sandbox' && $p_simulation_string !== null)
{
$t_seller_capture_note = (string)$p_simulation_string;
}
$t_orders_id = $this->get_orders_id_for_authorization_reference_id($p_auth_ref_id);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_capture_details_xml = $t_mws_request->proceed(
'Capture',
array(
'AmazonAuthorizationId' => $p_auth_ref_id,
'CaptureReferenceId' => $t_capture_ref_id,
'CaptureAmount.Amount' => $p_amount,
'CaptureAmount.CurrencyCode' => $p_currency,
'SellerCaptureNote' => $t_seller_capture_note,
)
);
$this->log('capture of '.$p_amount.' '.$p_currency.' against '.$p_auth_ref_id);
$this->log("capture details:\n".$t_capture_details_xml);
$t_capture_details = simplexml_load_string((string)$t_capture_details_xml);
if(isset($t_capture_details->Error))
{
$t_error_code = (string)$t_capture_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_capture_details->Error->Type.' / '.
(string)$t_capture_details->Error->Code.' / '.
(string)$t_capture_details->Error->Message;
$this->log('capture failed, '.$t_error_message);
$this->_update_orders_status($t_orders_id, $this->orders_status_capture_failed, $this->get_text('capture failed')."\n".$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
$t_order_reference_id = $this->get_order_reference_for_orders_id($t_orders_id);
$t_capture_reference_id = (string)$t_capture_details->CaptureResult->CaptureDetails->AmazonCaptureId;
$t_capture_state = (string)$t_capture_details->CaptureResult->CaptureDetails->CaptureState->State;
$this->_insert_capture($t_orders_id, $t_order_reference_id, $p_auth_ref_id, $t_capture_reference_id, $t_capture_state);
return $t_capture_details;
}
protected function _insert_capture($p_orders_id, $p_order_reference_id, $p_authorization_reference_id, $p_capture_reference_id, $p_capture_state = 'Pending')
{
$t_query =
'INSERT INTO
`amzadvpay_captures`
SET
`state` = \':state\',
`orders_id` = \':orders_id\',
`order_reference_id` = \':order_reference_id\',
`authorization_reference_id` = \':authorization_reference_id\',
`capture_reference_id` = \':capture_reference_id\'';
$t_query = strtr($t_query, array(
':state' => xtc_db_input($p_capture_state),
':orders_id' => (int)$p_orders_id,
':order_reference_id' => xtc_db_input($p_order_reference_id),
':authorization_reference_id' => xtc_db_input($p_authorization_reference_id),
':capture_reference_id' => xtc_db_input($p_capture_reference_id),
));
xtc_db_query($t_query);
}
public function get_capture_details($p_capture_id, $p_authorization_reference_id = '', $p_order_reference_id = '', $p_force_update = false)
{
$t_capture_details_xml = false;
$t_from_db = false;
$t_old_state = false;
$t_get_query =
'SELECT
`last_details`, `state`
FROM
`amzadvpay_captures`
WHERE
`capture_reference_id` = \':capture_reference_id\'';
$t_get_query = strtr($t_get_query, array(':capture_reference_id' => $p_capture_id));
$t_get_result = xtc_db_query($t_get_query);
while($t_get_row = xtc_db_fetch_array($t_get_result))
{
$t_old_state = $t_get_row['state'];
if($p_force_update === false)
{
$t_capture_details_xml = $t_get_row['last_details'];
}
}
if($t_capture_details_xml !== false)
{
$t_from_db = true;
$this->log('Retrieved CaptureDetails from database');
}
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
if($p_force_update || $t_capture_details_xml === false)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_capture_details_xml = $t_mws_request->proceed('GetCaptureDetails',
array(
'AmazonCaptureId' => $p_capture_id,
)
);
$this->log('Received CaptureDetails for '.$p_capture_id.":\n".$t_capture_details_xml."\n");
}
$t_capture_details = simplexml_load_string((string)$t_capture_details_xml);
if(isset($t_capture_details->Error))
{
$t_error_code = (string)$t_capture_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_capture_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_capture_details->Error->Type.' / '.
(string)$t_capture_details->Error->Code.' / '.
(string)$t_capture_details->Error->Message;
$this->log('GetcaptureDetails failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
if($t_from_db === false)
{
$t_orders_id = $this->get_orders_id_for_authorization_reference_id($p_authorization_reference_id);
$t_row_id = $this->_find_row_id('amzadvpay_captures', 'capture_reference_id', $p_capture_id);
if($t_row_id === false)
{
// capture has not been recorded yet
$t_order_reference_id = $p_order_reference_id;
if(empty($t_order_reference_id) === true)
{
$t_order_reference_id = $this->get_order_reference_for_orders_id($t_orders_id);
}
$this->_insert_capture($t_orders_id, $t_order_reference_id, $p_authorization_reference_id, $p_capture_id);
}
$t_state = (string)$t_capture_details->GetCaptureDetailsResult->CaptureDetails->CaptureStatus->State;
$t_last_update = (string)$t_capture_details->GetCaptureDetailsResult->CaptureDetails->CaptureStatus->LastUpdateTimestamp;
$t_last_update_datetime = $this->_convert_xml_timestamp_to_datetime($t_last_update);
$t_query =
'UPDATE
`amzadvpay_captures`
SET
`state` = \':state\',
`last_update` = \':last_update\',
`last_details` = \':last_details\'
WHERE
`capture_reference_id` = \':capture_reference_id\'';
$t_query = strtr($t_query, array(
':state' => xtc_db_input($t_state),
':last_update' => $t_last_update_datetime,
':last_details' => $t_capture_details_xml,
':capture_reference_id' => xtc_db_input($p_capture_id),
));
xtc_db_query($t_query);
if($t_old_state !== $t_state)
{
$this->log('state change for capture '.$p_capture_id.' '.$t_old_state.' -> '.$t_state);
}
if($t_old_state !== 'Completed' && $t_state === 'Completed')
{
$this->log('capture '.$p_capture_id.' completed');
$this->_update_orders_status($t_orders_id, $this->orders_status_captured, $this->get_text('capture_completed'));
}
if($t_old_state !== 'Closed' && $t_state === 'Closed')
{
$this->log('capture '.$p_capture_id.' closed');
}
if($t_old_state !== 'Declined' && $t_state === 'Declined')
{
$this->log('capture '.$p_capture_id.' declined');
$this->_update_orders_status($t_orders_id, $this->orders_status_capture_failed, $this->get_text('capture_failed'));
}
}
return $t_capture_details;
}
public function refund_payment($p_capture_id, $p_amount, $p_currency)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_refund_ref_id = substr(sha1(uniqid('', true)), 0, 32);
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_refund_details_xml = $t_mws_request->proceed(
'Refund',
array(
'AmazonCaptureId' => $p_capture_id,
'RefundReferenceId' => $t_refund_ref_id,
'RefundAmount.Amount' => $p_amount,
'RefundAmount.CurrencyCode' => $p_currency,
)
);
$this->log('refund of '.$p_amount.' '.$p_currency.' against '.$p_capture_id);
$this->log("refund details:\n".$t_refund_details_xml);
$t_refund_details = simplexml_load_string((string)$t_refund_details_xml);
if(isset($t_refund_details->Error))
{
$t_error_code = (string)$t_refund_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code == 'RequestThrottled')
{
$t_refund_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_refund_details->Error->Type.' / '.
(string)$t_refund_details->Error->Code.' / '.
(string)$t_refund_details->Error->Message;
$this->log('refund failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
$t_authorization_reference_id = $this->get_authorization_reference_id_for_capture_reference_id($p_capture_id);
$t_orders_id = $this->get_orders_id_for_authorization_reference_id($t_authorization_reference_id);
$t_order_reference_id = $this->get_order_reference_for_orders_id($t_orders_id);
$t_refund_reference_id = (string)$t_refund_details->RefundResult->RefundDetails->AmazonRefundId;
$this->_insert_refund($t_orders_id, $t_order_reference_id, $t_authorization_reference_id, $p_capture_id, $t_refund_reference_id);
return $t_refund_details;
}
protected function _insert_refund($p_orders_id, $p_order_reference_id, $p_authorization_reference_id, $p_capture_reference_id, $p_refund_reference_id)
{
$t_query =
'INSERT INTO
`amzadvpay_refunds`
SET
`orders_id` = \':orders_id\',
`order_reference_id` = \':order_reference_id\',
`authorization_reference_id` = \':authorization_reference_id\',
`capture_reference_id` = \':capture_reference_id\',
`refund_reference_id` = \':refund_reference_id\'';
$t_query = strtr($t_query, array(
':orders_id' => (int)$p_orders_id,
':order_reference_id' => xtc_db_input($p_order_reference_id),
':authorization_reference_id' => xtc_db_input($p_authorization_reference_id),
':capture_reference_id' => xtc_db_input($p_capture_reference_id),
':refund_reference_id' => xtc_db_input($p_refund_reference_id),
));
xtc_db_query($t_query);
}
public function get_refund_details($p_refund_id, $p_capture_reference_id = '', $p_authorization_reference_id = '', $p_order_reference_id = '', $p_force_update = false)
{
$t_refund_details_xml = false;
$t_from_db = false;
if($p_force_update === false)
{
$t_get_query =
'SELECT
`last_details`
FROM
`amzadvpay_refunds`
WHERE
`refund_reference_id` = \':refund_id\'';
$t_get_query = strtr($t_get_query, array(':refund_id' => $p_refund_id));
$t_get_result = xtc_db_query($t_get_query);
while($t_get_row = xtc_db_fetch_array($t_get_result))
{
$t_refund_details_xml = $t_get_row['last_details'];
}
if($t_refund_details_xml !== false)
{
$t_from_db = true;
$this->log('Retrieved RefundDetails from database');
}
}
$t_throttle_retries = $this->_throttle_max_retries;
$t_error = true;
while($t_error === true)
{
if($p_force_update || $t_refund_details_xml === false)
{
$t_endpoint_url = $this->get_oap_endpoint();
$t_request_params = array(
$t_endpoint_url,
$this->_configuration['aws_access_key'],
$this->_configuration['secret_key'],
$this->_configuration['seller_id'],
);
$t_mws_request = MainFactory::create_object('AmazonMWSRequest', $t_request_params);
$t_refund_details_xml = $t_mws_request->proceed('GetRefundDetails',
array(
'AmazonRefundId' => $p_refund_id,
)
);
$this->log('Received RefundDetails for '.$p_refund_id.":\n".$t_refund_details_xml."\n");
}
$t_refund_details = simplexml_load_string((string)$t_refund_details_xml);
if(isset($t_refund_details->Error))
{
$t_error_code = (string)$t_refund_details->Error->Code;
if($t_throttle_retries > 0 && $t_error_code === 'RequestThrottled')
{
$t_refund_details_xml = false;
$t_throttle_retries--;
$t_sleep_time = ($this->_throttle_max_retries - $t_throttle_retries) * $this->_retry_delay * 1000;
$this->log('Request throttled, delaying '.($t_sleep_time/1000).'ms before retrying');
usleep($t_sleep_time);
}
else
{
$t_error_message =
'ERROR: '.
(string)$t_refund_details->Error->Type.' / '.
(string)$t_refund_details->Error->Code.' / '.
(string)$t_refund_details->Error->Message;
$this->log('GetRefundDetails failed, '.$t_error_message);
throw new AmazonAdvancedPaymentException($t_error_message);
}
}
else
{
$t_error = false;
}
}
if($t_from_db !== true)
{
$t_row_id = $this->_find_row_id('amzadvpay_refunds', 'refund_reference_id', $p_refund_id);
if($t_row_id === false)
{
$t_capture_reference_id = $p_capture_reference_id;
if(empty($t_capture_reference_id) === true)
{
$t_capture_reference_id = $this->get_capture_reference_id_for_refund_reference_id($p_refund_id);
}
$t_authorization_reference_id = $p_authorization_reference_id;
if(empty($t_authorization_reference_id) === true)
{
$t_authorization_reference_id = $this->get_authorization_reference_id_for_capture_reference_id($t_capture_reference_id);
}
$t_orders_id = $this->get_orders_id_for_authorization_reference_id($t_authorization_reference_id);
$t_order_reference_id = $p_order_reference_id;
if(empty($t_order_reference_id))
{
$t_order_reference_id = $this->get_order_reference_for_orders_id($t_orders_id);
}
$this->_insert_refund($t_orders_id, $t_order_reference_id, $t_authorization_reference_id, $t_capture_reference_id, $p_refund_id);
}
$t_state = (string)$t_refund_details->GetRefundDetailsResult->RefundDetails->RefundStatus->State;
$t_last_update = (string)$t_refund_details->GetRefundDetailsResult->RefundDetails->RefundStatus->LastUpdateTimestamp;
$t_last_update_datetime = $this->_convert_xml_timestamp_to_datetime($t_last_update);
$t_query =
'UPDATE
`amzadvpay_refunds`
SET
`state` = \':state\',
`last_update` = \':last_update\',
`last_details` = \':last_details\'
WHERE
`refund_reference_id` = \':refund_reference_id\'';
$t_query = strtr($t_query, array(
':state' => xtc_db_input($t_state),
':last_update' => xtc_db_input($t_last_update_datetime),
':last_details' => xtc_db_input($t_refund_details_xml),
':refund_reference_id' => xtc_db_input($p_refund_id),
));
xtc_db_query($t_query);
}
return $t_refund_details;
}
/**
polls all OrderReference data and referenced data
*/
public function poll_data($p_order_reference_id)
{
$t_force_update = true;
$t_order_reference_details = $this->get_order_reference_details($p_order_reference_id, $t_force_update);
if(isset($t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->IdList))
{
foreach($t_order_reference_details->GetOrderReferenceDetailsResult->OrderReferenceDetails->IdList->member as $auth_member)
{
$t_amz_auth_id = (string)$auth_member;
$t_authorization_details = $this->get_authorization_details($t_amz_auth_id, $p_order_reference_id, $t_force_update);
if(isset($t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->IdList))
{
foreach($t_authorization_details->GetAuthorizationDetailsResult->AuthorizationDetails->IdList->member as $capture_member)
{
$t_capture_ref_id = (string)$capture_member;
$t_capture_details = $this->get_capture_details($t_capture_ref_id, $t_amz_auth_id, $p_order_reference_id, $t_force_update);
if(isset($t_capture_details->GetCaptureDetailsResult->CaptureDetails->IdList))
{
foreach($t_capture_details->GetCaptureDetailsResult->CaptureDetails->IdList->member as $refund_member)
{
$t_refund_id = (string)$refund_member;
$t_refund_details = $this->get_refund_details($t_refund_id, $t_capture_ref_id, $t_amz_auth_id, $p_order_reference_id, $t_force_update);
}
}
}
}
}
}
}
/* ---------------------------------------------------------------------------------------------- */
public function is_known_entity($p_type, $p_reference_id)
{
$t_is_known = false;
switch(strtolower($p_type))
{
case 'order':
$t_is_known = $this->_find_row_id('amzadvpay_orders', 'order_reference_id', $p_reference_id) !== false;
break;
case 'authorization':
$t_is_known = $this->_find_row_id('amzadvpay_authorizations', 'authorization_reference_id', $p_reference_id) !== false;
break;
case 'capture':
$t_is_known = $this->_find_row_id('amzadvpay_captures', 'capture_reference_id', $p_reference_id) !== false;
break;
case 'refund':
$t_is_known = $this->_find_row_id('amzadvpay_refunds', 'refund_reference_id', $p_reference_id) !== false;
break;
default:
throw new AmazonAdvancedPaymentException('unknown entity type '.$p_type);
}
return $t_is_known;
}
protected function _find_row_id($p_table, $p_column, $p_value)
{
$t_id = false;
$t_valid_tables = ['amzadvpay_orders', 'amzadvpay_authorizations', 'amzadvpay_captures', 'amzadvpay_refunds'];
if(in_array($p_table, $t_valid_tables, true) !== true)
{
throw new AmazonAdvancedPaymentException('invalid table name');
}
$t_query =
'SELECT
:tablename_id
FROM
:tablename
WHERE
`:column` = \':value\'';
$t_query = strtr($t_query, array(
':tablename' => xtc_db_input($p_table),
':column' => xtc_db_input($p_column),
':value' => xtc_db_input($p_value),
));
$t_ids = array();
$t_result = xtc_db_query($t_query, 'db_link', false);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_ids[] = $t_row[$p_table.'_id'];
$t_id = $t_row[$p_table.'_id'];
}
return $t_id;
}
public function get_orders_id_for_orders_reference_id($p_amz_order_reference_id)
{
$t_query =
'SELECT
`orders_id`
FROM
`amzadvpay_orders`
WHERE
`order_reference_id` = \':order_ref_id\'';
$t_query = strtr($t_query, array(':order_ref_id' => xtc_db_input($p_amz_order_reference_id)));
$t_orders_id = false;
$t_result = xtc_db_query($t_query);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_orders_id = $t_row['orders_id'];
}
return $t_orders_id;
}
public function get_order_reference_for_orders_id($p_orders_id)
{
$t_query =
'SELECT
`order_reference_id`
FROM
`amzadvpay_orders`
WHERE
`orders_id` = \':orders_id\'';
$t_query = strtr($t_query, array(':orders_id' => (int)$p_orders_id));
$t_order_reference_id = false;
$t_result = xtc_db_query($t_query);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_order_reference_id = $t_row['order_reference_id'];
}
return $t_order_reference_id;
}
public function get_orders_id_for_authorization_reference_id($p_amz_authorization_id)
{
$t_query =
'SELECT
`orders_id`
FROM
`amzadvpay_authorizations`
WHERE
`authorization_reference_id` = \':auth_id\'';
$t_query = strtr($t_query, array(':auth_id' => xtc_db_input($p_amz_authorization_id)));
$t_orders_id = false;
$t_result = xtc_db_query($t_query);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_orders_id = $t_row['orders_id'];
}
return $t_orders_id;
}
public function get_authorization_reference_id_for_capture_reference_id($p_capture_id)
{
$t_query =
'SELECT
`authorization_reference_id`
FROM
`amzadvpay_captures`
WHERE
`capture_reference_id` = \':capture_id\'';
$t_query = strtr($t_query, array(':capture_id' => xtc_db_input($p_capture_id)));
$t_authorization_id = false;
$t_result = xtc_db_query($t_query);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_authorization_id = $t_row['authorization_reference_id'];
}
return $t_authorization_id;
}
public function get_capture_reference_id_for_refund_reference_id($p_refund_reference_id)
{
$t_query =
'SELECT
`capture_reference_id`
FROM
`amzadvpay_refunds`
WHERE
`refund_reference_id` = \':refund_reference_id\'';
$t_query = strtr($t_query, array(
':refund_reference_id' => xtc_db_input($p_refund_reference_id),
));
$t_capture_reference_id = false;
$t_result = xtc_db_query($t_query);
while($t_row = xtc_db_fetch_array($t_result))
{
$t_capture_reference_id = $t_row['capture_reference_id'];
}
return $t_capture_reference_id;
}
protected function _convert_xml_timestamp_to_datetime($p_timestamp)
{
$t_real_timestamp = strtotime($p_timestamp);
$t_datetime = date('Y-m-d H:i:s', $t_real_timestamp);
return $t_datetime;
}
protected function _update_orders_status($p_orders_id, $p_orders_status_id, $p_comments = '')
{
xtc_db_perform(
'orders',
array(
'orders_status' => (int)$p_orders_status_id,
'last_modified' => 'now()'
),
'update',
'orders_id = '.(int)$p_orders_id);
xtc_db_perform(
'orders_status_history',
array(
'orders_id' => (int)$p_orders_id,
'orders_status_id' => (int)$p_orders_status_id,
'date_added' => 'now()',
'customer_notified' => '0',
'comments' => $p_comments,
),
'insert');
}
}
class AmazonAdvancedPaymentException extends Exception {}