amzn / amazon-pay-api-sdk-php

Amazon Pay API SDK (PHP)
Apache License 2.0
48 stars 31 forks source link

Use of stripcslashes breaks Amazon/Pay/API/Client::generateButtonSignature #13

Open jdart opened 3 years ago

jdart commented 3 years ago

I tried using this library today and was getting errors like below when clicking the checkout button in the browser:

Error Code: InvalidSignatureError

I was following the documentation here. After struggling with this issue I tried removing the call to stripcslashes on the line below.

https://github.com/amzn/amazon-pay-api-sdk-php/blob/master/Amazon/Pay/API/Client.php#L404

Without stripcslashes it looked like $hashedButtonRequest = self::AMAZON_SIGNATURE_ALGORITHM . "\n" . $this->hexAndHash($payload);. With that change suddenly my checkouts were working. I also found that mangling the value passed to payloadJSON with stripcslashes got things working as an alternative to editing the library.

Anyway, the stripcslashes seems to be causing issues.

shangamesh commented 3 years ago

Hi Thanks for the issue, We need to use stripcslashes($payload) to unescape sequences in payload but it will not cause any issue in terms of creating signature. Let us know about complete error/issues faced from your side

jdart commented 3 years ago

So this works for me, note I have to escape the payload before turning it into a js string

<?php

require '../vendor/autoload.php';

use Amazon\Pay\API\Client;

$publicKeyId = '...';

$payload =  json_encode([
    'storeId' => '...',
    'webCheckoutDetails' => [
        'checkoutReviewReturnUrl' => 'https://.../review',
    ],
]);

$client = new Client([
    'private_key' => file_get_contents('...pem'),
    'public_key_id' => $publicKeyId,
    'region' => 'US',
]);

$signature = $client->generateButtonSignature($payload);

?>
<html>
    <body>
    <div id="AmazonPayButton"></div>
    <script src="https://static-na.payments-amazon.com/checkout.js"></script>
    <script type="text/javascript" charset="utf-8">
        amazon.Pay.renderButton('#AmazonPayButton', {
            // set checkout environment
            merchantId: '...',
            publicKeyId: <?php echo json_encode($publicKeyId) ?>,
            ledgerCurrency: 'USD',
            checkoutLanguage: 'en_US',
            placement: 'Cart',
            buttonColor: 'Gold',
            createCheckoutSessionConfig: {
                payloadJSON: <?php echo json_encode(stripcslashes($payload)) ?>, // <--- the interesting bit
                signature: <?php echo json_encode($signature) ?>,
            }
        });
    </script>
    </body>
</html>

But this doesn't

<?php

require '../vendor/autoload.php';

use Amazon\Pay\API\Client;

$publicKeyId = '...';

$payload =  json_encode([
    'storeId' => '...',
    'webCheckoutDetails' => [
        'checkoutReviewReturnUrl' => 'https://.../review',
    ],
]);

$client = new Client([
    'private_key' => file_get_contents('...pem'),
    'public_key_id' => $publicKeyId,
    'region' => 'US',
]);

$signature = $client->generateButtonSignature($payload);

?>
<html>
    <body>
    <div id="AmazonPayButton"></div>
    <script src="https://static-na.payments-amazon.com/checkout.js"></script>
    <script type="text/javascript" charset="utf-8">
        amazon.Pay.renderButton('#AmazonPayButton', {
            // set checkout environment
            merchantId: '...',
            publicKeyId: <?php echo json_encode($publicKeyId) ?>,
            ledgerCurrency: 'USD',
            checkoutLanguage: 'en_US',
            placement: 'Cart',
            buttonColor: 'Gold',
            createCheckoutSessionConfig: {
                payloadJSON: <?php echo json_encode($payload) ?>, // <--- no strip cslashes
                signature: <?php echo json_encode($signature) ?>,
            }
        });
    </script>
    </body>
</html>