diff --git a/EventListener/OrderLineEntityListener.php b/EventListener/OrderLineEntityListener.php index 063eddd..e642d34 100644 --- a/EventListener/OrderLineEntityListener.php +++ b/EventListener/OrderLineEntityListener.php @@ -21,7 +21,6 @@ */ class OrderLineEntityListener { - public static $MOLLIE_MAPPED_ATTRIBUTES = ['freeFormProduct', 'quantity', 'priceType']; /** * @var MollieDtoMapperInterface diff --git a/Form/EventListener/ChannelSettingsTypeSubscriber.php b/Form/EventListener/ChannelSettingsTypeSubscriber.php index b64570e..28384f6 100644 --- a/Form/EventListener/ChannelSettingsTypeSubscriber.php +++ b/Form/EventListener/ChannelSettingsTypeSubscriber.php @@ -374,8 +374,8 @@ protected function setPaymentMethodConfigurations(ChannelSettings $channelSettin $paymentMethodConfigs = $this->paymentMethodController->getAll($channelSettings->getWebsiteProfile()->getId()); foreach ($paymentMethodConfigs as $paymentMethodConfig) { $paymentMethodSetting = null; - $paymentMethodConfigMollieIds[] = $paymentMethodConfig->getMollieId(); - if (array_key_exists($paymentMethodConfig->getMollieId(), $paymentMethodSettingsMap)) { + $paymentMethodConfigMollieIds[] = $paymentMethodConfig->getMollieId(); + if (array_key_exists($paymentMethodConfig->getMollieId(), $paymentMethodSettingsMap)) { $paymentMethodSetting = $paymentMethodSettingsMap[$paymentMethodConfig->getMollieId()]; } @@ -429,12 +429,12 @@ protected function setPaymentMethodConfigurations(ChannelSettings $channelSettin ); } - // Remove any saved method setting that is now missing in the Mollie API - foreach ($paymentMethodSettingsMap as $mollieMethodId => $paymentMethodSetting) { - if (!in_array($mollieMethodId, $paymentMethodConfigMollieIds)) { - $channelSettings->removePaymentMethodSetting($paymentMethodSetting); - } - } + // Remove any saved method setting that is now missing in the Mollie API + foreach ($paymentMethodSettingsMap as $mollieMethodId => $paymentMethodSetting) { + if (!in_array($mollieMethodId, $paymentMethodConfigMollieIds)) { + $channelSettings->removePaymentMethodSetting($paymentMethodSetting); + } + } } /** diff --git a/Form/Type/PaymentMethodSettingsType.php b/Form/Type/PaymentMethodSettingsType.php index 3a3b7cd..c5bfd22 100644 --- a/Form/Type/PaymentMethodSettingsType.php +++ b/Form/Type/PaymentMethodSettingsType.php @@ -23,7 +23,6 @@ use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Range; - /** * Form type for Mollie integration payment methods settings */ diff --git a/IntegrationCore/BusinessLogic/Authorization/AuthorizationService.php b/IntegrationCore/BusinessLogic/Authorization/AuthorizationService.php index 4960ba5..e4cc838 100644 --- a/IntegrationCore/BusinessLogic/Authorization/AuthorizationService.php +++ b/IntegrationCore/BusinessLogic/Authorization/AuthorizationService.php @@ -53,6 +53,16 @@ public function reset() } } + /** + * Returns Authorization token + * + * @return string + */ + public function getAuthToken() + { + return $this->getConfigService()->getAuthorizationToken(); + } + /** * @return Configuration */ diff --git a/IntegrationCore/BusinessLogic/Authorization/Interfaces/AuthorizationService.php b/IntegrationCore/BusinessLogic/Authorization/Interfaces/AuthorizationService.php index cc6e13f..54ebe1e 100644 --- a/IntegrationCore/BusinessLogic/Authorization/Interfaces/AuthorizationService.php +++ b/IntegrationCore/BusinessLogic/Authorization/Interfaces/AuthorizationService.php @@ -30,4 +30,11 @@ public function validateToken(TokenInterface $token); * Resets account */ public function reset(); + + /** + * Returns Authorization token + * + * @return string|null + */ + public function getAuthToken(); } diff --git a/IntegrationCore/BusinessLogic/Configuration.php b/IntegrationCore/BusinessLogic/Configuration.php index 6f6f554..73efd40 100644 --- a/IntegrationCore/BusinessLogic/Configuration.php +++ b/IntegrationCore/BusinessLogic/Configuration.php @@ -2,6 +2,7 @@ namespace Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Connect\DTO\AuthInfo; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\WebsiteProfile; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Logger\Logger; @@ -20,18 +21,21 @@ abstract class Configuration extends \Mollie\Bundle\PaymentBundle\IntegrationCor * @return string Integration version. */ abstract public function getIntegrationVersion(); + /** * Retrieves extension (plugin) name (for example MollieMagento2). * * @return string Extension name. */ abstract public function getExtensionName(); + /** * Retrieves extension (plugin) version. * * @return string Extension version. */ abstract public function getExtensionVersion(); + /** * Returns URL for checking extension version * @@ -62,6 +66,31 @@ public function removeConfigValue($name) return $entity ? $this->getRepository()->delete($entity) : true; } + /** + * Returns authorization token. + * + * @return AuthInfo|null Authorization token if found; otherwise, NULL. + */ + public function getAuthorizationInfo() + { + $authInfo = json_decode($this->getConfigValue('authToken'), true); + if (empty($authInfo)) { + return null; + } + + return AuthInfo::fromArray($authInfo); + } + + /** + * Sets authorization token. + * + * @param AuthInfo $authInfo Authorization token. + */ + public function setAuthorizationInfo($authInfo) + { + $this->saveConfigValue('authToken', json_encode($authInfo->toArray())); + } + /** * Returns authorization token. * @@ -75,11 +104,31 @@ public function getAuthorizationToken() /** * Sets authorization token. * - * @param string $token Authorization token. + * @param string $authToken Authorization token. + */ + public function setAuthorizationToken($authToken) + { + $this->saveConfigValue('authToken', $authToken); + } + + /** + * Returns state string. + * + * @return string|null State string if found; otherwise, NULL. + */ + public function getStateString() + { + return $this->getConfigValue('state') ?: null; + } + + /** + * Sets authorization token. + * + * @param string $state State string. */ - public function setAuthorizationToken($token) + public function setStateString($state) { - $this->saveConfigValue('authToken', $token); + $this->saveConfigValue('state', $state); } /** diff --git a/IntegrationCore/BusinessLogic/Connect/AuthorizationService.php b/IntegrationCore/BusinessLogic/Connect/AuthorizationService.php new file mode 100644 index 0000000..b68c2fb --- /dev/null +++ b/IntegrationCore/BusinessLogic/Connect/AuthorizationService.php @@ -0,0 +1,162 @@ +configuration = ServiceRegister::getService(Configuration::CLASS_NAME); + $this->tokenService = ServiceRegister::getService(TokenService::CLASS_NAME); + } + + + /** + * Gets string of Mollie permissions that are needed for application + * + * @return array + */ + abstract public function getApplicationPermissions(); + + /** + * Gets clients id + * + * @return string + */ + abstract public function getClientId(); + + /** + * Gets callback url + * + * @return string + */ + abstract public function getRedirectUrl(); + + /** + * Get client secret + * + * @return string + */ + abstract public function getClientSecret(); + + /** + * This function should generate Mollie authorize URL in the given language + * + * @param string $locale + * + * @return string + */ + public function getAuthorizeUrl($locale, $state = null) + { + $params = array( + 'client_id' => $this->getClientId(), + 'redirect_uri' => $this->getRedirectUrl(), + 'state' => $state ?: $this->generateStateString(), + 'scope' => $this->formatApplicationPermissions(), + 'response_type' => 'code', + 'approval_prompt' => 'force', + 'locale' => $locale, + ); + + return static::AUTHORIZE_URL . '?' . http_build_query($params); + } + + /** + * @return AuthInfo|null + * @throws UnprocessableEntityRequestException + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + */ + public function getAuthInfo() + { + $authInfo = $this->configuration->getAuthorizationInfo(); + if (!$authInfo) { + return null; + } + + $currentTime = $this->getCurrentTimeInSeconds(); + if ($authInfo->getAccessTokenDuration() < $currentTime) { + $authInfo = $this->tokenService->refreshToken($authInfo->getRefreshToken()); + } + + return $authInfo; + } + + /** + * {@inheritdoc} + * + * @return string|null + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + abstract public function getAuthToken(); + + /** + * Generates state string + * + * @return string + */ + private function generateStateString() + { + $state = md5(uniqid('', true)); + $this->configuration->setStateString($state); + + return $state; + } + + /** + * @return string + */ + private function formatApplicationPermissions() + { + $formattedPermission = ''; + foreach ($this->getApplicationPermissions() as $permission) { + $formattedPermission .= $permission . ' '; + } + + return trim($formattedPermission); + } + + /** + * Returns current time in seconds + * + * @return int + */ + private function getCurrentTimeInSeconds() + { + $time = new DateTime('now'); + + return $time->getTimestamp(); + } +} diff --git a/IntegrationCore/BusinessLogic/Connect/DTO/AuthInfo.php b/IntegrationCore/BusinessLogic/Connect/DTO/AuthInfo.php new file mode 100644 index 0000000..c86aab7 --- /dev/null +++ b/IntegrationCore/BusinessLogic/Connect/DTO/AuthInfo.php @@ -0,0 +1,116 @@ +accessToken = $accessToken; + $this->refreshToken = $refreshToken; + $this->accessTokenDuration = $accessTokenDuration; + } + + /** + * @return string + */ + public function getAccessToken() + { + return $this->accessToken; + } + + /** + * @param string $accessToken + */ + public function setAccessToken($accessToken) + { + $this->accessToken = $accessToken; + } + + /** + * @return string + */ + public function getRefreshToken() + { + return $this->refreshToken; + } + + /** + * @param string $refreshToken + */ + public function setRefreshToken($refreshToken) + { + $this->refreshToken = $refreshToken; + } + + /** + * @return int + */ + public function getAccessTokenDuration() + { + return $this->accessTokenDuration; + } + + /** + * @param int $accessTokenDuration + */ + public function setAccessTokenDuration($accessTokenDuration) + { + $this->accessTokenDuration = $accessTokenDuration; + } + + /** + * {@inheritdoc} + * + * @return array + */ + public function toArray() + { + return array( + 'access_token' => $this->getAccessToken(), + 'refresh_token' => $this->getRefreshToken(), + 'expires_in' => $this->getAccessTokenDuration(), + ); + } + + /** + * + * @param array $raw + * + * @return AuthInfo + */ + public static function fromArray(array $raw) + { + $authInfo = new AuthInfo('', '', 0); + $authInfo->setAccessToken(static::getValue($raw, 'access_token', null)); + $authInfo->setRefreshToken(static::getValue($raw, 'refresh_token', null)); + $authInfo->setAccessTokenDuration(static::getValue($raw, 'expires_in', null)); + + return $authInfo; + } +} diff --git a/IntegrationCore/BusinessLogic/Connect/DTO/TokenRequest.php b/IntegrationCore/BusinessLogic/Connect/DTO/TokenRequest.php new file mode 100644 index 0000000..6db130a --- /dev/null +++ b/IntegrationCore/BusinessLogic/Connect/DTO/TokenRequest.php @@ -0,0 +1,130 @@ +grantType = $grantType; + $this->code = $code; + $this->refreshToken = $refreshToken; + $this->redirectUrl = $redirectUrl; + } + + /** + * @return string + */ + public function getGrantType() + { + return $this->grantType; + } + + /** + * @param string $grantType + */ + public function setGrantType($grantType) + { + $this->grantType = $grantType; + } + + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * @param string $code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * @return string + */ + public function getRefreshToken() + { + return $this->refreshToken; + } + + /** + * @param string $refreshToken + */ + public function setRefreshToken($refreshToken) + { + $this->refreshToken = $refreshToken; + } + + /** + * @return string + */ + public function getRedirectUrl() + { + return $this->redirectUrl; + } + + /** + * @param string $redirectUrl + */ + public function setRedirectUrl($redirectUrl) + { + $this->redirectUrl = $redirectUrl; + } + + /** + * {@inheritdoc} + * + * @return array + */ + public function toArray() + { + $array = array(); + $array['grant_type'] = $this->getGrantType(); + if ($this->getGrantType() === 'authorization_code') { + $array['code'] = $this->getCode(); + } else { + $array['refresh_token'] = $this->getRefreshToken(); + } + + if ($this->getRedirectUrl() !== '') { + $array['redirect_uri'] = $this->getRedirectUrl(); + } + + return $array; + } +} diff --git a/IntegrationCore/BusinessLogic/Connect/TokenProxy.php b/IntegrationCore/BusinessLogic/Connect/TokenProxy.php new file mode 100644 index 0000000..30309a4 --- /dev/null +++ b/IntegrationCore/BusinessLogic/Connect/TokenProxy.php @@ -0,0 +1,117 @@ +call(self::HTTP_METHOD_POST, '', $request->toArray(), $clientId, $clientSecret); + $body = json_decode($response->getBody(), true); + $body['expires_in'] = $this->getExpiresInTime($body['expires_in']); + + return AuthInfo::fromArray($body); + } + + /** + * Revoke given token + * + * @param string $type Type of token (access_token or refresh_token) + * @param string $token + * + * @return void + * + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function revokeToken($type, $token) + { + $body = array( + 'token_type_hint' => $type, + 'token' => $token, + ); + + $this->call(self::HTTP_METHOD_DELETE, '', $body); + } + + /** + * @param string $method + * @param string $endpoint + * @param array $body + * @param string $clientId + * @param string $clientSecret + * @return HttpResponse + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function call($method, $endpoint, array $body = array(), $clientId = '', $clientSecret = '') + { + if ($this->configService->isTestMode()) { + $queryParams['testmode'] = 'true'; + } + + $url = static::TOKEN_URL . '?' . http_build_query($body); + $response = $this->client->request( + self::HTTP_METHOD_POST, + $url, + $this->getHeaders($clientId, $clientSecret), + $body + ); + + $this->validateResponse($response); + + return $response; + } + + /** + * @param integer $expiresIn + */ + private function getExpiresInTime($expiresIn) + { + $now = new \DateTime('now'); + $expiresIn -= 60; + $now = $now->modify("+ $expiresIn seconds"); + + return $now->getTimestamp(); + } + + /** + * Returns header + */ + private function getHeaders($clientId, $clientSecret) + { + return array('Authorization: Basic ' . base64_encode($clientId . ':' . $clientSecret)); + } +} diff --git a/IntegrationCore/BusinessLogic/Connect/TokenService.php b/IntegrationCore/BusinessLogic/Connect/TokenService.php new file mode 100644 index 0000000..1b627a8 --- /dev/null +++ b/IntegrationCore/BusinessLogic/Connect/TokenService.php @@ -0,0 +1,82 @@ +tokenProxy = $tokenProxy; + } + + /** + * Gets AuthInfo based on given code + * + * @param $authCode + * @param string $redirectUrl + * @param string $clientId + * @param string $clinetSecret + * + * @return AuthInfo + * + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function generate($authCode, $redirectUrl = '', $clientId = '', $clinetSecret = '') + { + $tokenRequest = new TokenRequest(static::AUTH_CODE, $authCode, '', $redirectUrl); + + return $this->tokenProxy->retrieveTokens($tokenRequest, $clientId, $clinetSecret); + } + + /** + * Gets AuthInfo based on given refresh token + * + * @param $refreshToken + * @param string $redirectUrl + * @param string $clientId + * @param string $clinetSecret + * @return AuthInfo + * + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function refreshToken($refreshToken, $redirectUrl = '', $clientId = '', $clinetSecret = '') + { + $tokenRequest = new TokenRequest(static::REFRESH_TOKEN, '', $refreshToken, $redirectUrl); + + return $this->tokenProxy->retrieveTokens($tokenRequest, $clientId, $clinetSecret); + } +} diff --git a/IntegrationCore/BusinessLogic/Http/BaseProxy.php b/IntegrationCore/BusinessLogic/Http/BaseProxy.php new file mode 100644 index 0000000..f818aac --- /dev/null +++ b/IntegrationCore/BusinessLogic/Http/BaseProxy.php @@ -0,0 +1,235 @@ +client = $client; + $this->configService = $configService; + $this->transformer = $transformer; + } + + /** + * Makes a HTTP call and returns response. + * + * @param string $method HTTP method (GET, POST, PUT, etc.). + * @param string $endpoint Endpoint resource on remote API. + * @param array $body Request payload body. + * + * @return HttpResponse Response from request. + * + * @throws HttpAuthenticationException + * @throws UnprocessableEntityRequestException + * @throws HttpCommunicationException + * @throws HttpRequestException + */ + public function call($method, $endpoint, array $body = array()) + { + $endpoint = ltrim($endpoint, '/'); + + $response = $this->client->request( + $method, + $this->getRequestUrl($method, $endpoint), + $this->getRequestHeaders(), + $this->getBodyAsString($method, $endpoint, $body) + ); + + $this->validateResponse($response); + + return $response; + } + + /** + * Creates full request URL for a given endpoint + * + * @param string $method HTTP method (GET, POST, PUT, etc.). + * @param string $endpoint Endpoint resource on remote API. + * + * @return string + */ + protected function getRequestUrl($method, $endpoint) + { + $url = static::BASE_URL . static::API_VERSION . $endpoint; + $this->transformer->adjustUrl($url, $endpoint, $method); + + return $url; + } + + /** + * @param string $method HTTP method (GET, POST, PUT, etc.). + * @param string $endpoint Endpoint resource on remote API. + * @param array $body Request payload body. + * + * @return false|string + */ + protected function getBodyAsString($method, $endpoint, array $body = array()) + { + if (strtoupper($method) === self::HTTP_METHOD_GET) { + return ''; + } + + $this->transformer->adjustBody($body, $endpoint); + + return empty($body) ? '{}' : json_encode($body); + } + + /** + * Validates HTTP response. + * + * @param HttpResponse $response HTTP response returned from API call. + * + * @throws HttpAuthenticationException + * @throws UnprocessableEntityRequestException + * @throws HttpRequestException + */ + protected function validateResponse(HttpResponse $response) + { + if (!$response->isSuccessful()) { + $httpCode = $response->getStatus(); + $error = $response->decodeBodyAsJson(); + $errorMessage = ''; + if (is_array($error)) { + if (array_key_exists('title', $error)) { + $errorMessage = $error['title']; + } elseif (array_key_exists('error', $error)) { + $errorMessage = $error['error']; + } + + if (array_key_exists('detail', $error)) { + $errorMessage .= ": {$error['detail']}"; + } + } + + Logger::logInfo( + 'Request to Mollie API was not successful.', + 'Core', + array( + 'ApiErrorMessage' => $errorMessage + ) + ); + + if ($httpCode === self::HTTP_STATUS_CODE_UNAUTHORIZED) { + throw new HttpAuthenticationException($errorMessage, $httpCode); + } + + if ($httpCode === self::HTTP_STATUS_CODE_UNPROCESSABLE) { + throw new UnprocessableEntityRequestException(array_key_exists('field', $error) ? $error['field'] : '', $errorMessage, $httpCode); + } + + throw new HttpRequestException($errorMessage, $httpCode); + } + } + + /** + * Returns headers together with authorization entry. + * + * @return array Formatted request headers. + */ + protected function getRequestHeaders() + { + $userAgents = array( + 'PHP/' . PHP_VERSION, + str_replace( + array(' ', "\t", "\n", "\r"), + '-', + $this->configService->getIntegrationName() . '/' . $this->configService->getIntegrationVersion() + ), + str_replace( + array(' ', "\t", "\n", "\r"), + '-', + $this->configService->getExtensionName() . '/' . $this->configService->getExtensionVersion() + ), + ); + + return array( + 'accept' => 'Accept: application/json', + 'content' => 'Content-Type: application/json', + 'useragent' => 'User-Agent: ' . implode(' ', $userAgents), + 'token' => 'Authorization: Bearer ' . $this->getAuthorizationService()->getAuthToken(), + ); + } + + /** + * Returns registered authorization service + * + * @return AuthorizationService + */ + protected function getAuthorizationService() + { + return ServiceRegister::getService(AuthorizationService::CLASS_NAME); + } +} diff --git a/IntegrationCore/BusinessLogic/Http/DTO/Amount.php b/IntegrationCore/BusinessLogic/Http/DTO/Amount.php index 8f23d32..5eeeb0a 100644 --- a/IntegrationCore/BusinessLogic/Http/DTO/Amount.php +++ b/IntegrationCore/BusinessLogic/Http/DTO/Amount.php @@ -32,14 +32,31 @@ class Amount extends BaseDto /* */ private static $map = array( 'BHD' => 3, + 'XOF' => 0, + 'BIF' => 0, + 'XAF' => 0, + 'CLP' => 0, 'CLF' => 4, + 'KMF' => 0, + 'DJF' => 0, + 'XPF' => 0, + 'GNF' => 0, + 'ISK' => 0, 'IQD' => 3, + 'JPY' => 0, 'JOD' => 3, + 'KRW' => 0, 'KWD' => 3, 'LYD' => 3, 'OMR' => 3, + 'PYG' => 0, + 'RWF' => 0, 'TND' => 3, + 'UGX' => 0, + 'UYI' => 0, 'UYW' => 4, + 'VUV' => 0, + 'VND' => 0, ); /* */ @@ -104,7 +121,7 @@ public function getAmountValue() */ public function getAmountValueInSmallestUnit() { - return (int)((float)$this->value * pow(10, $this->getMinorUnits())); + return (int)round((float)$this->value * pow(10, $this->getMinorUnits()), 0); } /** diff --git a/IntegrationCore/BusinessLogic/Http/DTO/Orders/Order.php b/IntegrationCore/BusinessLogic/Http/DTO/Orders/Order.php index ca7e781..f94b850 100644 --- a/IntegrationCore/BusinessLogic/Http/DTO/Orders/Order.php +++ b/IntegrationCore/BusinessLogic/Http/DTO/Orders/Order.php @@ -34,7 +34,7 @@ class Order extends BaseDto /** * @var string[] */ - protected $method; + protected $methods; /** * @var Amount */ @@ -156,7 +156,7 @@ public static function fromArray(array $raw) $order->profileId = static::getValue($raw, 'profileId'); $method = static::getValue($raw, 'method', array()); $method = is_array($method) ? $method : array($method); - $order->method = $method; + $order->methods = $method; $order->amount = Amount::fromArray(static::getValue($raw, 'amount', array())); $order->amountCaptured = Amount::fromArray(static::getValue($raw, 'amountCaptured', array())); $order->amountRefunded = Amount::fromArray(static::getValue($raw, 'amountRefunded', array())); @@ -232,7 +232,7 @@ public function toArray() 'resource' => $this->resource, 'id' => $this->id, 'profileId' => $this->profileId, - 'method' => $this->method, + 'method' => $this->methods, 'amount' => $this->amount->toArray(), 'amountRefunded' => $this->amountRefunded->toArray(), 'amountCaptured' => $this->amountCaptured->toArray(), @@ -313,17 +313,17 @@ public function setProfileId($profileId) /** * @return string[] */ - public function getMethod() + public function getMethods() { - return $this->method; + return $this->methods; } /** * @param string[] $method */ - public function setMethod($method) + public function setMethods($method) { - $this->method = $method; + $this->methods = $method; } /** diff --git a/IntegrationCore/BusinessLogic/Http/DTO/Payment.php b/IntegrationCore/BusinessLogic/Http/DTO/Payment.php index dfa91c2..b9fbeb3 100644 --- a/IntegrationCore/BusinessLogic/Http/DTO/Payment.php +++ b/IntegrationCore/BusinessLogic/Http/DTO/Payment.php @@ -59,7 +59,7 @@ class Payment extends BaseDto /** * @var string[] */ - protected $method; + protected $methods; /** * @var Address */ @@ -122,8 +122,7 @@ public static function fromArray(array $raw) $result->issuer = static::getValue($raw, 'issuer'); $result->setLocale(static::getValue($raw, 'locale')); $method = static::getValue($raw, 'method', array()); - $method = is_array($method) ? $method : array($method); - $result->method = $method; + $result->methods = is_array($method) ? $method : array($method); $result->metadata = static::getValue($raw, 'metadata', array()); $result->dueDate = \DateTime::createFromFormat(Order::MOLLIE_DATE_FORMAT, static::getValue($raw, 'dueDate')); @@ -180,7 +179,7 @@ public function toArray() 'redirectUrl' => $this->redirectUrl, 'webhookUrl' => $this->webhookUrl, 'locale' => $this->locale, - 'method' => $this->method, + 'method' => $this->methods, 'metadata' => $this->metadata, 'cardToken' => $this->cardToken, 'issuer' => $this->issuer, @@ -378,17 +377,17 @@ public function setLocale($locale) /** * @return string[] */ - public function getMethod() + public function getMethods() { - return $this->method; + return $this->methods; } /** * @param string[] $method */ - public function setMethod($method) + public function setMethods($method) { - $this->method = $method; + $this->methods = $method; } /** diff --git a/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php b/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php index f479d65..e063f8b 100644 --- a/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php +++ b/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php @@ -39,7 +39,7 @@ class ProxyDataProvider public function transformPayment(Payment $payment) { - $method = $payment->getMethod(); + $method = $payment->getMethods(); if (count($method) === 1) { $method = implode('', $method); } @@ -85,7 +85,7 @@ public function transformOrder(Order $order) $orderLines[] = $totalAdjustment; } - $method = $order->getMethod(); + $method = $order->getMethods(); if (count($method) === 1) { $method = implode('', $method); } diff --git a/IntegrationCore/BusinessLogic/Http/Proxy.php b/IntegrationCore/BusinessLogic/Http/Proxy.php index bdf29e7..b65abee 100644 --- a/IntegrationCore/BusinessLogic/Http/Proxy.php +++ b/IntegrationCore/BusinessLogic/Http/Proxy.php @@ -12,88 +12,19 @@ use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\TokenPermission; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\WebsiteProfile; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException; -use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\PaymentMethod\Model\PaymentMethodConfig; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpAuthenticationException; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpCommunicationException; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpRequestException; -use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\HttpClient; -use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\HttpResponse; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Logger\LogData; -use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Logger\Logger; -use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Configuration; /** * Class Proxy. In charge for communication with Mollie API. * * @package Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http */ -class Proxy +class Proxy extends BaseProxy { - /** - * Fully qualified name of this class. - */ - const CLASS_NAME = __CLASS__; - /** - * Mollie base API URL. - */ - const BASE_URL = 'https://api.mollie.com/'; - /** - * Mollie API version - */ - const API_VERSION = 'v2/'; - /** - * Unauthorized HTTP status code. - */ - const HTTP_STATUS_CODE_UNAUTHORIZED = 401; - /** - * Unprocessable entity status code - */ - const HTTP_STATUS_CODE_UNPROCESSABLE = 422; - /** - * HTTP GET method - */ - const HTTP_METHOD_GET = 'GET'; - /** - * HTTP POST method - */ - const HTTP_METHOD_POST = 'POST'; - /** - * HTTP PUT method - */ - const HTTP_METHOD_PATCH = 'PATCH'; - /** - * HTTP DELETE method - */ - const HTTP_METHOD_DELETE = 'DELETE'; - /** - * HTTP Client. - * - * @var HttpClient - */ - private $client; - /** - * @var Configuration - */ - private $configService; - /** - * @var ProxyDataProvider - */ - private $transformer; - - /** - * Proxy constructor. - * - * @param Configuration $configService Configuration service. - * @param HttpClient $client System HTTP client. - * @param ProxyDataProvider $transformer - */ - public function __construct(Configuration $configService, HttpClient $client, ProxyDataProvider $transformer) - { - $this->client = $client; - $this->configService = $configService; - $this->transformer = $transformer; - } /** * @param LogData $data @@ -292,7 +223,11 @@ public function getWebsiteProfiles() */ public function getAllPaymentMethods() { - $response = $this->call(self::HTTP_METHOD_GET, '/methods/all'); + $params = array( + 'include' => 'issuers', + ); + $queryString = http_build_query($params); + $response = $this->call(self::HTTP_METHOD_GET, "/methods/all?{$queryString}"); $result = $response->decodeBodyAsJson(); return PaymentMethod::fromArrayBatch( @@ -531,136 +466,6 @@ public function getShipments($orderId) return Shipment::fromArrayBatch($result['_embedded']['shipments']); } - /** - * Makes a HTTP call and returns response. - * - * @param string $method HTTP method (GET, POST, PUT, etc.). - * @param string $endpoint Endpoint resource on remote API. - * @param array $body Request payload body. - * - * @return HttpResponse Response from request. - * - * @throws HttpAuthenticationException - * @throws UnprocessableEntityRequestException - * @throws HttpCommunicationException - * @throws HttpRequestException - */ - protected function call($method, $endpoint, array $body = array()) - { - $endpoint = ltrim($endpoint, '/'); - - $response = $this->client->request( - $method, - $this->getRequestUrl($method, $endpoint), - $this->getRequestHeaders(), - $this->getBodyAsString($method, $endpoint, $body) - ); - - $this->validateResponse($response); - - return $response; - } - - /** - * Creates full request URL for a given endpoint - * - * @param string $method HTTP method (GET, POST, PUT, etc.). - * @param string $endpoint Endpoint resource on remote API. - * - * @return string - */ - protected function getRequestUrl($method, $endpoint) - { - $url = static::BASE_URL . static::API_VERSION . $endpoint; - $this->transformer->adjustUrl($url, $endpoint, $method); - - return $url; - } - - /** - * @param string $method HTTP method (GET, POST, PUT, etc.). - * @param string $endpoint Endpoint resource on remote API. - * @param array $body Request payload body. - * - * @return false|string - */ - protected function getBodyAsString($method, $endpoint, array $body = array()) - { - if (strtoupper($method) === self::HTTP_METHOD_GET) { - return ''; - } - - $this->transformer->adjustBody($body, $endpoint); - - return empty($body) ? '{}' : json_encode($body); - } - - /** - * Validates HTTP response. - * - * @param HttpResponse $response HTTP response returned from API call. - * - * @throws HttpAuthenticationException - * @throws UnprocessableEntityRequestException - * @throws HttpRequestException - */ - protected function validateResponse(HttpResponse $response) - { - if (!$response->isSuccessful()) { - $httpCode = $response->getStatus(); - $error = $message = $response->decodeBodyAsJson(); - if (is_array($error)) { - $message = "{$error['title']}: {$error['detail']}"; - } - - Logger::logInfo( - 'Request to Mollie API was not successful.', - 'Core', - array( - 'ApiErrorMessage' => $message - ) - ); - if ($httpCode === self::HTTP_STATUS_CODE_UNAUTHORIZED) { - throw new HttpAuthenticationException($message, $httpCode); - } - - if ($httpCode === self::HTTP_STATUS_CODE_UNPROCESSABLE) { - throw new UnprocessableEntityRequestException(array_key_exists('field', $error) ? $error['field'] : '', $message, $httpCode); - } - - throw new HttpRequestException($message, $httpCode); - } - } - - /** - * Returns headers together with authorization entry. - * - * @return array Formatted request headers. - */ - protected function getRequestHeaders() - { - $userAgents = array( - 'PHP/'.PHP_VERSION, - str_replace( - array(' ', "\t", "\n", "\r"), - '-', - $this->configService->getIntegrationName().'/'.$this->configService->getIntegrationVersion() - ), - str_replace( - array(' ', "\t", "\n", "\r"), - '-', - $this->configService->getExtensionName().'/'.$this->configService->getExtensionVersion() - ), - ); - - return array( - 'accept' => 'Accept: application/json', - 'content' => 'Content-Type: application/json', - 'useragent' => 'User-Agent: '.implode(' ', $userAgents), - 'token' => 'Authorization: Bearer ' . $this->configService->getAuthorizationToken(), - ); - } - /** * @param string $apiMethod * @param string $billingCountry diff --git a/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php b/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php index f3f32bd..ce025eb 100644 --- a/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php +++ b/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php @@ -35,19 +35,25 @@ class PaymentMethodConfig extends Entity const PRODUCT_ATTRIBUTE_DEFAULT = 'mollie_voucher_category'; const DEFAULT_TRANSACTION_DESCRIPTION = '{orderNumber}'; + /** * @var string[] */ - protected static $adiMethodRestrictions = array( + protected static $apiMethodRestrictions = array( PaymentMethods::KlarnaPayLater => self::API_METHOD_ORDERS, PaymentMethods::KlarnaSliceIt => self::API_METHOD_ORDERS, + PaymentMethods::KlarnaPayNow => self::API_METHOD_ORDERS, PaymentMethods::Vouchers => self::API_METHOD_ORDERS ); /** * @var array */ - protected static $surchargeRestrictedPaymentMethods = array(PaymentMethods::KlarnaPayLater, PaymentMethods::KlarnaSliceIt); + protected static $surchargeRestrictedPaymentMethods = array( + PaymentMethods::KlarnaPayLater, + PaymentMethods::KlarnaSliceIt, + PaymentMethods::KlarnaPayNow, + ); /** * @var array @@ -82,6 +88,7 @@ class PaymentMethodConfig extends Entity 'transactionDescription', 'voucherCategory', 'productAttribute', + 'sortOrder', ); /** @@ -133,6 +140,10 @@ class PaymentMethodConfig extends Entity * @var int */ protected $daysToPaymentExpire; + /** + * @var int + */ + protected $sortOrder = 0; /** * @var string */ @@ -195,7 +206,7 @@ public function isSurchargeRestricted() */ public function isApiMethodRestricted() { - return array_key_exists($this->getMollieId(), static::$adiMethodRestrictions); + return array_key_exists($this->getMollieId(), static::$apiMethodRestrictions); } /** @@ -296,14 +307,14 @@ public function setApiMethod($apiMethod) if ( $this->isApiMethodRestricted() && - $apiMethod !== static::$adiMethodRestrictions[$this->getMollieId()] + $apiMethod !== static::$apiMethodRestrictions[$this->getMollieId()] ) { throw new \InvalidArgumentException( sprintf( 'Invalid payment method api value %s. Payment method %s supports only %s API method', $apiMethod, $this->getMollieId(), - static::$adiMethodRestrictions[$this->getMollieId()] + static::$apiMethodRestrictions[$this->getMollieId()] ) ); } @@ -494,4 +505,20 @@ public function setProductAttribute($productAttribute) { $this->productAttribute = $productAttribute; } + + /** + * @return mixed + */ + public function getSortOrder() + { + return $this->sortOrder; + } + + /** + * @param mixed $sortOrder + */ + public function setSortOrder($sortOrder) + { + $this->sortOrder = $sortOrder; + } } diff --git a/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethodService.php b/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethodService.php index daf04c5..be02ee1 100644 --- a/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethodService.php +++ b/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethodService.php @@ -186,7 +186,7 @@ public function clearAllOther($profileId) * * @return PaymentMethodConfig[] */ - protected function getPaymentMethodConfigurationsMap($profileId) + public function getPaymentMethodConfigurationsMap($profileId) { $paymentMethodConfigsMap = array(); diff --git a/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethods.php b/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethods.php index fad9a76..fab66e6 100644 --- a/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethods.php +++ b/IntegrationCore/BusinessLogic/PaymentMethod/PaymentMethods.php @@ -12,6 +12,7 @@ class PaymentMethods const PayPal = 'paypal'; const KlarnaPayLater = 'klarnapaylater'; const KlarnaSliceIt = 'klarnasliceit'; + const KlarnaPayNow = 'klarnapaynow'; const CreditCard = 'creditcard'; const iDEAL = 'ideal'; const KBC = 'kbc'; diff --git a/IntegrationCore/BusinessLogic/Resources/currencies/currencies.json b/IntegrationCore/BusinessLogic/Resources/currencies/currencies.json new file mode 100644 index 0000000..a4fd8c4 --- /dev/null +++ b/IntegrationCore/BusinessLogic/Resources/currencies/currencies.json @@ -0,0 +1,1073 @@ +{ + "USD": { + "symbol": "$", + "name": "US Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "USD", + "name_plural": "US dollars" + }, + "CAD": { + "symbol": "CA$", + "name": "Canadian Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "CAD", + "name_plural": "Canadian dollars" + }, + "EUR": { + "symbol": "€", + "name": "Euro", + "symbol_native": "€", + "decimal_digits": 2, + "rounding": 0, + "code": "EUR", + "name_plural": "euros" + }, + "AED": { + "symbol": "AED", + "name": "United Arab Emirates Dirham", + "symbol_native": "د.إ.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "AED", + "name_plural": "UAE dirhams" + }, + "AFN": { + "symbol": "Af", + "name": "Afghan Afghani", + "symbol_native": "؋", + "decimal_digits": 0, + "rounding": 0, + "code": "AFN", + "name_plural": "Afghan Afghanis" + }, + "ALL": { + "symbol": "ALL", + "name": "Albanian Lek", + "symbol_native": "Lek", + "decimal_digits": 0, + "rounding": 0, + "code": "ALL", + "name_plural": "Albanian lekë" + }, + "AMD": { + "symbol": "AMD", + "name": "Armenian Dram", + "symbol_native": "դր.", + "decimal_digits": 0, + "rounding": 0, + "code": "AMD", + "name_plural": "Armenian drams" + }, + "ARS": { + "symbol": "AR$", + "name": "Argentine Peso", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "ARS", + "name_plural": "Argentine pesos" + }, + "AUD": { + "symbol": "AU$", + "name": "Australian Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "AUD", + "name_plural": "Australian dollars" + }, + "AZN": { + "symbol": "man.", + "name": "Azerbaijani Manat", + "symbol_native": "ман.", + "decimal_digits": 2, + "rounding": 0, + "code": "AZN", + "name_plural": "Azerbaijani manats" + }, + "BAM": { + "symbol": "KM", + "name": "Bosnia-Herzegovina Convertible Mark", + "symbol_native": "KM", + "decimal_digits": 2, + "rounding": 0, + "code": "BAM", + "name_plural": "Bosnia-Herzegovina convertible marks" + }, + "BDT": { + "symbol": "Tk", + "name": "Bangladeshi Taka", + "symbol_native": "৳", + "decimal_digits": 2, + "rounding": 0, + "code": "BDT", + "name_plural": "Bangladeshi takas" + }, + "BGN": { + "symbol": "BGN", + "name": "Bulgarian Lev", + "symbol_native": "лв.", + "decimal_digits": 2, + "rounding": 0, + "code": "BGN", + "name_plural": "Bulgarian leva" + }, + "BHD": { + "symbol": "BD", + "name": "Bahraini Dinar", + "symbol_native": "د.ب.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "BHD", + "name_plural": "Bahraini dinars" + }, + "BIF": { + "symbol": "FBu", + "name": "Burundian Franc", + "symbol_native": "FBu", + "decimal_digits": 0, + "rounding": 0, + "code": "BIF", + "name_plural": "Burundian francs" + }, + "BND": { + "symbol": "BN$", + "name": "Brunei Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "BND", + "name_plural": "Brunei dollars" + }, + "BOB": { + "symbol": "Bs", + "name": "Bolivian Boliviano", + "symbol_native": "Bs", + "decimal_digits": 2, + "rounding": 0, + "code": "BOB", + "name_plural": "Bolivian bolivianos" + }, + "BRL": { + "symbol": "R$", + "name": "Brazilian Real", + "symbol_native": "R$", + "decimal_digits": 2, + "rounding": 0, + "code": "BRL", + "name_plural": "Brazilian reals" + }, + "BWP": { + "symbol": "BWP", + "name": "Botswanan Pula", + "symbol_native": "P", + "decimal_digits": 2, + "rounding": 0, + "code": "BWP", + "name_plural": "Botswanan pulas" + }, + "BYN": { + "symbol": "Br", + "name": "Belarusian Ruble", + "symbol_native": "руб.", + "decimal_digits": 2, + "rounding": 0, + "code": "BYN", + "name_plural": "Belarusian rubles" + }, + "BZD": { + "symbol": "BZ$", + "name": "Belize Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "BZD", + "name_plural": "Belize dollars" + }, + "CDF": { + "symbol": "CDF", + "name": "Congolese Franc", + "symbol_native": "FrCD", + "decimal_digits": 2, + "rounding": 0, + "code": "CDF", + "name_plural": "Congolese francs" + }, + "CHF": { + "symbol": "CHF", + "name": "Swiss Franc", + "symbol_native": "CHF", + "decimal_digits": 2, + "rounding": 0.05, + "code": "CHF", + "name_plural": "Swiss francs" + }, + "CLP": { + "symbol": "CL$", + "name": "Chilean Peso", + "symbol_native": "$", + "decimal_digits": 0, + "rounding": 0, + "code": "CLP", + "name_plural": "Chilean pesos" + }, + "CNY": { + "symbol": "CN¥", + "name": "Chinese Yuan", + "symbol_native": "CN¥", + "decimal_digits": 2, + "rounding": 0, + "code": "CNY", + "name_plural": "Chinese yuan" + }, + "COP": { + "symbol": "CO$", + "name": "Colombian Peso", + "symbol_native": "$", + "decimal_digits": 0, + "rounding": 0, + "code": "COP", + "name_plural": "Colombian pesos" + }, + "CRC": { + "symbol": "₡", + "name": "Costa Rican Colón", + "symbol_native": "₡", + "decimal_digits": 0, + "rounding": 0, + "code": "CRC", + "name_plural": "Costa Rican colóns" + }, + "CVE": { + "symbol": "CV$", + "name": "Cape Verdean Escudo", + "symbol_native": "CV$", + "decimal_digits": 2, + "rounding": 0, + "code": "CVE", + "name_plural": "Cape Verdean escudos" + }, + "CZK": { + "symbol": "Kč", + "name": "Czech Republic Koruna", + "symbol_native": "Kč", + "decimal_digits": 2, + "rounding": 0, + "code": "CZK", + "name_plural": "Czech Republic korunas" + }, + "DJF": { + "symbol": "Fdj", + "name": "Djiboutian Franc", + "symbol_native": "Fdj", + "decimal_digits": 0, + "rounding": 0, + "code": "DJF", + "name_plural": "Djiboutian francs" + }, + "DKK": { + "symbol": "Dkr", + "name": "Danish Krone", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "DKK", + "name_plural": "Danish kroner" + }, + "DOP": { + "symbol": "RD$", + "name": "Dominican Peso", + "symbol_native": "RD$", + "decimal_digits": 2, + "rounding": 0, + "code": "DOP", + "name_plural": "Dominican pesos" + }, + "DZD": { + "symbol": "DA", + "name": "Algerian Dinar", + "symbol_native": "د.ج.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "DZD", + "name_plural": "Algerian dinars" + }, + "EEK": { + "symbol": "Ekr", + "name": "Estonian Kroon", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "EEK", + "name_plural": "Estonian kroons" + }, + "EGP": { + "symbol": "EGP", + "name": "Egyptian Pound", + "symbol_native": "ج.م.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "EGP", + "name_plural": "Egyptian pounds" + }, + "ERN": { + "symbol": "Nfk", + "name": "Eritrean Nakfa", + "symbol_native": "Nfk", + "decimal_digits": 2, + "rounding": 0, + "code": "ERN", + "name_plural": "Eritrean nakfas" + }, + "ETB": { + "symbol": "Br", + "name": "Ethiopian Birr", + "symbol_native": "Br", + "decimal_digits": 2, + "rounding": 0, + "code": "ETB", + "name_plural": "Ethiopian birrs" + }, + "GBP": { + "symbol": "£", + "name": "British Pound Sterling", + "symbol_native": "£", + "decimal_digits": 2, + "rounding": 0, + "code": "GBP", + "name_plural": "British pounds sterling" + }, + "GEL": { + "symbol": "GEL", + "name": "Georgian Lari", + "symbol_native": "GEL", + "decimal_digits": 2, + "rounding": 0, + "code": "GEL", + "name_plural": "Georgian laris" + }, + "GHS": { + "symbol": "GH₵", + "name": "Ghanaian Cedi", + "symbol_native": "GH₵", + "decimal_digits": 2, + "rounding": 0, + "code": "GHS", + "name_plural": "Ghanaian cedis" + }, + "GNF": { + "symbol": "FG", + "name": "Guinean Franc", + "symbol_native": "FG", + "decimal_digits": 0, + "rounding": 0, + "code": "GNF", + "name_plural": "Guinean francs" + }, + "GTQ": { + "symbol": "GTQ", + "name": "Guatemalan Quetzal", + "symbol_native": "Q", + "decimal_digits": 2, + "rounding": 0, + "code": "GTQ", + "name_plural": "Guatemalan quetzals" + }, + "HKD": { + "symbol": "HK$", + "name": "Hong Kong Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "HKD", + "name_plural": "Hong Kong dollars" + }, + "HNL": { + "symbol": "HNL", + "name": "Honduran Lempira", + "symbol_native": "L", + "decimal_digits": 2, + "rounding": 0, + "code": "HNL", + "name_plural": "Honduran lempiras" + }, + "HRK": { + "symbol": "kn", + "name": "Croatian Kuna", + "symbol_native": "kn", + "decimal_digits": 2, + "rounding": 0, + "code": "HRK", + "name_plural": "Croatian kunas" + }, + "HUF": { + "symbol": "Ft", + "name": "Hungarian Forint", + "symbol_native": "Ft", + "decimal_digits": 0, + "rounding": 0, + "code": "HUF", + "name_plural": "Hungarian forints" + }, + "IDR": { + "symbol": "Rp", + "name": "Indonesian Rupiah", + "symbol_native": "Rp", + "decimal_digits": 0, + "rounding": 0, + "code": "IDR", + "name_plural": "Indonesian rupiahs" + }, + "ILS": { + "symbol": "₪", + "name": "Israeli New Sheqel", + "symbol_native": "₪", + "decimal_digits": 2, + "rounding": 0, + "code": "ILS", + "name_plural": "Israeli new sheqels" + }, + "INR": { + "symbol": "Rs", + "name": "Indian Rupee", + "symbol_native": "টকা", + "decimal_digits": 2, + "rounding": 0, + "code": "INR", + "name_plural": "Indian rupees" + }, + "IQD": { + "symbol": "IQD", + "name": "Iraqi Dinar", + "symbol_native": "د.ع.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "IQD", + "name_plural": "Iraqi dinars" + }, + "IRR": { + "symbol": "IRR", + "name": "Iranian Rial", + "symbol_native": "﷼", + "decimal_digits": 0, + "rounding": 0, + "code": "IRR", + "name_plural": "Iranian rials" + }, + "ISK": { + "symbol": "Ikr", + "name": "Icelandic Króna", + "symbol_native": "kr", + "decimal_digits": 0, + "rounding": 0, + "code": "ISK", + "name_plural": "Icelandic krónur" + }, + "JMD": { + "symbol": "J$", + "name": "Jamaican Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "JMD", + "name_plural": "Jamaican dollars" + }, + "JOD": { + "symbol": "JD", + "name": "Jordanian Dinar", + "symbol_native": "د.أ.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "JOD", + "name_plural": "Jordanian dinars" + }, + "JPY": { + "symbol": "¥", + "name": "Japanese Yen", + "symbol_native": "¥", + "decimal_digits": 0, + "rounding": 0, + "code": "JPY", + "name_plural": "Japanese yen" + }, + "KES": { + "symbol": "Ksh", + "name": "Kenyan Shilling", + "symbol_native": "Ksh", + "decimal_digits": 2, + "rounding": 0, + "code": "KES", + "name_plural": "Kenyan shillings" + }, + "KHR": { + "symbol": "KHR", + "name": "Cambodian Riel", + "symbol_native": "៛", + "decimal_digits": 2, + "rounding": 0, + "code": "KHR", + "name_plural": "Cambodian riels" + }, + "KMF": { + "symbol": "CF", + "name": "Comorian Franc", + "symbol_native": "FC", + "decimal_digits": 0, + "rounding": 0, + "code": "KMF", + "name_plural": "Comorian francs" + }, + "KRW": { + "symbol": "₩", + "name": "South Korean Won", + "symbol_native": "₩", + "decimal_digits": 0, + "rounding": 0, + "code": "KRW", + "name_plural": "South Korean won" + }, + "KWD": { + "symbol": "KD", + "name": "Kuwaiti Dinar", + "symbol_native": "د.ك.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "KWD", + "name_plural": "Kuwaiti dinars" + }, + "KZT": { + "symbol": "KZT", + "name": "Kazakhstani Tenge", + "symbol_native": "тңг.", + "decimal_digits": 2, + "rounding": 0, + "code": "KZT", + "name_plural": "Kazakhstani tenges" + }, + "LBP": { + "symbol": "L.L.", + "name": "Lebanese Pound", + "symbol_native": "ل.ل.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "LBP", + "name_plural": "Lebanese pounds" + }, + "LKR": { + "symbol": "SLRs", + "name": "Sri Lankan Rupee", + "symbol_native": "SL Re", + "decimal_digits": 2, + "rounding": 0, + "code": "LKR", + "name_plural": "Sri Lankan rupees" + }, + "LTL": { + "symbol": "Lt", + "name": "Lithuanian Litas", + "symbol_native": "Lt", + "decimal_digits": 2, + "rounding": 0, + "code": "LTL", + "name_plural": "Lithuanian litai" + }, + "LVL": { + "symbol": "Ls", + "name": "Latvian Lats", + "symbol_native": "Ls", + "decimal_digits": 2, + "rounding": 0, + "code": "LVL", + "name_plural": "Latvian lati" + }, + "LYD": { + "symbol": "LD", + "name": "Libyan Dinar", + "symbol_native": "د.ل.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "LYD", + "name_plural": "Libyan dinars" + }, + "MAD": { + "symbol": "MAD", + "name": "Moroccan Dirham", + "symbol_native": "د.م.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "MAD", + "name_plural": "Moroccan dirhams" + }, + "MDL": { + "symbol": "MDL", + "name": "Moldovan Leu", + "symbol_native": "MDL", + "decimal_digits": 2, + "rounding": 0, + "code": "MDL", + "name_plural": "Moldovan lei" + }, + "MGA": { + "symbol": "MGA", + "name": "Malagasy Ariary", + "symbol_native": "MGA", + "decimal_digits": 0, + "rounding": 0, + "code": "MGA", + "name_plural": "Malagasy Ariaries" + }, + "MKD": { + "symbol": "MKD", + "name": "Macedonian Denar", + "symbol_native": "MKD", + "decimal_digits": 2, + "rounding": 0, + "code": "MKD", + "name_plural": "Macedonian denari" + }, + "MMK": { + "symbol": "MMK", + "name": "Myanma Kyat", + "symbol_native": "K", + "decimal_digits": 0, + "rounding": 0, + "code": "MMK", + "name_plural": "Myanma kyats" + }, + "MOP": { + "symbol": "MOP$", + "name": "Macanese Pataca", + "symbol_native": "MOP$", + "decimal_digits": 2, + "rounding": 0, + "code": "MOP", + "name_plural": "Macanese patacas" + }, + "MUR": { + "symbol": "MURs", + "name": "Mauritian Rupee", + "symbol_native": "MURs", + "decimal_digits": 0, + "rounding": 0, + "code": "MUR", + "name_plural": "Mauritian rupees" + }, + "MXN": { + "symbol": "MX$", + "name": "Mexican Peso", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "MXN", + "name_plural": "Mexican pesos" + }, + "MYR": { + "symbol": "RM", + "name": "Malaysian Ringgit", + "symbol_native": "RM", + "decimal_digits": 2, + "rounding": 0, + "code": "MYR", + "name_plural": "Malaysian ringgits" + }, + "MZN": { + "symbol": "MTn", + "name": "Mozambican Metical", + "symbol_native": "MTn", + "decimal_digits": 2, + "rounding": 0, + "code": "MZN", + "name_plural": "Mozambican meticals" + }, + "NAD": { + "symbol": "N$", + "name": "Namibian Dollar", + "symbol_native": "N$", + "decimal_digits": 2, + "rounding": 0, + "code": "NAD", + "name_plural": "Namibian dollars" + }, + "NGN": { + "symbol": "₦", + "name": "Nigerian Naira", + "symbol_native": "₦", + "decimal_digits": 2, + "rounding": 0, + "code": "NGN", + "name_plural": "Nigerian nairas" + }, + "NIO": { + "symbol": "C$", + "name": "Nicaraguan Córdoba", + "symbol_native": "C$", + "decimal_digits": 2, + "rounding": 0, + "code": "NIO", + "name_plural": "Nicaraguan córdobas" + }, + "NOK": { + "symbol": "Nkr", + "name": "Norwegian Krone", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "NOK", + "name_plural": "Norwegian kroner" + }, + "NPR": { + "symbol": "NPRs", + "name": "Nepalese Rupee", + "symbol_native": "नेरू", + "decimal_digits": 2, + "rounding": 0, + "code": "NPR", + "name_plural": "Nepalese rupees" + }, + "NZD": { + "symbol": "NZ$", + "name": "New Zealand Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "NZD", + "name_plural": "New Zealand dollars" + }, + "OMR": { + "symbol": "OMR", + "name": "Omani Rial", + "symbol_native": "ر.ع.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "OMR", + "name_plural": "Omani rials" + }, + "PAB": { + "symbol": "B/.", + "name": "Panamanian Balboa", + "symbol_native": "B/.", + "decimal_digits": 2, + "rounding": 0, + "code": "PAB", + "name_plural": "Panamanian balboas" + }, + "PEN": { + "symbol": "S/.", + "name": "Peruvian Nuevo Sol", + "symbol_native": "S/.", + "decimal_digits": 2, + "rounding": 0, + "code": "PEN", + "name_plural": "Peruvian nuevos soles" + }, + "PHP": { + "symbol": "₱", + "name": "Philippine Peso", + "symbol_native": "₱", + "decimal_digits": 2, + "rounding": 0, + "code": "PHP", + "name_plural": "Philippine pesos" + }, + "PKR": { + "symbol": "PKRs", + "name": "Pakistani Rupee", + "symbol_native": "₨", + "decimal_digits": 0, + "rounding": 0, + "code": "PKR", + "name_plural": "Pakistani rupees" + }, + "PLN": { + "symbol": "zł", + "name": "Polish Zloty", + "symbol_native": "zł", + "decimal_digits": 2, + "rounding": 0, + "code": "PLN", + "name_plural": "Polish zlotys" + }, + "PYG": { + "symbol": "₲", + "name": "Paraguayan Guarani", + "symbol_native": "₲", + "decimal_digits": 0, + "rounding": 0, + "code": "PYG", + "name_plural": "Paraguayan guaranis" + }, + "QAR": { + "symbol": "QR", + "name": "Qatari Rial", + "symbol_native": "ر.ق.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "QAR", + "name_plural": "Qatari rials" + }, + "RON": { + "symbol": "RON", + "name": "Romanian Leu", + "symbol_native": "RON", + "decimal_digits": 2, + "rounding": 0, + "code": "RON", + "name_plural": "Romanian lei" + }, + "RSD": { + "symbol": "din.", + "name": "Serbian Dinar", + "symbol_native": "дин.", + "decimal_digits": 0, + "rounding": 0, + "code": "RSD", + "name_plural": "Serbian dinars" + }, + "RUB": { + "symbol": "RUB", + "name": "Russian Ruble", + "symbol_native": "₽.", + "decimal_digits": 2, + "rounding": 0, + "code": "RUB", + "name_plural": "Russian rubles" + }, + "RWF": { + "symbol": "RWF", + "name": "Rwandan Franc", + "symbol_native": "FR", + "decimal_digits": 0, + "rounding": 0, + "code": "RWF", + "name_plural": "Rwandan francs" + }, + "SAR": { + "symbol": "SR", + "name": "Saudi Riyal", + "symbol_native": "ر.س.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "SAR", + "name_plural": "Saudi riyals" + }, + "SDG": { + "symbol": "SDG", + "name": "Sudanese Pound", + "symbol_native": "SDG", + "decimal_digits": 2, + "rounding": 0, + "code": "SDG", + "name_plural": "Sudanese pounds" + }, + "SEK": { + "symbol": "Skr", + "name": "Swedish Krona", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "SEK", + "name_plural": "Swedish kronor" + }, + "SGD": { + "symbol": "S$", + "name": "Singapore Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "SGD", + "name_plural": "Singapore dollars" + }, + "SOS": { + "symbol": "Ssh", + "name": "Somali Shilling", + "symbol_native": "Ssh", + "decimal_digits": 0, + "rounding": 0, + "code": "SOS", + "name_plural": "Somali shillings" + }, + "SYP": { + "symbol": "SY£", + "name": "Syrian Pound", + "symbol_native": "ل.س.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "SYP", + "name_plural": "Syrian pounds" + }, + "THB": { + "symbol": "฿", + "name": "Thai Baht", + "symbol_native": "฿", + "decimal_digits": 2, + "rounding": 0, + "code": "THB", + "name_plural": "Thai baht" + }, + "TND": { + "symbol": "DT", + "name": "Tunisian Dinar", + "symbol_native": "د.ت.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "TND", + "name_plural": "Tunisian dinars" + }, + "TOP": { + "symbol": "T$", + "name": "Tongan Paʻanga", + "symbol_native": "T$", + "decimal_digits": 2, + "rounding": 0, + "code": "TOP", + "name_plural": "Tongan paʻanga" + }, + "TRY": { + "symbol": "TL", + "name": "Turkish Lira", + "symbol_native": "TL", + "decimal_digits": 2, + "rounding": 0, + "code": "TRY", + "name_plural": "Turkish Lira" + }, + "TTD": { + "symbol": "TT$", + "name": "Trinidad and Tobago Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "TTD", + "name_plural": "Trinidad and Tobago dollars" + }, + "TWD": { + "symbol": "NT$", + "name": "New Taiwan Dollar", + "symbol_native": "NT$", + "decimal_digits": 2, + "rounding": 0, + "code": "TWD", + "name_plural": "New Taiwan dollars" + }, + "TZS": { + "symbol": "TSh", + "name": "Tanzanian Shilling", + "symbol_native": "TSh", + "decimal_digits": 0, + "rounding": 0, + "code": "TZS", + "name_plural": "Tanzanian shillings" + }, + "UAH": { + "symbol": "₴", + "name": "Ukrainian Hryvnia", + "symbol_native": "₴", + "decimal_digits": 2, + "rounding": 0, + "code": "UAH", + "name_plural": "Ukrainian hryvnias" + }, + "UGX": { + "symbol": "USh", + "name": "Ugandan Shilling", + "symbol_native": "USh", + "decimal_digits": 0, + "rounding": 0, + "code": "UGX", + "name_plural": "Ugandan shillings" + }, + "UYU": { + "symbol": "$U", + "name": "Uruguayan Peso", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "UYU", + "name_plural": "Uruguayan pesos" + }, + "UZS": { + "symbol": "UZS", + "name": "Uzbekistan Som", + "symbol_native": "UZS", + "decimal_digits": 0, + "rounding": 0, + "code": "UZS", + "name_plural": "Uzbekistan som" + }, + "VEF": { + "symbol": "Bs.F.", + "name": "Venezuelan Bolívar", + "symbol_native": "Bs.F.", + "decimal_digits": 2, + "rounding": 0, + "code": "VEF", + "name_plural": "Venezuelan bolívars" + }, + "VND": { + "symbol": "₫", + "name": "Vietnamese Dong", + "symbol_native": "₫", + "decimal_digits": 0, + "rounding": 0, + "code": "VND", + "name_plural": "Vietnamese dong" + }, + "XAF": { + "symbol": "FCFA", + "name": "CFA Franc BEAC", + "symbol_native": "FCFA", + "decimal_digits": 0, + "rounding": 0, + "code": "XAF", + "name_plural": "CFA francs BEAC" + }, + "XOF": { + "symbol": "CFA", + "name": "CFA Franc BCEAO", + "symbol_native": "CFA", + "decimal_digits": 0, + "rounding": 0, + "code": "XOF", + "name_plural": "CFA francs BCEAO" + }, + "YER": { + "symbol": "YR", + "name": "Yemeni Rial", + "symbol_native": "ر.ي.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "YER", + "name_plural": "Yemeni rials" + }, + "ZAR": { + "symbol": "R", + "name": "South African Rand", + "symbol_native": "R", + "decimal_digits": 2, + "rounding": 0, + "code": "ZAR", + "name_plural": "South African rand" + }, + "ZMK": { + "symbol": "ZK", + "name": "Zambian Kwacha", + "symbol_native": "ZK", + "decimal_digits": 0, + "rounding": 0, + "code": "ZMK", + "name_plural": "Zambian kwachas" + }, + "ZWL": { + "symbol": "ZWL$", + "name": "Zimbabwean Dollar", + "symbol_native": "ZWL$", + "decimal_digits": 0, + "rounding": 0, + "code": "ZWL", + "name_plural": "Zimbabwean Dollar" + } +} \ No newline at end of file diff --git a/IntegrationCore/BusinessLogic/Utility/CurrencySymbolService.php b/IntegrationCore/BusinessLogic/Utility/CurrencySymbolService.php new file mode 100644 index 0000000..1c27bb0 --- /dev/null +++ b/IntegrationCore/BusinessLogic/Utility/CurrencySymbolService.php @@ -0,0 +1,31 @@ +orderReference->getPayload()); $reminder = $this->getReminderDetail(); if ($reminder && $reminder->getRemainderMethod()) { - $voucherLabel = $this->getLabel($configs, $channelId, 'voucher'); $reminderLabel = $this->getLabel($configs, $channelId, $reminder->getRemainderMethod()); $voucherCurrencySymbol = $this->localeExtension->getCurrencySymbolByCurrency($order->getAmount()->getCurrency()); @@ -87,7 +86,7 @@ public function isVoucher() { $order = $this->getOrder(); - return $order && implode('', $order->getMethod()) === 'voucher'; + return $order && implode('', $order->getMethods()) === 'voucher'; } /** diff --git a/PaymentMethod/Factory/MollieConfigMapperDecorator.php b/PaymentMethod/Factory/MollieConfigMapperDecorator.php index 3a26b27..4d46b6b 100644 --- a/PaymentMethod/Factory/MollieConfigMapperDecorator.php +++ b/PaymentMethod/Factory/MollieConfigMapperDecorator.php @@ -58,7 +58,7 @@ public function getOrderData(PaymentTransaction $paymentTransaction) $orderData = $this->dtoMapper->getOrderData($paymentTransaction); if ($orderData) { $orderData->setProfileId($this->config->getProfileId()); - $orderData->setMethod([$this->config->getMollieId()]); + $orderData->setMethods([$this->config->getMollieId()]); $expiryDays = $this->config->getOrderExpiryDays(); if ($expiryDays > 0) { $orderData->calculateExpiresAt($expiryDays); @@ -102,7 +102,7 @@ public function getPaymentData(PaymentTransaction $paymentTransaction) { $paymentData = $this->dtoMapper->getPaymentData($paymentTransaction); $paymentData->setProfileId($this->config->getProfileId()); - $paymentData->setMethod([$this->config->getMollieId()]); + $paymentData->setMethods([$this->config->getMollieId()]); $this->setDueDate($paymentData); return $paymentData; diff --git a/PaymentMethod/Factory/MolliePaymentLinkMapperDecorator.php b/PaymentMethod/Factory/MolliePaymentLinkMapperDecorator.php index 1fa6d2e..ce31a92 100644 --- a/PaymentMethod/Factory/MolliePaymentLinkMapperDecorator.php +++ b/PaymentMethod/Factory/MolliePaymentLinkMapperDecorator.php @@ -44,7 +44,7 @@ public function getOrderData(PaymentTransaction $paymentTransaction) { $orderData = parent::getOrderData($paymentTransaction); if ($orderData) { - $orderData->setMethod($this->getPaymentLinkMethod($paymentTransaction)); + $orderData->setMethods($this->getPaymentLinkMethod($paymentTransaction)); } return $orderData; @@ -57,7 +57,7 @@ public function getPaymentData(PaymentTransaction $paymentTransaction) { $paymentData = parent::getPaymentData($paymentTransaction); - $paymentData->setMethod($this->getPaymentLinkMethod($paymentTransaction)); + $paymentData->setMethods($this->getPaymentLinkMethod($paymentTransaction)); return $paymentData; } diff --git a/README.md b/README.md index 9127024..443ec41 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ To finalize the installation you need to enter your organization API token in th Read more about the integration configuration on [our Wiki](https://github.com/mollie/orocommerce/wiki). ## Release notes - - **4.0.8:** + - **4.0.9:** + - Added support for the Klarna Pay Now payment method. + - **4.0.8:** - Optimization: Updated translations - Optimization: Fixed Composer version number - **4.0.7:** diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 485a621..7c33ec0 100755 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,5 +1,5 @@ parameters: - mollie_payment.version: 4.0.8 + mollie_payment.version: 4.0.9 mollie_payment.method.identifier_prefix.mollie_payment: 'mollie_payment' mollie_payment.uploader.public_image_path: 'bundles/molliepayment/img/uploads' mollie_payment.uploader.image_dir: '%kernel.project_dir%/public/%mollie_payment.uploader.public_image_path%' diff --git a/Resources/translations/messages.de.yml b/Resources/translations/messages.de.yml index 220940c..093b0da 100644 --- a/Resources/translations/messages.de.yml +++ b/Resources/translations/messages.de.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: 'Nach dem Kontrollieren Ihrer Bestellung werden Sie zur Website des Zahlungsanbieters weitergeleitet, um den Einkauf abzuschließen.' admin_link_error: 'Wir konnten Ihre Zahlung nicht verarbeiten. Überprüfen Sie bitte die Zahlungsinformationen und versuchen Sie es erneut.' selectBank: 'Bank auswählen' - cardHolder: 'Kartenhalter' - cardNumber: 'Kartennummer' - expiryDate: 'Verfallsdatum' - verificationCode: 'Verifizierungs-Schlüssel' + cardHolder: 'Name des Karteninhabers' + cardNumber: 'Kreditkartennummer' + expiryDate: 'MM/JJ' + verificationCode: 'CVV' config: authorization: label: 'Befugnis' diff --git a/Resources/translations/messages.de_DE.yml b/Resources/translations/messages.de_DE.yml index 220940c..093b0da 100644 --- a/Resources/translations/messages.de_DE.yml +++ b/Resources/translations/messages.de_DE.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: 'Nach dem Kontrollieren Ihrer Bestellung werden Sie zur Website des Zahlungsanbieters weitergeleitet, um den Einkauf abzuschließen.' admin_link_error: 'Wir konnten Ihre Zahlung nicht verarbeiten. Überprüfen Sie bitte die Zahlungsinformationen und versuchen Sie es erneut.' selectBank: 'Bank auswählen' - cardHolder: 'Kartenhalter' - cardNumber: 'Kartennummer' - expiryDate: 'Verfallsdatum' - verificationCode: 'Verifizierungs-Schlüssel' + cardHolder: 'Name des Karteninhabers' + cardNumber: 'Kreditkartennummer' + expiryDate: 'MM/JJ' + verificationCode: 'CVV' config: authorization: label: 'Befugnis' diff --git a/Resources/translations/messages.en.yml b/Resources/translations/messages.en.yml index 4e72d10..0f8b69c 100644 --- a/Resources/translations/messages.en.yml +++ b/Resources/translations/messages.en.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: 'You will be redirected to payment gateway website to complete your purchase after the order review step.' admin_link_error: 'We were unable to process your payment. Please verify your payment information and try again.' selectBank: 'Select bank' - cardHolder: 'Card Holder' - cardNumber: 'Card Number' - expiryDate: 'Expiry Date' - verificationCode: 'Verification Code' + cardHolder: 'Name on card' + cardNumber: 'Card number' + expiryDate: 'Expiry date' + verificationCode: 'CVC/CVV' config: authorization: label: 'Authorization' diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index afe5590..9a4b4cd 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: "Vous allez être redirigé vers le site web de la passerelle de paiement pour effectuer votre achat après l'étape de révision de la commande." admin_link_error: "Nous n'avons pas pu traiter votre paiement. Veuillez vérifier vos informations de paiement et try again." selectBank: 'Choisir une banque' - cardHolder: 'Titulaire de la carte' - cardNumber: 'Numéro de carte' - expiryDate: "Date d'expiration" - verificationCode: 'Code de vérification' + cardHolder: 'Nom du titulaire de la carte' + cardNumber: 'Numero de carte de credit' + expiryDate: 'MM/AA' + verificationCode: 'CVV' config: authorization: label: 'Autorisation' diff --git a/Resources/translations/messages.fr_FR.yml b/Resources/translations/messages.fr_FR.yml index afe5590..9a4b4cd 100644 --- a/Resources/translations/messages.fr_FR.yml +++ b/Resources/translations/messages.fr_FR.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: "Vous allez être redirigé vers le site web de la passerelle de paiement pour effectuer votre achat après l'étape de révision de la commande." admin_link_error: "Nous n'avons pas pu traiter votre paiement. Veuillez vérifier vos informations de paiement et try again." selectBank: 'Choisir une banque' - cardHolder: 'Titulaire de la carte' - cardNumber: 'Numéro de carte' - expiryDate: "Date d'expiration" - verificationCode: 'Code de vérification' + cardHolder: 'Nom du titulaire de la carte' + cardNumber: 'Numero de carte de credit' + expiryDate: 'MM/AA' + verificationCode: 'CVV' config: authorization: label: 'Autorisation' diff --git a/Resources/translations/messages.nl.yml b/Resources/translations/messages.nl.yml index 0e708f7..6f81819 100644 --- a/Resources/translations/messages.nl.yml +++ b/Resources/translations/messages.nl.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: 'Nadat je de bestelling hebt gecontroleerd, word je doorgestuurd naar de website van de betalingsprovider om je aankoop af te ronden.' admin_link_error: 'We hebben je betaling niet kunnen verwerken. Controleer je betalingsgegevens en probeer het opnieuw.' selectBank: 'Selecteer Bank' - cardHolder: 'Kaarthouder' - cardNumber: 'Kaartnummer' - expiryDate: 'Vervaldatum' - verificationCode: 'Verificatie code' + cardHolder: 'Naam kaarthouder' + cardNumber: 'Creditcardnummer' + expiryDate: 'MM/JJ' + verificationCode: 'CVV' config: authorization: label: 'Autorisatie' diff --git a/Resources/translations/messages.nl_NL.yml b/Resources/translations/messages.nl_NL.yml index 0e708f7..6f81819 100644 --- a/Resources/translations/messages.nl_NL.yml +++ b/Resources/translations/messages.nl_NL.yml @@ -35,10 +35,10 @@ mollie: redirect_to_mollie_payment: 'Nadat je de bestelling hebt gecontroleerd, word je doorgestuurd naar de website van de betalingsprovider om je aankoop af te ronden.' admin_link_error: 'We hebben je betaling niet kunnen verwerken. Controleer je betalingsgegevens en probeer het opnieuw.' selectBank: 'Selecteer Bank' - cardHolder: 'Kaarthouder' - cardNumber: 'Kaartnummer' - expiryDate: 'Vervaldatum' - verificationCode: 'Verificatie code' + cardHolder: 'Naam kaarthouder' + cardNumber: 'Creditcardnummer' + expiryDate: 'MM/JJ' + verificationCode: 'CVV' config: authorization: label: 'Autorisatie' diff --git a/Tests/Unit/BusinessLogic/Authorization/ApiKeyAuthServiceTest.php b/Tests/Unit/BusinessLogic/Authorization/ApiKeyAuthServiceTest.php new file mode 100644 index 0000000..a6f73f7 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Authorization/ApiKeyAuthServiceTest.php @@ -0,0 +1,124 @@ +httpClient = new TestHttpClient(); + TestServiceRegister::registerService( + HttpClient::CLASS_NAME, + function () use ($me) { + return $me->httpClient; + } + ); + TestServiceRegister::registerService( + Proxy::CLASS_NAME, + function () use ($me) { + return new Proxy($me->shopConfig, $me->httpClient, new ProxyDataProvider()); + } + ); + + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () use ($me) { + return ApiKeyAuthService::getInstance(); + } + ); + + + $this->authService = ApiKeyAuthService::getInstance(); + } + + protected function tearDown() + { + parent::tearDown(); + ApiKeyAuthService::resetInstance(); + } + + public function testConnection() + { + $this->httpClient->setMockResponses(array($this->getMockProfile(), $this->getMockProfile())); + $apiKey = new ApiKey('test_vzCV9AHCDpwuAMfEPtWz3Pah7RqA7j'); + $this->authService->connect($apiKey); + + $lastRequest = $this->httpClient->getLastRequest(); + $this->assertNotEmpty($lastRequest); + $this->assertEquals('Authorization: Bearer test_vzCV9AHCDpwuAMfEPtWz3Pah7RqA7j', $lastRequest['headers']['token']); + $this->assertNotContains('testmode=true', $lastRequest['url']); + } + + public function testConnectionWithInvalidKey() + { + $this->httpClient->setMockResponses(array(new HttpResponse(401, array(), ''))); + $apiKey = new ApiKey('test_vzCV9AHCDpwuAMfEPtWz3Pah7RqA7j'); + $this->expectException('Exception'); + $this->authService->connect($apiKey); + } + + public function testAuthorizationTokenValidation() + { + $this->httpClient->setMockResponses(array($this->getMockProfile())); + + $apiKey = new ApiKey('test_vzCV9AHCDpwuAMfEPtWz3Pah7RqA7j'); + $result = $this->authService->validateToken($apiKey); + + $lastRequest = $this->httpClient->getLastRequest(); + $this->assertTrue($result); + $this->assertNotEmpty($lastRequest); + $this->assertEquals('Authorization: Bearer test_vzCV9AHCDpwuAMfEPtWz3Pah7RqA7j', $lastRequest['headers']['token']); + $this->assertNotContains('testmode=true', $lastRequest['url']); + } + + public function testApiKeyTestMode() + { + $apiKey = new ApiKey('test_vzCV9AHCDpwuAMfEPtWz3Pah7RqA7j'); + $this->assertTrue($apiKey->isTest()); + } + + + public function testApiKeyNotInValidFormat() + { + $this->expectException('InvalidArgumentException'); + $this->authService->validateToken(new ApiKey('fajsdkljf')); + } + + private function getMockProfile() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/currentProfile.json'); + + return new HttpResponse(200, array(), $response); + } +} diff --git a/Tests/Unit/BusinessLogic/Authorization/OrgTokenAuthServiceTest.php b/Tests/Unit/BusinessLogic/Authorization/OrgTokenAuthServiceTest.php new file mode 100644 index 0000000..ba126e3 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Authorization/OrgTokenAuthServiceTest.php @@ -0,0 +1,172 @@ +httpClient = new TestHttpClient(); + TestServiceRegister::registerService( + HttpClient::CLASS_NAME, + function () use ($me) { + return $me->httpClient; + } + ); + TestServiceRegister::registerService( + Proxy::CLASS_NAME, + function () use ($me) { + return new Proxy($me->shopConfig, $me->httpClient, new ProxyDataProvider()); + } + ); + TestServiceRegister::registerService( + PaymentMethodService::CLASS_NAME, + function () { + return MockPaymentMethodService::getInstance(); + } + ); + + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () use ($me) { + return OrgTokenAuthService::getInstance(); + } + ); + + + $this->authService = OrgTokenAuthService::getInstance(); + $this->paymentMethodService = MockPaymentMethodService::getInstance(); + } + + protected function tearDown() + { + parent::tearDown(); + OrgTokenAuthService::resetInstance(); + MockPaymentMethodService::resetInstance(); + } + + public function testAuthorizationTokenValidation() + { + $this->httpClient->setMockResponses(array($this->getMockPermissions())); + $token = new OrgToken('test_token', true); + + $result = $this->authService->validateToken($token); + + $lastRequest = $this->httpClient->getLastRequest(); + $this->assertTrue($result); + $this->assertNotEmpty($lastRequest); + $this->assertEquals('Authorization: Bearer test_token', $lastRequest['headers']['token']); + $this->assertNotContains('testmode=true', $lastRequest['url']); + } + + public function testAuthorizationTokenValidationWithInsufficientPermissions() + { + $this->httpClient->setMockResponses(array($this->getMockInsufficientPermissions())); + + $result = $this->authService->validateToken(new OrgToken('test_token', true)); + + $lastRequest = $this->httpClient->getLastRequest(); + $this->assertFalse($result); + $this->assertNotEmpty($lastRequest); + $this->assertEquals('Authorization: Bearer test_token', $lastRequest['headers']['token']); + $this->assertNotContains('testmode=true', $lastRequest['url']); + } + + public function testAuthorizationTokenValidationFailure() + { + $response = new HttpResponse(401, array(), '{ "status": 401, "title": "Unauthorized Request" }'); + $this->httpClient->setMockResponses(array($response)); + + $result = $this->authService->validateToken(new OrgToken('test_token', false)); + + $lastRequest = $this->httpClient->getLastRequest(); + $this->assertFalse($result); + $this->assertNotEmpty($lastRequest); + $this->assertEquals('Authorization: Bearer test_token', $lastRequest['headers']['token']); + $this->assertNotContains('testmode=true', $lastRequest['url']); + } + + public function testAuthorizationTokenValidationConfigServiceCleanup() + { + $this->httpClient->setMockResponses(array($this->getMockPermissions())); + + $this->authService->validateToken(new OrgToken('test_token', true)); + + $this->assertNull($this->shopConfig->getAuthorizationToken()); + $this->assertFalse($this->shopConfig->isTestMode()); + } + + public function testResetting() + { + $profileId = 'test_dfklasjio11231'; + $this->shopConfig->setContext('test_context'); + $this->shopConfig->setAuthorizationToken('test_token'); + $this->shopConfig->setTestMode(true); + $this->shopConfig->setWebsiteProfile( + WebsiteProfile::fromArray(array( + 'resource' => 'profile', + 'id' => $profileId, + 'name' => 'Test profile', + )) + ); + + $this->authService->reset(); + + $clearPaymentsCallHistory = $this->paymentMethodService->getCallHistory('clear'); + $this->assertCount(1, $clearPaymentsCallHistory); + $this->assertEquals($profileId, $clearPaymentsCallHistory[0]['profileId']); + $this->assertNull($this->shopConfig->getAuthorizationToken()); + $this->assertFalse($this->shopConfig->isTestMode()); + $this->assertNull($this->shopConfig->getWebsiteProfile()); + } + + protected function getMockPermissions() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/permissions.json'); + + return new HttpResponse(200, array(), $response); + } + + protected function getMockInsufficientPermissions() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/insufficientPermissions.json'); + + return new HttpResponse(200, array(), $response); + } +} diff --git a/Tests/Unit/BusinessLogic/CheckoutLink/CheckoutLinkTest.php b/Tests/Unit/BusinessLogic/CheckoutLink/CheckoutLinkTest.php index 99a5bd1..5fca4bd 100644 --- a/Tests/Unit/BusinessLogic/CheckoutLink/CheckoutLinkTest.php +++ b/Tests/Unit/BusinessLogic/CheckoutLink/CheckoutLinkTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\CheckoutLink; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\CheckoutLink\CheckoutLinkService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\CheckoutLink\Exceptions\CheckoutLinkNotAvailableException; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException; @@ -92,6 +94,13 @@ function () { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () use ($me) { + return ApiKeyAuthService::getInstance(); + } + ); + $this->shopConfig->setAuthorizationToken('test_token'); $this->shopConfig->setTestMode(true); $this->checkoutLinkService = CheckoutLinkService::getInstance(); diff --git a/Tests/Unit/BusinessLogic/Common/ApiResponses/allShipments.json b/Tests/Unit/BusinessLogic/Common/ApiResponses/allShipments.json new file mode 100644 index 0000000..ec05af4 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/ApiResponses/allShipments.json @@ -0,0 +1,86 @@ +{ + "count": 2, + "_embedded": { + "shipments": [ + { + "resource": "shipment", + "id": "shp_3wmsgCJN4U", + "orderId": "ord_kEn1PlbGa", + "createdAt": "2018-08-09T14:33:54+00:00", + "tracking": { + "carrier": "PostNL", + "code": "3SKABA000000000", + "url": "http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C" + }, + "lines": [ + { + "resource": "orderline", + "id": "odl_dgtxyl", + "orderId": "ord_pbjz8x", + "name": "LEGO 42083 Bugatti Chiron", + "sku": "5702016116977", + "type": "physical", + "status": "shipping", + "metadata": null, + "isCancelable": true, + "quantity": 1, + "unitPrice": { + "value": "399.00", + "currency": "EUR" + }, + "vatRate": "21.00", + "vatAmount": { + "value": "51.89", + "currency": "EUR" + }, + "discountAmount": { + "value": "100.00", + "currency": "EUR" + }, + "totalAmount": { + "value": "299.00", + "currency": "EUR" + }, + "createdAt": "2018-08-02T09:29:56+00:00", + "_links": { + "productUrl": { + "href": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", + "type": "text/html" + }, + "imageUrl": { + "href": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", + "type": "text/html" + } + } + }, + { } + ], + "_links": { + "self": { + "href": "https://api.mollie.com/v2/order/ord_kEn1PlbGa/shipments/shp_3wmsgCJN4U", + "type": "application/hal+json" + }, + "order": { + "href": "https://api.mollie.com/v2/orders/ord_kEn1PlbGa", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/shipments-api/get-shipment", + "type": "text/html" + } + } + }, + { } + ] + }, + "_links": { + "self": { + "href": "https://api.mollie.com/v2/order/ord_kEn1PlbGa/shipments", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/shipments-api/list-shipments", + "type": "text/html" + } + } +} \ No newline at end of file diff --git a/Tests/Unit/BusinessLogic/Common/ApiResponses/currentProfile.json b/Tests/Unit/BusinessLogic/Common/ApiResponses/currentProfile.json new file mode 100644 index 0000000..d954054 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/ApiResponses/currentProfile.json @@ -0,0 +1,49 @@ +{ + "resource": "profile", + "id": "pfl_v9hTwCvYqw", + "mode": "live", + "name": "My website name", + "website": "https://www.mywebsite.com", + "email": "info@mywebsite.com", + "phone": "+31208202070", + "categoryCode": 5399, + "status": "verified", + "review": { + "status": "pending" + }, + "createdAt": "2018-03-20T09:28:37+00:00", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_123456789/settings/profiles/pfl_v9hTwCvYqw", + "type": "text/html" + }, + "chargebacks": { + "href": "https://api.mollie.com/v2/chargebacks", + "type": "application/hal+json" + }, + "methods": { + "href": "https://api.mollie.com/v2/methods", + "type": "application/hal+json" + }, + "payments": { + "href": "https://api.mollie.com/v2/payments", + "type": "application/hal+json" + }, + "refunds": { + "href": "https://api.mollie.com/v2/refunds", + "type": "application/hal+json" + }, + "checkoutPreviewUrl": { + "href": "https://www.mollie.com/payscreen/preview/pfl_v9hTwCvYqw", + "type": "text/html" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/profiles-api/get-profile-me", + "type": "text/html" + } + } +} \ No newline at end of file diff --git a/Tests/Unit/BusinessLogic/Common/ApiResponses/mollieTokens.json b/Tests/Unit/BusinessLogic/Common/ApiResponses/mollieTokens.json new file mode 100644 index 0000000..4d15c9b --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/ApiResponses/mollieTokens.json @@ -0,0 +1,7 @@ +{ + "access_token": "access_TRbHbeB3my8XywBAdT6HRkGAJMuh4", + "refresh_token": "refresh_FS4xc3Mgci2xQ5s5DzaLXh3HhaTZOP", + "expires_in": 3600, + "token_type": "bearer", + "scope": "payments.read organizations.read" +} \ No newline at end of file diff --git a/Tests/Unit/BusinessLogic/Common/ApiResponses/paymentMethodsAll.json b/Tests/Unit/BusinessLogic/Common/ApiResponses/paymentMethodsAll.json index c1f04ce..548bc68 100644 --- a/Tests/Unit/BusinessLogic/Common/ApiResponses/paymentMethodsAll.json +++ b/Tests/Unit/BusinessLogic/Common/ApiResponses/paymentMethodsAll.json @@ -360,6 +360,31 @@ } } }, + { + "resource": "method", + "id": "klarnapaynow", + "description": "Pay now.", + "minimumAmount": { + "value": "0.10", + "currency": "EUR" + }, + "maximumAmount": { + "value": "10000.00", + "currency": "EUR" + }, + "image": { + "size1x": "https://www.mollie.com/external/icons/payment-methods/klarnapaynow.png", + "size2x": "https://www.mollie.com/external/icons/payment-methods/klarnapaynow%402x.png", + "svg": "https://www.mollie.com/external/icons/payment-methods/klarnapaynow.svg" + }, + "status": "activated", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/methods/klarnapaynow", + "type": "application/hal+json" + } + } + }, { "resource": "method", "id": "klarnasliceit", diff --git a/Tests/Unit/BusinessLogic/Common/ApiResponses/version-check.json b/Tests/Unit/BusinessLogic/Common/ApiResponses/version-check.json new file mode 100644 index 0000000..25cc4a1 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/ApiResponses/version-check.json @@ -0,0 +1,27 @@ +{ + "name": "mollie/integration-core", + "version": "2.0.0", + "description": "Mollie integrations core library", + "type": "library", + "license": "proprietary", + "require": { + "php": ">=5.3" + }, + "autoload": { + "psr-4": { + "Mollie\Bundle\PaymentBundle\IntegrationCore\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Mollie\Bundle\PaymentBundle\IntegrationCore\\Tests\\": "tests", + "Mollie\Bundle\PaymentBundle\IntegrationCore\\Console\\": "console" + } + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35", + "codacy/coverage": "dev-master", + "ext-json": "*", + "symfony/console": "^5.1" + } +} \ No newline at end of file diff --git a/Tests/Unit/BusinessLogic/Common/TestComponents/MockAuthorizationService.php b/Tests/Unit/BusinessLogic/Common/TestComponents/MockAuthorizationService.php new file mode 100644 index 0000000..aa7fd19 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/TestComponents/MockAuthorizationService.php @@ -0,0 +1,116 @@ +getTimestamp()); + } + + /** + * Returns invalid AuthInfo object (accessToken is not valid) + * + * @return AuthInfo + */ + public function getInvalidMockupAuthInfo() + { + $time = new \DateTime('2021-6-1'); + + return new AuthInfo('accessToken', 'refreshToken', $time->getTimestamp()); + } + + /** + * {@inheritdoc} + * + * @return string + */ + public function getClientSecret() + { + return 'clientSecret'; + } + + /** + * {@inheritdoc} + * + * @return string + */ + public function getAuthToken() + { + return 'authToken'; + } +} diff --git a/Tests/Unit/BusinessLogic/Common/TestComponents/TestPaymentTransactionDescriptionService.php b/Tests/Unit/BusinessLogic/Common/TestComponents/TestPaymentTransactionDescriptionService.php new file mode 100644 index 0000000..633def8 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/TestComponents/TestPaymentTransactionDescriptionService.php @@ -0,0 +1,19 @@ +mockDescription; + } +} diff --git a/Tests/Unit/BusinessLogic/Common/TestComponents/TestVersionCheckService.php b/Tests/Unit/BusinessLogic/Common/TestComponents/TestVersionCheckService.php new file mode 100644 index 0000000..511306d --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/TestComponents/TestVersionCheckService.php @@ -0,0 +1,26 @@ +callHistory[] = array('latestverion' => $latestVersion); + + return $latestVersion; + } + + public function getCallHistory() + { + return $this->callHistory; + } +} diff --git a/Tests/Unit/BusinessLogic/Common/TestMaintenanceModeService.php b/Tests/Unit/BusinessLogic/Common/TestMaintenanceModeService.php new file mode 100644 index 0000000..50b023a --- /dev/null +++ b/Tests/Unit/BusinessLogic/Common/TestMaintenanceModeService.php @@ -0,0 +1,42 @@ +callHistory[] = array('called' => true); + } + + /** + * @return array + */ + public function getCallHistory() + { + return $this->callHistory; + } +} diff --git a/Tests/Unit/BusinessLogic/Connect/AuthorizationServiceTest.php b/Tests/Unit/BusinessLogic/Connect/AuthorizationServiceTest.php new file mode 100644 index 0000000..fb81cc4 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Connect/AuthorizationServiceTest.php @@ -0,0 +1,131 @@ +httpClient = new TestHttpClient(); + $self = $this; + + TestServiceRegister::registerService( + HttpClient::CLASS_NAME, + function () use ($self) { + return $self->httpClient; + } + ); + + TestServiceRegister::registerService( + Proxy::CLASS_NAME, + function () use ($self) { + return new Proxy($self->shopConfig, $self->httpClient, new ProxyDataProvider()); + } + ); + + TestServiceRegister::registerService( + TokenService::CLASS_NAME, + function () use ($self) { + return new TokenService(new TokenProxy($self->shopConfig, $self->httpClient, new ProxyDataProvider())); + } + ); + + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return new MockAuthorizationService(); + } + ); + } + + /** + * Tests getAuthInfo when accessToken is valid + * + * @throws UnprocessableEntityRequestException + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + */ + public function testValidGetAuthInfo() + { + $time = new \DateTime('now'); + $time->modify('+ 59 minutes'); + + $originalAuthInfo = new AuthInfo('accessToken', 'refreshToken', $time->getTimestamp()); + $this->shopConfig->setAuthorizationInfo(new AuthInfo('accessToken', 'refreshToken', $time->getTimestamp())); + + $authInfo = $this->getAuthorizationService()->getAuthInfo(); + + self::assertEquals($originalAuthInfo, $authInfo); + } + + /** + * Testing function for getting authorize url + */ + public function testGettingAuthorizeUrl() + { + $authorizeUrl = $this->getAuthorizationService()->getAuthorizeUrl('en_US'); + + $params = array( + 'client_id' => 'clientId', + 'redirect_uri' => 'https://test/tets', + 'state' => $this->shopConfig->getStateString(), + 'scope' => 'payments.read organizations.read', + 'response_type' => 'code', + 'approval_prompt' => 'force', + 'locale' => 'en_US', + ); + + $testAuthorizeUrl = 'https://www.mollie.com/oauth2/authorize' . '?' . http_build_query($params); + + self::assertEquals($authorizeUrl, $testAuthorizeUrl); + } + + /** + * Returns authorization service + * + * @return MockAuthorizationService + */ + public function getAuthorizationService() + { + return ServiceRegister::getService(AuthorizationService::CLASS_NAME); + } + + /** + * Returns Token service + * + * @return TokenService + */ + public function getTokenService() + { + return ServiceRegister::getService(TokenService::CLASS_NAME); + } +} diff --git a/Tests/Unit/BusinessLogic/Connect/DTO/AuthInfoTest.php b/Tests/Unit/BusinessLogic/Connect/DTO/AuthInfoTest.php new file mode 100644 index 0000000..755b93c --- /dev/null +++ b/Tests/Unit/BusinessLogic/Connect/DTO/AuthInfoTest.php @@ -0,0 +1,46 @@ + 'testAccess', + 'refresh_token' => 'testRefresh', + 'expires_in' => 542689, + ); + + $authInfo = new AuthInfo('testAccess', 'testRefresh', 542689); + + self::assertSame($array, $authInfo->toArray()); + } + + /** + * Tests Auth info fromArray function + */ + public function testAuthInfoFromArray() + { + $array = array( + 'access_token' => 'testAccess', + 'refresh_token' => 'testRefresh', + 'expires_in' => 542689, + ); + + $authInfo = new AuthInfo('testAccess', 'testRefresh', 542689); + $authInfoTest = AuthInfo::fromArray($array); + + self::assertEquals($authInfoTest, $authInfo); + } +} diff --git a/Tests/Unit/BusinessLogic/Connect/DTO/TokenRequestTest.php b/Tests/Unit/BusinessLogic/Connect/DTO/TokenRequestTest.php new file mode 100644 index 0000000..19260fc --- /dev/null +++ b/Tests/Unit/BusinessLogic/Connect/DTO/TokenRequestTest.php @@ -0,0 +1,33 @@ + 'authorization_code', + 'code' => 'testCode', + 'redirect_uri' => 'someUrl', + ); + + $arrayRefresh = array( + 'grant_type' => 'refresh_token', + 'refresh_token' => 'testRefresh', + ); + + $tokenCode = new TokenRequest('authorization_code', 'testCode', '', 'someUrl'); + $tokenRefresh = new TokenRequest('refresh_token', '', 'testRefresh', ''); + + self::assertSame($arrayCode, $tokenCode->toArray()); + self::assertSame($arrayRefresh, $tokenRefresh->toArray()); + } +} diff --git a/Tests/Unit/BusinessLogic/Connect/TokenServiceTest.php b/Tests/Unit/BusinessLogic/Connect/TokenServiceTest.php new file mode 100644 index 0000000..86dffe1 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Connect/TokenServiceTest.php @@ -0,0 +1,132 @@ +httpClient = new TestHttpClient(); + $self = $this; + + TestServiceRegister::registerService( + HttpClient::CLASS_NAME, + function () use ($self) { + return $self->httpClient; + } + ); + + TestServiceRegister::registerService( + Proxy::CLASS_NAME, + function () use ($self) { + return new Proxy($self->shopConfig, $self->httpClient, new ProxyDataProvider()); + } + ); + + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return new MockAuthorizationService(); + } + ); + + TestServiceRegister::registerService( + TokenProxy::CLASS_NAME, + function () use ($self) { + return new TokenProxy($self->shopConfig, $self->httpClient, new ProxyDataProvider()); + } + ); + + TestServiceRegister::registerService( + TokenService::CLASS_NAME, + function () use ($self) { + return new TokenService(new TokenProxy($self->shopConfig, $self->httpClient, new ProxyDataProvider())); + } + ); + } + + /** + * Test generate tokens from given code + * + * @throws UnprocessableEntityRequestException + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + */ + public function testGenerateTokens() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/mollieTokens.json'); + $this->httpClient->setMockResponses(array(new HttpResponse(200, array(), $response))); + + $authInfo = $this->getTokenService()->generate('code_54865asdbviyt6845asdasd'); + $authInfoTest = new AuthInfo( + 'access_TRbHbeB3my8XywBAdT6HRkGAJMuh4', + 'refresh_FS4xc3Mgci2xQ5s5DzaLXh3HhaTZOP', + $authInfo->getAccessTokenDuration() + ); + + self::assertEquals($authInfo, $authInfoTest); + } + + /** + * Test generate tokens from given refreshToken + * + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function testRefreshTokens() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/mollieTokens.json'); + $this->httpClient->setMockResponses(array(new HttpResponse(200, array(), $response))); + + $authInfo = $this->getTokenService()->refreshToken('refresh_54865asdbviyt6845asdasd'); + $authInfoTest = new AuthInfo( + 'access_TRbHbeB3my8XywBAdT6HRkGAJMuh4', + 'refresh_FS4xc3Mgci2xQ5s5DzaLXh3HhaTZOP', + $authInfo->getAccessTokenDuration() + ); + + self::assertEquals($authInfo, $authInfoTest); + } + + /** + * Get TokenService + * + * @return TokenService + */ + private function getTokenService() + { + return ServiceRegister::getService(TokenService::CLASS_NAME); + } +} diff --git a/Tests/Unit/BusinessLogic/Http/DTO/AmountTest.php b/Tests/Unit/BusinessLogic/Http/DTO/AmountTest.php index f4d2164..c2fab43 100644 --- a/Tests/Unit/BusinessLogic/Http/DTO/AmountTest.php +++ b/Tests/Unit/BusinessLogic/Http/DTO/AmountTest.php @@ -36,6 +36,17 @@ public function testAmountValueFromCurrencySmallestUnit() $this->assertSame('10.147', $amountArray['value']); } + public function testAmountValueWithoutMinorUnits() + { + $amount = Amount::fromSmallestUnit(10147, 'JPY'); + + $this->assertEquals(10147, $amount->getAmountValue()); + + $amountArray = $amount->toArray(); + + $this->assertSame('10147', $amountArray['value']); + } + public function testAmountValueToCurrencySmallestUnit() { $amount = Amount::fromArray(array( @@ -46,6 +57,16 @@ public function testAmountValueToCurrencySmallestUnit() $this->assertEquals(10147, $amount->getAmountValueInSmallestUnit()); } + public function testAmountConversionToCurrencySmallestUnit() + { + $amount = Amount::fromArray(array( + 'value' => 2.05, + 'currency' => 'EUR' + )); + + $this->assertEquals(205, $amount->getAmountValueInSmallestUnit()); + } + public function testExistingCurrency() { $amount = Amount::fromSmallestUnit(101475, 'UYW'); diff --git a/Tests/Unit/BusinessLogic/Http/ProxyTest.php b/Tests/Unit/BusinessLogic/Http/ProxyTest.php index 5a3bdba..f3c37ff 100644 --- a/Tests/Unit/BusinessLogic/Http/ProxyTest.php +++ b/Tests/Unit/BusinessLogic/Http/ProxyTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\Http; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Proxy; @@ -46,6 +48,13 @@ function () use ($self) { return new Proxy($self->shopConfig, $self->httpClient, new ProxyDataProvider()); } ); + + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); } /** diff --git a/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderAddressChangedEvenHandlerTest.php b/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderAddressChangedEvenHandlerTest.php index ab70616..b5048b7 100644 --- a/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderAddressChangedEvenHandlerTest.php +++ b/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderAddressChangedEvenHandlerTest.php @@ -16,6 +16,7 @@ */ class IntegrationOrderAddressChangedEvenHandlerTest extends IntegrationOrderEventHandlerTest { + /** * @throws \Exception */ diff --git a/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderEventHandlerTest.php b/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderEventHandlerTest.php index eaba0f1..9888751 100644 --- a/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderEventHandlerTest.php +++ b/Tests/Unit/BusinessLogic/Integration/EventHandler/IntegrationOrderEventHandlerTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\Integration\EventHandler; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Payment; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; @@ -90,6 +92,12 @@ function () { return $me->defaultChannel; }); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () use ($me) { + return ApiKeyAuthService::getInstance(); + } + ); $this->setUpTestOrderReferences(); } diff --git a/Tests/Unit/BusinessLogic/MaintenanceMode/MaintenanceModeServiceTest.php b/Tests/Unit/BusinessLogic/MaintenanceMode/MaintenanceModeServiceTest.php new file mode 100644 index 0000000..9de0387 --- /dev/null +++ b/Tests/Unit/BusinessLogic/MaintenanceMode/MaintenanceModeServiceTest.php @@ -0,0 +1,42 @@ +maintenanceModeService = TestMaintenanceModeService::getInstance(); + } + + public function tearDown() + { + TestMaintenanceModeService::resetInstance(); + + parent::tearDown(); + } + + public function testWhenInMaintenanceMode() + { + $this->maintenanceModeService->checkMaintenanceMode(); + + $this->assertNotEmpty($this->maintenanceModeService->getCallHistory()); + } + + + public function testWhenNotInMaintenanceMode() + { + TestMaintenanceModeService::$IN_MAINTENANCE = false; + $this->maintenanceModeService->checkMaintenanceMode(); + + $this->assertEmpty($this->maintenanceModeService->getCallHistory()); + } +} diff --git a/Tests/Unit/BusinessLogic/Orders/OrderServiceTest.php b/Tests/Unit/BusinessLogic/Orders/OrderServiceTest.php index 572889b..f97b411 100644 --- a/Tests/Unit/BusinessLogic/Orders/OrderServiceTest.php +++ b/Tests/Unit/BusinessLogic/Orders/OrderServiceTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\Orders; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; @@ -76,6 +78,13 @@ function () { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + $this->shopConfig->setAuthorizationToken('test_token'); $this->shopConfig->setTestMode(true); $this->orderService = OrderService::getInstance(); @@ -125,9 +134,14 @@ public function testOrderCreationWithMultiplePaymentMethods() { $shopReference = 'test_reference_id'; $profileId = 'pfl_URR55HPMGx'; - $paymentMethods = array(PaymentMethods::PayPal, PaymentMethods::KlarnaSliceIt, PaymentMethods::KlarnaPayLater); + $paymentMethods = array( + PaymentMethods::PayPal, + PaymentMethods::KlarnaSliceIt, + PaymentMethods::KlarnaPayLater, + PaymentMethods::KlarnaPayNow, + ); $order = $this->getOrderData($shopReference, $profileId); - $order->setMethod($paymentMethods); + $order->setMethods($paymentMethods); $this->httpClient->setMockResponses(array($this->getMockOrderResponse(), $this->getMockOrderResponse())); $createdOrder = $this->orderService->createOrder($shopReference, $order); diff --git a/Tests/Unit/BusinessLogic/PaymentMethod/PaymentMethodServiceTest.php b/Tests/Unit/BusinessLogic/PaymentMethod/PaymentMethodServiceTest.php index 4f7f36a..141132e 100644 --- a/Tests/Unit/BusinessLogic/PaymentMethod/PaymentMethodServiceTest.php +++ b/Tests/Unit/BusinessLogic/PaymentMethod/PaymentMethodServiceTest.php @@ -5,6 +5,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\PaymentMethod; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Amount; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\PaymentMethod; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\WebsiteProfile; @@ -59,6 +61,13 @@ function () use ($me) { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + $this->shopConfig->setAuthorizationToken('test_token'); $this->shopConfig->setTestMode(true); $testProfile = new WebsiteProfile(); @@ -103,7 +112,7 @@ public function testGettingAllPaymentMethodConfigurationsResultWhenDBIsEmpty() $result = $this->paymentMethodService->getAllPaymentMethodConfigurations($profileId); - $this->assertCount(16, $result); + $this->assertCount(17, $result); $this->assertNull($result[0]->getId()); $this->assertEquals($profileId, $result[0]->getProfileId()); $this->assertEquals('applepay', $result[0]->getMollieId()); @@ -131,7 +140,7 @@ public function testGettingAllPaymentMethodConfigurationsResultWithExistingDBCon $result = $this->paymentMethodService->getAllPaymentMethodConfigurations($profileId); - $this->assertCount(16, $result); + $this->assertCount(17, $result); $this->assertNotNull($result[0]->getId()); $this->assertEquals($profileId, $result[0]->getProfileId()); $this->assertEquals('applepay', $result[0]->getMollieId()); diff --git a/Tests/Unit/BusinessLogic/PaymentMethod/PaymentTransactionDescriptionServiceTest.php b/Tests/Unit/BusinessLogic/PaymentMethod/PaymentTransactionDescriptionServiceTest.php new file mode 100644 index 0000000..0c65c03 --- /dev/null +++ b/Tests/Unit/BusinessLogic/PaymentMethod/PaymentTransactionDescriptionServiceTest.php @@ -0,0 +1,59 @@ +transactionDescriptionService = TestPaymentTransactionDescriptionService::getInstance(); + } + + public function tearDown() + { + TestPaymentTransactionDescriptionService::resetInstance(); + + parent::tearDown(); + } + + public function testTransactionDescriptionWithAllParameters() + { + $orderNumber = 100; + $storeName = 'Test Store'; + $firstName = 'John'; + $lastName = 'Doe'; + $company = 'Test Company'; + $cartNumber = 'CART001'; + + $this->transactionDescriptionService->mockDescription = 'Store: {storeName}, Order number: {orderNumber}, Customer: {customerFirstname} {customerLastname}, Company: {customerCompany}, cart: {cartNumber}'; + + $parameters = new DescriptionParameters($orderNumber, $storeName, $firstName, $lastName, $company, $cartNumber); + $description = $this->transactionDescriptionService->formatPaymentDescription($parameters, 'test'); + $expected = "Store: $storeName, Order number: $orderNumber, Customer: $firstName $lastName, Company: $company, cart: $cartNumber"; + + $this->assertEquals($expected, $description); + } + + public function testTransactionDescriptionWithSomeParameters() + { + $this->transactionDescriptionService->mockDescription = 'Order number: {orderNumber}, Customer: {customerLastname}'; + $orderNumber = 100; + $lastName = 'Doe'; + + $parameters = DescriptionParameters::fromArray(array('orderNumber' => $orderNumber, 'customerLastname' => $lastName)); + + $description = $this->transactionDescriptionService->formatPaymentDescription($parameters, 'test'); + $expected = "Order number: $orderNumber, Customer: $lastName"; + + $this->assertEquals($expected, $description); + } +} diff --git a/Tests/Unit/BusinessLogic/Payments/PaymentServiceTest.php b/Tests/Unit/BusinessLogic/Payments/PaymentServiceTest.php index cd19744..31edbba 100644 --- a/Tests/Unit/BusinessLogic/Payments/PaymentServiceTest.php +++ b/Tests/Unit/BusinessLogic/Payments/PaymentServiceTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\Payments; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Payment; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException; @@ -76,6 +78,13 @@ function () { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + $this->shopConfig->setAuthorizationToken('test_token'); $this->shopConfig->setTestMode(true); $this->paymentService = PaymentService::getInstance(); @@ -274,7 +283,12 @@ public function testPaymentCreationWithMultiplePaymentMethods() { $profileId = 'pfl_QkEhN94Ba'; $shopReference = 'test_reference_id'; - $paymentMethods = array(PaymentMethods::PayPal, PaymentMethods::KlarnaSliceIt, PaymentMethods::KlarnaPayLater); + $paymentMethods = array( + PaymentMethods::PayPal, + PaymentMethods::KlarnaSliceIt, + PaymentMethods::KlarnaPayLater, + PaymentMethods::KlarnaPayNow, + ); $payment = Payment::fromArray(array( 'profileId' => $profileId, 'amount' => array( diff --git a/Tests/Unit/BusinessLogic/Refunds/RefundServiceTest.php b/Tests/Unit/BusinessLogic/Refunds/RefundServiceTest.php index ff4df48..b064dbb 100644 --- a/Tests/Unit/BusinessLogic/Refunds/RefundServiceTest.php +++ b/Tests/Unit/BusinessLogic/Refunds/RefundServiceTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\Refunds; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Amount; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\OrderLine; @@ -94,6 +96,13 @@ function () { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + $this->shopConfig->setAuthorizationToken('test_token'); $this->shopConfig->setTestMode(true); $this->refundService = RefundService::getInstance(); diff --git a/Tests/Unit/BusinessLogic/Shipments/ShipmentServiceTest.php b/Tests/Unit/BusinessLogic/Shipments/ShipmentServiceTest.php new file mode 100644 index 0000000..58abb50 --- /dev/null +++ b/Tests/Unit/BusinessLogic/Shipments/ShipmentServiceTest.php @@ -0,0 +1,163 @@ +httpClient = new TestHttpClient(); + TestServiceRegister::registerService( + HttpClient::CLASS_NAME, + function () use ($me) { + return $me->httpClient; + } + ); + TestServiceRegister::registerService( + Proxy::CLASS_NAME, + function () use ($me) { + return new Proxy($me->shopConfig, $me->httpClient, new ProxyDataProvider()); + } + ); + + TestServiceRegister::registerService( + OrderReferenceService::CLASS_NAME, + function () { + return OrderReferenceService::getInstance(); + } + ); + + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + + $this->shipmentService = ShipmentService::getInstance(); + $this->shopConfig->setAuthorizationToken('test_token'); + $this->shopConfig->setTestMode(true); + $testProfile = new WebsiteProfile(); + $testProfile->setId('pfl_htsmhPNGw3'); + $this->shopConfig->setWebsiteProfile($testProfile); + $this->orderReferenceRepository = RepositoryRegistry::getRepository(OrderReference::CLASS_NAME); + } + + public function tearDown() + { + ShipmentService::resetInstance(); + + parent::tearDown(); + } + + /** + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\OrderReference\Exceptions\ReferenceNotFoundException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpAuthenticationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpCommunicationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpRequestException + */ + public function testGetShipments() + { + $this->httpClient->setMockResponses(array($this->getMockAllShipments())); + $this->setUpTestOrderReferences('test_reference_id'); + $shopReference = 'test_reference_id'; + $shipments = $this->shipmentService->getShipments($shopReference); + $this->assertCount(2, $shipments); + + $this->assertInstanceOf('Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Shipment', $shipments[0]); + } + + /** + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\OrderReference\Exceptions\ReferenceNotFoundException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpAuthenticationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpCommunicationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpRequestException + */ + public function testCreateShipmentWhenPaymentsApiIsUsed() + { + $shopReference = 'test_reference_id'; + $this->setUpTestOrderReferences($shopReference, PaymentMethodConfig::API_METHOD_PAYMENT); + $this->expectException('\Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\OrderReference\Exceptions\ReferenceNotFoundException'); + $this->shipmentService->shipOrder($shopReference); + } + + /** + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\OrderReference\Exceptions\ReferenceNotFoundException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpAuthenticationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpCommunicationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpRequestException + */ + public function testGetShipmentsWhenReferenceNotFound() + { + $shopReference = 'unknown_reference'; + + $this->expectException('\Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\OrderReference\Exceptions\ReferenceNotFoundException'); + $this->shipmentService->getShipments($shopReference); + } + + /** + * @return HttpResponse + */ + protected function getMockAllShipments() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/allShipments.json'); + + return new HttpResponse(200, array(), $response); + } + + /** + * @param string $shopReference + * @param string $method + */ + protected function setUpTestOrderReferences($shopReference, $method = PaymentMethodConfig::API_METHOD_ORDERS) + { + $payload = file_get_contents(__DIR__ . '/../Common/ApiResponses/orderResponse.json'); + $order = Order::fromArray(json_decode($payload, true)); + OrderReferenceService::getInstance()->updateOrderReference( + $order, + $shopReference, + $method + ); + } +} diff --git a/Tests/Unit/BusinessLogic/UI/Controllers/WebsiteProfileControllerTest.php b/Tests/Unit/BusinessLogic/UI/Controllers/WebsiteProfileControllerTest.php index 884b715..e2da07d 100644 --- a/Tests/Unit/BusinessLogic/UI/Controllers/WebsiteProfileControllerTest.php +++ b/Tests/Unit/BusinessLogic/UI/Controllers/WebsiteProfileControllerTest.php @@ -5,6 +5,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\UI\Controllers; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\WebsiteProfile; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Proxy; @@ -59,6 +61,13 @@ function () { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + $this->websiteProfileController = new WebsiteProfileController(); $this->paymentMethodService = MockPaymentMethodService::getInstance(); } diff --git a/Tests/Unit/BusinessLogic/Utility/CurrencySymbolServiceTest.php b/Tests/Unit/BusinessLogic/Utility/CurrencySymbolServiceTest.php new file mode 100644 index 0000000..0e7121d --- /dev/null +++ b/Tests/Unit/BusinessLogic/Utility/CurrencySymbolServiceTest.php @@ -0,0 +1,23 @@ +versionCheckService = TestVersionCheckService::getInstance(); + + $this->httpClient = new TestHttpClient(); + $me = $this; + TestServiceRegister::registerService( + HttpClient::CLASS_NAME, + function () use ($me) { + return $me->httpClient; + } + ); + TestServiceRegister::registerService( + VersionCheckProxy::CLASS_NAME, + function () use ($me) { + return new VersionCheckProxy($me->shopConfig, $me->httpClient, new ProxyDataProvider()); + } + ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () { + return ApiKeyAuthService::getInstance(); + } + ); + } + + public function tearDown() + { + TestVersionCheckService::resetInstance(); + + parent::tearDown(); + } + + /** + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpAuthenticationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpCommunicationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpRequestException + */ + public function testVersionCheckWhenNewVersionAvailable() + { + $this->httpClient->setMockResponses(array($this->getMockNewVersionResults())); + $this->versionCheckService->checkForNewVersion(); + + $this->assertNotEmpty($this->versionCheckService->getCallHistory()); + } + + /** + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Exceptions\UnprocessableEntityRequestException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpAuthenticationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpCommunicationException + * @throws \Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\Http\Exceptions\HttpRequestException + */ + public function testVersionCheckWhenNewVersionNotAvailable() + { + TestShopConfiguration::$CURRENT_INTEGRATION_VERSION = '3.0.0'; + $this->httpClient->setMockResponses(array($this->getMockNewVersionResults())); + $this->versionCheckService->checkForNewVersion(); + + $this->assertEmpty($this->versionCheckService->getCallHistory()); + } + + /** + * @return HttpResponse + */ + protected function getMockNewVersionResults() + { + $response = file_get_contents(__DIR__ . '/../Common/ApiResponses/version-check.json'); + + return new HttpResponse(200, array(), $response); + } +} diff --git a/Tests/Unit/BusinessLogic/WebHook/WebHookTransformerTest.php b/Tests/Unit/BusinessLogic/WebHook/WebHookTransformerTest.php index be30c73..ccd190d 100644 --- a/Tests/Unit/BusinessLogic/WebHook/WebHookTransformerTest.php +++ b/Tests/Unit/BusinessLogic/WebHook/WebHookTransformerTest.php @@ -2,6 +2,8 @@ namespace Mollie\Bundle\PaymentBundle\Tests\Unit\BusinessLogic\WebHook; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\ApiKey\ApiKeyAuthService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Authorization\Interfaces\AuthorizationService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Payment; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; @@ -96,6 +98,13 @@ function () { } ); + TestServiceRegister::registerService( + AuthorizationService::CLASS_NAME, + function () use ($me) { + return ApiKeyAuthService::getInstance(); + } + ); + $this->setUpEventHandlers(); $this->setUpTestOrderReferences(); } diff --git a/composer.json b/composer.json index b1df1b3..052632f 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "mollie/orocommerce", - "version": "4.0.8", + "version": "4.0.9", "type": "symfony-bundle", "description": "Mollie Payment Module for OroCommerce", "keywords": [ @@ -38,6 +38,7 @@ "inghomepay", "klarna", "paylater", + "paynow", "sliceit", "mybank", "oro",