49 Commits

Author SHA1 Message Date
33a48f47de Update unit tests to allow skip if AWS API flood
on Github a lot of API tests will fail with "T001" flooding, so we just skip them
2025-01-21 11:11:56 +09:00
cf5ece0b5f github flow yml had tabs instead of spaces 2025-01-21 11:07:10 +09:00
db8df612b4 Remove phpunit from github actions 2025-01-21 11:05:58 +09:00
75f4d0b10a Add phpstan to compoer dev install 2025-01-21 11:02:55 +09:00
7fed1c2a85 Readme update 2025-01-21 10:55:11 +09:00
28a9e390cc Code clean up with declare strict and php stan level 9 checks
add "declare(strict_types=1);" to all pages

Add a json handler class to handle that json_decode always returns array<mixed> and throws error otherwise
On failure these will throw the normal JSON encoded error was FAILURE with code "J-" and the number is the json error
If 0 then the return was null or some other problem that did not return an array

amount is float and not string and checks are done that the returned value is a float

various updates for phpdoc array delcarations
- curl header is array<int, string>
- the log array is proper declared as array with string key and a list of mixed arrays
2025-01-21 10:48:41 +09:00
a565d2899b Comment typo fix 2024-08-21 11:22:33 +09:00
58b126ab83 Rename the github action job 2024-05-22 18:42:48 +09:00
e9a6332ad0 Add skip on error for funds test 2024-05-22 18:26:46 +09:00
a79fd519ed Gitbub action cache 2024-05-22 18:02:01 +09:00
04aa9fa019 Github actions add 2024-05-22 17:27:20 +09:00
d86ad8c051 Switch to PSR12 with spaces instead of tabs 2023-01-19 12:51:12 +09:00
6f5cd028b9 Minor fix for return type alignment
make sure string returned is set to string in config getter
2023-01-06 10:36:24 +09:00
3634c5bdfa Merge pull request #2 from kapierstau/fix/eu-region-for-eu-endpoint 2022-08-18 10:22:22 +09:00
kapierstau.io
37b4cbce40 Update AWS.php
Fixed region for EU endpoint
2022-08-17 13:54:10 +02:00
54a4d9e4c3 Remove composer.lock file 2022-06-14 09:16:14 +09:00
bd2a328956 Merge split git repositories into one agin 2022-06-14 09:15:37 +09:00
bcbf97b406 phpUnit tests updates and fixes
All gift card id checks are against string and not numeric.

Add missing checks for card status, card amount value, card amount
currency in any buy card checks.

Add epiration date regex check for buy card

Add request cancled card check.
2022-06-14 06:56:19 +09:00
422fc66137 phpUnit tests updates and fixes
All gift card id checks are against string and not numeric.

Add missing checks for card status, card amount value, card amount
currency in any buy card checks.

Add epiration date regex check for buy card

Add request cancled card check.
2022-06-14 06:55:38 +09:00
462d00cb42 Readme file update 2022-06-13 20:00:04 +09:00
308794488d Update Readme file with various fixes 2022-06-13 19:59:07 +09:00
96b24f9424 Add phpUnit testing and update test file.
Test file does not run any tests automatically but they need to be
triggered with the _GET parameters.

A full phpunit test has been added for the full functionality
2022-06-13 19:53:00 +09:00
d69781a709 Move decodeExceptionMessage to Exceptions class
The method "decodeExceptionMessage" previous located in the
AmazonIncentives\AmazonIncentives main class has been moved to the
AmazonIncentives\Exceptions\AmazonErrors where it logically belongs.

A deprecation phpdoc message has been added for the current version.

Update error messages in curl error part and remove double spaces.
2022-06-13 19:52:34 +09:00
2bcd42f4a5 Add phpUnit testing for Amazon Incentives class 2022-06-13 18:09:52 +09:00
05b33ac157 Move decode error method, minor text update for error strings
the method "decodeExceptionMessage" has moved from
AmazonIncentives\AmazonIncentives to
AmazonIncentives\Exceptions\AmazonErrors

The old method is currently tagged deprecated internal via @deprecated
PHPdoc entry
2022-06-13 18:06:16 +09:00
4f072d2226 Merge branch 'development' Wrapper method additions 2022-06-10 14:51:22 +09:00
774e553d90 Add new class create methods for proper phpunit testing
Instead of direct calling Client class and AWS class add a wrapper
method to call those so we can quicker replace under elements and
also do proper testing

Turn on mock tests on AWS side in normal test file
2022-06-10 14:50:32 +09:00
fd5477269b Turn on mock tests on AWS side in normal test file 2022-06-10 14:49:32 +09:00
afb11a6797 Add new class create methods for proper phpunit testing
instead of direct calling Client class and AWS class add a wrapper
method to call those so we can quicker replace under elements and also
do proper testing
2022-06-10 14:40:40 +09:00
d6382960bf Merge branch 'development' with phpDoc changes 2022-06-10 14:38:15 +09:00
b26cc82055 Add PHPdoc to all methods, minor code reorder
Move some methods around to have them together by call order logic.

Also update current test methods with composer based .env reader.
2022-06-10 14:37:07 +09:00
6f177986f9 Update PHPdoc in AmazonIncentive and Config class
Missing documentation for methods/class constructors
2022-06-10 14:30:20 +09:00
e1b5dc1bab Add PHPdoc to all methods, minor code reorder
Move some methods around to have them together by call order logic
2022-06-09 16:02:25 +09:00
7cb5e00a5f Add base phpUnit file 2022-06-09 09:26:42 +09:00
a51f4df53e Update core git config files, vendor installs for unit testing
Update .gitattributes with more files to ignore
Add .gitignore for php unit test cache
Install dotenv file parser for unit testing
Update current test pages with dotenv file parser (replaces function
call)

Documentation PHPdoc update for checkMe method call
2022-06-09 09:25:08 +09:00
42087a64fa Add .gitignore file for not needed files 2022-06-08 16:45:43 +09:00
ab95e1c21b Remove not needed files and folders for composer publish 2022-06-08 15:21:58 +09:00
1e836e9a2b Update to static checker file, add phpunit xml, update composer json 2022-06-08 15:04:59 +09:00
b1079e1d24 Install composer phpunit v9 for development testing 2022-06-08 06:34:47 +09:00
5b99da616b Just rename the readEnvFile function for testing
Until I find out how I can exclude folders from beeing deployed
Update composer ingore list
Add .gitattributes for ignore list
2022-03-18 09:24:27 +09:00
f60aa3e1bc Merge branch 'development'
PHPstan config updates, test file update
2021-11-25 17:45:13 +09:00
b041720a18 phpstan config updates, test code update 2021-11-25 17:44:04 +09:00
be6b2be55d Merge pull request #1 from arif-rh/minor-fix
Minor fix for README type on composer command and trailing , in config class
2021-11-25 17:42:33 +09:00
Arif RH
6163d26f50 minor fix Config 2021-11-25 14:55:55 +07:00
Arif RH
a4c06b9a36 minor fix README 2021-11-25 14:55:09 +07:00
24dc8426de Remove space from client interface 2021-10-27 17:55:29 +09:00
7ef4133537 Update composer json file to exclude test and static test files 2021-10-21 15:51:05 +09:00
4f90f2d916 Update test with simpl .env variables and include example file 2021-10-21 15:00:45 +09:00
192e4e54e1 Add psalm to level 3 and clean up more code 2021-10-21 14:57:29 +09:00
37 changed files with 3261 additions and 2483 deletions

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
test/ export-ignore
phpstan.neon export-ignore
phpunit.xml export-ignore
psalm.xml export-ignore
.phan/ export-ignore
.* export-ignore

49
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: CI
run-name: ${{ github.actor}} runs CI
on: [push]
jobs:
ci-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: php-actions/composer@v6
env:
COMPOSER_ROOT_VERSION: dev-master
- name: "Restore result cache"
uses: actions/cache/restore@v4
with:
path: ./tmp
key: "result-cache-v1-${{ matrix.php-version }}-${{ github.run_id }}"
restore-keys: |
result-cache-v1-${{ matrix.php-version }}-
- name: PHPStan Static Analysis
uses: php-actions/phpstan@v3
with:
path: src/
- name: "Save result cache"
uses: actions/cache/save@v4
if: always()
with:
path: ./tmp
key: "result-cache-v1-${{ matrix.php-version }}-${{ github.run_id }}"
# We need to use phpunit from the self install to get the class paths
# Skip auto tests here, there are too many problems with flooding of the AWS API from github
- name: PHPunit Tests Prepare
env:
AWS_GIFT_CARD_ENDPOINT: "${{ secrets.AWS_GIFT_CARD_ENDPOINT }}"
AWS_GIFT_CARD_KEY: "${{ secrets.AWS_GIFT_CARD_KEY }}"
AWS_GIFT_CARD_SECRET: "${{ secrets.AWS_GIFT_CARD_SECRET }}"
AWS_GIFT_CARD_PARTNER_ID: "${{ secrets.AWS_GIFT_CARD_PARTNER_ID }}"
AWS_GIFT_CARD_CURRENCY: "${{ secrets.AWS_GIFT_CARD_CURRENCY }}"
run: |
echo "AWS_GIFT_CARD_ENDPOINT=${AWS_GIFT_CARD_ENDPOINT}" > test/.env;
echo "AWS_GIFT_CARD_KEY=${AWS_GIFT_CARD_KEY}" >> test/.env;
echo "AWS_GIFT_CARD_SECRET=${AWS_GIFT_CARD_SECRET}" >> test/.env;
echo "AWS_GIFT_CARD_PARTNER_ID=${AWS_GIFT_CARD_PARTNER_ID}" >> test/.env;
echo "AWS_GIFT_CARD_CURRENCY=${AWS_GIFT_CARD_CURRENCY}" >> test/.env;
echo "AWS_DEBUG=1" >> test/.env;
- name: PHPunit Tests
run: |
vendor/bin/phpunit

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
vendor
.phpunit.result.cache
composer.lock

View File

@@ -26,72 +26,74 @@
// use Phan\Config; // use Phan\Config;
return [ return [
// If true, missing properties will be created when "minimum_target_php_version" => "7.4",
// they are first seen. If false, we'll report an // If true, missing properties will be created when
// error message. // they are first seen. If false, we'll report an
"allow_missing_properties" => false, // error message.
"allow_missing_properties" => false,
// Allow null to be cast as any type and for any // Allow null to be cast as any type and for any
// type to be cast to null. // type to be cast to null.
"null_casts_as_any_type" => false, "null_casts_as_any_type" => false,
// Backwards Compatibility Checking // Backwards Compatibility Checking
'backward_compatibility_checks' => true, 'backward_compatibility_checks' => true,
// Run a quick version of checks that takes less // Run a quick version of checks that takes less
// time // time
"quick_mode" => false, "quick_mode" => false,
// Only emit critical issues to start with // Only emit critical issues to start with
// (0 is low severity, 5 is normal severity, 10 is critical) // (0 is low severity, 5 is normal severity, 10 is critical)
"minimum_severity" => 10, "minimum_severity" => 10,
// default false for include path check // default false for include path check
"enable_include_path_checks" => true, "enable_include_path_checks" => true,
"include_paths" => [ "include_paths" => [
], ],
'ignore_undeclared_variables_in_global_scope' => true, 'ignore_undeclared_variables_in_global_scope' => true,
"file_list" => [ "file_list" => [
], ],
// A list of directories that should be parsed for class and // A list of directories that should be parsed for class and
// method information. After excluding the directories // method information. After excluding the directories
// defined in exclude_analysis_directory_list, the remaining // defined in exclude_analysis_directory_list, the remaining
// files will be statically analyzed for errors. // files will be statically analyzed for errors.
// //
// Thus, both first-party and third-party code being used by // Thus, both first-party and third-party code being used by
// your application should be included in this list. // your application should be included in this list.
'directory_list' => [ 'directory_list' => [
// Change this to include the folders you wish to analyze // Change this to include the folders you wish to analyze
// (and the folders of their dependencies) // (and the folders of their dependencies)
'.' 'src/'
// 'www', // 'www',
// To speed up analysis, we recommend going back later and // To speed up analysis, we recommend going back later and
// limiting this to only the vendor/ subdirectories your // limiting this to only the vendor/ subdirectories your
// project depends on. // project depends on.
// `phan --init` will generate a list of folders for you // `phan --init` will generate a list of folders for you
//'www/vendor', //'www/vendor',
], ],
// A list of directories holding code that we want // A list of directories holding code that we want
// to parse, but not analyze // to parse, but not analyze
"exclude_analysis_directory_list" => [ "exclude_analysis_directory_list" => [
'vendor', 'vendor',
], 'test',
'exclude_file_list' => [ ],
], 'exclude_file_list' => [
],
// what not to show as problem // what not to show as problem
'suppress_issue_types' => [ 'suppress_issue_types' => [
// 'PhanUndeclaredMethod', // 'PhanUndeclaredMethod',
'PhanEmptyFile', 'PhanEmptyFile',
], ],
// Override to hardcode existence and types of (non-builtin) globals in the global scope. // Override to hardcode existence and types of (non-builtin) globals in the global scope.
// Class names should be prefixed with `\`. // Class names should be prefixed with `\`.
// //
// (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`) // (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`)
'globals_type_map' => [], 'globals_type_map' => [],
]; ];

View File

@@ -1,12 +1,14 @@
# Amazon Incentives - Gift Codes on Demand stand alone class # Amazon Incentives - Gift Codes on Demand stand alone class
This is a abastract from (https://github.com/kamerk22/AmazonGiftCode) to be not dependend on Laravel base code. This is a abastract from [https://github.com/kamerk22/AmazonGiftCod](https://github.com/kamerk22/AmazonGiftCode) to be not dependend on Laravel base code.
Amazon Gift Codes On Demand (AGCOD). Integration for Amazon Incentive API. Amazon Gift Codes On Demand (AGCOD). Integration for Amazon Incentive API.
[General Amazon Incentives Documentation](https://developer.amazon.com/docs/incentives-api/digital-gift-cards.html)
## How to install ## How to install
`composer request gullevek/amazon-incentives` `composer require gullevek/amazon-incentives`
## _ENV variables needed ## _ENV variables needed
@@ -82,18 +84,21 @@ The error code is the curl handler error code.
The error message is json encoded array with the layout The error message is json encoded array with the layout
Use Use
```php ```php
$exception_array = gullevek\AmazonIncentives\AmazonIncentives::decodeExceptionMessage($exception_message); $exception_array = gullevek\AmazonIncentives\AmazonIncentives::decodeExceptionMessage($exception_message);
``` ```
to extract the below array from the thrown exception to extract the below array from the thrown exception
```php ```php
[ [
'status' => 'AWS Status FAILURE or RESEND', 'status' => 'AWS Status FAILURE or RESEND',
'code' => 'AWS Error Code Fnnn', 'code' => 'AWS Error Code Fnnn',
'type' => 'AWS Error info', 'type' => 'AWS Error info',
'message' => 'AWS long error message', 'message' => 'AWS long error message',
'log_id' => 'If logging is on the current log id', 'log_id' => 'If logging is on the current log id',
'log' => 'The complete log collected over all calls', 'log' => 'The complete log collected over all calls',
] ]
``` ```
@@ -106,7 +111,7 @@ to extract the below array from the thrown exception
if code is T001 then this is a request flood error: if code is T001 then this is a request flood error:
In this case the request has to be resend after a certain waiting period. In this case the request has to be resend after a certain waiting period.
### E9999 ### E999
if code is E999 some other critical error has happened if code is E999 some other critical error has happened
@@ -117,10 +122,16 @@ if code is E001 if the return create/cancel/check calls is not an array
### C001 ### C001
fif code is C001 curl failed to init fif code is C001 curl failed to init
### C002 ### C002
if code is C002 a curl error has happened if code is C002 a curl error has happened
### J-number
if a JSON error was encountered during some encoding this error will be found.
The number is the json error code.
### empty error code ### empty error code
any other NON amazon error will have only 'message' set if run through decode any other NON amazon error will have only 'message' set if run through decode
@@ -132,6 +143,7 @@ If AWS_DEBUG is set to 1 and internal array will be written with debug info.
The gulleek\AmazonIncentives\Debug\AmazonDebug class handles all this. The gulleek\AmazonIncentives\Debug\AmazonDebug class handles all this.
In the gulleek\AmazonIncentives\AmazonIncentives main class the debugger gets set In the gulleek\AmazonIncentives\AmazonIncentives main class the debugger gets set
* setDebug that turns debugger on/off and if on sets unique id (getId to check) * setDebug that turns debugger on/off and if on sets unique id (getId to check)
New entries can be written with New entries can be written with

View File

@@ -20,5 +20,15 @@
"minimum-stability": "dev", "minimum-stability": "dev",
"require": { "require": {
"php": ">=7.4.0" "php": ">=7.4.0"
} },
"archive": {
"exclude": ["/test/", "/test/*", "/phpstan.neon", "/psalm.xml", "/.phan/", "/.vscode/", "/phpunit.xml"]
},
"require-dev": {
"phpunit/phpunit": "^9",
"gullevek/dotenv": "dev-master",
"dg/bypass-finals": "dev-master",
"phpstan/phpstan": "2.1.x-dev",
"phpstan/phpstan-deprecation-rules": "2.0.x-dev"
}
} }

View File

@@ -1,15 +1,11 @@
# PHP Stan Config # PHP Stan Config
parameters: parameters:
tmpDir: /tmp/phpstan-codeblocks-amazon-incentives tmpDir: %currentWorkingDirectory%/tmp/phpstan-codeblocks-amazon-incentives
level: max level: 9
paths: paths:
- %currentWorkingDirectory% - %currentWorkingDirectory%/src
excludes_analyse: excludePaths:
# ignore composer # ignore composer
- vendor - vendor
# ignore errores with - test
ignoreErrors:
-
message: '#Strict comparison using === between false and true will always evaluate to false.#'
path: %currentWorkingDirectory%/test/aws_gift_card_tests.php

14
phpunit.xml Normal file
View File

@@ -0,0 +1,14 @@
<phpunit
colors="true"
verbose="false"
>
<!-- Below removes final from classes for mock tests -->
<extensions>
<extension class="test\phpUnit\Hook\BypassFinalHook" file="test/phpUnit/Hook/BypassFinalHook.php" />
</extensions>
<testsuites>
<testsuite name="unit">
<directory>test/phpUnit/</directory>
</testsuite>
</testsuites>
</phpunit>

16
psalm.xml Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<psalm
errorLevel="8"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="." />
<ignoreFiles>
<directory name="vendor" />
<directory name="test" />
</ignoreFiles>
</projectFiles>
</psalm>

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\AWS; namespace gullevek\AmazonIncentives\AWS;
use gullevek\AmazonIncentives\Client\Client; use gullevek\AmazonIncentives\Client\Client;
@@ -9,444 +11,532 @@ use gullevek\AmazonIncentives\Debug\AmazonDebug;
use gullevek\AmazonIncentives\Response\CancelResponse; use gullevek\AmazonIncentives\Response\CancelResponse;
use gullevek\AmazonIncentives\Response\CreateBalanceResponse; use gullevek\AmazonIncentives\Response\CreateBalanceResponse;
use gullevek\AmazonIncentives\Response\CreateResponse; use gullevek\AmazonIncentives\Response\CreateResponse;
use gullevek\AmazonIncentives\Handle\Json;
class AWS class AWS
{ {
public const SERVICE_NAME = 'AGCODService'; /** @var string What AWS Service to use: Gift Card on Demand (GCOD) */
public const ACCEPT_HEADER = 'accept'; public const SERVICE_NAME = 'AGCODService';
public const CONTENT_HEADER = 'content-type'; /** @var string */
public const HOST_HEADER = 'host'; public const ACCEPT_HEADER = 'accept';
public const X_AMZ_DATE_HEADER = 'x-amz-date'; /** @var string content-type */
public const X_AMZ_TARGET_HEADER = 'x-amz-target'; public const CONTENT_HEADER = 'content-type';
public const AUTHORIZATION_HEADER = 'Authorization'; /** @var string */
public const AWS_SHA256_ALGORITHM = 'AWS4-HMAC-SHA256'; public const HOST_HEADER = 'host';
public const KEY_QUALIFIER = 'AWS4'; /** @var string */
public const TERMINATION_STRING = 'aws4_request'; public const X_AMZ_DATE_HEADER = 'x-amz-date';
public const CREATE_GIFT_CARD_SERVICE = 'CreateGiftCard'; /** @var string */
public const CANCEL_GIFT_CARD_SERVICE = 'CancelGiftCard'; public const X_AMZ_TARGET_HEADER = 'x-amz-target';
public const GET_AVAILABLE_FUNDS_SERVICE = 'GetAvailableFunds'; /** @var string */
public const AUTHORIZATION_HEADER = 'Authorization';
/** @var string type of encryption type */
public const AWS_SHA256_ALGORITHM = 'AWS4-HMAC-SHA256';
/** @var string key type to use */
public const KEY_QUALIFIER = 'AWS4';
/** @var string */
public const TERMINATION_STRING = 'aws4_request';
/** @var string Service to use: Create Gift Card */
public const CREATE_GIFT_CARD_SERVICE = 'CreateGiftCard';
/** @var string Service to use: Cancle Gift Card */
public const CANCEL_GIFT_CARD_SERVICE = 'CancelGiftCard';
/** @var string Service to use: Get Available Funds */
public const GET_AVAILABLE_FUNDS_SERVICE = 'GetAvailableFunds';
/** /** @var Config Configuration class with all settings */
* @var Config private $config;
*/
private $config;
/** /**
* @param Config $config * Initialize the main AWS class. This class prepares and sends all the actions
*/ * and returns reponses as defined in in the CreateResponse class
public function __construct(Config $config) *
{ * @param Config $config
$this->config = $config; */
AmazonDebug::writeLog([__METHOD__ => date('Y-m-d H:m:s.u')]); public function __construct(Config $config)
} {
$this->config = $config;
AmazonDebug::writeLog([__METHOD__ => date('Y-m-d H:m:s.u')]);
}
/** /**
* @param float $amount * Bug a gift card
* @param string|null $creation_id *
* @return CreateResponse * @param float $amount Amount to buy a gifr card in set currencty
* * @param string|null $creation_id Override creation id, if not set will
* @throws AmazonErrors * be created automatically. If not valid error
*/ * will be thrown
public function getCode(float $amount, ?string $creation_id = null): CreateResponse * @return CreateResponse Object with AWS response data
{ *
$service_operation = self::CREATE_GIFT_CARD_SERVICE; * @throws AmazonErrors
$payload = $this->getGiftCardPayload($amount, $creation_id); */
$canonical_request = $this->getCanonicalRequest($service_operation, $payload); public function getCode(float $amount, ?string $creation_id = null): CreateResponse
$date_time_string = $this->getTimestamp(); {
AmazonDebug::writeLog(['call' => __METHOD__]); $service_operation = self::CREATE_GIFT_CARD_SERVICE;
$result = json_decode($this->makeRequest( $payload = $this->getGiftCardPayload($amount, $creation_id);
$payload, $canonical_request = $this->getCanonicalRequest($service_operation, $payload);
$canonical_request, $date_time_string = $this->getTimestamp();
$service_operation, AmazonDebug::writeLog(['call' => __METHOD__]);
$date_time_string $result = Json::jsonDecode($this->makeRequest(
), true); $payload,
return new CreateResponse($result); $canonical_request,
} $service_operation,
$date_time_string
));
return new CreateResponse($result);
}
/** /**
* @param string $creation_request_id * Cancle an ordered gift card, only possible within the the time limit
* @param string $gift_card_id *
* @return CancelResponse * @param string $creation_request_id Previously created creation request id
* * @param string $gift_card_id Previously created gift card id
* @throws AmazonErrors * @return CancelResponse Object with AWS response data
*/ *
public function cancelCode(string $creation_request_id, string $gift_card_id): CancelResponse * @throws AmazonErrors
{ */
$service_operation = self::CANCEL_GIFT_CARD_SERVICE; public function cancelCode(string $creation_request_id, string $gift_card_id): CancelResponse
$payload = $this->getCancelGiftCardPayload($creation_request_id, $gift_card_id); {
$canonical_request = $this->getCanonicalRequest($service_operation, $payload); $service_operation = self::CANCEL_GIFT_CARD_SERVICE;
$date_time_string = $this->getTimestamp(); $payload = $this->getCancelGiftCardPayload($creation_request_id, $gift_card_id);
AmazonDebug::writeLog(['call' => __METHOD__]); $canonical_request = $this->getCanonicalRequest($service_operation, $payload);
$result = json_decode($this->makeRequest( $date_time_string = $this->getTimestamp();
$payload, AmazonDebug::writeLog(['call' => __METHOD__]);
$canonical_request, $result = Json::jsonDecode($this->makeRequest(
$service_operation, $payload,
$date_time_string $canonical_request,
), true); $service_operation,
return new CancelResponse($result); $date_time_string
} ));
return new CancelResponse($result);
}
/** /**
* @return CreateBalanceResponse * Get current account funds
* *
* @throws AmazonErrors * @return CreateBalanceResponse Object with AWS response data
*/ *
public function getBalance(): CreateBalanceResponse * @throws AmazonErrors
{ */
$service_operation = self::GET_AVAILABLE_FUNDS_SERVICE; public function getBalance(): CreateBalanceResponse
$payload = $this->getAvailableFundsPayload(); {
$canonical_request = $this->getCanonicalRequest($service_operation, $payload); $service_operation = self::GET_AVAILABLE_FUNDS_SERVICE;
$date_time_string = $this->getTimestamp(); $payload = $this->getAvailableFundsPayload();
AmazonDebug::writeLog(['call' => __METHOD__]); $canonical_request = $this->getCanonicalRequest($service_operation, $payload);
$result = json_decode($this->makeRequest( $date_time_string = $this->getTimestamp();
$payload, AmazonDebug::writeLog(['call' => __METHOD__]);
$canonical_request, $result = Json::jsonDecode($this->makeRequest(
$service_operation, $payload,
$date_time_string $canonical_request,
), true); $service_operation,
return new CreateBalanceResponse($result); $date_time_string
} ));
return new CreateBalanceResponse($result);
}
/** /**
* @param string $payload * return a new curl connection client class
* @param string $canonical_request *
* @param string $service_operation * @return Client Curl connection Client
* @param string $date_time_string */
* @return string public function newClient(): Client
*/ {
public function makeRequest( return new Client();
string $payload, }
string $canonical_request,
string $service_operation,
string $date_time_string
): string {
// debug
AmazonDebug::writeLog([__METHOD__ => [
'Operation' => $service_operation,
'Payload' => $payload,
'Cannonical Request' => $canonical_request,
'Date Time String' => $date_time_string
]]); /**
$KEY_QUALIFIER = self::KEY_QUALIFIER; * General request method for all actions
$canonical_request_hash = $this->buildHash($canonical_request); * Calls the Client class that actually runs the json request
$string_to_sign = $this->buildStringToSign($canonical_request_hash); * For service_operation valid data see AWS GCOD documentation
$authorization_value = $this->buildAuthSignature($string_to_sign); *
* @param string $payload The data needed for this request
* @param string $canonical_request Header data to send for this request
* @param string $service_operation Service operation. CREATE_GIFT_CARD_SERVICE,
* CANCEL_GIFT_CARD_SERVICE or
* GET_AVAILABLE_FUNDS_SERVICE constant values
* @param string $date_time_string Ymd\THis\Z encoded timestamp, getTimestamp()
* @return string Request result as string, json data
*/
public function makeRequest(
string $payload,
string $canonical_request,
string $service_operation,
string $date_time_string
): string {
// debug
AmazonDebug::writeLog([__METHOD__ => [
'Operation' => $service_operation,
'Payload' => $payload,
'Cannonical Request' => $canonical_request,
'Date Time String' => $date_time_string
$secret_key = $this->config->getSecret(); ]]);
$endpoint = $this->config->getEndpoint(); $KEY_QUALIFIER = self::KEY_QUALIFIER;
$region_name = $this->getRegion(); $canonical_request_hash = $this->buildHash($canonical_request);
$string_to_sign = $this->buildStringToSign($canonical_request_hash);
$authorization_value = $this->buildAuthSignature($string_to_sign);
$SERVICE_NAME = 'AGCODService'; $secret_key = $this->config->getSecret();
$service_target = 'com.amazonaws.agcod.' . $SERVICE_NAME . '.' . $service_operation; $endpoint = $this->config->getEndpoint();
$date_string = $this->getDateString(); $region_name = $this->getRegion();
$signature_aws_key = $KEY_QUALIFIER . $secret_key; $SERVICE_NAME = 'AGCODService';
$service_target = 'com.amazonaws.agcod.' . $SERVICE_NAME . '.' . $service_operation;
$date_string = $this->getDateString();
$k_date = $this->hmac($date_string, $signature_aws_key); $signature_aws_key = $KEY_QUALIFIER . $secret_key;
$k_date_hexis = $this->hmac($date_string, $signature_aws_key, false);
$k_region = $this->hmac($region_name, $k_date);
$k_region_hexis = $this->hmac($region_name, $k_date, false);
$k_service_hexis = $this->hmac($SERVICE_NAME, $k_region, false);
AmazonDebug::writeLog([__METHOD__ => [ $k_date = $this->hmac($date_string, $signature_aws_key);
'Date' => $k_date_hexis, $k_date_hexis = $this->hmac($date_string, $signature_aws_key, false);
'Region' => $k_region_hexis, $k_region = $this->hmac($region_name, $k_date);
'Service' => $k_service_hexis, $k_region_hexis = $this->hmac($region_name, $k_date, false);
]]); $k_service_hexis = $this->hmac($SERVICE_NAME, $k_region, false);
$url = 'https://' . (string)$endpoint . '/' . $service_operation; AmazonDebug::writeLog([__METHOD__ => [
$headers = $this->buildHeaders($payload, $authorization_value, $date_time_string, $service_target); 'Date' => $k_date_hexis,
return (new Client())->request($url, $headers, $payload); 'Region' => $k_region_hexis,
} 'Service' => $k_service_hexis,
]]);
/** $url = 'https://' . $endpoint . '/' . $service_operation;
* @param string $payload $headers = $this->buildHeaders(
* @param string $authorization_value $payload,
* @param string $date_time_string $authorization_value,
* @param string $service_target $date_time_string,
* @return array<mixed> $service_target
*/ );
public function buildHeaders( return ($this->newClient())->request($url, $headers, $payload);
string $payload, }
string $authorization_value,
string $date_time_string,
string $service_target
): array {
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER;
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER;
$AUTHORIZATION_HEADER = self::AUTHORIZATION_HEADER;
return [
'Content-Type:' . $this->getContentType(),
'Content-Length: ' . strlen($payload),
$AUTHORIZATION_HEADER . ':' . $authorization_value,
$X_AMZ_DATE_HEADER . ':' . $date_time_string,
$X_AMZ_TARGET_HEADER . ':' . $service_target,
$ACCEPT_HEADER . ':' . $this->getContentType()
];
}
/** /**
* @param string $string_to_sign * Build the headers used in the makeRequest method.
* @return string * These are the HTML headers used with curl
*/ *
public function buildAuthSignature(string $string_to_sign): string * @param string $payload Paylout to create this header for
{ * @param string $authorization_value Auth string
$AWS_SHA256_ALGORITHM = self::AWS_SHA256_ALGORITHM; * @param string $date_time_string Ymd\THis\Z encoded timestamp, getTimestamp()
$SERVICE_NAME = self::SERVICE_NAME; * @param string $service_target Target service in the agcod string:
$TERMINATION_STRING = self::TERMINATION_STRING; * Value like com.amazonaws.agcod.<sn>.<so>
$ACCEPT_HEADER = self::ACCEPT_HEADER; * @return array<int,string> Header data as array for curl request
$HOST_HEADER = self::HOST_HEADER; */
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER; public function buildHeaders(
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER; string $payload,
string $authorization_value,
string $date_time_string,
string $service_target
): array {
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER;
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER;
$AUTHORIZATION_HEADER = self::AUTHORIZATION_HEADER;
return [
'Content-Type:' . $this->getContentType(),
'Content-Length: ' . strlen($payload),
$AUTHORIZATION_HEADER . ':' . $authorization_value,
$X_AMZ_DATE_HEADER . ':' . $date_time_string,
$X_AMZ_TARGET_HEADER . ':' . $service_target,
$ACCEPT_HEADER . ':' . $this->getContentType()
];
}
$aws_key_id = $this->config->getAccessKey(); /**
$region_name = $this->getRegion(); * The request string build with the actauly request data created by
* getCanonicalRequest(). This string is used in the auth signature call
*
* @param string $canonical_request_hash sha256 hash to build from
* @return string String to send to buildAuthSignature()
*/
public function buildStringToSign($canonical_request_hash): string
{
$AWS_SHA256_ALGORITHM = self::AWS_SHA256_ALGORITHM;
$TERMINATION_STRING = self::TERMINATION_STRING;
$SERVICE_NAME = self::SERVICE_NAME;
$region_name = $this->getRegion();
$date_time_string = $this->getTimestamp();
$date_string = $this->getDateString();
$string_to_sign = "$AWS_SHA256_ALGORITHM\n"
. "$date_time_string\n"
. "$date_string/$region_name/$SERVICE_NAME/$TERMINATION_STRING\n"
. "$canonical_request_hash";
$date_string = $this->getDateString(); return $string_to_sign;
$derived_key = $this->buildDerivedKey(); }
// Calculate signature per http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
$final_signature = $this->hmac($string_to_sign, $derived_key, false);
// Assemble Authorization Header with signing information /**
// per http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html * Build the authentication signature used in the buildHeaders method
$authorization_value = *
$AWS_SHA256_ALGORITHM * @param string $string_to_sign Data to sign, buildStringToSign()
. ' Credential=' . $aws_key_id * @return string Authorized value as string
. '/' . $date_string . '/' . $region_name . '/' . $SERVICE_NAME . '/' . $TERMINATION_STRING . ',' */
. ' SignedHeaders=' public function buildAuthSignature(string $string_to_sign): string
. $ACCEPT_HEADER . ';' . $HOST_HEADER . ';' . $X_AMZ_DATE_HEADER . ';' . $X_AMZ_TARGET_HEADER . ',' {
. ' Signature=' $AWS_SHA256_ALGORITHM = self::AWS_SHA256_ALGORITHM;
. $final_signature; $SERVICE_NAME = self::SERVICE_NAME;
$TERMINATION_STRING = self::TERMINATION_STRING;
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$HOST_HEADER = self::HOST_HEADER;
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER;
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER;
return $authorization_value; $aws_key_id = $this->config->getAccessKey();
} $region_name = $this->getRegion();
/** $date_string = $this->getDateString();
* @param string $canonical_request_hash $derived_key = $this->buildDerivedKey();
* @return string // Calculate signature per http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
*/ $final_signature = $this->hmac($string_to_sign, $derived_key, false);
public function buildStringToSign($canonical_request_hash): string
{
$AWS_SHA256_ALGORITHM = self::AWS_SHA256_ALGORITHM;
$TERMINATION_STRING = self::TERMINATION_STRING;
$SERVICE_NAME = self::SERVICE_NAME;
$region_name = $this->getRegion();
$date_time_string = $this->getTimestamp();
$date_string = $this->getDateString();
$string_to_sign = "$AWS_SHA256_ALGORITHM\n"
. "$date_time_string\n"
. "$date_string/$region_name/$SERVICE_NAME/$TERMINATION_STRING\n"
. "$canonical_request_hash";
return $string_to_sign; // Assemble Authorization Header with signing information
} // per http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
$authorization_value =
$AWS_SHA256_ALGORITHM
. ' Credential=' . $aws_key_id
. '/' . $date_string . '/' . $region_name . '/' . $SERVICE_NAME . '/' . $TERMINATION_STRING . ','
. ' SignedHeaders='
. $ACCEPT_HEADER . ';' . $HOST_HEADER . ';' . $X_AMZ_DATE_HEADER . ';' . $X_AMZ_TARGET_HEADER . ','
. ' Signature='
. $final_signature;
/** return $authorization_value;
* @param bool $rawOutput }
* @return string
*/
public function buildDerivedKey(bool $rawOutput = true): string
{
$KEY_QUALIFIER = self::KEY_QUALIFIER;
$TERMINATION_STRING = self::TERMINATION_STRING;
$SERVICE_NAME = self::SERVICE_NAME;
$aws_secret_key = $this->config->getSecret(); /**
// Append Key Qualifier, "AWS4", to secret key per * Build the derived key to build the final hmac signature string
// shttp://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html *
$signature_aws_key = $KEY_QUALIFIER . $aws_secret_key; * @param bool $rawOutput Set to true to create the hash based message
$region_name = $this->getRegion(); * authenticator string as normal text string or
$date_string = $this->getDateString(); * lowercase hexbits
* @return string Derived key (hmac type)
*/
public function buildDerivedKey(bool $rawOutput = true): string
{
$KEY_QUALIFIER = self::KEY_QUALIFIER;
$TERMINATION_STRING = self::TERMINATION_STRING;
$SERVICE_NAME = self::SERVICE_NAME;
$k_date = $this->hmac($date_string, $signature_aws_key); $aws_secret_key = $this->config->getSecret();
$k_region = $this->hmac($region_name, $k_date); // Append Key Qualifier, "AWS4", to secret key per
$k_service = $this->hmac($SERVICE_NAME, $k_region); // shttp://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
$signature_aws_key = $KEY_QUALIFIER . $aws_secret_key;
$region_name = $this->getRegion();
$date_string = $this->getDateString();
// Derived the Signing key (derivedKey aka kSigning) $k_date = $this->hmac($date_string, $signature_aws_key);
return $this->hmac($TERMINATION_STRING, $k_service, $rawOutput); $k_region = $this->hmac($region_name, $k_date);
} $k_service = $this->hmac($SERVICE_NAME, $k_region);
/** // Derived the Signing key (derivedKey aka kSigning)
* get the region based on endpoint return $this->hmac($TERMINATION_STRING, $k_service, $rawOutput);
* list as of 2021/10/20 }
* WHERE URL REGION
* North America https://agcod-v2-gamma.amazon.com us-east-1
* https://agcod-v2.amazon.com
* (US, CA, MX)
* Europe and Asia https://agcod-v2-eu-gamma.amazon.com eu-west-1
* https://agcod-v2-eu.amazon.com
* (IT, ES, DE, FR, UK, TR, UAE, KSA, PL, NL, SE)
* Far East https://agcod-v2-fe-gamma.amazon.com us-west-2
* https://agcod-v2-fe.amazon.com
* (JP, AU, SG)
*
* CURRENCY
* USD for US
* EUR for EU (IT, ES, DE, FR, PL, NL, SE)
* JPY for JP
* CAD for CA
* AUD for AU
* TRY for TR
* AED for UAE
* MXN for MX
* GBP for UK
*
* @return string
*/
public function getRegion(): string
{
$endpoint = $this->config->getEndpoint();
// default region
$region_name = 'us-east-1';
switch ($endpoint) { /**
case 'agcod-v2.amazon.com': * get the region based on endpoint
case 'agcod-v2-gamma.amazon.com': * list as of 2021/10/20
$region_name = 'us-east-1'; * WHERE URL REGION
break; * North America https://agcod-v2-gamma.amazon.com us-east-1
case 'agcod-v2-eu.amazon.com': * https://agcod-v2.amazon.com
case 'agcod-v2-eu-gamma.amazon.com': * (US, CA, MX)
$region_name = 'us-west-1'; * Europe and Asia https://agcod-v2-eu-gamma.amazon.com eu-west-1
break; * https://agcod-v2-eu.amazon.com
case 'agcod-v2-fe.amazon.com': * (IT, ES, DE, FR, UK, TR, UAE, KSA, PL, NL, SE)
case 'agcod-v2-fe-gamma.amazon.com': * Far East https://agcod-v2-fe-gamma.amazon.com us-west-2
$region_name = 'us-west-2'; * https://agcod-v2-fe.amazon.com
break; * (JP, AU, SG)
} *
return $region_name; * CURRENCY
} * USD for US
* EUR for EU (IT, ES, DE, FR, PL, NL, SE)
* JPY for JP
* CAD for CA
* AUD for AU
* TRY for TR
* AED for UAE
* MXN for MX
* GBP for UK
*
* @return string Region string depending on given endpoint url
*/
public function getRegion(): string
{
$endpoint = $this->config->getEndpoint();
// default region
$region_name = 'us-east-1';
switch ($endpoint) {
case 'agcod-v2.amazon.com':
case 'agcod-v2-gamma.amazon.com':
$region_name = 'us-east-1';
break;
case 'agcod-v2-eu.amazon.com':
case 'agcod-v2-eu-gamma.amazon.com':
$region_name = 'eu-west-1';
break;
case 'agcod-v2-fe.amazon.com':
case 'agcod-v2-fe-gamma.amazon.com':
$region_name = 'us-west-2';
break;
}
return $region_name;
}
/** /**
* @param float $amount * The actual data to send as json encoded string for creating a gift card.
* @param string|null $creation_id * The creation request id must be in the format:
* @return string * <partner_id>_<unique id 13 characters>
*/ *
public function getGiftCardPayload(float $amount, ?string $creation_id = null): string * @param float $amount Amount of currencty to create the gift card
{ * request for
$payload = [ * @param string|null $creation_id The creation id, if not set will be created here
'creationRequestId' => $creation_id ?: uniqid($this->config->getPartner() . '_'), * @return string JSON encoded array to be used as payload
'partnerId' => $this->config->getPartner(), * in get gift card call
'value' => */
[ public function getGiftCardPayload(float $amount, ?string $creation_id = null): string
'currencyCode' => $this->config->getCurrency(), {
'amount' => (float)$amount $payload = [
] 'creationRequestId' => $creation_id ?: uniqid($this->config->getPartner() . '_'),
]; 'partnerId' => $this->config->getPartner(),
return (json_encode($payload)) ?: ''; 'value' =>
} [
'currencyCode' => $this->config->getCurrency(),
'amount' => $amount
]
];
return (json_encode($payload)) ?: '';
}
/** /**
* @param string $creation_request_id * The actual data to send as json encoded string to cancel a created gift card
* @param string $gift_card_id *
* @return string * @param string $creation_request_id Creation request id from previous get gift card
*/ * @param string $gift_card_id Gift card id from previous get gift card
public function getCancelGiftCardPayload(string $creation_request_id, string $gift_card_id): string * @return string JSON encoded array to be used as payload
{ * in cancle gift card call
$payload = [ */
'creationRequestId' => $creation_request_id, public function getCancelGiftCardPayload(string $creation_request_id, string $gift_card_id): string
'partnerId' => $this->config->getPartner(), {
'gcId' => $gift_card_id $payload = [
]; 'creationRequestId' => $creation_request_id,
return (json_encode($payload)) ?: ''; 'partnerId' => $this->config->getPartner(),
} 'gcId' => $gift_card_id
];
return (json_encode($payload)) ?: '';
}
/** /**
* @return string * The actualy data to send as json encoded string for getting the current
*/ * account funds
public function getAvailableFundsPayload(): string *
{ * @return string JSON encoded array to be used as payload in funds call
$payload = [ */
'partnerId' => $this->config->getPartner(), public function getAvailableFundsPayload(): string
]; {
return (json_encode($payload)) ?: ''; $payload = [
} 'partnerId' => $this->config->getPartner(),
];
return (json_encode($payload)) ?: '';
}
/** /**
* @param string $service_operation * Heeders used in the getCanonicalRequest()
* @param string $payload *
* @return string * @param string $service_operation Service operation code in the service string request
*/ * Value is: com.amazonaws.agcod.AGCODService.<so>
public function getCanonicalRequest(string $service_operation, string $payload): string * @return string Header string to be used
{ */
$HOST_HEADER = self::HOST_HEADER; public function buildCanonicalHeaders(string $service_operation): string
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER; {
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER; $ACCEPT_HEADER = self::ACCEPT_HEADER;
$ACCEPT_HEADER = self::ACCEPT_HEADER; $HOST_HEADER = self::HOST_HEADER;
$payload_hash = $this->buildHash($payload); $X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER;
$canonical_headers = $this->buildCanonicalHeaders($service_operation); $X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER;
$canonical_request = "POST\n" $date_time_string = $this->getTimestamp();
. "/$service_operation\n\n" $endpoint = $this->config->getEndpoint();
. "$canonical_headers\n\n" $content_type = $this->getContentType();
. "$ACCEPT_HEADER;$HOST_HEADER;$X_AMZ_DATE_HEADER;$X_AMZ_TARGET_HEADER\n" return "$ACCEPT_HEADER:$content_type\n"
. "$payload_hash"; . "$HOST_HEADER:$endpoint\n"
return $canonical_request; . "$X_AMZ_DATE_HEADER:$date_time_string\n"
} . "$X_AMZ_TARGET_HEADER:com.amazonaws.agcod.AGCODService.$service_operation";
}
/** /**
* @param string $data * Headers used in the get/cancel/funds requests
* @return string *
*/ * @param string $service_operation Service operation code to be used in header request
public function buildHash(string $data): string * and main request call
{ * @param string $payload Payload from get/cancle Code or funds call
return hash('sha256', $data); * @return string Full POST service request code
} */
public function getCanonicalRequest(string $service_operation, string $payload): string
{
$HOST_HEADER = self::HOST_HEADER;
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER;
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER;
$ACCEPT_HEADER = self::ACCEPT_HEADER;
$payload_hash = $this->buildHash($payload);
$canonical_headers = $this->buildCanonicalHeaders($service_operation);
$canonical_request = "POST\n"
. "/$service_operation\n\n"
. "$canonical_headers\n\n"
. "$ACCEPT_HEADER;$HOST_HEADER;$X_AMZ_DATE_HEADER;$X_AMZ_TARGET_HEADER\n"
. "$payload_hash";
return $canonical_request;
}
/** /**
* @return string * Build sha256 hash from given data
*/ *
public function getTimestamp() * @param string $data Data to be hashed with sha256
{ * @return string sha256 hash
return gmdate('Ymd\THis\Z'); */
} public function buildHash(string $data): string
{
return hash('sha256', $data);
}
/** /**
* @param string $data * Create a sha256 based Hash-Based Message Authentication Code
* @param string $key * with the given key and data
* @param bool $raw *
* @return string * @param string $data Data to be hashed with key below
*/ * @param string $key Key to be used for creating the hash
public function hmac(string $data, string $key, bool $raw = true): string * @param bool $raw Returning data as ascii string or hexibits
{ * @return string Hash-Based Message Authentication Code
return hash_hmac('sha256', $data, $key, $raw); */
} public function hmac(string $data, string $key, bool $raw = true): string
{
return hash_hmac('sha256', $data, $key, $raw);
}
/** /**
* @return string * Build timestamp in the format used by AWS services
*/ * eg 20211009\T102030\Z
public function getDateString() *
{ * @return string date string based on current time. Ymd\THis\Z
return substr($this->getTimestamp(), 0, 8); */
} public function getTimestamp()
{
return gmdate('Ymd\THis\Z');
}
/** /**
* @return string * Get only the date string from the getTimestamp
*/ * eg 20211009
public function getContentType(): string *
{ * @return string Date string YYYYmmdd extracted from getTimestamp()
return 'application/json'; */
} public function getDateString()
{
return substr($this->getTimestamp(), 0, 8);
}
/** /**
* @param string $service_operation * Fixed content type for submission, is json
* @return string *
*/ * @return string 'application/json' string
public function buildCanonicalHeaders(string $service_operation): string */
{ public function getContentType(): string
$ACCEPT_HEADER = self::ACCEPT_HEADER; {
$HOST_HEADER = self::HOST_HEADER; return 'application/json';
$X_AMZ_DATE_HEADER = self::X_AMZ_DATE_HEADER; }
$X_AMZ_TARGET_HEADER = self::X_AMZ_TARGET_HEADER;
$date_time_string = $this->getTimestamp();
$endpoint = $this->config->getEndpoint();
$content_type = $this->getContentType();
return "$ACCEPT_HEADER:$content_type\n"
. "$HOST_HEADER:$endpoint\n"
. "$X_AMZ_DATE_HEADER:$date_time_string\n"
. "$X_AMZ_TARGET_HEADER:com.amazonaws.agcod.AGCODService.$service_operation";
}
} }
// __END__ // __END__

View File

@@ -14,141 +14,158 @@ use gullevek\AmazonIncentives\Debug\AmazonDebug;
final class AmazonIncentives final class AmazonIncentives
{ {
/** /**
* @var Config * @var Config
*/ */
private $config; private $config;
/** /**
* AmazonGiftCode constructor. * AmazonGiftCode constructor.
* *
* @param string|null $key * @param string|null $key Account key
* @param string|null $secret * @param string|null $secret Secret key
* @param string|null $partner * @param string|null $partner Partner ID
* @param string|null $endpoint * @param string|null $endpoint Endpoint URL including https://
* @param string|null $currency * @param string|null $currency Currency type. Eg USD, JPY, etc
* @param bool|null $debug * @param bool|null $debug Debug flag
*/ */
public function __construct( public function __construct(
string $key = null, ?string $key = null,
string $secret = null, ?string $secret = null,
string $partner = null, ?string $partner = null,
string $endpoint = null, ?string $endpoint = null,
string $currency = null, ?string $currency = null,
bool $debug = null ?bool $debug = null
) { ) {
// load AWS settings // load AWS settings
// fail here if settings missing // fail here if settings missing
$this->config = new Config($key, $secret, $partner, $endpoint, $currency, $debug); $this->config = new Config($key, $secret, $partner, $endpoint, $currency, $debug);
// init debug // init debug
AmazonDebug::setDebug($this->config->getDebug()); AmazonDebug::setDebug($this->config->getDebug());
} }
// ********************************************************************* // *********************************************************************
// PRIVATE HELPER METHODS // PRIVATE HELPER METHODS
// ********************************************************************* // *********************************************************************
// ********************************************************************* // *********************************************************************
// PUBLIC METHODS // PUBLIC METHODS
// ********************************************************************* // *********************************************************************
/** /**
* @param float $value * Buy a gift card
* @param string|null $creation_request_id AWS creationRequestId *
* @return Response\CreateResponse * @param float $value Amount to purchase a gift card
* * in currency value
* @throws AmazonErrors * @param string|null $creation_request_id Override automatically created request id
*/ * If not set will create a new one, or
public function buyGiftCard(float $value, string $creation_request_id = null): Response\CreateResponse * return data for created one
{ * @return Response\CreateResponse Returns new created response object or
return (new AWS($this->config))->getCode($value, $creation_request_id); * previous created if creation_request_id was used
} *
* @throws AmazonErrors
*/
public function buyGiftCard(float $value, ?string $creation_request_id = null): Response\CreateResponse
{
return ($this->newAWS())->getCode($value, $creation_request_id);
}
/** /**
* @param string $creation_request_id AWS creationRequestId * Cancel a previous created gift card, if within the time frame
* @param string $gift_card_id AWS gcId *
* @return Response\CancelResponse * @param string $creation_request_id Previous created request id from buyGiftCard
*/ * @param string $gift_card_id Previous gift card id from buyGiftCard (gcId)
public function cancelGiftCard(string $creation_request_id, string $gift_card_id): Response\CancelResponse * @return Response\CancelResponse Returns the cancled request object
{ *
return (new AWS($this->config))->cancelCode($creation_request_id, $gift_card_id); * @throws AmazonErrors
} */
public function cancelGiftCard(string $creation_request_id, string $gift_card_id): Response\CancelResponse
{
return ($this->newAWS())->cancelCode($creation_request_id, $gift_card_id);
}
/** /**
* @return Response\CreateBalanceResponse * Gets the current funds in this account
* *
* @throws AmazonErrors * @return Response\CreateBalanceResponse Returns the account funds object
*/ *
public function getAvailableFunds(): Response\CreateBalanceResponse * @throws AmazonErrors
{ */
return (new AWS($this->config))->getBalance(); public function getAvailableFunds(): Response\CreateBalanceResponse
} {
return ($this->newAWS())->getBalance();
}
/** /**
* AmazonIncentives make own client. * AmazonIncentives creates own client and returns it as static object
* *
* @param string|null $key * @param string|null $key Account key
* @param string|null $secret * @param string|null $secret Secret key
* @param string|null $partner * @param string|null $partner Partner ID
* @param string|null $endpoint * @param string|null $endpoint Endpoint URL including https://
* @param string|null $currency * @param string|null $currency Currency type. Eg USD, JPY, etc
* @param bool|null $debug * @param bool|null $debug Debug flag
* @return AmazonIncentives * @return AmazonIncentives self class
*/ */
public static function make( public static function make(
string $key = null, ?string $key = null,
string $secret = null, ?string $secret = null,
string $partner = null, ?string $partner = null,
string $endpoint = null, ?string $endpoint = null,
string $currency = null, ?string $currency = null,
bool $debug = null ?bool $debug = null
): AmazonIncentives { ): AmazonIncentives {
return new static($key, $secret, $partner, $endpoint, $currency, $debug); return new static($key, $secret, $partner, $endpoint, $currency, $debug);
} }
/** /**
* Decodes the Exception message body * wrapper to create new AWS class.
* Returns an array with code (Amazon error codes), type (Amazon error info) * used in all buy/cancel/get calss
* message (Amazon returned error message string) *
* * @return AWS Main AWS worker class
* @param string $message Exception message json string */
* @return array<mixed> Decoded with code, type, message fields public function newAWS(): AWS
*/ {
public static function decodeExceptionMessage(string $message): array return new AWS($this->config);
{ }
$message_ar = json_decode($message, true);
// if we have an error, build empty block and only fill message
if (json_last_error()) {
$message_ar = [
'status' => '',
'code' => '',
'type' => '',
'message' => $message,
'log_id' => '',
'log' => []
];
}
return $message_ar;
}
// ********************************************************************* /**
// PUBLIC TEST METHODS * Decodes the Exception message body
// ********************************************************************* * Returns an array with code (Amazon error codes), type (Amazon error info)
* message (Amazon returned error message string)
*
* @param string $message Exception message json string
* @return array<mixed> Decoded with code, type, message fields
*
* @deprecated use \gullevek\AmazonIncentives\Exceptions\AmazonErrors::decodeExceptionMessage()
*/
public static function decodeExceptionMessage(string $message): array
{
return AmazonErrors::decodeExceptionMessage($message);
}
/** // *********************************************************************
* @return array<mixed> // PUBLIC TEST METHODS
*/ // *********************************************************************
public function checkMe(): array
{
$data = [];
$data['ENV'] = $_ENV; /**
$data['CONFIG'] = $this->config; * Prints out ENV, CONFIG and KEY data
$data['KEY'] = $this->config->getAccessKey(); * This is for debug only, this will print out secrets.
* Use with care
*
* @return array<mixed>
*/
public function checkMe(): array
{
$data = [];
return $data; $data['ENV'] = $_ENV;
} $data['CONFIG'] = $this->config;
$data['KEY'] = $this->config->getAccessKey();
return $data;
}
} }
// __END__ // __END__

View File

@@ -1,118 +1,127 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Client; namespace gullevek\AmazonIncentives\Client;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors; use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug; use gullevek\AmazonIncentives\Debug\AmazonDebug;
use gullevek\AmazonIncentives\Handle\Json;
class Client implements ClientInterface class Client implements ClientInterface
{ {
// instead of JsonResponse::HTTP_OK /** @var int instead of JsonResponse::HTTP_OK */
private const HTTP_OK = 200; private const HTTP_OK = 200;
/** /**
* * Makes an request to the target url via curl
* @param string $url The URL being requested, including domain and protocol * Returns result as string (json)
* @param array<mixed> $headers Headers to be used in the request *
* @param array<mixed>|string $params Can be nested for arrays and hashes * @param string $url The URL being requested,
* * including domain and protocol
* * @param array<int,string> $headers Headers to be used in the request
* @return string * @param array<mixed>|string $params Can be nested for arrays and hashes
*/ * @return string Result as json string
public function request(string $url, array $headers, $params): string */
{ public function request(string $url, array $headers, $params): string
$handle = curl_init($url); {
if ($handle === false) { $handle = curl_init($url);
// throw Error here with all codes if ($handle === false) {
throw AmazonErrors::getError( // throw Error here with all codes
'FAILURE', throw AmazonErrors::getError(
'C001', 'FAILURE',
'CurlInitError', 'C001',
'Failed to init curl with url: ' . $url, 'CurlInitError',
0 'Failed to init curl with url: ' . $url,
); 0
} );
curl_setopt($handle, CURLOPT_POST, true); }
curl_setopt($handle, CURLOPT_HTTPHEADER, $headers); curl_setopt($handle, CURLOPT_POST, true);
// curl_setopt($handle, CURLOPT_FAILONERROR, true); curl_setopt($handle, CURLOPT_HTTPHEADER, $headers);
curl_setopt($handle, CURLOPT_POSTFIELDS, $params); // curl_setopt($handle, CURLOPT_FAILONERROR, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($handle, CURLOPT_POSTFIELDS, $params);
$result = curl_exec($handle); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($handle);
if ($result === false) { if ($result === false) {
$err = curl_errno($handle); $err = curl_errno($handle);
$message = curl_error($handle); $message = curl_error($handle);
$this->handleCurlError($url, $err, $message); $this->handleCurlError($url, $err, $message);
} }
if (curl_getinfo($handle, CURLINFO_HTTP_CODE) !== self::HTTP_OK) { if (curl_getinfo($handle, CURLINFO_HTTP_CODE) !== self::HTTP_OK) {
$err = curl_errno($handle); $err = curl_errno($handle);
AmazonDebug::writeLog(['CURL_REQUEST_RESULT' => $result]); AmazonDebug::writeLog(['CURL_REQUEST_RESULT' => $result]);
// extract all the error codes from Amazon // extract all the error codes from Amazon
$result_ar = json_decode((string)$result, true); // note we do not care about result errors here, if json decode fails, just set to empty
// if message is 'Rate exceeded', set different error try {
if (($result_ar['message'] ?? '') == 'Rate exceeded') { $result_ar = Json::jsonDecode((string)$result);
$error_status = 'RESEND'; } catch (AmazonErrors $e) {
$error_code = 'T001'; $result_ar = [];
$error_type = 'RateExceeded'; }
$message = $result_ar['message'] ?? 'Rate exceeded'; // if message is 'Rate exceeded', set different error
} else { if (($result_ar['message'] ?? '') == 'Rate exceeded') {
// for all other error messages $error_status = 'RESEND';
$error_status = $result_ar['agcodResponse']['status'] ?? 'FAILURE'; $error_code = 'T001';
$error_code = $result_ar['errorCode'] ?? 'E999'; $error_type = 'RateExceeded';
$error_type = $result_ar['errorType'] ?? 'OtherUnknownError'; $message = $result_ar['message'] ?? 'Rate exceeded';
$message = $result_ar['message'] ?? 'Unknown error occured'; } else {
} // for all other error messages
// throw Error here with all codes $error_status = $result_ar['agcodResponse']['status'] ?? 'FAILURE';
throw AmazonErrors::getError( $error_code = $result_ar['errorCode'] ?? 'E999';
$error_status, $error_type = $result_ar['errorType'] ?? 'OtherUnknownError';
$error_code, $message = $result_ar['message'] ?? 'Unknown error occured';
$error_type, }
$message, // throw Error here with all codes
$err throw AmazonErrors::getError(
); $error_status,
} $error_code,
return (string)$result; $error_type,
} $message,
$err
);
}
return (string)$result;
}
/** /**
* Undocumented function * handles any CURL errors and throws an error with the correct
* * error message
* @param string $url *
* @param int $errno * @param string $url The url that was originaly used
* @param string $message * @param int $errno Error number from curl handler
* @return void * @param string $message The error message string from curl
*/ * @return void
private function handleCurlError(string $url, int $errno, string $message): void */
{ private function handleCurlError(string $url, int $errno, string $message): void
switch ($errno) { {
case CURLE_COULDNT_CONNECT: switch ($errno) {
case CURLE_COULDNT_RESOLVE_HOST: case CURLE_COULDNT_CONNECT:
case CURLE_OPERATION_TIMEOUTED: case CURLE_COULDNT_RESOLVE_HOST:
$message = 'Could not connect to AWS (' . $url . '). Please check your ' case CURLE_OPERATION_TIMEOUTED:
. 'internet connection and try again. [' . $message . ']'; $message = 'Could not connect to AWS (' . $url . '). Please check your '
break; . 'internet connection and try again. [' . $message . ']';
case CURLE_SSL_CACERT: break;
case CURLE_SSL_PEER_CERTIFICATE: case CURLE_SSL_PEER_CERTIFICATE:
$message = 'Could not verify AWS SSL certificate. Please make sure ' $message = 'Could not verify AWS SSL certificate. Please make sure '
. 'that your network is not intercepting certificates. ' . 'that your network is not intercepting certificates. '
. '(Try going to ' . $url . 'in your browser.) ' . '(Try going to ' . $url . 'in your browser.) '
. '[' . $message . ']'; . '[' . $message . ']';
break; break;
case 0: case 0:
default: default:
$message = 'Unexpected error communicating with AWS: ' . $message; $message = 'Unexpected error communicating with AWS: ' . $message;
} }
// throw an error like in the normal reqeust, but set to CURL error // throw an error like in the normal reqeust, but set to CURL error
throw AmazonErrors::getError( throw AmazonErrors::getError(
'FAILURE', 'FAILURE',
'C002', 'C002',
'CurlError', 'CurlError',
$message, $message,
$errno $errno
); );
} }
} }
// __END__ // __END__

View File

@@ -1,19 +1,20 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Client; namespace gullevek\AmazonIncentives\Client;
interface ClientInterface interface ClientInterface
{ {
/** /**
* @param string $url The URL being requested, * @param string $url The URL being requested,
* including domain and protocol * including domain and protocol
* @param array<mixed> $headers Headers to be used in the request * @param array<mixed> $headers Headers to be used in the request
* @param array<mixed>|string $params Can be nested for arrays and hashes * @param array<mixed>|string $params Can be nested for arrays and hashes
* *
* @return String * @return String
*/ */
public function request(string $url, array $headers, $params): string;
public function request(string $url, array $headers, $params): string;
} }
// __END__ // __END__

View File

@@ -1,199 +1,216 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Config; namespace gullevek\AmazonIncentives\Config;
class Config implements ConfigInterface class Config implements ConfigInterface
{ {
/** /** @var string Endpoint URL without https:// */
* @var string private $endpoint = '';
*/ /** @var string Access Key */
private $endpoint; private $access_key = '';
/** /** @var string Secret Key */
* @var string private $secret_key = '';
*/ /** @var string Partner ID */
private $access_key; private $partner_id = '';
/** /** @var string Currency type as USD, JPY, etc */
* @var string private $currency = '';
*/ /** @var bool Debug flag on or off */
private $secret_key; private $debug = false;
/**
* @var string
*/
private $partner_id;
/**
* @var string
*/
private $currency;
/**
* @var bool
*/
private $debug;
/** /**
* @param string|null $key * @param string|null $key Access key
* @param string|null $secret * @param string|null $secret Secret Key
* @param string|null $partner * @param string|null $partner Partner ID
* @param string|null $endpoint * @param string|null $endpoint Endpoing URL including https://
* @param string|null $currency * @param string|null $currency Currency to use, see valid list on AWS documentation.
*/ * valid names are like USD, JPY, etc
public function __construct( * @param bool|null $debug Debug flag
?string $key, */
?string $secret, public function __construct(
?string $partner, ?string $key,
?string $endpoint, ?string $secret,
?string $currency, ?string $partner,
?bool $debug, ?string $endpoint,
) { ?string $currency,
$this->setAccessKey(($key) ?: $this->parseEnv('AWS_GIFT_CARD_KEY')); /** @phpstan-ignore-line */ ?bool $debug
$this->setSecret(($secret) ?: $this->parseEnv('AWS_GIFT_CARD_SECRET')); /** @phpstan-ignore-line */ ) {
$this->setPartner(($partner) ?: $this->parseEnv('AWS_GIFT_CARD_PARTNER_ID')); /** @phpstan-ignore-line */ /**
$this->setEndpoint(($endpoint) ?: $this->parseEnv('AWS_GIFT_CARD_ENDPOINT')); /** @phpstan-ignore-line */ * @psalm-suppress InvalidScalarArgument
$this->setCurrency(($currency) ?: $this->parseEnv('AWS_GIFT_CARD_CURRENCY')); /** @phpstan-ignore-line */ * @phpstan-ignore-next-line
$this->setDebug(($debug) ?: $this->parseEnv('AWS_DEBUG')); /** @phpstan-ignore-line */ */
} $this->setAccessKey(($key) ?: $this->parseEnv('AWS_GIFT_CARD_KEY'));
/**
* @psalm-suppress InvalidScalarArgument
* @phpstan-ignore-next-line
*/
$this->setSecret(($secret) ?: $this->parseEnv('AWS_GIFT_CARD_SECRET'));
/**
* @psalm-suppress InvalidScalarArgument
* @phpstan-ignore-next-line
*/
$this->setPartner(($partner) ?: $this->parseEnv('AWS_GIFT_CARD_PARTNER_ID'));
/**
* @psalm-suppress InvalidScalarArgument
* @phpstan-ignore-next-line
*/
$this->setEndpoint(($endpoint) ?: $this->parseEnv('AWS_GIFT_CARD_ENDPOINT'));
/**
* @psalm-suppress InvalidScalarArgument
* @phpstan-ignore-next-line
*/
$this->setCurrency(($currency) ?: $this->parseEnv('AWS_GIFT_CARD_CURRENCY'));
/**
* @psalm-suppress InvalidScalarArgument
* @phpstan-ignore-next-line
*/
$this->setDebug(($debug) ?: $this->parseEnv('AWS_DEBUG'));
}
/** /**
* string key to search, returns entry from _ENV * string key to search, returns entry from _ENV
* if not matchin key, returns empty * if not matchin key, returns empty
* *
* @param string $key To search in _ENV array * @param string $key To search in _ENV array
* @return string|bool Returns either string or true/false (DEBUG flag) * @return string|bool Returns either string or true/false (DEBUG flag)
*/ */
private function parseEnv(string $key) private function parseEnv(string $key)
{ {
$return = ''; $return = '';
switch ($key) { switch ($key) {
case 'AWS_DEBUG': case 'AWS_DEBUG':
$return = !empty($_ENV['AWS_DEBUG']) ? true : false; $return = !empty($_ENV['AWS_DEBUG']) ? true : false;
break; break;
case 'AWS_GIFT_CARD_KEY': case 'AWS_GIFT_CARD_KEY':
case 'AWS_GIFT_CARD_SECRET': case 'AWS_GIFT_CARD_SECRET':
case 'AWS_GIFT_CARD_PARTNER_ID': case 'AWS_GIFT_CARD_PARTNER_ID':
case 'AWS_GIFT_CARD_ENDPOINT': case 'AWS_GIFT_CARD_ENDPOINT':
case 'AWS_GIFT_CARD_CURRENCY': case 'AWS_GIFT_CARD_CURRENCY':
$return = $_ENV[$key] ?? ''; $return = !empty($_ENV[$key]) && is_string($_ENV[$key]) ?
break; $_ENV[$key] : '';
default: break;
break; default:
} break;
return $return; }
} return $return;
}
/** /**
* @return string|null * @return string Returns current set endpoint, without https://
*/ */
public function getEndpoint(): ?string public function getEndpoint(): string
{ {
return $this->endpoint; return $this->endpoint;
} }
/** /**
* @param string $endpoint * @param string $endpoint Full endpoint url with https://
* @return ConfigInterface * @return ConfigInterface Class interface (self)
*/ */
public function setEndpoint(string $endpoint): ConfigInterface public function setEndpoint(string $endpoint): ConfigInterface
{ {
// TODO: check valid endpoint + set region // TODO: check valid endpoint + set region
$this->endpoint = (parse_url($endpoint, PHP_URL_HOST)) ?: ''; $this->endpoint = (parse_url($endpoint, PHP_URL_HOST)) ?: '';
return $this; return $this;
} }
/** /**
* @return string|null * @return string Current access key
*/ */
public function getAccessKey(): ?string public function getAccessKey(): string
{ {
return $this->access_key; return $this->access_key;
} }
/** /**
* @param string $key * @param string $key Access Key to set
* @return ConfigInterface * @return ConfigInterface Class interface (self)
*/ */
public function setAccessKey(string $key): ConfigInterface public function setAccessKey(string $key): ConfigInterface
{ {
$this->access_key = $key; $this->access_key = $key;
return $this; return $this;
} }
/** /**
* @return string|null * @return string Current secret key
*/ */
public function getSecret(): ?string public function getSecret(): string
{ {
return $this->secret_key; return $this->secret_key;
} }
/** /**
* @param string $secret * @param string $secret Secret key to set
* @return ConfigInterface * @return ConfigInterface Class interface (self)
*/ */
public function setSecret(string $secret): ConfigInterface public function setSecret(string $secret): ConfigInterface
{ {
$this->secret_key = $secret; $this->secret_key = $secret;
return $this; return $this;
} }
/** /**
* @return string|null * @return string Current set currency
*/ */
public function getCurrency(): ?string public function getCurrency(): string
{ {
return $this->currency; return $this->currency;
} }
/** /**
* @param string $currency * @param string $currency Currency to set (eg USD, JPY, etc)
* @return ConfigInterface * @return ConfigInterface Class interface (self)
*/ */
public function setCurrency(string $currency): ConfigInterface public function setCurrency(string $currency): ConfigInterface
{ {
// TODO: check currency valid + currenc valid for region // TODO: check currency valid + currenc valid for region
$this->currency = $currency; $this->currency = $currency;
return $this; return $this;
} }
/** /**
* @return string|null * @return string Current set partner id
*/ */
public function getPartner(): ?string public function getPartner(): string
{ {
return $this->partner_id; return $this->partner_id;
} }
/** /**
* @param string $partner * @param string $partner Partner id to set
* @return ConfigInterface * @return ConfigInterface Class interface (self)
*/ */
public function setPartner(string $partner): ConfigInterface public function setPartner(string $partner): ConfigInterface
{ {
$this->partner_id = $partner; $this->partner_id = $partner;
return $this; return $this;
} }
/** /**
* @return bool * @return bool Current set debug flag as bool
*/ */
public function getDebug(): bool public function getDebug(): bool
{ {
return $this->debug; return $this->debug;
} }
/** /**
* @param bool $debug * @param bool $debug Set debug flag as bool
* @return ConfigInterface * @return ConfigInterface Class interface (self)
*/ */
public function setDebug(bool $debug): ConfigInterface public function setDebug(bool $debug): ConfigInterface
{ {
$this->debug = $debug; $this->debug = $debug;
return $this; return $this;
} }
} }
// __END__ // __END__

View File

@@ -1,74 +1,76 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Config; namespace gullevek\AmazonIncentives\Config;
interface ConfigInterface interface ConfigInterface
{ {
/** /**
* @return string|null * @return string Returns current set endpoint, without https://
*/ */
public function getEndpoint(): ?string; public function getEndpoint(): string;
/** /**
* @param string $endpoint * @param string $endpoint Full endpoint url with https://
* @return $this * @return ConfigInterface Class interface (self)
*/ */
public function setEndpoint(string $endpoint): ConfigInterface; public function setEndpoint(string $endpoint): ConfigInterface;
/** /**
* @return string|null * @return string Current access key
*/ */
public function getAccessKey(): ?string; public function getAccessKey(): string;
/** /**
* @param string $key * @param string $key Access Key to set
* @return $this * @return ConfigInterface Class interface (self)
*/ */
public function setAccessKey(string $key): ConfigInterface; public function setAccessKey(string $key): ConfigInterface;
/** /**
* @return string|null * @return string Current secret key
*/ */
public function getSecret(): ?string; public function getSecret(): string;
/** /**
* @param string $secret * @param string $secret Secret key to set
* @return $this * @return ConfigInterface Class interface (self)
*/ */
public function setSecret(string $secret): ConfigInterface; public function setSecret(string $secret): ConfigInterface;
/** /**
* @return string|null * @return string Current set currency
*/ */
public function getCurrency(): ?string; public function getCurrency(): string;
/** /**
* @param string $currency * @param string $currency Currency to set (eg USD, JPY, etc)
* @return $this * @return ConfigInterface Class interface (self)
*/ */
public function setCurrency(string $currency): ConfigInterface; public function setCurrency(string $currency): ConfigInterface;
/** /**
* @return string|null * @return string Current set partner id
*/ */
public function getPartner(): ?string; public function getPartner(): string;
/** /**
* @param string $partner * @param string $partner Partner id to set
* @return $this * @return ConfigInterface Class interface (self)
*/ */
public function setPartner(string $partner): ConfigInterface; public function setPartner(string $partner): ConfigInterface;
/** /**
* @return bool|null * @return bool Current set debug flag as bool
*/ */
public function getDebug(): ?bool; public function getDebug(): bool;
/** /**
* @param bool $debug * @param bool $debug Set debug flag as bool
* @return $this * @return ConfigInterface Class interface (self)
*/ */
public function setDebug(bool $debug): ConfigInterface; public function setDebug(bool $debug): ConfigInterface;
} }
// __END__ // __END__

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
// simple write all into an array that we can poll in the return group // simple write all into an array that we can poll in the return group
// to activate AmazonDebug::setDebug(true) must be called once // to activate AmazonDebug::setDebug(true) must be called once
@@ -7,109 +9,103 @@ namespace gullevek\AmazonIncentives\Debug;
class AmazonDebug class AmazonDebug
{ {
/** /** @var array<string,array<array<mixed>>> Log data array log id -> array of log entries */
* @var array<mixed> private static $log = [];
*/ /** @var bool debug flag */
private static $log = []; private static $debug = false;
/** /** @var string|null Last set internal log array id */
* @var bool private static $id = null;
*/
private static $debug = false;
/**
* @var string|null
*/
private static $id = null;
/** /**
* set the ID for current run * set the ID for current run
* if debug is off, nothing will be set and id is null * if debug is off, nothing will be set and id is null
* This is run on setFlag, if debug is true * This is run on setFlag, if debug is true
* *
* @param string|null $id If not set, will default to uniqid() call * @param string|null $id If not set, will default to uniqid() call
* @return void * @return void
*/ */
private static function setId(?string $id = null): void private static function setId(?string $id = null): void
{ {
if (self::$debug === false) { if (self::$debug === false) {
return; return;
} }
if ($id === null) { if ($id === null) {
$id = uniqid(); $id = uniqid();
} }
self::$id = $id; self::$id = $id;
} }
/** /**
* set the debug flag. * set the debug flag.
* This is automatically run in gullevek\AmazonIncentives\AmazonIncentives::__construct * This is automatically run in gullevek\AmazonIncentives\AmazonIncentives::__construct
* No need to run manuall * No need to run manuall
* *
* @param boolean $debug Can only be True or False * @param boolean $debug Can only be True or False
* @param string|null $id If not set, will default to uniqid() call * @param string|null $id If not set, will default to uniqid() call
* @return void * @return void
*/ */
public static function setDebug(bool $debug, ?string $id = null): void public static function setDebug(bool $debug, ?string $id = null): void
{ {
self::$debug = $debug; self::$debug = $debug;
if (self::$debug === false) { if (self::$debug === false) {
return; return;
} }
self::setId($id); self::setId($id);
} }
/** /**
* returns current debug flag status * returns current debug flag status
* *
* @return boolean True if debug is on, False if debug is off * @return boolean True if debug is on, False if debug is off
*/ */
public static function getDebug(): bool public static function getDebug(): bool
{ {
return self::$debug; return self::$debug;
} }
/** /**
* get the current set ID, can return null if debug is off * get the current set ID, can return null if debug is off
* *
* @return string|null Current set ID for this log run * @return string|null Current set ID for this log run
*/ */
public static function getId(): ?string public static function getId(): ?string
{ {
return self::$id; return self::$id;
} }
/** /**
* write a log entry * write a log entry
* Data is as array key -> value * Data is as array key -> value
* Will be pushed as new array entry int log * Will be pushed as new array entry int log
* Main key is the set Id for this run * Main key is the set Id for this run
* *
* @param array<mixed> $data Any array data to store in the log * @param array<mixed> $data Any array data to store in the log
* @return void * @return void
*/ */
public static function writeLog(array $data): void public static function writeLog(array $data): void
{ {
if (self::$debug === false) { if (self::$debug === false) {
return; return;
} }
self::$log[self::getId() ?? ''][] = $data; self::$log[self::getId() ?? ''][] = $data;
} }
/** /**
* get all logs written since first class run * get all logs written since first class run
* or get all log entries for given ID * or get all log entries for given ID
* *
* @param string|null $id If set returns only this id logs * @param string|null $id If set returns only this id logs
* or empty array if not found * or empty array if not found
* @return array<mixed> Always array, empty if not data or not found * @return array<mixed> Always array, empty if not data or not found
*/ */
public static function getLog(?string $id = null): array public static function getLog(?string $id = null): array
{ {
if ($id === null) { if ($id === null) {
return self::$log; return self::$log;
} else { } else {
return self::$log[$id] ?? []; return self::$log[$id] ?? [];
} }
} }
} }
// __END__ // __END__

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Exceptions; namespace gullevek\AmazonIncentives\Exceptions;
use RuntimeException; use RuntimeException;
@@ -7,35 +9,63 @@ use gullevek\AmazonIncentives\Debug\AmazonDebug;
final class AmazonErrors extends RuntimeException final class AmazonErrors extends RuntimeException
{ {
/** /**
* @param string $error_status agcodResponse->status from Amazon * Returns an Runtime exception including a json encoded string with all
* @param string $error_code errorCode from Amazon * parameters including last log id and log
* @param string $error_type errorType from Amazon *
* @param string $message * @param string $error_status agcodResponse->status from Amazon
* @param int $_error_code * @param string $error_code errorCode from Amazon
* @return AmazonErrors * @param string $error_type errorType from Amazon
*/ * @param string $message Message string to ad
public static function getError( * @param int $_error_code Error code to set
string $error_status, * @return AmazonErrors Exception Class
string $error_code, */
string $error_type, public static function getError(
string $message, string $error_status,
int $_error_code string $error_code,
): self { string $error_type,
// NOTE: if xdebug.show_exception_trace is set to 1 this will print ERRORS string $message,
return new static( int $_error_code
(json_encode([ ): self {
'status' => $error_status, // NOTE: if xdebug.show_exception_trace is set to 1 this will print ERRORS
'code' => $error_code, return new static(
'type' => $error_type, (json_encode([
'message' => $message, 'status' => $error_status,
// atach log data if exists 'code' => $error_code,
'log_id' => AmazonDebug::getId(), 'type' => $error_type,
'log' => AmazonDebug::getLog(), 'message' => $message,
])) ?: 'AmazonErrors: json encode problem: ' . $message, // attach log data if exists
$_error_code 'log_id' => AmazonDebug::getId(),
); 'log' => AmazonDebug::getLog(),
} ])) ?: 'AmazonErrors: json encode problem: ' . $message,
$_error_code
);
}
/**
* Decodes the Exception message body
* Returns an array with code (Amazon error codes), type (Amazon error info)
* message (Amazon returned error message string)
*
* @param string $message Exception message json string
* @return array<mixed> Decoded with code, type, message fields
*/
public static function decodeExceptionMessage(string $message): array
{
$message_ar = json_decode($message, true);
// if we have an error, build empty block and only fill message
if (json_last_error() || $message_ar === null || !is_array($message_ar)) {
$message_ar = [
'status' => '',
'code' => '',
'type' => '',
'message' => $message,
'log_id' => '',
'log' => []
];
}
return $message_ar;
}
} }
// __END__ // __END__

42
src/Handle/Json.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
/**
* Handle json conversions
*/
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Handle;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
class Json
{
/**
* decode json string
*
* @param string $json
* @return array<mixed>
* @throws AmazonErrors
*/
public static function jsonDecode(string $json): array
{
$result = json_decode($json, true);
if (
($json_last_error = json_last_error()) ||
$result === null ||
!is_array($result)
) {
throw AmazonErrors::getError(
'FAILURE',
'J-' . $json_last_error,
'jsonDecoreError',
'Failed to decode json data',
0
);
}
return $result;
}
}
// __END__

View File

@@ -1,115 +1,105 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Response; namespace gullevek\AmazonIncentives\Response;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug; use gullevek\AmazonIncentives\Debug\AmazonDebug;
class CancelResponse class CancelResponse
{ {
/** /** @var string Amazon Gift Card gcId (gift card id). */
* Amazon Gift Card gcId. protected $id = '';
* /** @var string Amazon Gift Card creationRequestId (creation request id) */
* @var string protected $creation_request_id = '';
*/ /** @var string Amazon Gift Card status */
protected $id; protected $status = '';
/** /** @var array<mixed> Amazon Gift Card Raw JSON */
* Amazon Gift Card creationRequestId protected $raw_json = [];
*
* @var string
*/
protected $creation_request_id;
/**
* Amazon Gift Card status
*
* @var string
*/
protected $status;
/**
* Amazon Gift Card Raw JSON
*
* @var array<mixed>
*/
protected $raw_json;
/** /**
* Response constructor. * Response constructor for canceling gitf cards
* @param array<mixed> $json_response *
*/ * @param array<mixed> $json_response JSON response from web request to AWS
public function __construct(array $json_response) */
{ public function __construct(array $json_response)
$this->raw_json = $json_response; {
$this->parseJsonResponse($json_response); $this->raw_json = $json_response;
} $this->parseJsonResponse($json_response);
}
/** /**
* @return array<mixed> * Get log entry with current set log id
*/ *
public function getLog(): array * @return array<mixed> Log array
{ */
return AmazonDebug::getLog(AmazonDebug::getId()); public function getLog(): array
} {
return AmazonDebug::getLog(AmazonDebug::getId());
}
/** /**
* @return string * The gift card id as created by the previous get code call
*/ *
public function getId(): string * @return string Gift card id
{ */
return $this->id; public function getId(): string
} {
return $this->id;
}
/** /**
* @return string * Creation Request id from original get code call
*/ *
public function getCreationRequestId(): string * @return string Creation request id
{ */
return $this->creation_request_id; public function getCreationRequestId(): string
} {
return $this->creation_request_id;
}
/** /**
* @return string * Request status
*/ *
public function getStatus(): string * @return string Request status as string: SUCCESS, FAILURE, RESEND
{ */
return $this->status; public function getStatus(): string
} {
return $this->status;
}
/** /**
* @return string * Returns the request data as json string. This is a re-encode from decoded
*/ * makeRequest call
public function getRawJson(): string *
{ * @return string JSON encoded string from the return values
return (json_encode($this->raw_json)) ?: ''; */
} public function getRawJson(): string
{
return (json_encode($this->raw_json)) ?: '';
}
/** /**
* @param array<mixed> $json_response * Set class variables with response data from makeRequest and return self
* @return CancelResponse *
*/ * @param array<mixed> $json_response JSON response as array
public function parseJsonResponse(array $json_response): self * @return CancelResponse Return self object
{ */
if (!is_array($json_response)) { public function parseJsonResponse(array $json_response): self
throw AmazonErrors::getError( {
'FAILURE', if (array_key_exists('gcId', $json_response)) {
'E001', $this->id = $json_response['gcId'];
'NonScalarValue', }
'Response must be a scalar value', if (array_key_exists('creationRequestId', $json_response)) {
0 $this->creation_request_id = $json_response['creationRequestId'];
); }
} // SUCCESS, FAILURE, RESEND
if (array_key_exists('gcId', $json_response)) { if (array_key_exists('status', $json_response)) {
$this->id = $json_response['gcId']; $this->status = $json_response['status'];
} }
if (array_key_exists('creationRequestId', $json_response)) {
$this->creation_request_id = $json_response['creationRequestId'];
}
// SUCCESS, FAILURE, RESEND
if (array_key_exists('status', $json_response)) {
$this->status = $json_response['status'];
}
return $this; return $this;
} }
} }
// __END__ // __END__

View File

@@ -1,133 +1,127 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Response; namespace gullevek\AmazonIncentives\Response;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug; use gullevek\AmazonIncentives\Debug\AmazonDebug;
class CreateBalanceResponse class CreateBalanceResponse
{ {
/** /** @var float Amazon Gift Card Balance Amount */
* Amazon Gift Card Balance Amount protected $amount = 0;
* /** @var string Amazon Gift Card Balance Currency */
* @var string protected $currency = '';
*/ /** @var string Amazon Gift Card Balance Status */
protected $amount; protected $status = '';
/** /** @var string Amazon Gift Card Balance Timestamp */
* Amazon Gift Card Balance Currency protected $timestamp = '';
* /** @var array<mixed> Amazon Gift Card Raw JSON */
* @var string protected $raw_json = [];
*/
protected $currency;
/**
* Amazon Gift Card Balance Status
*
* @var string
*/
protected $status;
/**
* Amazon Gift Card Balance Timestamp
*
* @var string
*/
protected $timestamp;
/**
* Amazon Gift Card Raw JSON
*
* @var array<mixed>
*/
protected $raw_json;
/** /**
* Response constructor. * Response constructor for requesting account funds status
* *
* @param array<mixed> $json_response * @param array<mixed> $json_response JSON response from web request to AWS
*/ */
public function __construct(array $json_response) public function __construct(array $json_response)
{ {
$this->raw_json = $json_response; $this->raw_json = $json_response;
$this->parseJsonResponse($json_response); $this->parseJsonResponse($json_response);
} }
/** /**
* @return array<mixed> * Get log entry with current set log id
*/ *
public function getLog(): array * @return array<mixed> Log array
{ */
return AmazonDebug::getLog(AmazonDebug::getId()); public function getLog(): array
} {
return AmazonDebug::getLog(AmazonDebug::getId());
}
/** /**
* @return string * Return the current available funds amount
*/ *
public function getAmount(): string * @return float Funds amount in set currency
{ */
return $this->amount; public function getAmount(): float
} {
return $this->amount;
}
/** /**
* @return string * Get the set currency type
*/ *
public function getCurrency(): string * @return string Currency type. Eg USD, JPY, etc
{ */
return $this->currency; public function getCurrency(): string
} {
return $this->currency;
}
/** /**
* @return string * Get timestamp as set.
*/ * eg 20220609T061446Z
public function getStatus(): string *
{ * @return string Timestamp string. Ymd\THis\Z
return $this->status; */
} public function getTimestamp(): string
{
return $this->timestamp;
}
/** /**
* @return string * Request status
*/ *
public function getTimestamp(): string * @return string Request status as string: SUCCESS, FAILURE, RESEND
{ */
return $this->timestamp; public function getStatus(): string
} {
return $this->status;
}
/** /**
* @return string * Returns the request data as json string. This is a re-encode from decoded
*/ * makeRequest call
public function getRawJson(): string *
{ * @return string JSON encoded string from the return values
return (json_encode($this->raw_json)) ?: ''; */
} public function getRawJson(): string
{
return (json_encode($this->raw_json)) ?: '';
}
/** /**
* Undocumented function * Set class variables with response data from makeRequest and return self
* *
* @param array<mixed> $json_response * @param array<mixed> $json_response JSON response as array
* @return CreateBalanceResponse * @return CreateBalanceResponse Return self object
*/ */
public function parseJsonResponse(array $json_response): self public function parseJsonResponse(array $json_response): self
{ {
if (!is_array($json_response)) { if (
throw AmazonErrors::getError( is_array($json_response['availableFunds']) &&
'FAILURE', array_key_exists('amount', $json_response['availableFunds']) &&
'E001', is_numeric($json_response['availableFunds']['amount'])
'NonScalarValue', ) {
'Response must be a scalar value', $this->amount = (float)$json_response['availableFunds']['amount'];
0 }
); if (
} is_array($json_response['availableFunds']) &&
if (array_key_exists('amount', $json_response['availableFunds'])) { array_key_exists('currencyCode', $json_response['availableFunds']) &&
$this->amount = $json_response['availableFunds']['amount']; is_string($json_response['availableFunds']['currencyCode'])
} ) {
if (array_key_exists('currencyCode', $json_response['availableFunds'])) { $this->currency = $json_response['availableFunds']['currencyCode'];
$this->currency = $json_response['availableFunds']['currencyCode']; }
} // SUCCESS, FAILURE, RESEND
// SUCCESS, FAILURE, RESEND if (array_key_exists('status', $json_response)) {
if (array_key_exists('status', $json_response)) { $this->status = $json_response['status'];
$this->status = $json_response['status']; }
} if (array_key_exists('timestamp', $json_response)) {
if (array_key_exists('timestamp', $json_response)) { $this->timestamp = $json_response['timestamp'];
$this->timestamp = $json_response['timestamp']; }
}
return $this; return $this;
} }
} }

View File

@@ -1,205 +1,184 @@
<?php <?php
declare(strict_types=1);
namespace gullevek\AmazonIncentives\Response; namespace gullevek\AmazonIncentives\Response;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\AmazonIncentives\Debug\AmazonDebug; use gullevek\AmazonIncentives\Debug\AmazonDebug;
class CreateResponse class CreateResponse
{ {
/** /** @var string Amazon Gift Card gcId */
* Amazon Gift Card gcId. protected $id = '';
* /** @var string Amazon Gift Card creationRequestId */
* @var string protected $creation_request_id = '';
*/ /** @var string Amazon Gift Card gcClaimCode */
protected $id; protected $claim_code = '';
/** @var float Amazon Gift Card amount */
protected $value = 0;
/** @var string Amazon Gift Card currency */
protected $currency = '';
/** @var string Amazon Gift Card status */
protected $status = '';
/** @var string Amazon Gift Card Expiration Date */
protected $expiration_date = '';
/** @var string Amazon Gift Card Expiration Date */
protected $card_status = '';
/** @var array<mixed> Amazon Gift Card Raw JSON as array */
protected $raw_json = [];
/** /**
* Amazon Gift Card creationRequestId * Response constructor for creating gift cards
* *
* @var string * @param array<mixed> $json_response JSON response from web request to AWS
*/ */
protected $creation_request_id; public function __construct(array $json_response)
{
$this->raw_json = $json_response;
$this->parseJsonResponse($json_response);
}
/** /**
* Amazon Gift Card gcClaimCode * Get log entry with current set log id
* *
* @var string * @return array<mixed> Log array
*/ */
protected $claim_code; public function getLog(): array
{
return AmazonDebug::getLog(AmazonDebug::getId());
}
/** /**
* Amazon Gift Card amount * Gift Card ID returned from AWS. Can be used in the cancel request
* *
* @var float * @return string Gift card id
*/ */
protected $value; public function getId(): string
{
return $this->id;
}
/** /**
* Amazon Gift Card currency * Either the one set with the method parameter, or automatically created
* * during get code request
* @var string *
*/ * @return string Creation request id
protected $currency; */
/** public function getCreationRequestId(): string
* Amazon Gift Card status {
* return $this->creation_request_id;
* @var string }
*/
protected $status;
/**
* Amazon Gift Card Expiration Date
*
* @var string
*/
protected $expiration_date;
/**
* Amazon Gift Card Expiration Date
*
* @var string
*/
protected $card_status;
/**
* Amazon Gift Card Raw JSON
*
* @var array<mixed>
*/
protected $raw_json;
/** /**
* Response constructor. * The actual gift code, recommended not to be stored anywhere and only shown
* @param array<mixed> $json_response * to user
*/ *
public function __construct(array $json_response) * @return string Gift order claim code on AWS
{ */
$this->raw_json = $json_response; public function getClaimCode(): string
$this->parseJsonResponse($json_response); {
} return $this->claim_code;
}
/** /**
* @return array<mixed> * The ordered gift code value in given currency
*/ *
public function getLog(): array * @return float Gift order value in currency
{ */
return AmazonDebug::getLog(AmazonDebug::getId()); public function getValue(): float
} {
return $this->value;
}
/** /**
* @return string * The currently set currency
*/ *
public function getId(): string * @return string Currency type. Eg USD, JPY, etc
{ */
return $this->id; public function getCurrency(): string
} {
return $this->currency;
}
/** /**
* @return string * Expiration date for the ordered gift code.
*/ * eg 20220609T061446Z
public function getCreationRequestId(): string *
{ * @return string Timestamp until when the gift code is valid. Ymd\THis\Z
return $this->creation_request_id; */
} public function getExpirationDate(): string
{
return $this->expiration_date;
}
/** /**
* @return string * Gift card status. If the same creation request id is sent again and the
*/ * gift card got cancled, this is reflected here
public function getClaimCode(): string *
{ * @return string Gift card status
return $this->claim_code; */
} public function getCardStatus(): string
{
return $this->card_status;
}
/** /**
* @return float * Request status
*/ *
public function getValue(): float * @return string Request status as string: SUCCESS, FAILURE, RESEND
{ */
return $this->value; public function getStatus(): string
} {
return $this->status;
}
/** /**
* @return string * @Returns the request data as json string. This is a re-encode from decoded
*/ * makeRequest call
public function getCurrency(): string *
{ * @return string JSON encoded string from the return values
return $this->currency; */
} public function getRawJson(): string
{
return (json_encode($this->raw_json)) ?: '';
}
/** /**
* @return string * Set class variables with response data from makeRequest and return self
*/ *
public function getStatus(): string * @param array<mixed> $json_response JSON response as array
{ * @return CreateResponse Return self object
return $this->status; */
} public function parseJsonResponse(array $json_response): self
{
if (array_key_exists('gcId', $json_response)) {
$this->id = $json_response['gcId'];
}
if (array_key_exists('creationRequestId', $json_response)) {
$this->creation_request_id = $json_response['creationRequestId'];
}
if (array_key_exists('gcClaimCode', $json_response)) {
$this->claim_code = $json_response['gcClaimCode'];
}
if (array_key_exists('amount', $json_response['cardInfo']['value'])) {
$this->value = $json_response['cardInfo']['value']['amount'];
}
if (array_key_exists('currencyCode', $json_response['cardInfo']['value'])) {
$this->currency = $json_response['cardInfo']['value']['currencyCode'];
}
if (array_key_exists('gcExpirationDate', $json_response)) {
$this->expiration_date = $json_response['gcExpirationDate'];
}
if (array_key_exists('cardStatus', $json_response['cardInfo'])) {
$this->card_status = $json_response['cardInfo']['cardStatus'];
}
// SUCCESS, FAILURE, RESEND
if (array_key_exists('status', $json_response)) {
$this->status = $json_response['status'];
}
/** return $this;
* @return string }
*/
public function getExpirationDate(): string
{
return $this->expiration_date;
}
/**
* @return string
*/
public function getCardStatus(): string
{
return $this->card_status;
}
/**
* @return string
*/
public function getRawJson(): string
{
return (json_encode($this->raw_json)) ?: '';
}
/**
* @param array<mixed> $json_response
* @return CreateResponse
*/
public function parseJsonResponse(array $json_response): self
{
if (!is_array($json_response)) {
throw AmazonErrors::getError(
'FAILURE',
'E001',
'NonScalarValue',
'Response must be a scalar value',
0
);
}
if (array_key_exists('gcId', $json_response)) {
$this->id = $json_response['gcId'];
}
if (array_key_exists('creationRequestId', $json_response)) {
$this->creation_request_id = $json_response['creationRequestId'];
}
if (array_key_exists('gcClaimCode', $json_response)) {
$this->claim_code = $json_response['gcClaimCode'];
}
if (array_key_exists('amount', $json_response['cardInfo']['value'])) {
$this->value = $json_response['cardInfo']['value']['amount'];
}
if (array_key_exists('currencyCode', $json_response['cardInfo']['value'])) {
$this->currency = $json_response['cardInfo']['value']['currencyCode'];
}
if (array_key_exists('gcExpirationDate', $json_response)) {
$this->expiration_date = $json_response['gcExpirationDate'];
}
if (array_key_exists('cardStatus', $json_response['cardInfo'])) {
$this->card_status = $json_response['cardInfo']['cardStatus'];
}
// SUCCESS, FAILURE, RESEND
if (array_key_exists('status', $json_response)) {
$this->status = $json_response['status'];
}
return $this;
}
} }
// __END__ // __END__

7
test/.env.example Normal file
View File

@@ -0,0 +1,7 @@
# for AWS gift card testing
AWS_GIFT_CARD_ENDPOINT=
AWS_GIFT_CARD_KEY=
AWS_GIFT_CARD_SECRET=
AWS_GIFT_CARD_PARTNER_ID=
AWS_GIFT_CARD_CURRENCY=
AWS_DEBUG=

View File

@@ -0,0 +1,140 @@
# Return data from AWS as json string
## Mock tests self
Tests run in local mock tests without connection to AWS
### funds
```json
{"availableFunds":{"amount":0.0,"currencyCode":"JPY"},"status":"SUCCESS","timestamp":"20220610T085450Z"}
```
### buy
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a309167e7a4","gcClaimCode":"LJ49-AKDUV6-UYCP","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5535125272070255","status":"SUCCESS"}
```
### cancel
```json
{"creationRequestId":"EG3bd_62a309167e7a4","gcId":"5535125272070255","status":"SUCCESS"}
```
### buy other 1
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"RefundedToPurchaser","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a309167e7a4","gcClaimCode":"LJ49-AKDUV6-UYCP","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5535125272070255","status":"SUCCESS"}
```
### buy aother 2
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a30923e9705","gcClaimCode":"UM97-FD5QKK-WKCT","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5540334324324221","status":"SUCCESS"}
```
### buy other 2 (same create request id)
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a30923e9705","gcClaimCode":"UM97-FD5QKK-WKCT","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5540334324324221","status":"SUCCESS"}
```
## AWS GCOD Mocks
Mocking on AWS side, these will be returned if given request ID codes are sent.
A working test account must exist for this
## success
### buy gift card F0000
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":500.0,"currencyCode":"JPY"}},"creationRequestId":"F0000","gcClaimCode":"ZYXW-VUTS-RQPO","gcExpirationDate":null,"gcId":"ABC123ZYX987","status":"SUCCESS"}
```
## errors
### F1000 -> F100
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F100","errorType":"GeneralError","message":"General Error"}
```
### F2003 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidAmountInput","message":"Amount can't be null"}
```
### F2004 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidAmountValue","message":"Amount must be larger than 0"}
```
### F2005 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidCurrencyCodeInput","message":"Currency Code can't be null or empty"}
```
### F2010 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CardAlreadyActivatedWithDifferentRequestId","message":"The card was already activated with a different request id"}
```
### F2015 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"MaxAmountExceeded","message":"Max Amount Exceeded"}
```
### F2016 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CurrencyCodeMismatch","message":"Currency Code Mismatch"}
```
### F2017 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"FractionalAmountNotAllowed","message":"Fractional Amount Not Allowed"}
```
### F2047 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CancelRequestArrivedAfterTimeLimit","message":"Cancellation cannot be processed as too much time has elapsed since creation"}
```
### F3003 -> F300
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"InsufficientFunds","message":"Insufficient Funds"}
```
### F3005 -> F300
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"GeneralError","message":"General Error"}
```
### F3010 -> F300
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"CustomerSurpassedDailyVelocityLimit","message":"Customer has exceeded daily velocity limit"}
```
### F4000 -> F400
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"RESEND"},"errorCode":"F400","errorType":"SystemTemporarilyUnavailable","message":"System Temporarily Unavailable"}
```
### F5000 -> F500
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F500","errorType":"GeneralError","message":"General Error"}
```

View File

@@ -11,10 +11,10 @@
*/ */
function writeLog(array $data): string function writeLog(array $data): string
{ {
return json_encode([ return json_encode([
'date' => date('Y-m-d H:i:s'), 'date' => date('Y-m-d H:i:s'),
'log' => $data 'log' => $data
]) . "\n"; ]) . "\n";
} }
/** /**
@@ -25,7 +25,7 @@ function writeLog(array $data): string
*/ */
function dateTr(string $date): string function dateTr(string $date): string
{ {
return date('Y-m-d H:i:s', (strtotime($date)) ?: null); return date('Y-m-d H:i:s', (strtotime($date)) ?: null);
} }
/** /**
@@ -38,18 +38,18 @@ function dateTr(string $date): string
* @return void * @return void
*/ */
function printException( function printException(
string $call_request, string $call_request,
int $error_code, int $error_code,
array $error, array $error,
bool $debug_print bool $debug_print
): void { ): void {
print "AWS: " . $call_request . ": " . $error['status'] print "AWS: " . $call_request . ": " . $error['status']
. " [" . $error_code . "]: " . " [" . $error_code . "]: "
. $error['code'] . " | " . $error['type'] . $error['code'] . " | " . $error['type']
. " | " . $error['message']; . " | " . $error['message'];
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>"; print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
} }
} }
// composer auto loader // composer auto loader
@@ -57,13 +57,13 @@ $loader = require '../vendor/autoload.php';
// need to add this or it will not load here // need to add this or it will not load here
$loader->addPsr4('gullevek\\', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'src'); $loader->addPsr4('gullevek\\', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'src');
// print "LOADER: <pre>" . print_r($loader, true) . "</pre>"; // print "LOADER: <pre>" . print_r($loader, true) . "</pre>";
// env file loader (simple)
require 'read_env_file.php';
use gullevek\AmazonIncentives\AmazonIncentives; use gullevek\AmazonIncentives\AmazonIncentives;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\dotEnv\DotEnv;
// load env data with dotenv // load env data with dotenv
readEnvFile(__DIR__); DotEnv::readEnvFile(__DIR__);
print "<h1>Amazon Gift Card Incentives</h1><br>"; print "<h1>Amazon Gift Card Incentives</h1><br>";
@@ -76,241 +76,253 @@ print "<h1>Amazon Gift Card Incentives</h1><br>";
// optional // optional
// debug: AWS_DEBUG (if not set: off) // debug: AWS_DEBUG (if not set: off)
// as in .env // run info test (prints ENV vars)
// AWS_GIFT_CARD_ENDPOINT.TEST $run_info_test = !empty($_GET['info']) ? true : false;
// AWS_GIFT_CARD_ENDPOINT.LIVE // run test to get funds info
$run_fund_test = !empty($_GET['fund']) ? true : false;
// run the normal get/cancel gift card tests
$run_gift_tests = !empty($_GET['gift']) ? true : false;
// run mock error check tests
$run_mocks = !empty($_GET['mocks']) ? true : false;
define('LOCATION', 'test'); // should we print debug info
foreach ( $debug_print = !empty($_GET['debug']) ? true : false;
[ // how long to wait between each call
'AWS_GIFT_CARD_KEY', 'AWS_GIFT_CARD_SECRET', 'AWS_GIFT_CARD_PARTNER_ID', $debug_wait = 2;
'AWS_GIFT_CARD_ENDPOINT', 'AWS_GIFT_CARD_CURRENCY', 'AWS_DEBUG' // if set to true will print all the debug logs too
] as $key $mock_debug = !empty($_GET['debug_mock']) ? true : false;
) { // wait in seconds between mock tests
// $mock_wait = 2;
$_ENV[$key] = $_ENV[$key . '.' . strtoupper((LOCATION))] ?? $_ENV[$key] ?? '';
if (empty($_GET)) {
print "<b>Use _GET parameters to start tests</b>";
} }
// open debug file output // open debug file output
$fp = fopen('log/debug.' . date('YmdHis') . '.log', 'w'); $fp = fopen('log/debug.' . date('YmdHis') . '.log', 'w');
if (!is_resource($fp)) { if (!is_resource($fp)) {
die("Cannot open log debug file"); die("Cannot open log debug file");
} }
// run info test (prints ENV vars)
$run_info_test = false;
// run test to get funds info
$run_fund_test = true;
// run the normal get/cancel gift card tests
$run_gift_tests = true;
// run mock error check tests
$run_mocks = false;
// should we print debug info
$debug_print = false;
// how long to wait between each call
$debug_wait = 2;
// if set to true will print all the debug logs too
$mock_debug = false;
// wait in seconds between mock tests
$mock_wait = 2;
if ($run_info_test === true) { if ($run_info_test === true) {
$aws = new AmazonIncentives(); $aws = new AmazonIncentives();
print "checkMe: <pre>" . print_r($aws->checkMe(), true) . "</pre>"; $aws_check_me = $aws->checkMe();
fwrite($fp, writeLog($aws->checkMe())); print "checkMe: <pre>" . print_r($aws_check_me, true) . "</pre>";
print "<hr>"; fwrite($fp, writeLog($aws_check_me));
print "<hr>";
} }
// check balance // check balance
if ($run_fund_test === true) { if ($run_fund_test === true) {
try { try {
$aws_test = AmazonIncentives::make()->getAvailableFunds(); $aws_test = AmazonIncentives::make()->getAvailableFunds();
print "AWS: getAvailableFunds: " . $aws_test->getStatus() . ": " print "AWS: getAvailableFunds: " . $aws_test->getStatus() . ": "
. "Amount: " . $aws_test->getAmount() . ", " . "Amount: " . $aws_test->getAmount() . ", "
. "Currency: " . $aws_test->getCurrency() . ", " . "Currency: " . $aws_test->getCurrency() . ", "
. "Timestamp: " . $aws_test->getTimestamp(); . "Timestamp: " . $aws_test->getTimestamp();
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>"; print "<pre>" . print_r($aws_test, true) . "</pre>";
} }
fwrite($fp, writeLog((array)$aws_test)); fwrite($fp, writeLog((array)$aws_test));
} catch (Exception $e) { } catch (Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage()); $error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('getAvailableFunds', $e->getCode(), $error, $debug_print); printException('getAvailableFunds', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error)); fwrite($fp, writeLog($error));
}; };
print "<br>"; print "<br>";
sleep($debug_wait); sleep($debug_wait);
// print "LOG: <pre>" . print_r($aws_test->getLog(), true) . "</pre><br>"; // print "LOG: <pre>" . print_r($aws_test->getLog(), true) . "</pre><br>";
print "<hr>"; print "<hr>";
} }
if ($run_gift_tests === true) { if ($run_gift_tests === true) {
// create card // create card
$value = 1000; $value = 1000;
$creation_request_id = ''; $creation_request_id = '';
$gift_card_id = ''; $gift_card_id = '';
try { try {
// we must be sure we pass FLOAT there // we must be sure we pass FLOAT there
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value); $aws_test = AmazonIncentives::make()->buyGiftCard((float)$value);
$creation_request_id = $aws_test->getCreationRequestId(); $creation_request_id = $aws_test->getCreationRequestId();
$gift_card_id = $aws_test->getId(); $gift_card_id = $aws_test->getId();
$claim_code = $aws_test->getClaimCode(); $claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate(); $expiration_date = $aws_test->getExpirationDate();
$request_status = $aws_test->getStatus(); $request_status = $aws_test->getStatus();
print "AWS: buyGiftCard: " . $request_status . ": " print "AWS: buyGiftCard: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", " . "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, " . "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>"; . "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>"; print "<pre>" . print_r($aws_test, true) . "</pre>";
} }
fwrite($fp, writeLog((array)$aws_test)); fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) { } catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage()); $error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print); printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error)); fwrite($fp, writeLog($error));
} }
print "<br>"; print "<br>";
sleep($debug_wait); sleep($debug_wait);
try { try {
// cancel above created card card // cancel above created card card
$aws_test = AmazonIncentives::make()->cancelGiftCard($creation_request_id, $gift_card_id); $aws_test = AmazonIncentives::make()->cancelGiftCard($creation_request_id, $gift_card_id);
$request_status = $aws_test->getStatus(); $request_status = $aws_test->getStatus();
print "AWS: cancelGiftCard: " . $request_status . ": " print "AWS: cancelGiftCard: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id; . "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id;
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>"; print "<pre>" . print_r($aws_test, true) . "</pre>";
} }
fwrite($fp, writeLog((array)$aws_test)); fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) { } catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage()); $error = AmazonErrors::decodeExceptionMessage($e->getMessage());
print "AWS: cancelGiftCard: " . $error['status'] print "AWS: cancelGiftCard: " . $error['status']
. " [" . $e->getCode() . "]: " . " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type'] . $error['code'] . " | " . $error['type']
. " | " . $error['message']; . " | " . $error['message'];
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>"; print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
} }
fwrite($fp, writeLog($error)); fwrite($fp, writeLog($error));
} }
print "<br>"; print "<br>";
sleep($debug_wait); sleep($debug_wait);
// request same card again and get error
try {
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value, $creation_request_id);
$request_status = $aws_test->getStatus();
// same?
$claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate();
print "AWS: buyGiftCard: CANCLED SAME CODE AGAIN: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>";
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
print "<br>";
sleep($debug_wait);
// set same request ID twice to get same response test // set same request ID twice to get same response test
try { try {
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value); $aws_test = AmazonIncentives::make()->buyGiftCard((float)$value);
$creation_request_id = $aws_test->getCreationRequestId(); $creation_request_id = $aws_test->getCreationRequestId();
$gift_card_id = $aws_test->getId(); $gift_card_id = $aws_test->getId();
$claim_code = $aws_test->getClaimCode(); $claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate(); $expiration_date = $aws_test->getExpirationDate();
$request_status = $aws_test->getStatus(); $request_status = $aws_test->getStatus();
print "AWS: buyGiftCard: CODE A: " . $request_status . ": " print "AWS: buyGiftCard: CODE A: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", " . "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, " . "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>"; . "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>"; print "<pre>" . print_r($aws_test, true) . "</pre>";
} }
fwrite($fp, writeLog((array)$aws_test)); fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) { } catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage()); $error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('cancelGiftCard', $e->getCode(), $error, $debug_print); printException('cancelGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error)); fwrite($fp, writeLog($error));
} }
print "<br>"; print "<br>";
sleep($debug_wait); sleep($debug_wait);
try { try {
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$value, $creation_request_id); $aws_test = AmazonIncentives::make()->buyGiftCard((float)$value, $creation_request_id);
$request_status = $aws_test->getStatus(); $request_status = $aws_test->getStatus();
// same? // same?
$claim_code = $aws_test->getClaimCode(); $claim_code = $aws_test->getClaimCode();
$expiration_date = $aws_test->getExpirationDate(); $expiration_date = $aws_test->getExpirationDate();
print "AWS: buyGiftCard: SAME CODE A AGAIN: " . $request_status . ": " print "AWS: buyGiftCard: SAME CODE A AGAIN: " . $request_status . ": "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", " . "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, " . "EXPIRE DATE: <b>" . dateTr($expiration_date) . "</b>, "
. "CLAIM CODE: <b>" . $claim_code . "</b>"; . "CLAIM CODE: <b>" . $claim_code . "</b>";
if ($debug_print === true) { if ($debug_print === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>"; print "<pre>" . print_r($aws_test, true) . "</pre>";
} }
fwrite($fp, writeLog((array)$aws_test)); fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) { } catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage()); $error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print); printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error)); fwrite($fp, writeLog($error));
} }
print "<br>"; print "<br>";
print "<hr>"; print "<hr>";
sleep($debug_wait); sleep($debug_wait);
} }
// MOCK TEST // MOCK TEST
if ($run_mocks === true) { if ($run_mocks === true) {
$mock_ok = '<span style="color:green;">MOCK OK</span>'; $mock_ok = '<span style="color:green;">MOCK OK</span>';
$mock_failure = '<span style="color:red;">MOCK FAILURE</span>'; $mock_failure = '<span style="color:red;">MOCK FAILURE</span>';
$mock_value = 500; $mock_value = 500;
$mock = []; $mock = [];
$mock['F0000'] = [ 'ret' => '', 'st' => 'SUCCESS']; // success mock $mock['F0000'] = [ 'ret' => '', 'st' => 'SUCCESS']; // success mock
$mock['F1000'] = [ 'ret' => 'F100', 'st' => 'FAILURE']; // SimpleAmountIsNull, etc $mock['F1000'] = [ 'ret' => 'F100', 'st' => 'FAILURE']; // SimpleAmountIsNull, etc
$mock['F2003'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidAmountInput $mock['F2003'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidAmountInput
$mock['F2004'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidAmountValue $mock['F2004'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidAmountValue
$mock['F2005'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidCurrencyCodeInput $mock['F2005'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // InvalidCurrencyCodeInput
$mock['F2010'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // CardActivatedWithDifferentRequestId $mock['F2010'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // CardActivatedWithDifferentRequestId
$mock['F2015'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // MaxAmountExceeded $mock['F2015'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // MaxAmountExceeded
$mock['F2016'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // CurrencyCodeMismatch $mock['F2016'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // CurrencyCodeMismatch
$mock['F2017'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // FractionalAmountNotAllowed $mock['F2017'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // FractionalAmountNotAllowed
$mock['F2047'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // CancelRequestArrivedAfterTimeLimit $mock['F2047'] = [ 'ret' => 'F200', 'st' => 'FAILURE']; // CancelRequestArrivedAfterTimeLimit
$mock['F3003'] = [ 'ret' => 'F300', 'st' => 'FAILURE']; // InsufficientFunds $mock['F3003'] = [ 'ret' => 'F300', 'st' => 'FAILURE']; // InsufficientFunds
$mock['F3005'] = [ 'ret' => 'F300', 'st' => 'FAILURE']; // AccountHasProblems $mock['F3005'] = [ 'ret' => 'F300', 'st' => 'FAILURE']; // AccountHasProblems
$mock['F3010'] = [ 'ret' => 'F300', 'st' => 'FAILURE']; // CustomerSurpassedDailyVelocityLimit $mock['F3010'] = [ 'ret' => 'F300', 'st' => 'FAILURE']; // CustomerSurpassedDailyVelocityLimit
$mock['F4000'] = [ 'ret' => 'F400', 'st' => 'RESEND']; // SystemTemporarilyUnavailable $mock['F4000'] = [ 'ret' => 'F400', 'st' => 'RESEND']; // SystemTemporarilyUnavailable
$mock['F5000'] = [ 'ret' => 'F500', 'st' => 'FAILURE']; // UnknownError $mock['F5000'] = [ 'ret' => 'F500', 'st' => 'FAILURE']; // UnknownError
foreach ($mock as $creation_id => $mock_return) { foreach ($mock as $creation_id => $mock_return) {
print "<b>TS: " . microtime() . "</b>: "; print "<b>TS: " . microtime() . "</b>: ";
try { try {
$aws_test = AmazonIncentives::make()->buyGiftCard((float)$mock_value, $creation_id); $aws_test = AmazonIncentives::make()->buyGiftCard((float)$mock_value, $creation_id);
$creation_request_id = $aws_test->getCreationRequestId(); $creation_request_id = $aws_test->getCreationRequestId();
$gift_card_id = $aws_test->getId(); $gift_card_id = $aws_test->getId();
$claim_code = $aws_test->getClaimCode(); $claim_code = $aws_test->getClaimCode();
$request_status = $aws_test->getStatus(); $request_status = $aws_test->getStatus();
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: <b>" . $request_status . "</b>: " print "AWS: MOCK: " . $creation_id . ": buyGiftCard: <b>" . $request_status . "</b>: "
. "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", " . "creationRequestId: " . $creation_request_id . ", gcId: " . $gift_card_id . ", "
. "CLAIM CODE: <b>" . $claim_code . "</b>: "; . "CLAIM CODE: <b>" . $claim_code . "</b>: ";
if ($mock_return['st'] == $request_status) { if ($mock_return['st'] == $request_status) {
print $mock_ok; print $mock_ok;
} else { } else {
print $mock_failure; print $mock_failure;
} }
if ($mock_debug === true) { if ($mock_debug === true) {
print "<pre>" . print_r($aws_test, true) . "</pre>"; print "<pre>" . print_r($aws_test, true) . "</pre>";
} }
fwrite($fp, writeLog((array)$aws_test)); fwrite($fp, writeLog((array)$aws_test));
} catch (Exception $e) { } catch (Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage()); $error = AmazonErrors::decodeExceptionMessage($e->getMessage());
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $error['status'] print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $error['status']
. " [" . $e->getCode() . "]: " . " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type'] . $error['code'] . " | " . $error['type']
. " | " . $error['message'] . ": "; . " | " . $error['message'] . ": ";
if ( if (
$mock_return['ret'] == $error['code'] && $mock_return['ret'] == $error['code'] &&
$mock_return['st'] == $error['status'] $mock_return['st'] == $error['status']
) { ) {
print $mock_ok; print $mock_ok;
} else { } else {
print $mock_failure; print $mock_failure;
} }
if ($mock_debug === true) { if ($mock_debug === true) {
print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>"; print "<pre>" . print_r($error['log'][$error['log_id'] ?? ''] ?? [], true) . "</pre>";
} }
fwrite($fp, writeLog($error)); fwrite($fp, writeLog($error));
} }
print "<br>"; print "<br>";
// Waiting a moment, so we don't flood // Waiting a moment, so we don't flood
sleep($mock_wait); sleep($mock_wait);
} }
print "<hr>"; print "<hr>";
} }
fclose($fp); fclose($fp);

View File

@@ -0,0 +1,23 @@
<?php
// just print out env data nd connect data
// checkMe from AmazonIntentives call is requal to
// run_info_test === true in aws_gift_card_tests.php
$loader = require '../vendor/autoload.php';
// need to add this or it will not load here
$loader->addPsr4('gullevek\\', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'src');
// print "LOADER: <pre>" . print_r($loader, true) . "</pre>";
use gullevek\AmazonIncentives\AmazonIncentives;
use gullevek\dotEnv\DotEnv;
// load env data with dotenv
DotEnv::readEnvFile(__DIR__);
print "_ENV: <pre>" . print_r($_ENV, true) . "</pre>";
$aws = new AmazonIncentives();
print "checkMe: <pre>" . print_r($aws->checkMe(), true) . "</pre>";
// __END__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
<?php
// strip the final name from a to be mocked class
declare(strict_types=1);
namespace test\phpUnit\Hook;
use DG\BypassFinals;
use PHPUnit\Runner\BeforeFirstTestHook;
// only works if it is the FIRST load and not before EACH test
final class BypassFinalHook implements BeforeFirstTestHook
{
public function executeBeforeFirstTest(): void
{
BypassFinals::enable();
}
}
// __END__

View File

@@ -1,84 +0,0 @@
<?php
/**
* parses .env file
*
* Rules for .env file
* variable is any alphanumeric string followed by = on the same line
* content starts with the first non space part
* strings can be contained in "
* strings MUST be contained in " if they are multiline
* if string starts with " it will match until another " is found
* anything AFTER " is ignored
* if there are two variables with the same name only the first is used
* variables are case sensitive
*
* @param string $path Folder to file, default is __DIR__
* @param string $env_file What file to load, default is .env
* @return int -1 other error
* 0 for success full load
* 1 for file loadable, but no data inside
* 2 for file not readable
* 3 for file not found
*/
function readEnvFile(string $path = __DIR__, string $env_file = '.env'): int
{
// default -1;
$status = -1;
$env_file_target = $path . DIRECTORY_SEPARATOR . $env_file;
// this is not a file -> abort
if (!is_file($env_file_target)) {
$status = 3;
return $status;
}
// cannot open file -> abort
if (($fp = fopen($env_file_target, 'r')) === false) {
$status = 2;
return $status;
}
// set to readable but not yet any data loaded
$status = 1;
$block = false;
$var = '';
while ($line = fgets($fp)) {
// main match for variable = value part
if (preg_match("/^\s*([\w_.]+)\s*=\s*((\"?).*)/", $line, $matches)) {
$var = $matches[1];
$value = $matches[2];
$quotes = $matches[3];
// wirte only if env is not set yet, and write only the first time
if (empty($_ENV[$var])) {
if (!empty($quotes)) {
// match greedy for first to last so we move any " if there are
if (preg_match('/^"(.*[^\\\])"/U', $value, $matches)) {
$value = $matches[1];
} else {
// this is a multi line
$block = true;
// first " in string remove
// add removed new line back because this is a multi line
$value = ltrim($value, '"') . PHP_EOL;
}
}
// if block is set, we strip line of slashes
$_ENV[$var] = $block === true ? stripslashes($value) : $value;
// set successful load
$status = 0;
}
} elseif ($block === true) {
// read line until there is a unescaped "
// this also strips everything after the last "
if (preg_match("/(.*[^\\\])\"/", $line, $matches)) {
$block = false;
// strip ending " and EVERYTHING that follows after that
$line = $matches[1];
}
// strip line of slashes
$_ENV[$var] .= stripslashes($line);
}
}
fclose($fp);
return $status;
}
// __END__

2
tmp/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

7
vendor/autoload.php vendored
View File

@@ -1,7 +0,0 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64::getLoader();

View File

@@ -1,572 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-var array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
}

View File

@@ -1,21 +0,0 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,10 +0,0 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@@ -1,9 +0,0 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -1,10 +0,0 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'gullevek\\AmazonIncentives\\' => array($baseDir . '/src'),
);

View File

@@ -1,55 +0,0 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit0c8f6bec90a6d60040a922f19a1f0e64', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

View File

@@ -1,36 +0,0 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64
{
public static $prefixLengthsPsr4 = array (
'G' =>
array (
'gullevek\\AmazonIncentives\\' => 26,
),
);
public static $prefixDirsPsr4 = array (
'gullevek\\AmazonIncentives\\' =>
array (
0 => __DIR__ . '/../..' . '/src',
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit0c8f6bec90a6d60040a922f19a1f0e64::$classMap;
}, null, ClassLoader::class);
}
}