update
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "pay-now/paynow-php-sdk",
|
||||
"description": "PHP client library for accessing Paynow API",
|
||||
"version": "2.2.2",
|
||||
"version": "2.4.4",
|
||||
"keywords": [
|
||||
"paynow",
|
||||
"mbank",
|
||||
@@ -20,7 +20,7 @@
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=7.1",
|
||||
"php": ">=7.2",
|
||||
"psr/http-message": "^1.0 || ^2.0",
|
||||
"php-http/client-implementation": "^1.0 || ^2.0",
|
||||
"php-http/message-factory": "^1.0 || ^2.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"php-http/httplug": "^2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"phpunit/phpunit": "^8.5.36",
|
||||
"php-http/mock-client": "^1.3",
|
||||
"squizlabs/php_codesniffer": "^3.4",
|
||||
"friendsofphp/php-cs-fixer": "^2.15",
|
||||
@@ -52,5 +52,11 @@
|
||||
"test": "vendor/bin/phpunit",
|
||||
"cs-check": "php-cs-fixer fix --no-interaction --dry-run --diff",
|
||||
"cs-fix": "php-cs-fixer fix -v --diff"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public const API_VERSION = 'v1';
|
||||
public const API_VERSION_V2 = 'v2';
|
||||
public const API_VERSION_V3 = 'v3';
|
||||
|
||||
public const API_PRODUCTION_URL = 'https://api.paynow.pl';
|
||||
public const API_SANDBOX_URL = 'https://api.sandbox.paynow.pl';
|
||||
public const USER_AGENT = 'paynow-php-sdk';
|
||||
@@ -32,7 +34,7 @@ class Configuration implements ConfigurationInterface
|
||||
*/
|
||||
private function get($key)
|
||||
{
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
return $this->data[$key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,11 +13,11 @@ class PaynowException extends Exception
|
||||
/**
|
||||
* PaynowException constructor.
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param int|null $code
|
||||
* @param string|null $body
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(string $message, int $code = 0, ?string $body = null, Throwable $previous = null)
|
||||
public function __construct(string $message, ?int $code = 0, ?string $body = null, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
namespace Paynow\HttpClient;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
class ApiResponse
|
||||
{
|
||||
/**
|
||||
* Body content
|
||||
*
|
||||
* @var string
|
||||
* @var StreamInterface
|
||||
*/
|
||||
public $body;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class HttpClient implements HttpClientInterface
|
||||
} catch (NotFoundException $exception) {
|
||||
$this->client = HttpClientDiscovery::find();
|
||||
}
|
||||
$this->url = Psr17FactoryDiscovery::findUrlFactory()->createUri((string)$config->getUrl());
|
||||
$this->url = Psr17FactoryDiscovery::findUriFactory()->createUri((string)$config->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,8 +60,8 @@ class HttpClient implements HttpClientInterface
|
||||
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @throws HttpClientException
|
||||
* @return ApiResponse
|
||||
* @throws HttpClientException
|
||||
*/
|
||||
private function send(RequestInterface $request): ApiResponse
|
||||
{
|
||||
@@ -76,16 +76,17 @@ class HttpClient implements HttpClientInterface
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
* @param string|null $idempotencyKey
|
||||
* @throws HttpClientException
|
||||
* @return ApiResponse
|
||||
* @throws HttpClientException
|
||||
*/
|
||||
public function post(string $url, array $data, ?string $idempotencyKey = null): ApiResponse
|
||||
{
|
||||
$headers = $this->prepareHeaders($data);
|
||||
$isv3 = strpos($url, Configuration::API_VERSION_V3) !== false;
|
||||
$headers = $this->prepareHeaders($data, [], $idempotencyKey, $isv3);
|
||||
|
||||
if ($idempotencyKey) {
|
||||
$headers['Idempotency-Key'] = $idempotencyKey;
|
||||
}
|
||||
if ($idempotencyKey && !$isv3) {
|
||||
$headers['Idempotency-Key'] = $idempotencyKey;
|
||||
}
|
||||
|
||||
$request = $this->messageFactory->createRequest(
|
||||
'POST',
|
||||
@@ -104,12 +105,13 @@ class HttpClient implements HttpClientInterface
|
||||
/**
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
* @throws HttpClientException
|
||||
* @param string|null $idempotencyKey
|
||||
* @return ApiResponse
|
||||
* @throws HttpClientException
|
||||
*/
|
||||
public function patch(string $url, array $data): ApiResponse
|
||||
public function patch(string $url, array $data, ?string $idempotencyKey = null): ApiResponse
|
||||
{
|
||||
$headers = $this->prepareHeaders($data);
|
||||
$headers = $this->prepareHeaders($data, [], $idempotencyKey, strpos($url, Configuration::API_VERSION_V3) !== false);
|
||||
$request = $this->messageFactory->createRequest(
|
||||
'PATCH',
|
||||
$this->url->withPath($url)
|
||||
@@ -127,17 +129,49 @@ class HttpClient implements HttpClientInterface
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string|null $query
|
||||
* @throws HttpClientException
|
||||
* @param string|null $idempotencyKey
|
||||
* @return ApiResponse
|
||||
* @throws HttpClientException
|
||||
*/
|
||||
public function get(string $url, string $query = null): ApiResponse
|
||||
public function get(string $url, ?string $query = null, ?string $idempotencyKey = null): ApiResponse
|
||||
{
|
||||
$request = $this->messageFactory->createRequest(
|
||||
'GET',
|
||||
$query ? $this->url->withPath($url)->withQuery($query) : $this->url->withPath($url)
|
||||
);
|
||||
|
||||
foreach ($this->prepareHeaders() as $name => $value) {
|
||||
$parameters = [];
|
||||
if ($query) {
|
||||
parse_str(urldecode($query), $parameters);
|
||||
}
|
||||
|
||||
foreach ($this->prepareHeaders(null, $parameters, $idempotencyKey, strpos($url, Configuration::API_VERSION_V3) !== false) as $name => $value) {
|
||||
$request = $request->withHeader($name, $value);
|
||||
}
|
||||
|
||||
return $this->send($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $idempotencyKey
|
||||
* @param string|null $query
|
||||
* @return ApiResponse
|
||||
* @throws HttpClientException
|
||||
*/
|
||||
public function delete(string $url, string $idempotencyKey, ?string $query = null): ApiResponse
|
||||
{
|
||||
$request = $this->messageFactory->createRequest(
|
||||
'DELETE',
|
||||
$query ? $this->url->withPath($url)->withQuery($query) : $this->url->withPath($url)
|
||||
);
|
||||
|
||||
$parameters = [];
|
||||
if ($query) {
|
||||
parse_str(urldecode($query), $parameters);
|
||||
}
|
||||
|
||||
foreach ($this->prepareHeaders(null, $parameters, $idempotencyKey, strpos($url, Configuration::API_VERSION_V3) !== false) as $name => $value) {
|
||||
$request = $request->withHeader($name, $value);
|
||||
}
|
||||
|
||||
@@ -150,24 +184,40 @@ class HttpClient implements HttpClientInterface
|
||||
*/
|
||||
private function arrayAsJson(array $data): string
|
||||
{
|
||||
return json_encode($data);
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|array $data
|
||||
* @param array|null $body
|
||||
* @param array $query
|
||||
* @param string|null $idempotencyKey
|
||||
* @param bool $isv3
|
||||
* @return array
|
||||
*/
|
||||
private function prepareHeaders(?array $data = null)
|
||||
private function prepareHeaders(?array $body = null, array $query = [], ?string $idempotencyKey = '', bool $isv3 = true): array
|
||||
{
|
||||
$headers = [
|
||||
'Api-Key' => $this->config->getApiKey(),
|
||||
'User-Agent' => $this->getUserAgent(),
|
||||
'Accept' => 'application/json'
|
||||
'Accept' => 'application/json',
|
||||
];
|
||||
|
||||
if ($data) {
|
||||
if ($isv3) {
|
||||
$headers['Idempotency-Key'] = $idempotencyKey;
|
||||
$headers['Signature'] = SignatureCalculator::generateV3(
|
||||
$this->config->getApiKey(),
|
||||
$this->config->getSignatureKey(),
|
||||
$idempotencyKey,
|
||||
$body ? json_encode($body, JSON_UNESCAPED_SLASHES) : '',
|
||||
$query
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_null($body)) {
|
||||
$headers['Content-Type'] = 'application/json';
|
||||
$headers['Signature'] = (string)new SignatureCalculator($this->config->getSignatureKey(), json_encode($data));
|
||||
if (!$isv3) {
|
||||
$headers['Signature'] = SignatureCalculator::generate($this->config->getSignatureKey(), json_encode($body, JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
|
||||
@@ -6,7 +6,9 @@ interface HttpClientInterface
|
||||
{
|
||||
public function post(string $url, array $data, ?string $idempotencyKey = null): ApiResponse;
|
||||
|
||||
public function patch(string $url, array $data): ApiResponse;
|
||||
public function patch(string $url, array $data, ?string $idempotencyKey = null): ApiResponse;
|
||||
|
||||
public function get(string $url, ?string $query = null): ApiResponse;
|
||||
public function get(string $url, ?string $query = null, ?string $idempotencyKey = null): ApiResponse;
|
||||
|
||||
public function delete(string $url, string $idempotencyKey, ?string $query = null): ApiResponse;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,12 @@ class PaymentMethod
|
||||
private $image;
|
||||
private $status;
|
||||
private $authorizationType;
|
||||
/**
|
||||
* @var SavedInstrument[]
|
||||
*/
|
||||
private $savedInstruments = [];
|
||||
|
||||
public function __construct($id, $type, $name, $description, $image, $status, $authorizationType)
|
||||
public function __construct($id, $type, $name, $description, $image, $status, $authorizationType, $savedInstruments = [])
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->type = $type;
|
||||
@@ -21,6 +25,18 @@ class PaymentMethod
|
||||
$this->image = $image;
|
||||
$this->status = $status;
|
||||
$this->authorizationType = $authorizationType;
|
||||
if (!empty($savedInstruments)) {
|
||||
foreach ($savedInstruments as $savedInstrument) {
|
||||
$this->savedInstruments[] = new SavedInstrument(
|
||||
$savedInstrument->name,
|
||||
$savedInstrument->expirationDate,
|
||||
$savedInstrument->brand,
|
||||
$savedInstrument->image,
|
||||
$savedInstrument->token,
|
||||
$savedInstrument->status
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getId()
|
||||
@@ -65,4 +81,12 @@ class PaymentMethod
|
||||
{
|
||||
return $this->authorizationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SavedInstrument[]
|
||||
*/
|
||||
public function getSavedInstruments()
|
||||
{
|
||||
return $this->savedInstruments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,6 @@ class Type
|
||||
public const GOOGLE_PAY = 'GOOGLE_PAY';
|
||||
public const APPLE_PAY = 'APPLE_PAY';
|
||||
public const PBL = 'PBL';
|
||||
public const PAYPO = 'PAYPO';
|
||||
public const CLICK_TO_PAY = 'CLICK_TO_PAY';
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class PaymentMethods
|
||||
/**
|
||||
* @var PaymentMethod[]
|
||||
*/
|
||||
private $list;
|
||||
private $list = [];
|
||||
|
||||
public function __construct($body)
|
||||
{
|
||||
@@ -25,7 +25,8 @@ class PaymentMethods
|
||||
$item->description,
|
||||
$item->image,
|
||||
$item->status,
|
||||
$item->authorizationType ?? null
|
||||
$item->authorizationType ?? null,
|
||||
$item->savedInstruments ?? []
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,25 +13,30 @@ class DataProcessing extends Service
|
||||
* Retrieve data processing notice
|
||||
*
|
||||
* @param string|null $locale
|
||||
*
|
||||
* @throws PaynowException
|
||||
* @param string|null $idempotencyKey
|
||||
* @return Notices
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function getNotices(?string $locale): Notices
|
||||
public function getNotices(?string $locale, ?string $idempotencyKey = null): Notices
|
||||
{
|
||||
$parameters = [];
|
||||
if (! empty($locale)) {
|
||||
if (!empty($locale)) {
|
||||
$parameters['locale'] = $locale;
|
||||
}
|
||||
|
||||
try {
|
||||
if (empty($idempotencyKey)) {
|
||||
$idempotencyKey = md5(($locale ?? '') . '_' . $this->getClient()->getConfiguration()->getApiKey());
|
||||
}
|
||||
|
||||
$decodedApiResponse = $this->getClient()
|
||||
->getHttpClient()
|
||||
->get(
|
||||
Configuration::API_VERSION . "/payments/dataprocessing/notices",
|
||||
http_build_query($parameters, '', '&')
|
||||
)
|
||||
->decode();
|
||||
->getHttpClient()
|
||||
->get(
|
||||
Configuration::API_VERSION_V3 . "/payments/dataprocessing/notices",
|
||||
http_build_query($parameters, '', '&'),
|
||||
$idempotencyKey
|
||||
)
|
||||
->decode();
|
||||
|
||||
return new Notices($decodedApiResponse);
|
||||
} catch (HttpClientException $exception) {
|
||||
|
||||
@@ -16,25 +16,29 @@ class Payment extends Service
|
||||
*
|
||||
* @param array $data
|
||||
* @param string|null $idempotencyKey
|
||||
* @throws PaynowException
|
||||
* @return Authorize
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function authorize(array $data, ?string $idempotencyKey = null): Authorize
|
||||
{
|
||||
try {
|
||||
if (empty($idempotencyKey)) {
|
||||
$idempotencyKey = ($data['externalId'] ?? null) ? md5($data['externalId']) : md5('_' . $this->getClient()->getConfiguration()->getApiKey());
|
||||
}
|
||||
|
||||
$decodedApiResponse = $this->getClient()
|
||||
->getHttpClient()
|
||||
->post(
|
||||
'/' . Configuration::API_VERSION . '/payments',
|
||||
'/' . Configuration::API_VERSION_V3 . '/payments',
|
||||
$data,
|
||||
$idempotencyKey ?? $data['externalId']
|
||||
$idempotencyKey
|
||||
)
|
||||
->decode();
|
||||
|
||||
return new Authorize(
|
||||
$decodedApiResponse->paymentId,
|
||||
$decodedApiResponse->status,
|
||||
! empty($decodedApiResponse->redirectUrl) ? $decodedApiResponse->redirectUrl : null
|
||||
!empty($decodedApiResponse->redirectUrl) ? $decodedApiResponse->redirectUrl : null
|
||||
);
|
||||
} catch (HttpClientException $exception) {
|
||||
throw new PaynowException(
|
||||
@@ -52,30 +56,42 @@ class Payment extends Service
|
||||
* @param string|null $currency
|
||||
* @param int|null $amount
|
||||
* @param bool $applePayEnabled
|
||||
* @param string|null $idempotencyKey
|
||||
* @param string|null $buyerExternalId
|
||||
* @return PaymentMethods
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function getPaymentMethods(?string $currency = null, ?int $amount = 0, bool $applePayEnabled = true): PaymentMethods
|
||||
public function getPaymentMethods(?string $currency = null, ?int $amount = 0, bool $applePayEnabled = true, ?string $idempotencyKey = null, ?string $buyerExternalId = null): PaymentMethods
|
||||
{
|
||||
$parameters = [
|
||||
'applePayEnabled' => $applePayEnabled,
|
||||
];
|
||||
if (! empty($currency)) {
|
||||
$parameters['currency'] = $currency;
|
||||
}
|
||||
$parameters = [];
|
||||
|
||||
if ($amount > 0) {
|
||||
$parameters['amount'] = $amount;
|
||||
}
|
||||
|
||||
$parameters['applePayEnabled'] = $applePayEnabled;
|
||||
|
||||
if (!empty($currency)) {
|
||||
$parameters['currency'] = $currency;
|
||||
}
|
||||
|
||||
if (!empty($buyerExternalId)) {
|
||||
$parameters['externalBuyerId'] = $buyerExternalId;
|
||||
}
|
||||
|
||||
try {
|
||||
if (empty($idempotencyKey)) {
|
||||
$idempotencyKey = md5($currency . '_' . $amount . '_' . $this->getClient()->getConfiguration()->getApiKey());
|
||||
}
|
||||
|
||||
$decodedApiResponse = $this->getClient()
|
||||
->getHttpClient()
|
||||
->get(
|
||||
Configuration::API_VERSION_V2 . '/payments/paymentmethods',
|
||||
http_build_query($parameters, '', '&')
|
||||
)
|
||||
->decode();
|
||||
->getHttpClient()
|
||||
->get(
|
||||
Configuration::API_VERSION_V3 . '/payments/paymentmethods',
|
||||
http_build_query($parameters, '', '&'),
|
||||
$idempotencyKey
|
||||
)
|
||||
->decode();
|
||||
return new PaymentMethods($decodedApiResponse);
|
||||
} catch (HttpClientException $exception) {
|
||||
throw new PaynowException(
|
||||
@@ -87,19 +103,59 @@ class Payment extends Service
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $externalBuyerId
|
||||
* @param string $token
|
||||
* @param string $idempotencyKey
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function removeSavedInstrument(string $externalBuyerId, string $token, string $idempotencyKey): void
|
||||
{
|
||||
$parameters = [
|
||||
'externalBuyerId' => $externalBuyerId,
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
try {
|
||||
$this->getClient()
|
||||
->getHttpClient()
|
||||
->delete(
|
||||
Configuration::API_VERSION_V3 . '/payments/paymentmethods/saved',
|
||||
$idempotencyKey,
|
||||
http_build_query($parameters, '', '&')
|
||||
);
|
||||
} catch (HttpClientException $exception) {
|
||||
throw new PaynowException(
|
||||
$exception->getMessage(),
|
||||
$exception->getStatus(),
|
||||
$exception->getBody(),
|
||||
$exception
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve payment status
|
||||
*
|
||||
* @param string $paymentId
|
||||
* @throws PaynowException
|
||||
* @param string|null $idempotencyKey
|
||||
* @return Status
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function status(string $paymentId): Status
|
||||
public function status(string $paymentId, ?string $idempotencyKey = null): Status
|
||||
{
|
||||
try {
|
||||
if (empty($idempotencyKey)) {
|
||||
$idempotencyKey = md5($paymentId);
|
||||
}
|
||||
|
||||
$decodedApiResponse = $this->getClient()
|
||||
->getHttpClient()
|
||||
->get(Configuration::API_VERSION . "/payments/$paymentId/status")
|
||||
->get(
|
||||
Configuration::API_VERSION_V3 . "/payments/$paymentId/status",
|
||||
null,
|
||||
$idempotencyKey
|
||||
)
|
||||
->decode();
|
||||
|
||||
return new Status($decodedApiResponse->paymentId, $decodedApiResponse->status);
|
||||
|
||||
@@ -16,8 +16,8 @@ class Refund extends Service
|
||||
* @param string $idempotencyKey
|
||||
* @param int $amount
|
||||
* @param null $reason
|
||||
* @throws PaynowException
|
||||
* @return Status
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function create(string $paymentId, string $idempotencyKey, int $amount, $reason = null): Status
|
||||
{
|
||||
@@ -25,7 +25,7 @@ class Refund extends Service
|
||||
$decodedApiResponse = $this->getClient()
|
||||
->getHttpClient()
|
||||
->post(
|
||||
'/' . Configuration::API_VERSION . '/payments/' . $paymentId . '/refunds',
|
||||
'/' . Configuration::API_VERSION_V3 . '/payments/' . $paymentId . '/refunds',
|
||||
[
|
||||
'amount' => $amount,
|
||||
'reason' => $reason
|
||||
@@ -45,17 +45,25 @@ class Refund extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve refund status
|
||||
* @param $refundId
|
||||
* @throws PaynowException
|
||||
* @param string|null $idempotencyKey
|
||||
* @return Status
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function status($refundId): Status
|
||||
public function status($refundId, ?string $idempotencyKey = null): Status
|
||||
{
|
||||
try {
|
||||
if (empty($idempotencyKey)) {
|
||||
$idempotencyKey = md5($refundId);
|
||||
}
|
||||
|
||||
$decodedApiResponse = $this->getClient()
|
||||
->getHttpClient()
|
||||
->get(Configuration::API_VERSION . "/refunds/$refundId/status")
|
||||
->get(
|
||||
Configuration::API_VERSION_V3 . "/refunds/$refundId/status",
|
||||
null,
|
||||
$idempotencyKey
|
||||
)
|
||||
->decode();
|
||||
|
||||
return new Status($decodedApiResponse->refundId, $decodedApiResponse->status);
|
||||
|
||||
@@ -9,24 +9,35 @@ use Paynow\HttpClient\HttpClientException;
|
||||
|
||||
class ShopConfiguration extends Service
|
||||
{
|
||||
/**
|
||||
* @param string $continueUrl
|
||||
* @param string $notificationUrl
|
||||
* @throws PaynowException
|
||||
* @return ApiResponse
|
||||
*/
|
||||
public function changeUrls(string $continueUrl, string $notificationUrl)
|
||||
public const STATUS_ENABLED = 'ENABLED';
|
||||
public const STATUS_DISABLED = 'DISABLED';
|
||||
public const STATUS_UNINSTALLED = 'UNINSTALLED';
|
||||
public const STATUS_UPDATED = 'UPDATED';
|
||||
|
||||
/**
|
||||
* @param string $continueUrl
|
||||
* @param string $notificationUrl
|
||||
* @param string|null $idempotencyKey
|
||||
* @return ApiResponse
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function changeUrls(string $continueUrl, string $notificationUrl, ?string $idempotencyKey = null): ApiResponse
|
||||
{
|
||||
$data = [
|
||||
'continueUrl' => $continueUrl,
|
||||
'notificationUrl' => $notificationUrl,
|
||||
];
|
||||
try {
|
||||
if (empty($idempotencyKey)) {
|
||||
$idempotencyKey = md5($this->getClient()->getConfiguration()->getApiKey());
|
||||
}
|
||||
|
||||
return $this->getClient()
|
||||
->getHttpClient()
|
||||
->patch(
|
||||
'/' . Configuration::API_VERSION.'/configuration/shop/urls',
|
||||
$data
|
||||
'/' . Configuration::API_VERSION_V3 . '/configuration/shop/urls',
|
||||
$data,
|
||||
$idempotencyKey
|
||||
);
|
||||
} catch (HttpClientException $exception) {
|
||||
throw new PaynowException(
|
||||
@@ -37,4 +48,31 @@ class ShopConfiguration extends Service
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $statuses
|
||||
* @return ApiResponse
|
||||
* @throws PaynowException
|
||||
*/
|
||||
public function status(array $statuses): ApiResponse
|
||||
{
|
||||
try {
|
||||
$idempotencyKey = md5($this->getClient()->getConfiguration()->getApiKey());
|
||||
|
||||
return $this->getClient()
|
||||
->getHttpClient()
|
||||
->post(
|
||||
'/' . Configuration::API_VERSION_V3 . '/configuration/shop/plugin/status',
|
||||
$statuses,
|
||||
$idempotencyKey
|
||||
);
|
||||
} catch (HttpClientException $exception) {
|
||||
throw new PaynowException(
|
||||
$exception->getMessage(),
|
||||
$exception->getStatus(),
|
||||
$exception->getBody(),
|
||||
$exception
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,56 @@ class SignatureCalculator
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(string $signatureKey, string $data)
|
||||
{
|
||||
$this->hash = self::generate($signatureKey, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $apiKey
|
||||
* @param string $signatureKey
|
||||
* @param string $idempotencyKey
|
||||
* @param string $data
|
||||
* @param array $parameters
|
||||
* @return string
|
||||
*/
|
||||
public static function generateV3(string $apiKey, string $signatureKey, string $idempotencyKey, string $data = '', array $parameters = []): string
|
||||
{
|
||||
if (empty($apiKey)) {
|
||||
throw new InvalidArgumentException('You did not provide a api key');
|
||||
}
|
||||
|
||||
if (empty($signatureKey)) {
|
||||
throw new InvalidArgumentException('You did not provide a Signature key');
|
||||
}
|
||||
|
||||
if (empty($idempotencyKey)) {
|
||||
throw new InvalidArgumentException('You did not provide a idempotency key');
|
||||
}
|
||||
|
||||
$parsedParameters = [];
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
$parsedParameters[$key] = is_array($value) ? $value : [$value];
|
||||
}
|
||||
|
||||
$signatureBody = [
|
||||
'headers' => [
|
||||
'Api-Key' => $apiKey,
|
||||
'Idempotency-Key' => $idempotencyKey,
|
||||
],
|
||||
'parameters' => $parsedParameters ?: new \stdClass(),
|
||||
'body' => $data,
|
||||
];
|
||||
|
||||
return base64_encode(hash_hmac('sha256', json_encode($signatureBody, JSON_UNESCAPED_SLASHES), $signatureKey, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $signatureKey
|
||||
* @param string $data
|
||||
* @return string
|
||||
*/
|
||||
public static function generate(string $signatureKey, string $data): string
|
||||
{
|
||||
if (empty($signatureKey)) {
|
||||
throw new InvalidArgumentException('You did not provide a Signature key');
|
||||
@@ -23,7 +73,8 @@ class SignatureCalculator
|
||||
if (empty($data)) {
|
||||
throw new InvalidArgumentException('You did not provide any data');
|
||||
}
|
||||
$this->hash = base64_encode(hash_hmac('sha256', $data, $signatureKey, true));
|
||||
|
||||
return base64_encode(hash_hmac('sha256', $data, $signatureKey, true));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,7 @@ class NotificationTest extends TestCase
|
||||
* @param $payload
|
||||
* @param $headers
|
||||
* @throws SignatureVerificationException
|
||||
* @suppress PhanNoopNew
|
||||
*/
|
||||
public function testVerifyPayloadSuccessfully($payload, $headers)
|
||||
{
|
||||
@@ -40,6 +41,11 @@ class NotificationTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws SignatureVerificationException
|
||||
* @suppress PhanNoopNew
|
||||
*/
|
||||
public function testShouldThrowExceptionOnIncorrectSignature()
|
||||
{
|
||||
// given
|
||||
@@ -53,12 +59,14 @@ class NotificationTest extends TestCase
|
||||
// then
|
||||
}
|
||||
|
||||
/**
|
||||
* @suppress PhanNoopNew
|
||||
* @return void
|
||||
*/
|
||||
public function testShouldThrowExceptionOnMissingPayload()
|
||||
{
|
||||
// given
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$payload = null;
|
||||
$headers = [];
|
||||
|
||||
// when
|
||||
new Notification('s3ecret-k3y', null, null);
|
||||
@@ -66,12 +74,16 @@ class NotificationTest extends TestCase
|
||||
// then
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws SignatureVerificationException
|
||||
* @suppress PhanNoopNew
|
||||
*/
|
||||
public function testShouldThrowExceptionOnMissingPayloadHeaders()
|
||||
{
|
||||
// given
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$payload = $this->loadData('notification.json', true);
|
||||
$headers = null;
|
||||
|
||||
// when
|
||||
new Notification('s3ecret-k3y', $payload, null);
|
||||
|
||||
@@ -12,6 +12,9 @@ class TestCase extends BaseTestCase
|
||||
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @suppress PhanAccessMethodInternal
|
||||
*/
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
$this->client = new Client(
|
||||
|
||||
Reference in New Issue
Block a user