jlevers / selling-partner-api

A PHP client library for Amazon's Selling Partner API
BSD 3-Clause "New" or "Revised" License
398 stars 185 forks source link

Can't upload Invoice PDF, error "Access to the resource is forbidden" #521

Closed seannycrow closed 1 year ago

seannycrow commented 1 year ago

Problem description:

Hello guys,

I'm trying to send a PDF Invoice with SPAPI but i get an error "Access to the resource is forbidden" at the very end when trying to create the Feed. There are no other details so I cannot find what I did wrong. Could someone tell me please? The exception happens on the last try, on the line " $apiInstance->createFeed($body);"

Error:

Exception when calling FeedsApi->createFeed: [403] {
  "errors": [
    {
      "code": "Unauthorized",
      "message": "Access to the resource is forbidden",
      "details": ""
    }
  ]
}

Code

<?
require_once('/home/iziflux0/www/amazon/api/vendor/autoload.php');
use SellingPartnerApi\Api;
use SellingPartnerApi\Configuration;
use SellingPartnerApi\Endpoint;   
use SellingPartnerApi\Api\FeedsV20210630Api as FeedsApi;
use SellingPartnerApi\FeedType;
use SellingPartnerApi\Model\FeedsV20210630 as Feeds;

$config = new SellingPartnerApi\Configuration([
    "lwaClientId" => "amzn1.application-XXXXXXXXXXXXXXXXXXXXXXXX",
    "lwaClientSecret" => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "lwaRefreshToken" => "Atzr|XXXXXXXXXXXXXX",
    "awsAccessKeyId" => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "awsSecretAccessKey" => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "endpoint" => SellingPartnerApi\Endpoint::EU
]);

$feedType = FeedType::UPLOAD_VAT_INVOICE; 

$apiInstance = new FeedsApi($config);
$docSpecs = new Feeds\CreateFeedDocumentSpecification(['content_type' => $feedType['contentType']]);
$feedInfos = null;
try {
    $result = $apiInstance->createFeedDocument($docSpecs);
    $feedInfos = $result;

    echo "We created the Feed Document ! Now, let's upload the invoice\n";
    echo "The document ID is {$feedInfos->getFeedDocumentId()}\n";
} catch (Exception $e) {
    die('Exception when calling FeedsApi->createFeedDocument : ' . $e->getMessage() . PHP_EOL);
}

$feedUrl="XXXXXXXXXXXXXXXXXXXXX/Facture.402-5775620-1813149.FA042891.pdf"; //URL OF THE PDF
$tabValeursNom=explode(".",$feedUrl);
$orderid=$tabValeursNom[2];
$invoiceid=$tabValeursNom[3];
echo "OrderID=$orderid\r\n";
echo "invoiceid=$invoiceid\r\n";

try {
    echo "Uploading the PDF file\n";
    $doc = new SellingPartnerApi\Document($feedInfos, $feedType);
    $doc->upload(file_get_contents($feedUrl));
} catch (Exception $e) {
    echo ("Exception when calling Document->upload :\n" . $e->getMessage() . PHP_EOL);
}

$body = new Feeds\CreateFeedSpecification([
    'feed_type' => 'UPLOAD_VAT_INVOICE',
    'marketplace_ids' => ["A13V1IB3VIYZZH"], 
    'input_feed_document_id' => $feedInfos->getFeedDocumentId(),
    'feed_options' => [
        'metadata:Documentype' => 'Invoice',
        'metadata:InvoiceNumber' => "$invoiceid",
        'metadata:OrderId' => "$orderid",
        ]
    ]
);

try {
        echo "Linking the PDF uploaded to the order\n";
        $result = $apiInstance->createFeed($body);
        $feedId = $result->getFeedId();
        echo $feedId;

} catch (Exception $e) {
    echo 'Exception when calling FeedsApi->createFeed: ', $e->getMessage(), PHP_EOL;
}

Seller Central SP API config page screenshot

your screenshot here

seannycrow commented 1 year ago

It doesn't seem to be a problem with our developer roles, they're all checked in our profile (same for the application profile), and we can send any other feed type without any problems, but no matter what I get a 403 error on createFeed with this feed type, I don't understand.

MannikJ commented 1 year ago

Hey, since you closed this issue, can you tell us the solution? I have the exact same problem. The other feeds work fine, but the invoice feed does not. Maybe its just a permission issue.

MannikJ commented 1 year ago

@jlevers Do you have any idea? We didn't have the "Tax Invoicing" role activated for our app a few weeks ago, but it looks like it was now accepted. I also renewed the RefreshToken afterwards, but still receive this message. I don't encrypt the documents I'm sending, maybe this is a problem? But as far as I have seen, the package doesn't even return any encryption details I would need.

seannycrow commented 1 year ago

The issue was that I didn't refresh the token, like a moron! My code was good (well, it works at least, good idk), it sill is like that now and works no problem. With jlevers you don't need to encrypt.

Here is the code as it is now:

`use SellingPartnerApi\Api; use SellingPartnerApi\Configuration; use SellingPartnerApi\Endpoint;
use SellingPartnerApi\Api\FeedsV20210630Api as FeedsApi; use SellingPartnerApi\FeedType; use SellingPartnerApi\Model\FeedsV20210630 as Feeds;

[...] REMOVED FOR SECURITY

$feedUrl=FEEDURL; $numFacture=ORDERID."-".INVOICEID.".pdf"; system("wget -q -t 2 --no-check-certificate -U firefox -O ./".$numFacture." ".$feedUrl,$trtr); $orderid=ORDERID; $invoiceid=INVOICEID;

try { // echo "Uploading the PDF file\n"; $doc = new SellingPartnerApi\Document($feedInfos, $feedType); $doc->upload(file_get_contents($numFacture)); unlink($numFacture); } catch (Exception $e) { // echo ("Exception when calling Document->upload :\n" . $e->getMessage() . PHP_EOL); unlink($numFacture); }

// Finally, you must link the uploaded PDF to your Amazon Order. To do so, create a FeedSpecification: $createFeedSpec = new Feeds\CreateFeedSpecification([ 'feed_type' => 'UPLOAD_VAT_INVOICE', 'marketplace_ids' => [MARKETPLACEID], // This is the FR Amazon Marketplace ID 'input_feed_document_id' => $feedInfos->getFeedDocumentId(), 'feed_options' => [ 'metadata:Documentype' => 'Invoice', 'metadata:InvoiceNumber' => "$invoiceid", 'metadata:OrderId' => "$orderid", // Should have the NNN-NNNNNNN-NNNNNNN format ] ] );

try { // echo "Linking the PDF uploaded to the order\n"; $result = $apiInstance->createFeed($createFeedSpec); $feedId = $result->getFeedId(); } catch (Exception $e) { echo 'Exception when calling FeedsApi->createFeed: ', $e->getMessage(), PHP_EOL; }`

MannikJ commented 1 year ago

Thank you for the insights!

So I am now indeed a step further, my feed is accepted and processed, but still there is no invoice linked to the Amazon order. I guess the problem before was also that the old credentials did not have the new roles attached. After creating new tokens the forbidden error was gone. But something must still be wrong. Do you base64-encode the invoice pdf document before uploading or do you just upload the content string?

UPDATE: Its now working without base64. I actually forgot the metadata:DocumentType parameter