Invalid signature on amazon v2 - php

I have a problem on setting signature in this part of the guide (http://amazonpaycheckoutintegrationguide.s3.amazonaws.com/amazon-pay-checkout/set-payment-info.html). Here' my code:
<?
header('Content-Type: application/json');
define("STORE_ID", "amzn1.application-oa2-client.fb120c0b541e4007aaf987a73b365a3e");
define("VENDOR_ID", "A6SFQPANHYSL0");
define("PUBLIC_KEY_ID", "AGBUUNBAKQW5OMTKHP5WZH55");
define("PRIVATE_KEY_ID", "AmazonPay_AGBUUNBAKQW5OMTKHP5WZH55.pem");
$method = 'POST';
// API Merchant Scan
$url = 'https://pay-api.amazon.eu/sandbox/v2/checkoutSessions/'.$_GET['amazonCheckoutSessionId'];
$payload = array(
'webCheckoutDetails' => array(
'checkoutResultReturnUrl'=> 'https://a.com/merchant-confirm-page'
),
'paymentDetails' => array(
'paymentIntent'=> 'AuthorizeWithCapture',
'canHandlePendingAuthorization'=>false,
'softDescriptor'=> 'Descriptor',
'chargeAmount'=> array(
'amount'=> '1',
'currencyCode'=> 'EUR'
),
),
'merchantMetadata'=> array(
'merchantReferenceId'=> 'Merchant reference ID',
'merchantStoreName'=> 'Merchant store name',
'noteToBuyer'=> 'Note to buyer',
'customInformation'=> 'Custom information'
)
);
// Convert to json string
$payload = json_encode($payload);
$requestParameters = array();
include 'amazon-pay-api-sdk-php-master/vendor/autoload.php';
$amazonpay_config = array(
'public_key_id' => PUBLIC_KEY_ID,
'private_key' => PRIVATE_KEY_ID,
'region' => 'EU',
'sandbox' => true
);
$client = new Amazon\Pay\API\Client($amazonpay_config);
// Create an array that will contain the parameters for the charge API call
$pre_signed_headers = array();
$pre_signed_headers['Accept'] = 'application/json';
$pre_signed_headers['Content-Type'] = 'application/json';
$pre_signed_headers['X-Amz-Pay-Region'] = 'eu';
$timestamp_data = date("Ymd");
$timestamp_orario = date("His");
$timestamp = $timestamp_data."T".$timestamp_orario."Z";
$signedInput = $client->createSignature($method, $url, $requestParameters, $pre_signed_headers, $payload, $timestamp);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://pay-api.amazon.eu/sandbox/v2/checkoutSessions/'.$_GET['amazonCheckoutSessionId']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$headers = array();
$headers[] = 'Authorization: AMZN-PAY-RSASSA-PSS PublicKeyId=AGBUUNBAKQW5OMTKHP5WZH55, SignedHeaders=accept;content-type;x-amz-pay-date;x-amz-pay-host;x-amz-pay-region, Signature= '.$signedInput;
$headers[] = 'X-Amz-Pay-Date: '.$timestamp;
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
$json = json_decode($result);
print_r($json);
?>
The class for $client->createSignature is:
public function createSignature($http_request_method, $request_uri, $request_parameters, $pre_signed_headers, $request_payload, $timeStamp)
{
$rsa = $this->setupRSA();
$pre_signed_headers['X-Amz-Pay-Date'] = $timeStamp;
$pre_signed_headers['X-Amz-Pay-Host'] = $this->getHost($request_uri);
$hashedPayload = $this->hexAndHash($request_payload);
$canonicalURI = $this->getCanonicalURI($request_uri);
$canonicalQueryString = $this->createCanonicalQuery($request_parameters);
$canonicalHeader = $this->getHeaderString($pre_signed_headers);
$signedHeaders = $this->getCanonicalHeadersNames($pre_signed_headers);
$canonicalRequest = (
$http_request_method . "\n" .
$canonicalURI . "\n" .
$canonicalQueryString . "\n" .
$canonicalHeader . "\n" .
$signedHeaders . "\n" .
$hashedPayload
);
$hashedCanonicalRequest = self::AMAZON_SIGNATURE_ALGORITHM . "\n" . $this->hexAndHash($canonicalRequest);
$signature = $rsa->sign($hashedCanonicalRequest);
if ($signature === false) {
throw new \Exception('Unable to sign request, is your RSA private key valid?');
}
return base64_encode($signature);
}
The problem i received from the page i want to laod is:
[reasonCode] => InvalidRequestSignature
[message] => Unable to verify signature, signing String ...
Do you know how i can get a valid signature? I can use the one i got 2 steps before (the one that create the button for amazon pay) but i don't think it is the same.
Thank you for your time.

Related

Need to connect iTunes Connect API, always shows not authorized for JWT

I'm trying to generate a token to sign my requests to the iTunes Connect API. That's my PHP file:
function encode($data)
{
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
}
function sign($data)
{
if (!$key = openssl_pkey_get_private('file://AuthKey_qwerty.p8')) {
throw new \Exception('Failed to read PEM');
}
if (!openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA256)) {
throw new \Exception('Claims signing failed');
}
return $signature;
}
function create()
{
$header = encode(
json_encode([
'kid' => 'frfc343r4',
'alg' => 'ES256',
'typ' => 'JWT',
])
);
$claims = encode(
json_encode([
'iss' => 'ddd-aaa-bbbb-cccc-ddddd',
'exp' => time() + (20 * 60),
'aud' => 'appstoreconnect-v1',
])
);
$signature = encode(
sign("$header.$claims")
);
return $header . '.' . $claims . '.' . $signature;
}
echo create();
which gives an error, "Authentication credentials are missing or invalid.",App Store Connect API must be signed with ES256 encryption
require_once '../vendor/autoload.php';
use Curl\Curl;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
$signer = new Sha256();
$privateKey = new Key('file://AuthKey_ed2erd424.p8');
$time = time();
$Issuer_ID = "3455355-3535-4f8g-8x2r-3dcfrr43ed33";
$Key_ID = "4DD3R45DT45";
$token = (new Builder())->issuedBy($Issuer_ID)// Configures the issuer (iss claim)
->permittedFor("appstoreconnect-v1")// Configures the audience (aud claim)
//->identifiedBy('XXYYZZ', true)// Configures the id (jti claim), replicating as a header item
->withHeader('kid', $Key_ID)
->withHeader('type', 'JWT')
->withHeader('alg', 'ES256')
->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + 1200)// Configures the expiration time of the token (exp claim)
->withClaim('uid', 1)// Configures a new claim, called "uid"
->getToken($signer, $privateKey); // Retrieves the generated token
$token->getHeaders(); // Retrieves the token headers
$token->getClaims(); // Retrieves the token claims
$date = $_GET['date'];
$url ='https://api.appstoreconnect.apple.com/v1/salesReports';
$dataArray = array(
'filter[frequency]'=>'DAILY',
'filter[reportDate]'=>$date,
'filter[reportSubType]'=>'SUMMARY',
'filter[reportType]'=>'SALES',
'filter[vendorNumber]'=>'345434463',
'filter[version]'=>'1_0'
);
$ch = curl_init();
$data = http_build_query($dataArray);
$getUrl = $url."?".$data;
$authorization = "Authorization: Bearer ".$token; // Prepare the authorisation token
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization )); // Inject the token into the header
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $getUrl);
curl_setopt($ch, CURLOPT_TIMEOUT, 80);
$response = curl_exec($ch);
if(curl_error($ch)){
echo 'Request Error:' . curl_error($ch);
}
else
{
// if(!gzdecode($response)){ echo $response; exit; }
$uncompressed = $fp = #gzdecode($response);
if ($uncompressed === false) {
// do something related to error here
echo $response; exit;
}
;
$fp1 = array();
$myArray = [];
$lines = explode(PHP_EOL, $uncompressed);
$l = 0;
foreach($lines as $line) {
if($line == ''){continue;}
if($l == 0){ $myArray[$l] = explode("\t", $line); $l++; continue;}
//explode("\t", $line);
$key =0;
foreach(explode("\t", $line) as $value){
$myArray[$l][$myArray[0][$key]] = $value;
$key++;
}
$fp1[] = $myArray[$l];
$l++;
}
echo json_encode($fp1);
//echo $response;
}
curl_close($ch);

PHP AMAZON API GATEWAY : The request signature we calculated does not match the signature you provided

I want to get response from website content.geappliances.io using AWS API Gateway but always get error :
{"message":"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.\n\nThe Canonical String for this request should have been\n'GET\n/search/b2b/results\n\ncontent-type:\nhost:content.geappliances.io\nx-amz-date:20170401T041050Z\n\ncontent-type;host;x-amz-date\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20170401T041050Z\n20170401/us-east-1/execute-api/aws4_request\na8aec6a82c0f9a2471bd17faa5f2ce5cd810a16f129fca9b04347ceed54fdc61'\n"}
please somebody help me, what's wrong with my code. Here's the code :
function signRequest(){
$method ='GET';
$uri = '/search/b2b/results?N=0&Ntk=SKU&Ntt=GTX33EASKWW';
$access_key = 'my-access-key';
$secretKey = 'my-secret-key';
$region = 'us-east-1';
$kService = 'execute-api';
$service = 'execute-api';
$options = array();
$headers = array();
$host = "content.geappliances.io";
$alg = 'sha256';
$date = new DateTime( 'UTC' );
$dd = $date->format( 'Ymd\THis\Z' );
$amzdate2 = new DateTime( 'UTC' );
$amzdate2 = $amzdate2->format( 'Ymd' );
$amzdate = $dd;
$algorithm = 'AWS4-HMAC-SHA256';
$requestPayload = "UNSIGNED_PAYLOAD";
$hashedPayload = hash($alg, $requestPayload);
$canonical_uri = $uri;
$canonical_querystring = '';
$canonical_headers = "content-type:"."application/json"."\n"."host:".$host."\n"."x-amz-date:".$amzdate."\n";
$signed_headers = 'content-type;host;x-amz-date';
$canonical_request = "".$method."\n".$canonical_uri."\n".$canonical_querystring."\n".$canonical_headers."\n".$signed_headers."\n".$hashedPayload;
$credential_scope = $amzdate2 . '/' . $region . '/' . $service . '/' . 'aws4_request';
$string_to_sign = "".$algorithm."\n".$amzdate ."\n".$credential_scope."\n".hash('sha256', $canonical_request)."";
$kSecret = 'AWS4' . $secretKey;
$kDate = hash_hmac( $alg, $amzdate2, $kSecret, true );
$kRegion = hash_hmac( $alg, $region, $kDate, true );
$kService = hash_hmac( $alg, $service, $kRegion, true );
$kSigning = hash_hmac( $alg, 'aws4_request', $kService, true );
$signature = hash_hmac( $alg, $string_to_sign, $kSigning );
$authorization_header = $algorithm . ' ' . 'Credential=' . $access_key . '/' . $credential_scope . ', ' . 'SignedHeaders=' . $signed_headers . ', ' . 'Signature=' . $signature;
$headers = array(
'content-typeapplication/json',
"cache-control: no-cache",
"host: content.geappliances.io",
'x-amz-date: '.$amzdate.'',
'Authorization: '.$authorization_header.''
);
return $headers;
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt_array($curl, array(
CURLOPT_URL => "https://content.geappliances.io/search/b2b/results?N=0&Ntk=SKU&Ntt=GTX33EASKWW",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => signRequest(),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
in the postman, I generate my access key and secret key then it works nicely.
postman result
Take a look at your code
$access_key = 'my-access-key';
$secretKey = 'my-secret-key';
You have to enter your values for access key and secret key there. I assume Amazon provided them for you?
Because your error message says
The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method.

How do i fix my JSON format by using php

I try to send json format to my android app , but i find that my json format is uncorrect.
{data={"image":"http:\/\/www.androidhive.info\/wp-content\/uploads\/2016\/01\/Air-1.png","message":{"chat_room_id":"","created_at":"2017-03-22 3:34:30","message_id":"","message":"77"},"user":{"user_id":null,"gcm_registration_id":null,"name":null,"created_at":null,"email":null}}, flag=0, title=Google Cloud Messaging, is_background=false}
I set the data like this:
$app->post('/users/send_to_all',
function() use ($app) {
$response = array();
verifyRequiredParams(array('user_id', 'message'));
require_once __DIR__ . '/../libs/gcm/gcm.php';
require_once __DIR__ . '/../libs/gcm/push.php';
$db = new DbHandler();
$user_id = $app->request->post('user_id');
$message = $app->request->post('message');
require_once __DIR__ . '/../libs/gcm/gcm.php';
require_once __DIR__ . '/../libs/gcm/push.php';
$gcm = new GCM();
$push = new Push();
//get the user using userid
$user = $db->getUser($user_id);
//creating tmp message , skipping database insertion
$msg = array();
$msg['message'] = $message;
$msg['message_id'] = '';
$msg['chat_room_id'] = '';
$msg['created_at'] = date('Y-m-d G:i:s');
$data = array();
$data['user'] = $user;
$data['message'] = $msg;
$data['image'] = 'http://www.androidhive.info/wp-content/uploads/2016/01/Air-1.png';
$push->setTitle("Google Cloud Messaging");
$push->setIsBackground(FALSE);
$push->setFlag(PUSH_FLAG_USER);
$push->setData($data);
//sending message to topic `global`
//on the device every user should subscribe to `global` topic
$gcm->sendToTopic('global', $push->getPush());
$response['user'] = $user;
$response['error'] = false;
echoRespnse(200, $response);
});
Here is my Push.php about getPush():
public function getPush() {
$res = array();
$res['title'] = $this->title;
$res['is_background'] = $this->is_background;
$res['flag'] = $this->flag;
$res['data'] = $this->data;
return $res;
}
Here is my Gcm.php about sendToTopic:
//sending message to a topic by topic id
public function sendToTopic($to, $message) {
$fields = array(
'to' => '/topics/' . $to,
'data' => $message,
);
return $this->sendPushNotification($fields);
}
I'm really not familiar with php , how do i fix the JSON format ?
Any help would be appreciated , thanks in advance !
I update my question , i find json_encode in my Gcm.php:
It's on curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
class GCM {
//constructor
function __construct() {
}
//sending push message to single user by gcm registration id (array 最後面有, 待看)
public function send($to, $message) {
$fields = array(
'to' => $to,
'data' => $message,
);
return $this->sendPushNotification($fields);
}
//sending message to a topic by topic id
public function sendToTopic($to, $message) {
$fields = array(
'to' => '/topics/' . $to,
'data' => $message,
);
return $this->sendPushNotification($fields);
}
//sending push message to multiple users by gcm registration ids
public function sendMultiple($registration_ids, $message) {
$fields = array(
'registration_ids' => $registration_ids,
'data' => $message,
);
return $this->sendPushNotification($fields);
}
//function makes curl request to gcm servers (__DIR__ 待看)
private function sendPushNotification($fields) {
//include config
include_once __DIR__ . '/../../include/config.php';
//Set POST variable
//$url = 'https://gcm-http.googleapis.com/gcm/send';
$url='https://fcm.googleapis.com/fcm/send';
$headers = array(
'Authorization: key=' . GOOGLE_API_KEY,
'Content-Type: application/json'
);
//open connection
$ch = curl_init();
//set the url , number of POST vars , POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
//Execute post (=有三個?)
$result = curl_exec($ch);
if ($result === FALSE){
die('Curl failed: '. curl_error($ch));
}
//close connection
curl_close($ch);
return $result;
}
}
?>
It's still let my json format incorrect , how do i fix ?
PHP has some built-in json functions, you need json_encode() and json_decode().
For example this code:
<?php
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
echo json_encode($arr);
?>
Will print:
{"a":1,"b":2,"c":3,"d":4,"e":5}
Here's the link to documentation for json_encode() and for the entire json in php documentation.
Hope this helps.
Your JSON is invalid. try:
{"data":{"image":"http:\/\/www.androidhive.info\/wp-content\/uploads\/2016\/01\/Air-1.png","message":{"chat_room_id":"","created_at":"2017-03-22 3:34:30","message_id":"","message":"77"},"user":{"user_id":null,"gcm_registration_id":null,"name":null,"created_at":null,"email":null}}, "flag":0, "title":"Google Cloud Messaging", "is_background":false}
Notice ive replaced usage of = with : and wrapped keys and strings in quotes (")
To get it into a nice json string with php you need to build your array correctly first. Possible way is to setup a response array and then you can json_encode() it.
$response =[
'data' => $data,
'flag' => 0,
'title' => 'Google Cloud Messaging',
'is_background' => false.
];
now you can
json_encode($response);

Quickblox error "incorrect event" sending a push notification with AP

I'm using Quickblox to send push notifications to iPhone users. I created PHP functions for session and creating a user and API is working fine, but testing sending a push notification, I got an error on Dashboard/Queue: "incorrect event" on the message column. The event is created but never arrived.
The response of the API is OK, like the documentation.
I don't know why I got that error.
This is my code:
if (isset($_POST['mensaje'])) {
// Quickblox user Sign Up
$session = createSession( . . . , '...', '...', '...', '...');
$token = $session->token;
$group = '...'; // Hardcoded only for testing
$resp = sendQBPush($_POST['mensaje'], $group, $token);
}
and the function:
function sendQBPush($msg, $group, $token)
{
if (!$msg) {
return false;
}
$message = base64_encode($msg);
// Build post body
$post_body = array(
'event' => array(
'notification_type' => 'push',
'environment' => 'production',
'user' => array(
'tags' => array(
'any' => $group
)
) ,
'push_type' => 'apns',
'message' => 'payload=' . $message
)
);
$request = json_encode($post_body);
$ch = curl_init('http://api.quickblox.com/events.json');
curl_setopt($ch, CURLOPT_POST, true); // Use POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $request); // Setup post body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'QuickBlox-REST-API-Version: 0.1.0',
'QB-Token: ' . $token
));
$resultJSON = curl_exec($ch);
$responseJSON = json_decode($resultJSON);
echo $resultJSON;
// Check errors
if ($responseJSON) {
return $responseJSON;
}
else {
$error = curl_error($curl) . '(' . curl_errno($curl) . ')';
return $error;
}
// Close connection
curl_close($curl);
}
Thanks for your help

Smart Debit Payment Issue

I am using Smart Debit Payment Gateway to do the payment from a website...
I am facing a error on submit through CURL,
Couldn't init Money from [nil, 8000]
Can you please tell me why i am having this issue, all the credentials are fine..
I.N: I am testing this on my local xampp server not online and also on test account not live account.:
Code i am using is :
<?php
$request_host = 'https://secure.ddprocessing.co.uk';
$request_path = '/api/ddi/variable/create';
$user = "myusername";
$password = "mypassword";
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_POST => true,
CURLOPT_USERPWD => $user . ":" . $password,
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_HTTPHEADER => array("Accept: application/XML"),
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'], // Let SmartDebit see ho we are
);
$session = curl_init($request_host . $request_path);
curl_setopt_array( $session, $options );
// tell cURL to accept an SSL certificate if presented
if(ereg("^(https)", $request_host)) {
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
}
// The request parameters
$pslid = 'pslidcode';
$payer_ref = 'XYZ-12345';
$first_name = 'John';
$last_name = 'Smith';
$address_1 = "123 Fake St";
$town = "London";
$postcode = "07666";
$country = "United State";
$account_name = "John Smith";
$sort_code = "40-12-23";
$account_number = "12345678";
$regular_amount = 1000;
$frequency_type = "M";
// urlencode and concatenate the POST arguments
$postargs = 'variable_ddi[service_user][pslid]=' . $pslid;
$postargs .= '&variable_ddi[payer_reference]=' . urlencode($payer_ref);
$postargs .= '&variable_ddi[first_name]=' . urlencode($first_name);
$postargs .= '&variable_ddi[last_name]=' . urlencode($last_name);
$postargs .= '&variable_ddi[address_1]=' . urlencode($address_1);
$postargs .= '&variable_ddi[town]=' . urlencode($town);
$postargs .= '&variable_ddi[postcode]=' . urlencode($postcode);
$postargs .= '&variable_ddi[country]=' . urlencode($country);
$postargs .= '&variable_ddi[account_name]=' . urlencode($account_name);
$postargs .= '&variable_ddi[sort_code]=' . urlencode($sort_code);
$postargs .= '&variable_ddi[account_number]=' . urlencode($account_number);
$postargs .= '&variable_ddi[regular_amount]=' . urlencode($regular_amount);
$postargs .= '&variable_ddi[frequency_type]=' . urlencode($frequency_type);
// Tell curl that this is the body of the POST
$smrtoutput = curl_setopt($session, CURLOPT_POSTFIELDS, $postargs);
// $output contains the output string
$output = curl_exec($session);
print_r($output);die;
$header = curl_getinfo($session);
// close curl resource to free up system resources
curl_close($session);
if(curl_errno($session)) {
echo 'Curl error: ' . curl_error($session);
}
else {
switch ($header["http_code"]) {
case 200:
echo "Variable DDI created";
break;
default:
echo "HTTP Error: " . $header["http_code"];
}
}
?>

Categories