如何解决Amazon Gift Card在Php Laravel中加载Amazon Balance Api集成
我想通过在用户的亚马逊帐户中提供礼品卡余额来奖励他们注册我的应用程序,并且为此我使用了类似于Amazon Incentive API的Load Amazon Balance API。
Amazon需要数字签名的授权有效载荷才能访问api。我已经将代码与使用AWS密钥和AWS访问密钥进行亚马逊数字签名的过程进行了比较。但是它仍然给我
"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."
我在帖子中附上我班的代码。任何人都可以通过查看代码并告诉我在将信息发送到api所执行的过程中是否存在任何错误来帮助我。谢谢。
<?PHP
/**
* Created by PHPStorm.
*
* Date: 07-09-2018
* Time: 01:18 PM
*/
namespace App;
use App\AppConstant\AppConstant;
use App\Entities\Models\User;
use Illuminate\Support\Facades\Auth;
class AmazonReward
{
/**
* This is the bulk of the logic for making AGCOD calls.
*/
//Constants
public static $apikey;
public static $clientId = env("client_id");
public static $clientSecret = env("client_secret");
public static $awsSecretKey = env("client_secret");
public static $partnerId = env("partner_id");
public static $SERVICE_NAME = "AGCODService";
public static $ACCEPT_HEADER = "accept";
public static $CONTENT_HEADER = "content-type";
public static $HOST_HEADER = "host";
public static $XAMZDATE_HEADER = "x-amz-date";
public static $XAMZTARGET_HEADER = "x-amz-target";
public static $AUTHORIZATION_HEADER = "Authorization";
public static $AWS_SHA256_ALGORITHM = "AWS4-HMAC-SHA256";
public static $KEY_QUALIFIER = "AWS4";
public static $TERMINATION_STRING = "aws4_request";
const SERVICE_NAME = "AGCODService";
const ACCEPT_HEADER = "accept";
const CONTENT_HEADER = "content-type";
const HOST_HEADER = "host";
const XAMZDATE_HEADER = "x-amz-date";
const XAMZTARGET_HEADER = "x-amz-target";
const AUTHORIZATION_HEADER = "Authorization";
const AWS_SHA256_ALGORITHM = "AWS4-HMAC-SHA256";
const KEY_QUALIFIER = "AWS4";
const TERMINATION_STRING = "aws4_request";
const ENDPOINT ='agcod-v2.amazon.com';
// const ENDPOINT ='agcod-v2-gamma.amazon.com';
public static function get_paypload_giftcard($partnerId,$gcRequestId,$currencyCode,$gcAmount,$customer_id)
{
$amount = trim($gcAmount);
$payload = array(
"loadBalanceRequestId" => $gcRequestId,"partnerId" => $partnerId,"amount" =>
array(
"currencyCode" => $currencyCode,"value" => floatval($amount)
),"account" =>
array(
"id" => $customer_id,"type" => "2"
),"timestamp" => time(),// "transactionSource" => [
// "sourceId" => ""
// ],"externalReference" => "","notificationDetails" => [
"notificationMessage" => ""
]
);
return json_encode($payload);
}
/**
* Builds the "formal" request that can be hashed to verify the contents of the request.
* The request does not get sent to the server in this format,but the hash of this is.
*
* @return The formal request
*/
public static function buildCanonicalRequest($serviceOperation,$payloadHash,$customer_id) {
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$HOST_HEADER = self::HOST_HEADER;
$XAMZDATE_HEADER = self::XAMZDATE_HEADER;
$XAMZTARGET_HEADER = self::XAMZTARGET_HEADER;
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$dateTimeString = Self::getTimeStamp();
$header1 = Self::header1($serviceOperation);
$canonicalRequest = "POST\n/$serviceOperation HTTP/1.1\n\n$header1\n\n$ACCEPT_HEADER;$HOST_HEADER;$XAMZDATE_HEADER;$XAMZTARGET_HEADER\n$payloadHash";
return $canonicalRequest;
}
/**
* Returns part of the header used in the canonical request.
*
* @return the portion of the header.
*/
public static function header1($serviceOperation) {
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$XAMZDATE_HEADER = self::XAMZDATE_HEADER;
$XAMZTARGET_HEADER = self::XAMZTARGET_HEADER;
$HOST_HEADER = Self::HOST_HEADER;
$dateTimeString = Self::getTimeStamp();
$endpoint = self::ENDPOINT;
$contentType = Self::getContentType();
return
"$ACCEPT_HEADER:$contentType\n$HOST_HEADER:$endpoint\n$XAMZDATE_HEADER:$dateTimeString\n$XAMZTARGET_HEADER:com.amazonaws.agcod.AGCODService.$serviceOperation";
}
public static function disburseFunds($customer_id){
$apiString = "https://" . Self::ENDPOINT . "/LoadamazonBalance";
$ch = curl_init();
$xAmzDateTime = gmdate('Ymd\THis\Z');
$xAmzDate = substr($xAmzDateTime,8);
$xAmzTarget = "com.amazonaws.agcod.AGCODService.LoadamazonBalance";
$region = "us-east-1";
$serviceOperation = "LoadamazonBalance";
// $canonicalRequestHash = Self::myHash($canonicalRequest);
$payload = Self::get_paypload_giftcard( Self::$partnerId,Self::$partnerId . time(),"USD",5.00,$customer_id);
$payloadHash = Self::myHash($payload);
$canonicalRequest = Self::buildCanonicalRequest($serviceOperation,$customer_id);
$dateTimeString = Self::getTimeStamp();
$curl_response = Self::invokeRequest($payload,$xAmzDateTime,$canonicalRequest,$serviceOperation);
echo "<pre>";
print_r($curl_response);
exit;
$json = json_decode($curl_response);
if ( isset($json->message) || ! isset($json->cardInfo) )
{
echo "<pre>";
print_r($json);
exit;
$ret = array();
$ret['success']=false;
$ret['errorCode'] = time();
return $ret;
}
$ret = array();
$ret['success']=true;
$ret['gcValue']= $json->cardInfo->value->amount;
$ret["gcCode"]= $json->gcclaimCode;
$ret["gcResponseId"]= $json->gcId; ////done
$ret["gcRequestId"]=$json->creationRequestId;
echo "<pre>";
print_r($ret);
exit;
return $ret;
// echo "<pre>";
// print_r($canonicalRequestHash);
// exit;
// // $canonicalRequestHash = myHash($canonicalRequest);
// // $stringToSign = buildStringToSign($canonicalRequestHash);
// echo "<pre>";
// print_r($this->buildAuthSignature($stringToSign));
// exit;
// $authotization = "AWS4-HMAC-SHA256 Credential=AKIAIGHKAVYIDBOH3O3A/" . $xAmzTarget . "/" . $region . "/AGCODService/aws4_request,SignedHeaders=accept;host;x-amz-date;x-amz-target,Signature=ec86661c1d39f74b5891666505bb7656b172b0d060d911bee3b6a1c29ae17657";
// /*$post = http_build_query([
// ["Authorization" => "DEMO1"],// ["x-amz-date" => $xAmzDate],// ["x-amz-target" => $xAmzTarget],// ["Accept" => "application/json"],// ["Host" => "agcod-v2-gamma.amazon.com"]
// ]);*/
// // $post = [];
// $post = [];
// $post["loadBalanceRequestId"] = "Amazon123456";
// $post["partnerId"] = "";
// $post["amount"] = [];
// $post["amount"]["currencyCode"] = "";
// $post["amount"]["value"] = "";
// $post["account"] = [];
// $post["account"]["id"] = "F2044";
// $post["account"]["type"] = "0";
// $post["transactionSource"] = [];
// $post["transactionSource"]["sourceId"] = "";
// $post["externalReference"] = "";
// $post["notificationDetails"] = [];
// $post["notificationDetails"]["notificationMessage"] = "";
// $customHeaders = [
// "Authorization" => "Amazon",// "x-amz-date" => $xAmzDateTime,// "x-amz-target" => $xAmzTarget,// "Accept" => "application/json",// "Host" => "agcod-v2-gamma.amazon.com"
// ];
// curl_setopt($ch,CURLOPT_URL,$apiString);
// curl_setopt($ch,CURLOPT_POST,1);
// curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
// curl_setopt($ch,CURLOPT_HTTPHEADER,$customHeaders);
// curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
// $server_output = curl_exec($ch);
// curl_close ($ch);
// // Further processing ...
// if ($server_output == "OK") {
// }else{
// }
}
/**
* Builds the authenication string used to prove that the request is allowed and made by the right party.
*
* @param $stringToSign The string to sign.
* @return The authenication signature.
*/
public static function buildAuthSignature($dateString,$stringToSign) {
$AWS_SHA256_ALGORITHM = Self::AWS_SHA256_ALGORITHM;
$SERVICE_NAME = Self::SERVICE_NAME;
$TERMINATION_STRING = Self::TERMINATION_STRING;
$ACCEPT_HEADER = Self::ACCEPT_HEADER;
$HOST_HEADER = Self::HOST_HEADER;
$XAMZDATE_HEADER = Self::XAMZDATE_HEADER;
$XAMZTARGET_HEADER = Self::XAMZTARGET_HEADER;
$awsKeyId = Self::$clientId;
$regionName= Self::getRegion();
$derivedKey = Self::buildDerivedKey(Self::getDateString($dateString));
$derivedKey_lower = Self::buildDerivedKey(Self::getDateString($dateString),false);
$dateString = Self::getDateString($dateString);
// Calculate signature per http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
$finalSignature = Self::hmac($stringToSign,$derivedKey,false);
// Assemble Authorization Header with signing information
// per http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
$authorizationValue =
$AWS_SHA256_ALGORITHM
. " Credential=" . $awsKeyId
. "/" . $dateString . "/" . $regionName . "/" . $SERVICE_NAME . "/" . $TERMINATION_STRING . ","
. " SignedHeaders="
. $ACCEPT_HEADER . ";" . $HOST_HEADER . ";" . $XAMZDATE_HEADER . ";" . $XAMZTARGET_HEADER . ","
. " Signature="
. $finalSignature;
return $authorizationValue;
}
/**
* Hashes the string using sha256,the standard AWS hash.
*
* @param $data a string to sign
* @return a string hash of $data
*/
public static function myHash($data) {
return hash("sha256",$data);
}
/**
* Builds the string that gets hashed and used in the authenication.
*
* @param $canonicalRequestHash The hash of the canonicalRequest
* @return The string to sign.
*/
public static function buildStringToSign($canonicalRequestHash){
$AWS_SHA256_ALGORITHM = Self::AWS_SHA256_ALGORITHM;
$TERMINATION_STRING = Self::TERMINATION_STRING;
$SERVICE_NAME = Self::SERVICE_NAME;
$awsSecretKey = Self::$awsSecretKey;
$regionName = Self::getRegion();
$dateTimeString = Self::getTimeStamp();
$dateString = Self::getDateString($dateTimeString);
$stringToSign = "$AWS_SHA256_ALGORITHM\n$dateTimeString\n$dateString/$regionName/$SERVICE_NAME/$TERMINATION_STRING\n$canonicalRequestHash";
return $stringToSign;
}
/**
* Gets the time stamp used to make the request. If not set by the client it is set to the current time on the first call to this function.
*
* @return The time stamp
*/
public static function getTimeStamp() {
global $timeStamp;
if(!isset($timeStamp)) {
//GMT time. Format is YYYYMMDDTHHmmssZ where T and Z are literals,YYYY is 4 digit year,MM is 2 digit month,DD is 2 digit day,HH is 2 digit hour (24 hour clock) mm is 2 digit minute,ss is 2 digit second.
$timeStamp = gmdate('Ymd\THis\Z');
}
return $timeStamp;
}
/**
* Get the format that we will make the request in. This tells the server how to parse the request.
* This value is retrieved from the client and can either be json or xml.
*
* @return The request format as to be passed to the AGCOD server.
*/
public static function getContentType() {
return "application/json"; //Request in JSON format
}
/**
* Makes the service call to the AGCOD server.
*
* @return The repsonse from the server (in XML or JSON format) with HTML character escaped.
*/
public static function invokeRequest($payload,$dateTimeString,$serviceOperation) {
$KEY_QUALIFIER = self::KEY_QUALIFIER;
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$CONTENT_HEADER = self::CONTENT_HEADER;
$HOST_HEADER = self::HOST_HEADER;
$XAMZDATE_HEADER = self::XAMZDATE_HEADER;
$XAMZTARGET_HEADER = self::XAMZTARGET_HEADER;
$AUTHORIZATION_HEADER = self::AUTHORIZATION_HEADER;
$canonicalRequestHash = Self::myHash($canonicalRequest);
$stringToSign = Self::buildStringToSign($canonicalRequestHash);
$authorizationValue = Self::buildAuthSignature($dateTimeString,$stringToSign);
$endpoint = Self::ENDPOINT;
$regionName = Self::getRegion();
$SERVICE_NAME = "AGCODService";
$serviceTarget = "com.amazonaws.agcod." . $SERVICE_NAME . "." . $serviceOperation;
$contentType = Self::getContentType();
$url = "https://" . Self::ENDPOINT . "/" . $serviceOperation;
// print_r($url);
// exit;
//Prepare to send the data to the server
$handle = curl_init($url);
//Yes,do POST not GET
curl_setopt($handle,true);
//This is header,not post fields
curl_setopt($handle,array(
"Content-Type:$contentType",'Content-Length: ' . strlen($payload),$AUTHORIZATION_HEADER. ":" . $authorizationValue,$XAMZDATE_HEADER . ":" . $dateTimeString,$XAMZTARGET_HEADER . ":" . $serviceTarget,"host:" . Self::ENDPOINT,$ACCEPT_HEADER . ":" . $contentType
));
curl_setopt($handle,$payload);
//Yes,don't print the result to the web page,just give it to us in a string.
curl_setopt($handle,true);
//Do the request
$result = curl_exec($handle);
if (empty($result)) {
// some kind of an error happened
die(curl_error($handle));
curl_close($handle); // close cURL handler
}
//Free the resource
curl_close($handle);
$signaturePos = strpos($authorizationValue,"Signature=");
if($signaturePos == FALSE || $signaturePos + 10 >= strlen($authorizationValue)) {
$signatureStr = "Malformed";
}
else {
$signatureStr = substr($authorizationValue,$signaturePos + 10);
}
print_r($result);
exit;
return $result;
}
/**
* Gets the region based on the server we connect too.
*
* @return The region.
*/
public static function getRegion() {
$endpoint = Self::ENDPOINT;
$regionName = "us-east-1";
if ($endpoint == "agcod-v2-eu.amazon.com" || $endpoint == "agcod-v2-eu-gamma.amazon.com") {
$regionName = "eu-west-1";
}
else if ($endpoint == "agcod-v2-fe.amazon.com" || $endpoint == "agcod-v2-fe-gamma.amazon.com") {
$regionName = "us-west-2";
}
return $regionName;
}
/**
* Performs a hmac hash using sha256,which is what AWS uses.
*
* @param $data The data to sign.
* @param $key The key to sign the data with.
* @param $raw true to provide a raw ascii string,false to use a hex string.
* @return the hash of $data
*/
public static function hmac($data,$key,$raw = true) {
return hash_hmac("sha256",$data,$raw);
}
/**
* Gets the date for the request,which is either what the client passed in,or today if none was given.
*
* @return The date in YYYYMMDD format.
*/
public static function getDateString($dateTimeString) {
// $dateTimeString = Self::getTimeStamp();
return substr($dateTimeString,8);
}
/**
* Builds the derived key,which is used for authorizating the request.
*
* @param $rawOutput true to return an ascii string using raw byes,false to return a hex string
*/
public static function buildDerivedKey($dateString,$rawOutput = true) {
$KEY_QUALIFIER = Self::KEY_QUALIFIER;
$TERMINATION_STRING = Self::TERMINATION_STRING;
$SERVICE_NAME= Self::SERVICE_NAME;
// Get pasted AWS Secret Key from user input
$awsSecretKey = Self::$awsSecretKey;
// Append Key Qaulifier,"AWS4",to secret key per http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
$signatureAWSKey = $KEY_QUALIFIER . $awsSecretKey;
$regionName = Self::getRegion();
// $dateString = Self::getDateString();
$kDate = Self::hmac($dateString,$signatureAWSKey);
$kRegion = Self::hmac($regionName,$kDate);
$kService = Self::hmac($SERVICE_NAME,$kRegion);
// Derived the Signing key (derivedKey aka kSigning)
$derivedKey = Self::hmac($TERMINATION_STRING,$kService,$rawOutput);
return $derivedKey;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。