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

DecryptionFailedException On Order Report #30

Closed codesticle closed 3 years ago

codesticle commented 3 years ago

We're downloading a report with Report Type of GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_GENERAL. It's a pretty big report that includes 30 days of order (the raw data is around 60mb).

Randomly we'll receive a "DecryptionFailedException" when our script reaches this:

$report = new Document($result->getPayload(), "text/tab-separated-values");
$contents = $report->download();

Here is the file/method throwing the exception: Jsq\EncryptionStreams\AesDecryptingStream::decryptBlock ...\vendor\jsq\psr7-stream-encryption\src\AesDecryptingStream.php:127

Calling our script again every minute or so, it eventually gets past this and the data gets downloaded, but if we call our script again on the same Report ID, it could throw the exception again, or could download the data successfully - it's random and we have not been able to guarantee reproducing it.

codesticle commented 3 years ago

I should note that I have not encountered this on other reports we're pulling (they happen to be much smaller)

codesticle commented 3 years ago

Further to this - I wrote a quick script to download and process the report (not using this API) and we were able to download, decrypt, and unzip quickly with no errors repeatedly.

jlevers commented 3 years ago

Interesting, thanks for reporting -- this is going to be challenging for me to reproduce, because I don't think I have access to any Seller accounts where I'll be able to generate reports that large.

Is it possible that you're running out of memory? The reports get stored in memory while they're decrypting/unzipping because of Amazon's data protection policy. You could try increasing PHP's memory_limit and see if that helps.

akreu commented 3 years ago

Further to this - I wrote a quick script to download and process the report (not using this API) and we were able to download, decrypt, and unzip quickly with no errors repeatedly.

@codesticle , I'm running into this as well, seems to be random on Order Reports; care to share your solution for decrypting and unzipping?

EDIT, here's what I'm doing and seems to work every time without error in my testing.

$reportDocumentInfo = $reportsApi->getReportDocument('insert_document_id')->getPayload();
$key = base64_decode($reportDocumentInfo->getEncryptionDetails()->getKey());
$iv = base64_decode($reportDocumentInfo->getEncryptionDetails()->getInitializationVector());
$contents = openssl_decrypt(file_get_contents($reportDocumentInfo->getUrl()), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
codesticle commented 3 years ago

That's pretty much what we're doing except we were bypassing the API entirely to get the document payload.

Further to this - I wrote a quick script to download and process the report (not using this API) and we were able to download, decrypt, and unzip quickly with no errors repeatedly.

@codesticle , I'm running into this as well, seems to be random on Order Reports; care to share your solution for decrypting and unzipping?

EDIT, here's what I'm doing and seems to work every time without error in my testing.

$reportDocumentInfo = $reportsApi->getReportDocument('insert_document_id')->getPayload();
$key = base64_decode($reportDocumentInfo->getEncryptionDetails()->getKey());
$iv = base64_decode($reportDocumentInfo->getEncryptionDetails()->getInitializationVector());
$contents = openssl_decrypt(file_get_contents($reportDocumentInfo->getUrl()), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
jlevers commented 3 years ago

@akreu, I like your solution here -- I didn't think to download directly from the document URL to a $contents variable, which a) doesn't violate Amazon's data protection policy (I think, IANAL), and b) is wayyyy simpler than what I'm doing.

Do I understand correctly that you need to enable allow_url_fopen in php.ini in order to download URLs directly in file_get_contents?

akreu commented 3 years ago

Do I understand correctly that you need to enable allow_url_fopen in php.ini in order to download URLs directly in file_get_contents?

@jlevers It looks like that's the case. I just tested with allow_url_fopen disabled and it did not work.

jlevers commented 3 years ago

Thank you, I appreciate it. If you're alright with it, I'm going to use your code in v3.0.0 to hopefully solve this problem permanently.

akreu commented 3 years ago

@jlevers Sounds good!

jlevers commented 3 years ago

This should be fixed in v3.0.0. Feel free to reopen if you're still running into issues.