php - 如何使用 PHP 调用亚马逊 MWS 订单?

标签 php amazon-web-services curl amazon-mws

在设置 API 调用亚马逊 MWS订单部分时,我遇到了很多麻烦和挫折。

当我使用 Amazon MWS Scratchpad 时我能够获得成功的响应,但是当我自己调用电话时出现错误:

The request signature we calculated does not match the signature you provided.
Check your AWS Secret Access Key and signing method.
Consult the service documentation for details.

我可能是错的,但我认为我实际调用的方式一定有问题,因为即使我使用通过 Scratchpad 创建的确切调用,我仍然会收到相同的错误。

不过,这里是我尝试构建请求的代码:

<?php

$secretKey = '<MY SECRET KEY>';

$parameters = array();

// required parameters
$parameters['Action']               = 'ListOrders';
$parameters['AWSAccessKeyId']       = '<MY ACCESS KEY>';
$parameters['MWSAuthToken']         = '<MY AUTH TOKEN>';
$parameters['SellerId']             = '<MY SELLER ID>';
$parameters['SignatureMethod']      = 'HmacSHA256';
$parameters['SignatureVersion']     = '2';
$parameters['Timestamp']            = gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time());
$parameters['Version']              = '2013-09-01';

// optional parameters
$parameters['MarketplaceId.Id.1']   = '<MARKETPLACE ID>';
$parameters['CreatedAfter']         = '2015-10-04T04%3A00%3A00Z';

/**
 * Calculate String to Sign
 * 
 * @param array $parameters request parameters
 * @return String to Sign
 */
function _calculateStringToSign(array $parameters) {
    $data = "POST\n";
    $data .= "mws.amazonservices.com\n";
    $data .= "/Orders/2013-09-01\n";        
    $data .= _getParametersAsString($parameters);
    return $data;
}


/**
 * Convert paremeters to Url encoded query string
 */
function _getParametersAsString(array $parameters)
{
    uksort($parameters, 'strcmp');
    $queryParameters = array();
    foreach ($parameters as $key => $value) {
        $queryParameters[] = $key . '=' . _urlencode($value);
    }
    return implode('&', $queryParameters);
}

function _urlencode($value) {
    return str_replace('%7E', '~', rawurlencode($value));
}

/**
 * Computes RFC 2104-compliant HMAC signature.
 */
function _sign($stringToSign, $secretKey)
{
    $hash = 'sha256';

    return urlencode(base64_encode(
        hash_hmac($hash, $stringToSign, $secretKey, true)
    ));
}

/**
 * Builds up the request.
 */
function buildRequest(array $parameters, $secretKey) {
    $endpoint = 'https://mws.amazonservices.com/Orders/2013-09-01';

    $signature = _sign(_calculateStringToSign($parameters), $secretKey);
    $parameters['Signature'] = $signature;

    uksort($parameters, 'strcmp');
    return $endpoint . '?' . _getParametersAsString($parameters);
}

下面是实际调用的代码:

$request = buildRequest($parameters, $secretKey);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/39.0.2171.71 Safari/537.36');
$page = curl_exec($ch);
curl_close($ch);
var_dump($page);

我需要帮助来确定这个脚本哪里出了问题,以及为什么我无法获得成功的响应。

最佳答案

解决方法:

$secretKey = 'ENTERVALUE';

$parameters = array();

// required parameters
$parameters['AWSAccessKeyId']       = 'ENTERVALUE';
$parameters['Action']               = 'GetOrder';
$parameters['AmazonOrderId.Id.1']   = 'ENTERVALUE';
$parameters['SellerId']             = 'ENTERVALUE';
$parameters['SignatureMethod']      = 'HmacSHA256';
$parameters['SignatureVersion']     = '2';
$parameters['Timestamp']            = gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time());
$parameters['Version']              = '2013-09-01';




/**
 * Calculate String to Sign
 * 
 * @param array $parameters request parameters
 * @return String to Sign
 */
function _calculateStringToSign(array $parameters) {
    $data = "POST\n";
    $data .= "mws.amazonservices.com\n";
    $data .= "/Orders/2013-09-01\n";        
    $data .= _getParametersAsString($parameters);
    return $data;
}


/**
 * Convert paremeters to Url encoded query string
 */
function _getParametersAsString(array $parameters)
{
    uksort($parameters, 'strcmp');
    $queryParameters = array();
    foreach ($parameters as $key => $value) {
        $queryParameters[] = $key . '=' . _urlencode($value);
    }
    return implode('&', $queryParameters);
}

function _urlencode($value) {
    return str_replace('%7E', '~', rawurlencode($value));
}

/**
 * Computes RFC 2104-compliant HMAC signature.
 */
function _sign($stringToSign, $secretKey)
{
    //HmacSHA1
    $hash = 'sha256';

    return base64_encode(
        hash_hmac($hash, $stringToSign, $secretKey, true)
    );
}

/**
 * Builds up the request.
 */
function buildRequest(array $parameters, $secretKey) {
    //$endpoint = 'https://mws.amazonservices.com/Orders/2013-09-01';

    $signature = _sign(_calculateStringToSign($parameters), $secretKey);
    $parameters['Signature'] = $signature;

    uksort($parameters, 'strcmp');
    return _getParametersAsString($parameters);
}

$request = buildRequest($parameters, $secretKey);



$allHeaders = array();
    $allHeaders['Content-Type'] = "application/x-www-form-urlencoded; charset=utf-8"; // We need to make sure to set utf-8 encoding here
    $allHeaders['Expect'] = null; // Don't expect 100 Continue
    $allHeadersStr = array();
    foreach($allHeaders as $name => $val) {
        $str = $name . ": ";
        if(isset($val)) {
            $str = $str . $val;
        }
        $allHeadersStr[] = $str;
    }


//complete string
//echo $endpoint . '?' .$request;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://mws.amazonservices.com/Orders/2013-09-01');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_HTTPHEADER, $allHeadersStr);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) chrome/39.0.2171.71 Safari/537.36');
$response = curl_exec($ch);
echo $response;
$xml = simplexml_load_string( $response );
echo curl_error($ch);
curl_close($ch);

关于php - 如何使用 PHP 调用亚马逊 MWS 订单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33945170/

相关文章:

php - 如何在 php 标签之间使用 html5 显示带有 href 标签的按钮?

python - aws boto3 抓取子网信息

amazon-web-services - EKS 无法使用 Kubectl 对 Kubernetes 进行身份验证 - "User: is not authorized to perform: sts:AssumeRole"

php - 如何设置 PHP cURL 下载的最大大小限制?

python - pycurl: RETURNTRANSFER 选项不存在

php - 当查询本身有效时,为什么 php 脚本中的此查询不起作用?

php - 使用 Laravel 基于 SAML 的单点登录

php - 如何限制登录到 Symfony2 中已经登录的用户

amazon-web-services - 如何在 AWS Cognito 中编辑更改密码的尝试限制?

Python 捕获子进程中的成功或失败