diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ea652382..ae228866 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -60,7 +60,11 @@ jobs:
grep -r -l "$string" tests/ | xargs sed -i "s/$string//g"
- name: PHPUnit
- run: composer exec phpunit -- --configuration phpunit.ci.xml --coverage-xml ./.coverage
+ run: |
+ case ${{ matrix.php }} in
+ 8.1|8.2|8.3 ) composer exec phpunit -- --configuration phpunit.ci.8.xml --coverage-xml ./.coverage;;
+ *) composer exec phpunit -- --configuration phpunit.ci.xml --coverage-xml ./.coverage;;
+ esac
env:
XDEBUG_MODE: coverage
diff --git a/.gitignore b/.gitignore
index dd74e98b..ee982aca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,5 @@ phpunit.xml
.phpunit.cache/
composer.lock
.DS_Store
-.env
\ No newline at end of file
+.env
+.coverage/
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 75370ae0..b75e4d03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# CHANGELOG
+## v2.2.0 - 2024-09-05
+
+### Changes
+
+### 🚀 New Features
+
+- Add function for HMAC verification (#132)
+
+#### Contributors
+
+@Benjamin-Freoua-Alma, @CamilleFljt, @Francois-Gomis and @carine-bonnafous
+
## v2.1.0 - 2024-07-29
### Changes
@@ -149,6 +161,7 @@
// Handle errors
}
+
```
* Add fields and docs to the Payment entity
* Add a Refund entity and extract refunds data within the Payment entity constructor
@@ -268,10 +281,15 @@ Getting more serious with a 1.0.0 release! 🎉
## v0.0.1
* Initial "pre-release" of the API Client
+
* Includes two main endpoints: Payments and Merchants
+
* Provides what's necessary for a typical payment flow:
+
* `Payments.createPayment` and `Payments.eligibility`
* `Merchants.me`
* Base `Alma\API\Client` class can be configured with API key and live/test mode
+
* TLS is automatically forced to TLS 1.2 to meet Alma's security requirements, but configurable
+
diff --git a/Dockerfile b/Dockerfile
index 12545aa0..8796849a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,6 +3,7 @@ ARG COMPOSER_VERSION
FROM composer:${COMPOSER_VERSION} as composer
FROM php:${PHP_VERSION}-fpm
+ARG PHP_VERSION
ENV DEBIAN_FRONTEND noninteractive
@@ -16,6 +17,11 @@ RUN apt update && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+RUN case ${PHP_VERSION} in \
+ 8.0|8.1|8.2|8.3 ) pecl install xdebug-3.3.2 && docker-php-ext-enable xdebug;; \
+ *) pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug;; \
+ esac
+
RUN usermod -u 1000 www-data
RUN groupmod -g 1000 www-data
diff --git a/Dockerfile.legacy b/Dockerfile.legacy
index 4223fa91..1692a16f 100644
--- a/Dockerfile.legacy
+++ b/Dockerfile.legacy
@@ -20,6 +20,10 @@ RUN apt update && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+# Install xdebug for code coverage
+RUN pecl install xdebug-2.5.5 \
+&& docker-php-ext-enable xdebug
+
RUN usermod -u 1000 www-data
RUN groupmod -g 1000 www-data
diff --git a/Taskfile.php.yml b/Taskfile.php.yml
index 9c03f34f..65fc9160 100644
--- a/Taskfile.php.yml
+++ b/Taskfile.php.yml
@@ -27,9 +27,9 @@ tasks:
cmds:
- >-
{{ if eq .PHP_VERSION "5.6" "7.0" }}
- docker compose run {{ .COMPOSE_SERVICE }} ./tests/legacy_tests.sh
+ docker compose run --rm {{ .COMPOSE_SERVICE }} ./tests/legacy_tests.sh
{{ else }}
- docker compose run {{ .COMPOSE_SERVICE }} composer exec phpunit --verbose -- --configuration phpunit.dist.xml --testsuite "Alma PHP Client Unit Test Suite"
+ docker compose run --rm {{ .COMPOSE_SERVICE }} composer exec phpunit --verbose -- --configuration {{ .PHPUNIT_FILE }} --testsuite "Alma PHP Client Unit Test Suite" --coverage-xml ./.coverage
{{ end }}
tests:integration:
@@ -39,9 +39,9 @@ tasks:
cmds:
- >-
{{ if eq .PHP_VERSION "5.6" "7.0" }}
- docker compose run {{ .COMPOSE_SERVICE }} ./tests/legacy_integration_tests.sh
+ docker compose run --rm {{ .COMPOSE_SERVICE }} ./tests/legacy_integration_tests.sh
{{ else }}
- docker compose run {{ .COMPOSE_SERVICE }} composer exec phpunit --verbose -- --configuration phpunit.dist.xml --testsuite "Alma PHP Client Integration Test Suite"
+ docker compose run --rm {{ .COMPOSE_SERVICE }} composer exec phpunit --verbose -- --configuration {{ .PHPUNIT_FILE }} --testsuite "Alma PHP Client Integration Test Suite"
{{ end }}
shell:
@@ -49,5 +49,5 @@ tasks:
deps:
- docker:build
cmds:
- - sed 's/{MYVERSION}/{{ .PHPUNIT_VERSION }}/g' phpunit.dist.xml > phpunit.xml
- - docker compose run {{ .COMPOSE_SERVICE }} bash
+ - sed 's/{MYVERSION}/{{ .PHPUNIT_VERSION }}/g' {{ .PHPUNIT_FILE }} > phpunit.xml
+ - docker compose run --rm {{ .COMPOSE_SERVICE }} bash
diff --git a/Taskfile.yml b/Taskfile.yml
index 74ede9f8..2e09d806 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -44,14 +44,17 @@ includes:
taskfile: Taskfile.php.yml
vars:
PHP_VERSION: "8.1"
+ PHPUNIT_FILE: phpunit.dist.8.xml
"8.2":
taskfile: Taskfile.php.yml
vars:
PHP_VERSION: "8.2"
+ PHPUNIT_FILE: phpunit.dist.8.xml
"8.3":
taskfile: Taskfile.php.yml
vars:
PHP_VERSION: "8.3"
+ PHPUNIT_FILE: phpunit.dist.8.xml
tasks:
default:
diff --git a/compose.yml b/compose.yml
index b73909d7..7c3bd0c7 100644
--- a/compose.yml
+++ b/compose.yml
@@ -12,6 +12,8 @@ services:
volumes:
- ./:/app
- /app/vendor
+ environment:
+ XDEBUG_MODE: coverage
php-legacy:
user: ${UID:-1000}:${GID:-1000}
diff --git a/composer.json b/composer.json
index 6e02ebf4..f9c14f5e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "alma/alma-php-client",
"description": "PHP API client for the Alma payments API",
- "version": "2.1.0",
+ "version": "2.2.0",
"type": "library",
"require": {
"php": "^5.6 || ~7.0 || ~7.1 || ~7.2 || ~7.3 || ~7.4 || ~8.0 || ~8.1 || ~8.2 || ~8.3",
diff --git a/phpunit.ci.8.xml b/phpunit.ci.8.xml
new file mode 100644
index 00000000..851e6fb7
--- /dev/null
+++ b/phpunit.ci.8.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ tests/Unit
+
+
+
+
+
+
+
+
+ ./src/*
+
+
+
+
diff --git a/phpunit.dist.8.xml b/phpunit.dist.8.xml
new file mode 100644
index 00000000..550e8793
--- /dev/null
+++ b/phpunit.dist.8.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+ tests/Unit
+
+
+ tests/Integration
+
+
+
+
+
+
+
+
+ ./src/*
+
+
+
+
+
+
+
+
diff --git a/phpunit.dist.xml b/phpunit.dist.xml
index 72837d2a..e3ff90a3 100644
--- a/phpunit.dist.xml
+++ b/phpunit.dist.xml
@@ -1,5 +1,10 @@
-
+
tests/Unit
@@ -8,6 +13,11 @@
tests/Integration
+
+
+ ./src/*
+
+
diff --git a/src/Client.php b/src/Client.php
index ed371ea6..5176acb3 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -30,7 +30,7 @@
class Client
{
- const VERSION = '2.1.0';
+ const VERSION = '2.2.0';
const LIVE_MODE = 'live';
const TEST_MODE = 'test';
diff --git a/src/Lib/PaymentValidator.php b/src/Lib/PaymentValidator.php
index 8bdda9e5..cc4f0f0c 100644
--- a/src/Lib/PaymentValidator.php
+++ b/src/Lib/PaymentValidator.php
@@ -34,6 +34,9 @@
*/
class PaymentValidator
{
+
+ const HEADER_SIGNATURE_KEY = 'X-Alma-Signature';
+
/**
* Ensure that the purchase amount is an integer
*
@@ -53,4 +56,17 @@ public static function checkPurchaseAmount($data)
));
}
}
-}
\ No newline at end of file
+
+ /**
+ * @param string $data
+ * @param string $apiKey
+ * @param string $signature
+ * @return bool
+ */
+ public function isHmacValidated($data, $apiKey, $signature)
+ {
+ return is_string($data) &&
+ is_string($apiKey) &&
+ hash_hmac('sha256', $data, $apiKey) === $signature;
+ }
+}
diff --git a/tests/Unit/Lib/PaymentValidatorTest.php b/tests/Unit/Lib/PaymentValidatorTest.php
new file mode 100644
index 00000000..284288f4
--- /dev/null
+++ b/tests/Unit/Lib/PaymentValidatorTest.php
@@ -0,0 +1,128 @@
+paymentValidator = new PaymentValidator();
+ }
+
+ /**
+ * @dataProvider checkHmacInvalidDataProvider
+ * @param $data
+ * @param $apiKey
+ * @param $signature
+ * @return void
+ */
+ public function testHmacDataDifferentFromSignature($data, $apiKey, $signature)
+ {
+ $this->assertFalse($this->paymentValidator->isHmacValidated($data, $apiKey, $signature));
+ }
+
+ public function testHmacDataEqualsSignature()
+ {
+ $data = 'payment_id_test';
+ $apiKey = 'api_key_test';
+ $signature = '4545854d3b8704d4b21cf88bc8b5da5680c46b2ab9d45c8cffe6278d8a8b1860';
+
+ $this->assertTrue($this->paymentValidator->isHmacValidated($data, $apiKey, $signature));
+ }
+
+ public static function checkHmacInvalidDataProvider()
+ {
+ return [
+ 'String data' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 'api_key_test',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Empty array data' => [
+ 'data' => [],
+ 'apiKey' => 'api_key_test',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Empty array apiKey' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => [],
+ 'signature' => 'wrong_signature'
+ ],
+ 'Empty array signature' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 'api_key_test',
+ 'signature' => []
+ ],
+ 'Empty string data' => [
+ 'data' => '',
+ 'apiKey' => 'api_key_test',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Empty string apiKey' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => '',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Empty string signature' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 'api_key_test',
+ 'signature' => ''
+ ],
+ 'Object data' => [
+ 'data' => new stdClass(),
+ 'apiKey' => 'api_key_test',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Object apiKey' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => new stdClass(),
+ 'signature' => 'wrong_signature'
+ ],
+ 'Object signature' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 'api_key_test',
+ 'signature' => new stdClass()
+ ],
+ 'Boolean data' => [
+ 'data' => false,
+ 'apiKey' => 'api_key_test',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Boolean apiKey' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => true,
+ 'signature' => 'wrong_signature'
+ ],
+ 'Boolean signature' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 'api_key_test',
+ 'signature' => true
+ ],
+ 'Int data' => [
+ 'data' => 1,
+ 'apiKey' => 'api_key_test',
+ 'signature' => 'wrong_signature'
+ ],
+ 'Int apiKey' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 2,
+ 'signature' => 'wrong_signature'
+ ],
+ 'Int signature' => [
+ 'data' => 'payment_id_test',
+ 'apiKey' => 'api_key_test',
+ 'signature' => 3
+ ]
+
+ ];
+ }
+}
diff --git a/tests/legacy_tests.sh b/tests/legacy_tests.sh
index b21daaf9..a3eca141 100755
--- a/tests/legacy_tests.sh
+++ b/tests/legacy_tests.sh
@@ -11,4 +11,4 @@ string=': void'
grep -r -l "$string" tests/ | xargs sed -i "s/$string//g"
# Run tests
-composer exec phpunit --verbose -- --configuration phpunit.dist.xml --testsuite "Alma PHP Client Unit Test Suite"
+composer exec phpunit --verbose -- --configuration phpunit.dist.xml --testsuite "Alma PHP Client Unit Test Suite" --coverage-xml ./.coverage