File: /var/www/vhost/disk-apps/magento.bikenow.co/vendor/amzn/amazon-pay-sdk-php/AmazonPay/Client.php
<?php
namespace AmazonPay;
/* Class Client
* Takes configuration information
* Makes API calls to MWS for Amazon Pay
* returns Response Object
*/
require_once 'ResponseParser.php';
require_once 'HttpCurl.php';
require_once 'ClientInterface.php';
require_once 'Regions.php';
if (!interface_exists('\Psr\Log\LoggerAwareInterface')) {
require_once(__DIR__.'/../Psr/Log/LoggerAwareInterface.php');
}
if (!interface_exists('\Psr\Log\LoggerInterface')) {
require_once(__DIR__.'/../Psr/Log/LoggerInterface.php');
}
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
class Client implements ClientInterface, LoggerAwareInterface
{
const SDK_VERSION = '3.7.1';
const MWS_VERSION = '2013-01-01';
const MAX_ERROR_RETRY = 3;
// Construct User agent string based off of the application_name, application_version, PHP platform
private $userAgent = null;
private $parameters = null;
private $mwsEndpointPath = null;
private $mwsEndpointUrl = null;
private $profileEndpoint = null;
private $config = array(
'merchant_id' => null,
'secret_key' => null,
'access_key' => null,
'region' => null,
'currency_code' => null,
'sandbox' => false,
'platform_id' => null,
'cabundle_file' => null,
'application_name' => null,
'application_version' => null,
'proxy_host' => null,
'proxy_port' => -1,
'proxy_username' => null,
'proxy_password' => null,
'client_id' => null,
'app_id' => null,
'handle_throttle' => true,
'override_service_url' => null
);
private $modePath = null;
// Final URL to where the API parameters POST done, based off the config['region'] and respective $mwsServiceUrls
private $mwsServiceUrl = null;
private $mwsServiceUrls;
private $profileEndpointUrls;
private $regionMappings;
// Implement a logging library that utilizes the PSR 3 logger interface
private $logger = null;
// Boolean variable to check if the API call was a success
public $success = false;
/* Takes user configuration array from the user as input
* Takes JSON file path with configuration information as input
* Validates the user configuration array against existing config array
*/
public function __construct($config = null)
{
$this->getRegionUrls();
if (!is_null($config)) {
if (is_array($config)) {
$configArray = $config;
} elseif (!is_array($config)) {
$configArray = $this->checkIfFileExists($config);
}
// Invoke sandbox setter to throw exception if not Boolean datatype
if (!empty($configArray['sandbox'])) {
$this->setSandbox($configArray['sandbox']);
}
if (is_array($configArray)) {
$this->checkConfigKeys($configArray);
} else {
throw new \Exception('$config is of the incorrect type ' . gettype($configArray) . ' and should be of the type array');
}
} else {
throw new \Exception('$config cannot be null.');
}
}
public function setLogger(LoggerInterface $logger = null) {
$this->logger = $logger;
}
/* Helper function to log data within the Client */
private function logMessage($message) {
if ($this->logger) {
$this->logger->debug($message);
}
}
/* Get the Region specific properties from the Regions class.*/
private function getRegionUrls()
{
$regionObject = new Regions();
$this->mwsServiceUrls = $regionObject->mwsServiceUrls;
$this->regionMappings = $regionObject->regionMappings;
$this->profileEndpointUrls = $regionObject->profileEndpointUrls;
}
/* checkIfFileExists - check if the JSON file exists in the path provided */
private function checkIfFileExists($config)
{
if (file_exists($config)) {
$jsonString = file_get_contents($config);
$configArray = json_decode($jsonString, true);
$jsonError = json_last_error();
if ($jsonError != 0) {
$errorMsg = "Error with message - content is not in json format" . $this->getErrorMessageForJsonError($jsonError) . " " . $configArray;
throw new \Exception($errorMsg);
}
} else {
$errorMsg ='$config is not a Json File path or the Json File was not found in the path provided';
throw new \Exception($errorMsg);
}
return $configArray;
}
/* Checks if the keys of the input configuration matches the keys in the config array
* if they match the values are taken else throws exception
* strict case match is not performed
*/
private function checkConfigKeys($config)
{
$config = array_change_key_case($config, CASE_LOWER);
$config = $this->trimArray($config);
foreach ($config as $key => $value) {
if (array_key_exists($key, $this->config)) {
$this->config[$key] = $value;
} else {
throw new \Exception('Key ' . $key . ' is either not part of the configuration or has incorrect Key name.
check the config array key names to match your key names of your config array', 1);
}
}
}
/* Convert a json error code to a descriptive error message
*
* @param int $jsonError message code
*
* @return string error message
*/
private function getErrorMessageForJsonError($jsonError)
{
switch ($jsonError) {
case JSON_ERROR_DEPTH:
return " - maximum stack depth exceeded.";
break;
case JSON_ERROR_STATE_MISMATCH:
return " - invalid or malformed JSON.";
break;
case JSON_ERROR_CTRL_CHAR:
return " - control character error.";
break;
case JSON_ERROR_SYNTAX:
return " - syntax error.";
break;
default:
return ".";
break;
}
}
/* Setter for sandbox
* Sets the Boolean value for config['sandbox'] variable
*/
public function setSandbox($value)
{
if (is_bool($value)) {
$this->config['sandbox'] = $value;
} else {
throw new \Exception('sandbox value ' . $value . ' is of type ' . gettype($value) . ' and should be a boolean value');
}
}
/* Setter for config['client_id']
* Sets the value for config['client_id'] variable
*/
public function setClientId($value)
{
if (!empty($value)) {
$this->config['client_id'] = $value;
} else {
throw new \Exception('setter value for client ID provided is empty');
}
}
/* Setter for config['app_id']
* Sets the value for config['app_id'] variable
*/
public function setAppId($value)
{
if (!empty($value)) {
$this->config['app_id'] = $value;
} else {
throw new \Exception('setter value for app ID provided is empty');
}
}
/* Setter for Proxy
* input $proxy [array]
* @param $proxy['proxy_user_host'] - hostname for the proxy
* @param $proxy['proxy_user_port'] - hostname for the proxy
* @param $proxy['proxy_user_name'] - if your proxy required a username
* @param $proxy['proxy_user_password'] - if your proxy required a password
*/
public function setProxy($proxy)
{
if (!empty($proxy['proxy_user_host']))
$this->config['proxy_host'] = $proxy['proxy_user_host'];
if (!empty($proxy['proxy_user_port']))
$this->config['proxy_port'] = $proxy['proxy_user_port'];
if (!empty($proxy['proxy_user_name']))
$this->config['proxy_username'] = $proxy['proxy_user_name'];
if (!empty($proxy['proxy_user_password']))
$this->config['proxy_password'] = $proxy['proxy_user_password'];
}
/* Setter for $mwsServiceUrl
* Set the URL to which the post request has to be made for unit testing
*/
public function setMwsServiceUrl($url)
{
$this->mwsServiceUrl = $url;
}
/* Getter
* Gets the value for the key if the key exists in config
*/
public function __get($name)
{
if (array_key_exists(strtolower($name), $this->config)) {
return $this->config[strtolower($name)];
} else {
throw new \Exception('Key ' . $name . ' is either not a part of the configuration array config or the ' . $name . ' does not match the key name in the config array', 1);
}
}
/* Getter for parameters string
* Gets the value for the parameters string for unit testing
*/
public function getParameters()
{
return trim($this->parameters);
}
/* Trim the input Array key values */
private function trimArray($array)
{
foreach ($array as $key => $value) {
// Do not attemp to trim array variables, boolean variables, or the proxy password
// Trimming a boolean value (as a string) may not produce the expected output, so pass it through as-is
if (!is_array($value) && !is_bool($value) && $key !== 'proxy_password') {
$array[$key] = trim($value);
}
}
return $array;
}
/* GetUserInfo convenience function - Returns user's profile information from Amazon using the access token returned by the Button widget.
*
* @see http://login.amazon.com/website Step 4
* @param $accessToken [String]
*/
public function getUserInfo($accessToken)
{
// Get the correct Profile Endpoint URL based off the country/region provided in the config['region']
$this->profileEndpointUrl();
if (empty($accessToken)) {
throw new \InvalidArgumentException('Access Token is a required parameter and is not set');
}
// To make sure double encoding doesn't occur decode first and encode again.
$accessToken = urldecode($accessToken);
$url = $this->profileEndpoint . '/auth/o2/tokeninfo';
$httpCurlRequest = new HttpCurl($this->config);
$httpCurlRequest->setAccessToken($accessToken);
$httpCurlRequest->setHttpHeader();
$response = $httpCurlRequest->httpGet($url);
$data = json_decode($response);
// Ensure that the Access Token matches either the supplied Client ID *or* the supplied App ID
// Web apps and Mobile apps will have different Client ID's but App ID should be the same
// As long as one of these matches, from a security perspective, we have done our due diligence
if (!isset($data->aud)) {
throw new \Exception('The tokeninfo API call did not succeed');
}
if (($data->aud != $this->config['client_id']) && ($data->app_id != $this->config['app_id'])) {
// The access token does not belong to us
throw new \Exception('The Access Token belongs to neither your Client ID nor App ID');
}
// Exchange the access token for user profile
$url = $this->profileEndpoint . '/user/profile';
$httpCurlRequest = new HttpCurl($this->config);
$httpCurlRequest->setAccessToken($accessToken);
$httpCurlRequest->setHttpHeader();
$response = $httpCurlRequest->httpGet($url);
$userInfo = json_decode($response, true);
return $userInfo;
}
/* setParametersAndPost - sets the parameters array with non empty values from the requestParameters array sent to API calls.
* If Provider Credit Details is present, values are set by setProviderCreditDetails
* If Provider Credit Reversal Details is present, values are set by setProviderCreditDetails
*/
private function setParametersAndPost($parameters, $fieldMappings, $requestParameters)
{
/* For loop to take all the non empty parameters in the $requestParameters and add it into the $parameters array,
* if the keys are matched from $requestParameters array with the $fieldMappings array
*/
foreach ($requestParameters as $param => $value) {
// Do not use trim on boolean values, or it will convert them to '0' or '1'
if (!is_array($value) && !is_bool($value)) {
$value = trim($value);
}
// Ensure that no unexpected type coercions have happened
if ($param === 'capture_now' || $param === 'confirm_now' || $param === 'inherit_shipping_address' || $param === 'request_payment_authorization' || $param === 'expect_immediate_authorization') {
if (!is_bool($value)) {
throw new \Exception($param . ' value ' . $value . ' is of type ' . gettype($value) . ' and should be a boolean value');
}
} elseif ($param === 'provider_credit_details' || $param === 'provider_credit_reversal_details' || $param === 'order_item_categories' || $param === 'notification_configuration_list') {
if (!is_array($value)) {
throw new \Exception($param . ' value ' . $value . ' is of type ' . gettype($value) . ' and should be an array value');
}
}
// When checking for non-empty values, consider any boolean as non-empty
if (array_key_exists($param, $fieldMappings) && (is_bool($value) || $value!='')) {
if (is_array($value)) {
// If the parameter is a provider_credit_details or provider_credit_reversal_details, call the respective functions to set the values
if ($param === 'provider_credit_details') {
$parameters = $this->setProviderCreditDetails($parameters, $value);
} elseif ($param === 'provider_credit_reversal_details') {
$parameters = $this->setProviderCreditReversalDetails($parameters, $value);
} elseif ($param === 'order_item_categories') {
$parameters = $this->setOrderItemCategories($parameters, $value);
} elseif ($param == 'notification_configuration_list') {
$parameters = $this->setNotificationConfigurationList($parameters, $value);
}
} else {
$parameters[$fieldMappings[$param]] = $value;
}
}
}
$parameters = $this->setDefaultValues($parameters, $fieldMappings, $requestParameters);
$responseObject = $this->calculateSignatureAndPost($parameters);
return $responseObject;
}
/* calculateSignatureAndPost - convert the Parameters array to string and curl POST the parameters to MWS */
private function calculateSignatureAndPost($parameters)
{
// Call the signature and Post function to perform the actions. Returns XML in array format
$parametersString = $this->calculateSignatureAndParametersToString($parameters);
// POST using curl the String converted Parameters
$response = $this->invokePost($parametersString);
// Send this response as args to ResponseParser class which will return the object of the class.
$responseObject = new ResponseParser($response);
return $responseObject;
}
/* If merchant_id is not set via the requestParameters array then it's taken from the config array
*
* Set the platform_id if set in the config['platform_id'] array
*
* If currency_code is set in the $requestParameters and it exists in the $fieldMappings array, strtoupper it
* else take the value from config array if set
*/
private function setDefaultValues($parameters, $fieldMappings, $requestParameters)
{
if (empty($requestParameters['merchant_id']))
$parameters['SellerId'] = $this->config['merchant_id'];
if (array_key_exists('platform_id', $fieldMappings)) {
if (empty($requestParameters['platform_id']) && !empty($this->config['platform_id']))
$parameters[$fieldMappings['platform_id']] = $this->config['platform_id'];
}
if (array_key_exists('currency_code', $fieldMappings)) {
if (!empty($requestParameters['currency_code'])) {
$parameters[$fieldMappings['currency_code']] = strtoupper($requestParameters['currency_code']);
} else if (!(array_key_exists('Action', $parameters) &&
($parameters['Action'] === 'SetOrderAttributes' || $parameters['Action'] === 'ConfirmOrderReference' || $parameters['Action'] === 'SetBillingAgreementDetails'))) {
// Only supply a default CurrencyCode parameter if not using SetOrderAttributes, ConfirmOrderReference, or SetBillingAgreementDetails
$parameters[$fieldMappings['currency_code']] = strtoupper($this->config['currency_code']);
}
}
return $parameters;
}
/* setOrderItemCategories - helper function used by SetOrderAttributes API to set
* one or more Order Item Categories
*/
private function setOrderItemCategories($parameters, $categories)
{
$categoryIndex = 0;
$categoryString = 'OrderAttributes.SellerOrderAttributes.OrderItemCategories.OrderItemCategory.';
foreach ($categories as $value) {
$categoryIndex = $categoryIndex + 1;
$parameters[$categoryString . $categoryIndex] = $value;
}
return $parameters;
}
/* setMerchantNotificationUrls - helper function used by SetMerchantNotificationConfiguration API to set
* one or more Notification Configurations
*/
private function setNotificationConfigurationList($parameters, $configuration)
{
$configurationIndex = 0;
if (!is_array($configuration)) {
throw new \Exception('Notification Configuration List value ' . $configuration . ' is of type ' . gettype($configuration) . ' and should be an array value');
}
foreach ($configuration as $url => $events) {
$configurationIndex = $configurationIndex + 1;
$parameters['NotificationConfigurationList.NotificationConfiguration.' . $configurationIndex . '.NotificationUrl'] = $url;
$eventIndex = 0;
if (!is_array($events)) {
throw new \Exception('Notification Configuration Events value ' . $events . ' is of type ' . gettype($events) . ' and should be an array value');
}
foreach ($events as $event) {
$eventIndex = $eventIndex + 1;
$parameters['NotificationConfigurationList.NotificationConfiguration.' . $configurationIndex . '.EventTypes.EventTypeList.' . $eventIndex] = $event;
}
}
return $parameters;
}
/* setProviderCreditDetails - sets the provider credit details sent via the Capture or Authorize API calls
* @param provider_id - [String]
* @param credit_amount - [String]
* @optional currency_code - [String]
*/
private function setProviderCreditDetails($parameters, $providerCreditInfo)
{
$providerIndex = 0;
$providerString = 'ProviderCreditList.member.';
$fieldMappings = array(
'provider_id' => 'ProviderId',
'credit_amount' => 'CreditAmount.Amount',
'currency_code' => 'CreditAmount.CurrencyCode'
);
foreach ($providerCreditInfo as $key => $value) {
$value = array_change_key_case($value, CASE_LOWER);
$providerIndex = $providerIndex + 1;
foreach ($value as $param => $val) {
if (array_key_exists($param, $fieldMappings) && trim($val)!='') {
$parameters[$providerString.$providerIndex. '.' .$fieldMappings[$param]] = $val;
}
}
// If currency code is not entered take it from the config array
if (empty($parameters[$providerString.$providerIndex. '.' .$fieldMappings['currency_code']])) {
$parameters[$providerString.$providerIndex. '.' .$fieldMappings['currency_code']] = strtoupper($this->config['currency_code']);
}
}
return $parameters;
}
/* setProviderCreditReversalDetails - sets the reverse provider credit details sent via the Refund API call.
* @param provider_id - [String]
* @param credit_amount - [String]
* @optional currency_code - [String]
*/
private function setProviderCreditReversalDetails($parameters, $providerCreditInfo)
{
$providerIndex = 0;
$providerString = 'ProviderCreditReversalList.member.';
$fieldMappings = array(
'provider_id' => 'ProviderId',
'credit_reversal_amount' => 'CreditReversalAmount.Amount',
'currency_code' => 'CreditReversalAmount.CurrencyCode'
);
foreach ($providerCreditInfo as $key => $value) {
$value = array_change_key_case($value, CASE_LOWER);
$providerIndex = $providerIndex + 1;
foreach ($value as $param => $val) {
if (array_key_exists($param, $fieldMappings) && trim($val)!='') {
$parameters[$providerString.$providerIndex. '.' .$fieldMappings[$param]] = $val;
}
}
// If currency code is not entered take it from the config array
if (empty($parameters[$providerString.$providerIndex. '.' .$fieldMappings['currency_code']])) {
$parameters[$providerString.$providerIndex. '.' .$fieldMappings['currency_code']] = strtoupper($this->config['currency_code']);
}
}
return $parameters;
}
/* GetMerchantAccountStatus API call - Returns the status of the Merchant Account.
* @see TODO
* @param requestParameters['merchant_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getMerchantAccountStatus($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetMerchantAccountStatus';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetOrderReferenceDetails API call - Returns details about the Order Reference object and its current state.
* @see https://pay.amazon.com/developer/documentation/apireference/201751970
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @optional requestParameters['address_consent_token'] - [String]
* @optional requestParameters['access_token'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*
* You cannot pass both address_consent_token and access_token in
* the same call or you will encounter a 400/"AmbiguousToken" error
*/
public function getOrderReferenceDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetOrderReferenceDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'address_consent_token' => 'AddressConsentToken',
'access_token' => 'AccessToken',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* ListOrderReference API call - Returns details about the Order Reference object and its current state from the sellers.
* @see https://pay.amazon.com/developer/documentation/apireference/201751970
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['query_id'] - [String]
* @param requestParameters['query_id_type'] - [String] (SellerOrderId)
* @optional requestParameters['page_size'] - [Int]
* @optional requestParameters['created_start_time'] - [String] (Date/Time ISO8601)
* @optional requestParameters['created_end_time'] - [String] (Date/Time ISO8601) Limited to 31 days
* @optional requestParameters['sort_order'] - [String] (Ascending/Descending)
* @optional requestParameters['mws_auth_token'] - [String]
* @optional requestParameters['order_status_list'] - [Array]
*/
public function listOrderReference($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'ListOrderReference';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$payment_domains = array(
"us" => "NA_USD",
"jp" => "FE_JPY",
"de" => "EU_EUR",
"uk" => "EU_GBP"
);
$requestParameters['payment_domain'] = $payment_domains[strtolower($this->config['region'])];
$fieldMappings = array(
'merchant_id' => 'SellerId',
'mws_auth_token' => 'MWSAuthToken',
'query_id' => 'QueryId',
'query_id_type' => 'QueryIdType',
'page_size' => 'PageSize',
'created_start_time' => 'CreatedTimeRange.StartTime',
'created_end_time' => 'CreatedTimeRange.EndTime',
'sort_order' => 'SortOrder',
'payment_domain' => 'PaymentDomain'
);
if( $requestParameters['order_status_list'] ){
$status_index = 0;
foreach ($requestParameters['order_status_list'] as $status) {
$status_index++;
$requestParameters['order_status_list_'.$status_index] = $status;
$fieldMappings['order_status_list_'.$status_index] = 'OrderReferenceStatusListFilter.OrderReferenceStatus.'.$status_index;
}
}
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* ListOrderReferenceByNextToken API call - Returns details about the Order Reference object and its current
* state from the sellers.
* @see https://pay.amazon.com/developer/documentation/apireference/201751970
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['next_token'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function listOrderReferenceByNextToken($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'ListOrderReferenceByNextToken';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'mws_auth_token' => 'MWSAuthToken',
'next_page_token' => 'NextPageToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* SetOrderReferenceDetails API call - Sets order reference details such as the order total and a description for the order.
* @see https://pay.amazon.com/developer/documentation/apireference/201751960
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @param requestParameters['amount'] - [String]
* @param requestParameters['currency_code'] - [String]
* @optional requestParameters['platform_id'] - [String]
* @optional requestParameters['seller_note'] - [String]
* @optional requestParameters['seller_order_id'] - [String]
* @optional requestParameters['store_name'] - [String]
* @optional requestParameters['custom_information'] - [String]
* @optional requestParameters['supplementary_data'] - [String]
* @optional requestParameters['request_payment_authorization'] - [Boolean]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function setOrderReferenceDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'SetOrderReferenceDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'amount' => 'OrderReferenceAttributes.OrderTotal.Amount',
'currency_code' => 'OrderReferenceAttributes.OrderTotal.CurrencyCode',
'platform_id' => 'OrderReferenceAttributes.PlatformId',
'seller_note' => 'OrderReferenceAttributes.SellerNote',
'seller_order_id' => 'OrderReferenceAttributes.SellerOrderAttributes.SellerOrderId',
'store_name' => 'OrderReferenceAttributes.SellerOrderAttributes.StoreName',
'custom_information' => 'OrderReferenceAttributes.SellerOrderAttributes.CustomInformation',
'supplementary_data' => 'OrderReferenceAttributes.SellerOrderAttributes.SupplementaryData',
'request_payment_authorization' => 'OrderReferenceAttributes.RequestPaymentAuthorization',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* SetOrderAttributes API call - Sets order reference details such as the order total and a description for the order.
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @optional requestParameters['amount'] - [String]
* @optional requestParameters['currency_code'] - [String]
* @optional requestParameters['platform_id'] - [String]
* @optional requestParameters['seller_note'] - [String]
* @optional requestParameters['seller_order_id'] - [String]
* @optional requestParameters['store_name'] - [String]
* @optional requestParameters['custom_information'] - [String]
* @optional requestParameters['supplementary_data'] - [String]
* @optional requestParameters['request_payment_authorization'] - [Boolean]
* @optional requestParameters['payment_service_provider_id'] - [String]
* @optional requestParameters['payment_service_provider_order_id'] - [String]
* @optional requestParameters['order_item_categories'] - [array()]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function setOrderAttributes($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'SetOrderAttributes';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'amount' => 'OrderAttributes.OrderTotal.Amount',
'currency_code' => 'OrderAttributes.OrderTotal.CurrencyCode',
'platform_id' => 'OrderAttributes.PlatformId',
'seller_note' => 'OrderAttributes.SellerNote',
'seller_order_id' => 'OrderAttributes.SellerOrderAttributes.SellerOrderId',
'store_name' => 'OrderAttributes.SellerOrderAttributes.StoreName',
'custom_information' => 'OrderAttributes.SellerOrderAttributes.CustomInformation',
'supplementary_data' => 'OrderAttributes.SellerOrderAttributes.SupplementaryData',
'request_payment_authorization' => 'OrderAttributes.RequestPaymentAuthorization',
'payment_service_provider_id' => 'OrderAttributes.PaymentServiceProviderAttributes.PaymentServiceProviderId',
'payment_service_provider_order_id' => 'OrderAttributes.PaymentServiceProviderAttributes.PaymentServiceProviderOrderId',
'order_item_categories' => array(),
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* ConfirmOrderReference API call - Confirms that the order reference is free of constraints and all required information has been set on the order reference.
* @see https://pay.amazon.com/developer/documentation/apireference/201751980
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @optional requestParameters['success_url'] - [String]
* @optional requestParameters['failure_url'] - [String]
* @optional requestParameters['authorization_amount'] - [String]
* @optional requestParameters['currency_code'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
* @optional requestParameters['expect_immediate_authorization'] - [Boolean] Default value is false
*/
public function confirmOrderReference($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'ConfirmOrderReference';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'success_url' => 'SuccessUrl',
'failure_url' => 'FailureUrl',
'authorization_amount' => 'AuthorizationAmount.Amount',
'currency_code' => 'AuthorizationAmount.CurrencyCode',
'mws_auth_token' => 'MWSAuthToken',
'expect_immediate_authorization' => 'ExpectImmediateAuthorization'
);
if (isset($requestParameters['authorization_amount']) && !isset($requestParameters['currency_code'])) {
$requestParameters['currency_code'] = strtoupper($this->config['currency_code']);
}
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* CancelOrderReference API call - Cancels a previously confirmed order reference.
* @see https://pay.amazon.com/developer/documentation/apireference/201751990
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @optional requestParameters['cancelation_reason'] [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function cancelOrderReference($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'CancelOrderReference';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'cancelation_reason' => 'CancelationReason',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* CloseOrderReference API call - Confirms that an order reference has been fulfilled (fully or partially)
* and that you do not expect to create any new authorizations on this order reference.
* @see https://pay.amazon.com/developer/documentation/apireference/201752000
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @optional requestParameters['closure_reason'] [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function closeOrderReference($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'CloseOrderReference';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'closure_reason' => 'ClosureReason',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* CloseAuthorization API call - Closes an authorization.
* @see https://pay.amazon.com/developer/documentation/apireference/201752070
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_authorization_id'] - [String]
* @optional requestParameters['closure_reason'] [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function closeAuthorization($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'CloseAuthorization';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_authorization_id' => 'AmazonAuthorizationId',
'closure_reason' => 'ClosureReason',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* Authorize API call - Reserves a specified amount against the payment method(s) stored in the order reference.
* @see https://pay.amazon.com/developer/documentation/apireference/201752010
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_order_reference_id'] - [String]
* @param requestParameters['authorization_amount'] [String]
* @param requestParameters['currency_code'] - [String]
* @param requestParameters['authorization_reference_id'] [String]
* @optional requestParameters['capture_now'] [Boolean]
* @optional requestParameters['provider_credit_details'] - [array (array())]
* @optional requestParameters['seller_authorization_note'] [String]
* @optional requestParameters['transaction_timeout'] [String] - Defaults to 1440 minutes
* @optional requestParameters['soft_descriptor'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function authorize($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'Authorize';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_order_reference_id' => 'AmazonOrderReferenceId',
'authorization_amount' => 'AuthorizationAmount.Amount',
'currency_code' => 'AuthorizationAmount.CurrencyCode',
'authorization_reference_id' => 'AuthorizationReferenceId',
'capture_now' => 'CaptureNow',
'provider_credit_details' => array(),
'seller_authorization_note' => 'SellerAuthorizationNote',
'transaction_timeout' => 'TransactionTimeout',
'soft_descriptor' => 'SoftDescriptor',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetAuthorizationDetails API call - Returns the status of a particular authorization and the total amount captured on the authorization.
* @see https://pay.amazon.com/developer/documentation/apireference/201752030
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_authorization_id'] [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getAuthorizationDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetAuthorizationDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_authorization_id' => 'AmazonAuthorizationId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* Capture API call - Captures funds from an authorized payment instrument.
* @see https://pay.amazon.com/developer/documentation/apireference/201752040
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_authorization_id'] - [String]
* @param requestParameters['capture_amount'] - [String]
* @param requestParameters['currency_code'] - [String]
* @param requestParameters['capture_reference_id'] - [String]
* @optional requestParameters['provider_credit_details'] - [array (array())]
* @optional requestParameters['seller_capture_note'] - [String]
* @optional requestParameters['soft_descriptor'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function capture($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'Capture';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_authorization_id' => 'AmazonAuthorizationId',
'capture_amount' => 'CaptureAmount.Amount',
'currency_code' => 'CaptureAmount.CurrencyCode',
'capture_reference_id' => 'CaptureReferenceId',
'provider_credit_details' => array(),
'seller_capture_note' => 'SellerCaptureNote',
'soft_descriptor' => 'SoftDescriptor',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetCaptureDetails API call - Returns the status of a particular capture and the total amount refunded on the capture.
* @see https://pay.amazon.com/developer/documentation/apireference/201752060
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_capture_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getCaptureDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetCaptureDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_capture_id' => 'AmazonCaptureId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* Refund API call - Refunds a previously captured amount.
* @see https://pay.amazon.com/developer/documentation/apireference/201752080
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_capture_id'] - [String]
* @param requestParameters['refund_reference_id'] - [String]
* @param requestParameters['refund_amount'] - [String]
* @param requestParameters['currency_code'] - [String]
* @optional requestParameters['provider_credit_reversal_details'] - [array(array())]
* @optional requestParameters['seller_refund_note'] [String]
* @optional requestParameters['soft_descriptor'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function refund($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'Refund';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_capture_id' => 'AmazonCaptureId',
'refund_reference_id' => 'RefundReferenceId',
'refund_amount' => 'RefundAmount.Amount',
'currency_code' => 'RefundAmount.CurrencyCode',
'provider_credit_reversal_details' => array(),
'seller_refund_note' => 'SellerRefundNote',
'soft_descriptor' => 'SoftDescriptor',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetRefundDetails API call - Returns the status of a particular refund.
* @see https://pay.amazon.com/developer/documentation/apireference/201752100
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_refund_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getRefundDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetRefundDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_refund_id' => 'AmazonRefundId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetServiceStatus API Call - Returns the operational status of the OffAmazonPayments API section
* @see https://pay.amazon.com/developer/documentation/apireference/201752110
*
* The GetServiceStatus operation returns the operational status of the OffAmazonPayments API
* section of Amazon Marketplace Web Service (Amazon MWS).
* Status values are GREEN, GREEN_I, YELLOW, and RED.
*
* @param requestParameters['merchant_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getServiceStatus($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetServiceStatus';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* CreateOrderReferenceForId API Call - Creates an order reference for the given object
* @see https://pay.amazon.com/developer/documentation/apireference/201751670
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['id'] - [String]
* @optional requestParameters['inherit_shipping_address'] [Boolean]
* @optional requestParameters['confirm_now'] - [Boolean]
* @optional Amount (required when confirm_now is set to true) [String]
* @optional requestParameters['currency_code'] - [String]
* @optional requestParameters['seller_note'] - [String]
* @optional requestParameters['seller_order_id'] - [String]
* @optional requestParameters['store_name'] - [String]
* @optional requestParameters['supplementary_data'] - [String]
* @optional requestParameters['custom_information'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function createOrderReferenceForId($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'CreateOrderReferenceForId';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'id' => 'Id',
'id_type' => 'IdType',
'inherit_shipping_address' => 'InheritShippingAddress',
'confirm_now' => 'ConfirmNow',
'amount' => 'OrderReferenceAttributes.OrderTotal.Amount',
'currency_code' => 'OrderReferenceAttributes.OrderTotal.CurrencyCode',
'platform_id' => 'OrderReferenceAttributes.PlatformId',
'seller_note' => 'OrderReferenceAttributes.SellerNote',
'seller_order_id' => 'OrderReferenceAttributes.SellerOrderAttributes.SellerOrderId',
'store_name' => 'OrderReferenceAttributes.SellerOrderAttributes.StoreName',
'supplementary_data' => 'OrderReferenceAttributes.SupplementaryData',
'custom_information' => 'OrderReferenceAttributes.SellerOrderAttributes.CustomInformation',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetBillingAgreementDetails API Call - Returns details about the Billing Agreement object and its current state.
* @see https://pay.amazon.com/developer/documentation/apireference/201751690
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_billing_agreement_id'] - [String]
* @optional requestParameters['address_consent_token'] - [String]
* @optional requestParameters['access_token'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*
* You cannot pass both address_consent_token and access_token in
* the same call or you will encounter a 400/"AmbiguousToken" error
*/
public function getBillingAgreementDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetBillingAgreementDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_billing_agreement_id' => 'AmazonBillingAgreementId',
'address_consent_token' => 'AddressConsentToken',
'access_token' => 'AccessToken',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* SetBillingAgreementDetails API call - Sets Billing Agreement details such as a description of the agreement and other information about the seller.
* @see https://pay.amazon.com/developer/documentation/apireference/201751700
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_billing_agreement_id'] - [String]
* @param requestParameters['amount'] - [String]
* @param requestParameters['currency_code'] - [String]
* @optional requestParameters['platform_id'] - [String]
* @optional requestParameters['seller_note'] - [String]
* @optional requestParameters['seller_billing_agreement_id'] - [String]
* @optional requestParameters['store_name'] - [String]
* @optional requestParameters['custom_information'] - [String]
* @optional requestParameters['billing_agreement_type'] - [String] either 'CustomerInitiatedTransaction' or 'MerchantInitiatedTransaction'
* @optional requestParameters['subscription_amount'] - [String]
* @optional requestParameters['currency_code'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function setBillingAgreementDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'SetBillingAgreementDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_billing_agreement_id' => 'AmazonBillingAgreementId',
'platform_id' => 'BillingAgreementAttributes.PlatformId',
'seller_note' => 'BillingAgreementAttributes.SellerNote',
'seller_billing_agreement_id' => 'BillingAgreementAttributes.SellerBillingAgreementAttributes.SellerBillingAgreementId',
'custom_information' => 'BillingAgreementAttributes.SellerBillingAgreementAttributes.CustomInformation',
'store_name' => 'BillingAgreementAttributes.SellerBillingAgreementAttributes.StoreName',
'billing_agreement_type' => 'BillingAgreementAttributes.BillingAgreementType',
'subscription_amount' => 'BillingAgreementAttributes.SubscriptionAmount.Amount',
'currency_code' => 'BillingAgreementAttributes.SubscriptionAmount.CurrencyCode',
'mws_auth_token' => 'MWSAuthToken'
);
if (isset($requestParameters['subscription_amount']) && !isset($requestParameters['currency_code'])) {
$requestParameters['currency_code'] = strtoupper($this->config['currency_code']);
}
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* ConfirmBillingAgreement API Call - Confirms that the Billing Agreement is free of constraints and all required information has been set on the Billing Agreement.
* @see https://pay.amazon.com/developer/documentation/apireference/201751710
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_billing_agreement_id'] - [String]
* @optional requestParameters['success_url'] - [String]
* @optional requestParameters['failure_url'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function confirmBillingAgreement($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'ConfirmBillingAgreement';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_billing_agreement_id' => 'AmazonBillingAgreementId',
'success_url' => 'SuccessUrl',
'failure_url' => 'FailureUrl',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* ValidateBillignAgreement API Call - Validates the status of the Billing Agreement object and the payment method associated with it.
* @see https://pay.amazon.com/developer/documentation/apireference/201751720
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_billing_agreement_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function validateBillingAgreement($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'ValidateBillingAgreement';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_billing_agreement_id' => 'AmazonBillingAgreementId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* AuthorizeOnBillingAgreement API call - Reserves a specified amount against the payment method(s) stored in the Billing Agreement.
* @see https://pay.amazon.com/developer/documentation/apireference/201751940
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_billing_agreement_id'] - [String]
* @param requestParameters['authorization_reference_id'] - [String]
* @param requestParameters['authorization_amount'] - [String]
* @param requestParameters['currency_code'] - [String]
* @optional requestParameters['seller_authorization_note'] [String]
* @optional requestParameters['transaction_timeout'] - Defaults to 1440 minutes
* @optional requestParameters['capture_now'] [Boolean]
* @optional requestParameters['soft_descriptor'] - - [String]
* @optional requestParameters['seller_note'] - [String]
* @optional requestParameters['platform_id'] - [String]
* @optional requestParameters['custom_information'] - [String]
* @optional requestParameters['seller_order_id'] - [String]
* @optional requestParameters['store_name'] - [String]
* @optional requestParameters['supplementary_data'] - [String]
* @optional requestParameters['inherit_shipping_address'] [Boolean] - Defaults to true
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function authorizeOnBillingAgreement($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'AuthorizeOnBillingAgreement';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_billing_agreement_id' => 'AmazonBillingAgreementId',
'authorization_reference_id' => 'AuthorizationReferenceId',
'authorization_amount' => 'AuthorizationAmount.Amount',
'currency_code' => 'AuthorizationAmount.CurrencyCode',
'seller_authorization_note' => 'SellerAuthorizationNote',
'transaction_timeout' => 'TransactionTimeout',
'capture_now' => 'CaptureNow',
'soft_descriptor' => 'SoftDescriptor',
'seller_note' => 'SellerNote',
'platform_id' => 'PlatformId',
'custom_information' => 'SellerOrderAttributes.CustomInformation',
'seller_order_id' => 'SellerOrderAttributes.SellerOrderId',
'store_name' => 'SellerOrderAttributes.StoreName',
'supplementary_data' => 'SellerOrderAttributes.SupplementaryData',
'inherit_shipping_address' => 'InheritShippingAddress',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* CloseBillingAgreement API Call - Returns details about the Billing Agreement object and its current state.
* @see https://pay.amazon.com/developer/documentation/apireference/201751950
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_billing_agreement_id'] - [String]
* @optional requestParameters['closure_reason'] [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function closeBillingAgreement($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'CloseBillingAgreement';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_billing_agreement_id' => 'AmazonBillingAgreementId',
'closure_reason' => 'ClosureReason',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetMerchantNotificationConfiguration API Call - Returns details about the defined IPN endpoints
*
* @param requestParameters['merchant_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getMerchantNotificationConfiguration($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetMerchantNotificationConfiguration';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* SetMerchantNotificationConfiguration API Call - Set IPN endpoints
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['notification_configuration_list'] - [Array]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function setMerchantNotificationConfiguration($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'SetMerchantNotificationConfiguration';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'notification_configuration_list' => array(),
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* charge convenience method
* Performs the API calls
* 1. SetOrderReferenceDetails / SetBillingAgreementDetails
* 2. ConfirmOrderReference / ConfirmBillingAgreement
* 3. Authorize (with Capture) / AuthorizeOnBillingAgreeemnt (with Capture)
*
* @param requestParameters['merchant_id'] - [String]
*
* @param requestParameters['amazon_reference_id'] - [String] : Order Reference ID /Billing Agreement ID
* If requestParameters['amazon_reference_id'] is empty then the following is required,
* @param requestParameters['amazon_order_reference_id'] - [String] : Order Reference ID
* or,
* @param requestParameters['amazon_billing_agreement_id'] - [String] : Billing Agreement ID
*
* @param $requestParameters['charge_amount'] - [String] : Amount value to be captured
* @param requestParameters['currency_code'] - [String] : Currency Code for the Amount
* @param requestParameters['authorization_reference_id'] - [String]- Any unique string that needs to be passed
* @optional requestParameters['charge_note'] - [String] : Seller Note sent to the buyer
* @optional requestParameters['transaction_timeout'] - [String] : Defaults to 1440 minutes
* @optional requestParameters['charge_order_id'] - [String] : Custom Order ID provided
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function charge($requestParameters = array()) {
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$requestParameters = $this->trimArray($requestParameters);
$setParameters = $authorizeParameters = $confirmParameters = $requestParameters;
$chargeType = '';
if (!empty($requestParameters['amazon_order_reference_id'])) {
$chargeType = 'OrderReference';
} elseif (!empty($requestParameters['amazon_billing_agreement_id'])) {
$chargeType = 'BillingAgreement';
} elseif (!empty($requestParameters['amazon_reference_id'])) {
switch (substr(strtoupper($requestParameters['amazon_reference_id']), 0, 1)) {
case 'P':
case 'S':
$chargeType = 'OrderReference';
$setParameters['amazon_order_reference_id'] = $requestParameters['amazon_reference_id'];
$authorizeParameters['amazon_order_reference_id'] = $requestParameters['amazon_reference_id'];
$confirmParameters['amazon_order_reference_id'] = $requestParameters['amazon_reference_id'];
break;
case 'B':
case 'C':
$chargeType = 'BillingAgreement';
$setParameters['amazon_billing_agreement_id'] = $requestParameters['amazon_reference_id'];
$authorizeParameters['amazon_billing_agreement_id'] = $requestParameters['amazon_reference_id'];
$confirmParameters['amazon_billing_agreement_id'] = $requestParameters['amazon_reference_id'];
break;
default:
throw new \Exception('Invalid Amazon Reference ID');
}
} else {
throw new \Exception('key amazon_order_reference_id or amazon_billing_agreement_id is null and is a required parameter');
}
// Set the other parameters if the values are present
$setParameters['amount'] = !empty($requestParameters['charge_amount']) ? $requestParameters['charge_amount'] : '';
$authorizeParameters['authorization_amount'] = !empty($requestParameters['charge_amount']) ? $requestParameters['charge_amount'] : '';
$setParameters['seller_note'] = !empty($requestParameters['charge_note']) ? $requestParameters['charge_note'] : '';
$authorizeParameters['seller_authorization_note'] = !empty($requestParameters['charge_note']) ? $requestParameters['charge_note'] : '';
$authorizeParameters['seller_note'] = !empty($requestParameters['charge_note']) ? $requestParameters['charge_note'] : '';
$setParameters['seller_order_id'] = !empty($requestParameters['charge_order_id']) ? $requestParameters['charge_order_id'] : '';
$setParameters['seller_billing_agreement_id'] = !empty($requestParameters['charge_order_id']) ? $requestParameters['charge_order_id'] : '';
$authorizeParameters['seller_order_id'] = !empty($requestParameters['charge_order_id']) ? $requestParameters['charge_order_id'] : '';
$authorizeParameters['capture_now'] = !empty($requestParameters['capture_now']) ? $requestParameters['capture_now'] : false;
$response = $this->makeChargeCalls($chargeType, $setParameters, $confirmParameters, $authorizeParameters);
return $response;
}
/* makeChargeCalls - makes API calls based off the charge type (OrderReference or BillingAgreement) */
private function makeChargeCalls($chargeType, $setParameters, $confirmParameters, $authorizeParameters)
{
switch ($chargeType) {
case 'OrderReference':
// Get the Order Reference details and feed the response object to the ResponseParser
$responseObj = $this->getOrderReferenceDetails($setParameters);
// Call the function getOrderReferenceDetailsStatus in ResponseParser.php providing it the XML response
// $oroStatus is an array containing the State of the Order Reference ID
$oroStatus = $responseObj->getOrderReferenceDetailsStatus($responseObj->toXml());
if ($oroStatus['State'] === 'Draft') {
$response = $this->setOrderReferenceDetails($setParameters);
if ($this->success) {
$this->confirmOrderReference($confirmParameters);
}
}
$responseObj = $this->getOrderReferenceDetails($setParameters);
// Check the Order Reference Status again before making the Authorization.
$oroStatus = $responseObj->getOrderReferenceDetailsStatus($responseObj->toXml());
if ($oroStatus['State'] === 'Open') {
if ($this->success) {
$response = $this->authorize($authorizeParameters);
}
}
if ($oroStatus['State'] != 'Open' && $oroStatus['State'] != 'Draft') {
throw new \Exception('The Order Reference is in the ' . $oroStatus['State'] . " State. It should be in the Draft or Open State");
}
return $response;
case 'BillingAgreement':
// Get the Billing Agreement details and feed the response object to the ResponseParser
$responseObj = $this->getBillingAgreementDetails($setParameters);
// Call the function getBillingAgreementDetailsStatus in ResponseParser.php providing it the XML response
// $baStatus is an array containing the State of the Billing Agreement
$baStatus = $responseObj->getBillingAgreementDetailsStatus($responseObj->toXml());
if ($baStatus['State'] === 'Draft') {
$response = $this->setBillingAgreementDetails($setParameters);
if ($this->success) {
$response = $this->confirmBillingAgreement($confirmParameters);
}
}
// Check the Billing Agreement status again before making the Authorization.
$responseObj = $this->getBillingAgreementDetails($setParameters);
$baStatus = $responseObj->getBillingAgreementDetailsStatus($responseObj->toXml());
if ($this->success && $baStatus['State'] === 'Open') {
$response = $this->authorizeOnBillingAgreement($authorizeParameters);
}
if ($baStatus['State'] != 'Open' && $baStatus['State'] != 'Draft') {
throw new \Exception('The Billing Agreement is in the ' . $baStatus['State'] . " State. It should be in the Draft or Open State");
}
return $response;
default:
throw new \Exception('Invalid Charge Type');
}
}
/* GetProviderCreditDetails API Call - Get the details of the Provider Credit.
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_provider_credit_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getProviderCreditDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetProviderCreditDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_provider_credit_id' => 'AmazonProviderCreditId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* GetProviderCreditReversalDetails API Call - Get details of the Provider Credit Reversal.
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_provider_credit_reversal_id'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function getProviderCreditReversalDetails($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'GetProviderCreditReversalDetails';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_provider_credit_reversal_id' => 'AmazonProviderCreditReversalId',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* ReverseProviderCredit API Call - Reverse the Provider Credit.
*
* @param requestParameters['merchant_id'] - [String]
* @param requestParameters['amazon_provider_credit_id'] - [String]
* @optional requestParameters['credit_reversal_reference_id'] - [String]
* @param requestParameters['credit_reversal_amount'] - [String]
* @optional requestParameters['currency_code'] - [String]
* @optional requestParameters['credit_reversal_note'] - [String]
* @optional requestParameters['mws_auth_token'] - [String]
*/
public function reverseProviderCredit($requestParameters = array())
{
$parameters = array();
$parameters['Action'] = 'ReverseProviderCredit';
$requestParameters = array_change_key_case($requestParameters, CASE_LOWER);
$fieldMappings = array(
'merchant_id' => 'SellerId',
'amazon_provider_credit_id' => 'AmazonProviderCreditId',
'credit_reversal_reference_id' => 'CreditReversalReferenceId',
'credit_reversal_amount' => 'CreditReversalAmount.Amount',
'currency_code' => 'CreditReversalAmount.CurrencyCode',
'credit_reversal_note' => 'CreditReversalNote',
'mws_auth_token' => 'MWSAuthToken'
);
$responseObject = $this->setParametersAndPost($parameters, $fieldMappings, $requestParameters);
return ($responseObject);
}
/* Create an Array of required parameters, sort them
* Calculate signature and invoke the POST to the MWS Service URL
*
* @param AWSAccessKeyId [String]
* @param Version [String]
* @param SignatureMethod [String]
* @param Timestamp [String]
* @param Signature [String]
*/
private function calculateSignatureAndParametersToString($parameters = array())
{
foreach ($parameters as $key => $value) {
// Ensure that no unexpected type coercions have happened
if ($key === 'CaptureNow' || $key === 'ConfirmNow' || $key === 'InheritShippingAddress' || $key === 'RequestPaymentAuthorization') {
if (!is_bool($value)) {
throw new \Exception($key . ' value ' . $value . ' is of type ' . gettype($value) . ' and should be a boolean value');
}
}
// Ensure boolean values are outputed as 'true' or 'false'
if (is_bool($value)) {
$parameters[$key] = json_encode($value);
}
}
$parameters['AWSAccessKeyId'] = $this->config['access_key'];
$parameters['Version'] = self::MWS_VERSION;
$parameters['SignatureMethod'] = 'HmacSHA256';
$parameters['SignatureVersion'] = 2;
$parameters['Timestamp'] = $this->getFormattedTimestamp();
uksort($parameters, 'strcmp');
$this->createServiceUrl();
$parameters['Signature'] = $this->signParameters($parameters);
$parameters = $this->getParametersAsString($parameters);
// Save these parameters in the parameters variable so that it can be returned for unit testing.
$this->parameters = $parameters;
return $parameters;
}
/* Computes RFC 2104-compliant HMAC signature for request parameters
* Implements AWS Signature, as per following spec:
*
* If Signature Version is 0, it signs concatenated Action and Timestamp
*
* If Signature Version is 1, it performs the following:
*
* Sorts all parameters (including SignatureVersion and excluding Signature,
* the value of which is being created), ignoring case.
*
* Iterate over the sorted list and append the parameter name (in original case)
* and then its value. It will not URL-encode the parameter values before
* constructing this string. There are no separators.
*
* If Signature Version is 2, string to sign is based on following:
*
* 1. The HTTP Request Method followed by an ASCII newline (%0A)
* 2. The HTTP Host header in the form of lowercase host, followed by an ASCII newline.
* 3. The URL encoded HTTP absolute path component of the URI
* (up to but not including the query string parameters);
* if this is empty use a forward '/'. This parameter is followed by an ASCII newline.
* 4. The concatenation of all query string components (names and values)
* as UTF-8 characters which are URL encoded as per RFC 3986
* (hex characters MUST be uppercase), sorted using lexicographic byte ordering.
* Parameter names are separated from their values by the '=' character
* (ASCII character 61), even if the value is empty.
* Pairs of parameter and values are separated by the '&' character (ASCII code 38).
*
*/
private function signParameters(array $parameters)
{
$signatureVersion = $parameters['SignatureVersion'];
$algorithm = "HmacSHA1";
$stringToSign = null;
if (2 === $signatureVersion) {
$algorithm = "HmacSHA256";
$parameters['SignatureMethod'] = $algorithm;
$stringToSign = $this->calculateStringToSignV2($parameters);
} else {
throw new \Exception("Invalid Signature Version specified");
}
return $this->sign($stringToSign, $algorithm);
}
/* Calculate String to Sign for SignatureVersion 2
* @param array $parameters request parameters
* @return String to Sign
*/
private function calculateStringToSignV2(array $parameters)
{
$data = 'POST';
$data .= "\n";
$data .= $this->mwsEndpointUrl;
$data .= "\n";
$data .= $this->mwsEndpointPath;
$data .= "\n";
$data .= $this->getParametersAsString($parameters);
$this->logMessage($this->sanitizeRequestData($data));
return $data;
}
/* Convert paremeters to Url encoded query string */
private function getParametersAsString(array $parameters)
{
$queryParameters = array();
foreach ($parameters as $key => $value) {
$queryParameters[] = $key . '=' . $this->urlEncode($value);
}
return implode('&', $queryParameters);
}
private function urlEncode($value)
{
return str_replace('%7E', '~', rawurlencode($value));
}
/* Computes RFC 2104-compliant HMAC signature */
private function sign($data, $algorithm)
{
if ($algorithm === 'HmacSHA1') {
$hash = 'sha1';
} else if ($algorithm === 'HmacSHA256') {
$hash = 'sha256';
} else {
throw new \Exception("Non-supported signing method specified");
}
return base64_encode(hash_hmac($hash, $data, $this->config['secret_key'], true));
}
/* Formats date as ISO 8601 timestamp */
private function getFormattedTimestamp()
{
return gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time());
}
/* invokePost takes the parameters and invokes the httpPost function to POST the parameters
* Exponential retries on error 500 and 503
* The response from the POST is an XML which is converted to Array
*/
private function invokePost($parameters)
{
$response = array();
$statusCode = 200;
$this->success = false;
// Submit the request and read response body
try {
$shouldRetry = true;
$retries = 0;
do {
try {
$this->constructUserAgentHeader();
$httpCurlRequest = new HttpCurl($this->config);
$response = $httpCurlRequest->httpPost($this->mwsServiceUrl, $this->userAgent, $parameters);
$curlResponseInfo = $httpCurlRequest->getCurlResponseInfo();
$statusCode = $curlResponseInfo["http_code"];
$this->logMessage($this->userAgent);
$response = array(
'Status' => $statusCode,
'ResponseBody' => $response
);
$statusCode = $response['Status'];
if ($statusCode == 200) {
$shouldRetry = false;
$this->success = true;
} elseif ($statusCode == 500 || $statusCode == 503) {
$shouldRetry = true;
if ($shouldRetry && strtolower($this->config['handle_throttle'])) {
$this->pauseOnRetry(++$retries, $statusCode);
}
} else {
$shouldRetry = false;
}
} catch (\Exception $e) {
throw $e;
}
} while ($shouldRetry);
} catch (\Exception $se) {
throw $se;
}
$this->logMessage($this->sanitizeResponseData($response['ResponseBody']));
return $response;
}
/* Exponential sleep on failed request
* Up to three retries will occur if first reqest fails
* after 1.0 second, 2.2 seconds, and finally 7.0 seconds
* @param retries current retry
* @throws Exception if maximum number of retries has been reached
*/
private function pauseOnRetry($retries, $status)
{
if ($retries <= self::MAX_ERROR_RETRY) {
// PHP delays are in microseconds (1 million microsecond = 1 sec)
// 1st delay is (4^1) * 100000 + 600000 = 0.4 + 0.6 second = 1.0 sec
// 2nd delay is (4^2) * 100000 + 600000 = 1.6 + 0.6 second = 2.2 sec
// 3rd delay is (4^3) * 100000 + 600000 = 6.4 + 0.6 second = 7.0 sec
$delay = (int) (pow(4, $retries) * 100000) + 600000;
usleep($delay);
} else {
throw new \Exception('Error Code: '. $status.PHP_EOL.'Maximum number of retry attempts - '. $retries .' reached');
}
}
/* Create MWS service URL and the Endpoint path */
private function createServiceUrl()
{
$this->modePath = strtolower($this->config['sandbox']) ? 'OffAmazonPayments_Sandbox' : 'OffAmazonPayments';
if (!empty($this->config['region'])) {
$region = strtolower($this->config['region']);
if (array_key_exists($region, $this->regionMappings)) {
if (!is_null($this->config['override_service_url'])) {
$this->mwsEndpointUrl = preg_replace("(https?://)", "", $this->config['override_service_url']);
} else {
$this->mwsEndpointUrl = $this->mwsServiceUrls[$this->regionMappings[$region]];
}
$this->mwsServiceUrl = 'https://' . $this->mwsEndpointUrl . '/' . $this->modePath . '/' . self::MWS_VERSION;
$this->mwsEndpointPath = '/' . $this->modePath . '/' . self::MWS_VERSION;
} else {
throw new \Exception($region . ' is not a valid region');
}
} else {
throw new \Exception("config['region'] is a required parameter and is not set");
}
}
/* Based on the config['region'] and config['sandbox'] values get the user profile URL */
private function profileEndpointUrl()
{
$profileEnvt = strtolower($this->config['sandbox']) ? "api.sandbox" : "api";
if (!empty($this->config['region'])) {
$region = strtolower($this->config['region']);
if (array_key_exists($region, $this->regionMappings) ) {
$this->profileEndpoint = 'https://' . $profileEnvt . '.' . $this->profileEndpointUrls[$region];
} else {
throw new \Exception($region . ' is not a valid region');
}
} else {
throw new \Exception("config['region'] is a required parameter and is not set");
}
}
/* Create the User Agent Header sent with the POST request */
/* Protected because of PSP module usaged */
protected function constructUserAgentHeader()
{
$this->userAgent = 'amazon-pay-sdk-php/' . self::SDK_VERSION . ' (';
if (($this->config['application_name']) || ($this->config['application_version'])) {
if ($this->config['application_name']) {
$this->userAgent .= $this->quoteApplicationName($this->config['application_name']);
if ($this->config['application_version']) {
$this->userAgent .= '/';
}
}
if ($this->config['application_version']) {
$this->userAgent .= $this->quoteApplicationVersion($this->config['application_version']);
}
$this->userAgent .= '; ';
}
$this->userAgent .= 'PHP/' . phpversion() . '; ';
$this->userAgent .= php_uname('s') . '/' . php_uname('m') . '/' . php_uname('r');
$this->userAgent .= ')';
}
/* Collapse multiple whitespace characters into a single ' ' and backslash escape '\',
* and '/' characters from a string.
* @param $s
* @return string
*/
private function quoteApplicationName($s)
{
$quotedString = preg_replace('/ {2,}|\s/', ' ', $s);
$quotedString = preg_replace('/\\\\/', '\\\\\\\\', $quotedString);
$quotedString = preg_replace('/\//', '\\/', $quotedString);
return $quotedString;
}
/* Collapse multiple whitespace characters into a single ' ' and backslash escape '\',
* and '(' characters from a string.
*
* @param $s
* @return string
*/
private function quoteApplicationVersion($s)
{
$quotedString = preg_replace('/ {2,}|\s/', ' ', $s);
$quotedString = preg_replace('/\\\\/', '\\\\\\\\', $quotedString);
$quotedString = preg_replace('/\\(/', '\\(', $quotedString);
return $quotedString;
}
private function sanitizeRequestData($input)
{
$patterns = array();
$patterns[0] = '/(SellerNote=)(.+)(&)/ms';
$patterns[1] = '/(SellerAuthorizationNote=)(.+)(&)/ms';
$patterns[2] = '/(SellerCaptureNote=)(.+)(&)/ms';
$patterns[3] = '/(SellerRefundNote=)(.+)(&)/ms';
$replacements = array();
$replacements[0] = '$1REMOVED$3';
$replacements[1] = '$1REMOVED$3';
$replacements[2] = '$1REMOVED$3';
$replacements[3] = '$1REMOVED$3';
return preg_replace($patterns, $replacements, $input);
}
private function sanitizeResponseData($input)
{
$patterns = array();
$patterns[0] = '/(<Buyer>)(.+)(<\/Buyer>)/ms';
$patterns[1] = '/(<PhysicalDestination>)(.+)(<\/PhysicalDestination>)/ms';
$patterns[2] = '/(<BillingAddress>)(.+)(<\/BillingAddress>)/ms';
$patterns[3] = '/(<SellerNote>)(.+)(<\/SellerNote>)/ms';
$patterns[4] = '/(<AuthorizationBillingAddress>)(.+)(<\/AuthorizationBillingAddress>)/ms';
$patterns[5] = '/(<SellerAuthorizationNote>)(.+)(<\/SellerAuthorizationNote>)/ms';
$patterns[6] = '/(<SellerCaptureNote>)(.+)(<\/SellerCaptureNote>)/ms';
$patterns[7] = '/(<SellerRefundNote>)(.+)(<\/SellerRefundNote>)/ms';
$replacements = array();
$replacements[0] = '$1 REMOVED $3';
$replacements[1] = '$1 REMOVED $3';
$replacements[2] = '$1 REMOVED $3';
$replacements[3] = '$1 REMOVED $3';
$replacements[4] = '$1 REMOVED $3';
$replacements[5] = '$1 REMOVED $3';
$replacements[6] = '$1 REMOVED $3';
$replacements[7] = '$1 REMOVED $3';
return preg_replace($patterns, $replacements, $input);
}
/* Computes RFC 2104-compliant HMAC signature */
public static function getSignature($stringToSign, $secretKey)
{
return base64_encode(hash_hmac('sha256', $stringToSign, $secretKey, true));
}
}