diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a56c6f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Package Control +/composer.lock + +# Vendor Files +/vendor + +# IDE/Workspace settings +/.idea + diff --git a/README.md b/README.md index 2dea16b..894ca0d 100755 --- a/README.md +++ b/README.md @@ -25,6 +25,40 @@ public function registerBundles() } ``` +### Optional Installation steps + +#### Money Amount Conversion + +By default sylius stores prices as integer values representing the amount in cents/pence or smallest unit. + +If you have modified sylius to store money amounts in a different format, or with a different precision, then you will need to override. + +Example, if your copy of sylius stores 4 decimals instead of 2, then you will need to override the class like this: + +```php +getAmount() / 10000); + } +} +``` + +and add an entry to your service config to point to it: +```yaml + Sbarbat\SyliusSagepayPlugin\Provider\AmountProvider: + class: App\Provider\Sagepay\AmountProvider + +``` ### Test Cards diff --git a/composer.json b/composer.json index 3f4be70..498a01f 100755 --- a/composer.json +++ b/composer.json @@ -13,27 +13,18 @@ ], "require": { "php": "^7.1", - - "sylius/sylius": "^1.1" + "sylius/sylius": "^1.1", + "ext-curl": "*", + "ext-json": "*" }, "require-dev": { - "php-http/guzzle6-adapter": "^1.0", - "phpspec/phpspec": "^3.2", - "phpunit/phpunit": "^7", - "behat/behat": "^3.3", - "behat/mink": "^1.7", - "behat/mink-browserkit-driver": "^1.3", - "behat/mink-extension": "^2.2", - "behat/mink-selenium2-driver": "^1.3", - "friends-of-behat/context-service-extension": "^1.0", - "friends-of-behat/cross-container-extension": "^1.0", - "friends-of-behat/service-container-extension": "^1.0", - "friends-of-behat/symfony-extension": "^1.0", - "friends-of-behat/variadic-extension": "^1.0", - "lakion/mink-debug-extension": "^1.2.3", - "se/selenium-server-standalone": "^2.52", - "symplify/easy-coding-standard": "^2.4", - "sylius-labs/coding-standard": "^1.0" + "phpunit/phpunit": "^9.5", + "phpspec/phpspec": "^7.1", + "php-http/guzzle6-adapter": "^2.0", + "behat/behat": "^3.8", + "symplify/easy-coding-standard": "^9.4", + "sylius-labs/coding-standard": "^4.1", + "phpstan/phpstan": "^0.12.94" }, "autoload": { "psr-4": { diff --git a/ecs.php b/ecs.php new file mode 100644 index 0000000..413ac33 --- /dev/null +++ b/ecs.php @@ -0,0 +1,35 @@ +parameters(); + $parameters->set(Option::PATHS, [ + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + + $services = $containerConfigurator->services(); + $services->set(ArraySyntaxFixer::class) + ->call('configure', [[ + 'syntax' => 'short', + ]]); + + // run and fix, one by one + $containerConfigurator->import(SetList::SPACES); + $containerConfigurator->import(SetList::ARRAY); + $containerConfigurator->import(SetList::SYMFONY); + $containerConfigurator->import(SetList::PSR_12); + $containerConfigurator->import(SetList::STRICT); + $containerConfigurator->import(SetList::NAMESPACES); + $containerConfigurator->import(SetList::CONTROL_STRUCTURES); + $containerConfigurator->import(SetList::PHP_CS_FIXER); + $containerConfigurator->import(SetList::DOCBLOCK); + $containerConfigurator->import(SetList::CLEAN_CODE); + $containerConfigurator->import(SetList::SYMPLIFY); +}; diff --git a/src/Action/Api/DirectApiAwareAction.php b/src/Action/Api/DirectApiAwareAction.php index 571e253..5b39f7a 100644 --- a/src/Action/Api/DirectApiAwareAction.php +++ b/src/Action/Api/DirectApiAwareAction.php @@ -9,12 +9,12 @@ use Payum\Core\ApiAwareTrait; use Payum\Core\GatewayAwareInterface; use Payum\Core\GatewayAwareTrait; - use Sbarbat\SyliusSagepayPlugin\SagepayDirectApi; -abstract class DirectApiAwareAction implements GatewayAwareInterface, ApiAwareInterface +abstract class DirectApiAwareAction implements ActionInterface, GatewayAwareInterface, ApiAwareInterface { use GatewayAwareTrait; + use ApiAwareTrait; public function __construct() diff --git a/src/Action/Api/FormApiAwareAction.php b/src/Action/Api/FormApiAwareAction.php index fb549f6..e7b1f66 100644 --- a/src/Action/Api/FormApiAwareAction.php +++ b/src/Action/Api/FormApiAwareAction.php @@ -9,12 +9,12 @@ use Payum\Core\ApiAwareTrait; use Payum\Core\GatewayAwareInterface; use Payum\Core\GatewayAwareTrait; - use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; abstract class FormApiAwareAction implements ActionInterface, GatewayAwareInterface, ApiAwareInterface { use GatewayAwareTrait; + use ApiAwareTrait; public function __construct() diff --git a/src/Action/Integrations/Direct/CaptureAction.php b/src/Action/Integrations/Direct/CaptureAction.php index 862b522..eed06e5 100644 --- a/src/Action/Integrations/Direct/CaptureAction.php +++ b/src/Action/Integrations/Direct/CaptureAction.php @@ -4,36 +4,22 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct; -use Payum\Core\Action\ActionInterface; -use Payum\Core\ApiAwareInterface; -use Payum\Core\ApiAwareTrait; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; -use Payum\Core\Request\Convert; +use Payum\Core\Reply\HttpResponse; use Payum\Core\Request\Capture; use Payum\Core\Request\GetHttpRequest; use Payum\Core\Request\RenderTemplate; -use Payum\Core\Reply\HttpResponse; use Payum\Core\Security\GenericTokenFactoryAwareInterface; use Payum\Core\Security\GenericTokenFactoryAwareTrait; - -use Sylius\Component\Core\Model\PaymentInterface; - -use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; use Sbarbat\SyliusSagepayPlugin\Action\Api\DirectApiAwareAction; -use Sbarbat\SyliusSagepayPlugin\Request\Api\ExecutePayment; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\ExecutePaymentAction; +use Sylius\Component\Core\Model\PaymentInterface; -class CaptureAction extends DirectApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface, GenericTokenFactoryAwareInterface +class CaptureAction extends DirectApiAwareAction implements GenericTokenFactoryAwareInterface { - use GatewayAwareTrait; use GenericTokenFactoryAwareTrait; /** - * {@inheritDoc} - * * @param Capture $request */ public function execute($request) @@ -42,44 +28,41 @@ public function execute($request) $model = ArrayObject::ensureArrayObject($request->getModel()); $payment = $request->getFirstModel(); - + $getHttpRequest = new GetHttpRequest(); $this->gateway->execute($getHttpRequest); if ('POST' === $getHttpRequest->method) { if (isset($getHttpRequest->request['get_merchant_session']) && ( - "true" === $getHttpRequest->request['get_merchant_session'] + 'true' === $getHttpRequest->request['get_merchant_session'] || true === $getHttpRequest->request['get_merchant_session'] )) { throw new HttpResponse($this->api->getMerchantSessionKey()); } - + $model['card-identifier'] = $getHttpRequest->request['card-identifier']; $model['merchant-session-key'] = $getHttpRequest->request['merchant-session-key']; return; } - + $template = $this->api->getOption('payum.sagepay.template.layout'); - $this->gateway->execute($renderTemplate = new RenderTemplate($template, array( + $this->gateway->execute($renderTemplate = new RenderTemplate($template, [ 'model' => $model, 'payment' => $payment, - 'sagepayJs' => $this->api->getApiEndpoint() . 'js/sagepay.js', + 'sagepayJs' => $this->api->getApiEndpoint().'js/sagepay.js', 'merchantSessionRoute' => $this->api->getOption('payum.sagepay.merchant_session_route_name'), 'token' => $request->getToken(), - 'actionUrl' => $request->getToken() ? $request->getToken()->getTargetUrl() : null, - ))); + 'actionUrl' => $request->getToken() ? $request->getToken() + ->getTargetUrl() : null, + ])); throw new HttpResponse($renderTemplate->getResult()); } - /** - * {@inheritDoc} - */ public function supports($request) { - return - $request instanceof Capture && + return $request instanceof Capture && $request->getModel() instanceof \ArrayAccess && $request->getFirstModel() instanceof PaymentInterface ; diff --git a/src/Action/Integrations/Direct/ConvertPaymentAction.php b/src/Action/Integrations/Direct/ConvertPaymentAction.php index fa426e2..1e97575 100644 --- a/src/Action/Integrations/Direct/ConvertPaymentAction.php +++ b/src/Action/Integrations/Direct/ConvertPaymentAction.php @@ -4,38 +4,20 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct; -use Payum\Core\Action\ActionInterface; -use Payum\Core\ApiAwareInterface; -use Payum\Core\ApiAwareTrait; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; use Payum\Core\Request\Convert; -use Payum\Core\Request\Capture; -use Payum\Core\Request\GetHttpRequest; -use Payum\Core\Reply\HttpPostRedirect; -use Payum\Core\Reply\HttpRedirect; use Payum\Core\Security\GenericTokenFactoryAwareInterface; use Payum\Core\Security\GenericTokenFactoryAwareTrait; +use Sbarbat\SyliusSagepayPlugin\Action\Api\DirectApiAwareAction; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\PaymentInterface; -use Sbarbat\SyliusSagepayPlugin\SagepayDirectApi; -use Sbarbat\SyliusSagepayPlugin\Action\Api\DirectApiAwareAction; - -class ConvertPaymentAction extends DirectApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface, GenericTokenFactoryAwareInterface +class ConvertPaymentAction extends DirectApiAwareAction implements GenericTokenFactoryAwareInterface { - use GatewayAwareTrait; use GenericTokenFactoryAwareTrait; - public function __construct() - { - $this->apiClass = SagepayDirectApi::class; - } /** - * {@inheritDoc} - * * @param Convert $request */ public function execute($request) @@ -57,19 +39,15 @@ public function execute($request) $details['customerLocale'] = $order->getLocaleCode(); $details['countryCode'] = null !== $order->getShippingAddress() ? $order->getShippingAddress()->getCountryCode() : null; $details['currencyCode'] = $payment->getCurrencyCode(); - + $request->setResult((array) $details); } - /** - * {@inheritDoc} - */ public function supports($request) { - return - $request instanceof Convert && + return $request instanceof Convert && $request->getSource() instanceof PaymentInterface && - $request->getTo() == 'array' + 'array' === $request->getTo() ; } } diff --git a/src/Action/Integrations/Direct/ExecutePaymentAction.php b/src/Action/Integrations/Direct/ExecutePaymentAction.php index 69a272b..f20fc35 100644 --- a/src/Action/Integrations/Direct/ExecutePaymentAction.php +++ b/src/Action/Integrations/Direct/ExecutePaymentAction.php @@ -4,56 +4,44 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct; -use Payum\Core\ApiAwareTrait; -use Payum\Core\Request\Capture; -use Payum\Core\Request\Convert; -use Payum\Core\ApiAwareInterface; -use Payum\Core\GatewayAwareTrait; -use Payum\Core\Reply\HttpRedirect; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\Action\ActionInterface; use Payum\Core\Bridge\Spl\ArrayObject; -use Payum\Core\Reply\HttpPostRedirect; -use Payum\Core\Request\GetHttpRequest; -use Payum\Core\Request\GetStatusInterface; -use Sbarbat\SyliusSagepayPlugin\SagepayDirectApi; -use Sylius\Component\Core\Model\PaymentInterface; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayResponse; - use Payum\Core\Exception\RequestNotSupportedException; - -use Payum\Core\Security\GenericTokenFactoryAwareTrait; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayStatusType; -use Sbarbat\SyliusSagepayPlugin\Sanitizers\NameSanitizer; - -use Payum\Core\Security\GenericTokenFactoryAwareInterface; +use Payum\Core\Request\GetStatusInterface; +use Sbarbat\SyliusSagepayPlugin\Action\Api\DirectApiAwareAction; use Sbarbat\SyliusSagepayPlugin\Request\Api\ExecutePayment; use Sbarbat\SyliusSagepayPlugin\Sanitizers\AddressSanitizer; +use Sbarbat\SyliusSagepayPlugin\Sanitizers\NameSanitizer; use Sbarbat\SyliusSagepayPlugin\Sanitizers\SanitizerInterface; -use Sbarbat\SyliusSagepayPlugin\Action\Api\DirectApiAwareAction; +use Sylius\Component\Addressing\Provider\ProvinceNamingProviderInterface; -final class ExecutePaymentAction extends DirectApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface +final class ExecutePaymentAction extends DirectApiAwareAction { - use GatewayAwareTrait; + public const US_CODE = 'US'; - const US_CODE = "US"; - - /** @var SanitizerInterface */ + /** + * @var SanitizerInterface + */ private $nameSanitizer; - /** @var SanitizerInterface */ + /** + * @var SanitizerInterface + */ private $addressSanitizer; - public function __construct() + /** + * @var ProvinceNamingProviderInterface + */ + private $provinceNamingProvider; + + public function __construct(ProvinceNamingProviderInterface $provinceNamingProvider) { - $this->apiClass = SagepayDirectApi::class; + parent::__construct(); $this->nameSanitizer = new NameSanitizer(); $this->addressSanitizer = new AddressSanitizer(); + $this->provinceNamingProvider = $provinceNamingProvider; } /** - * {@inheritDoc} - * * @param GetStatusInterface $request */ public function execute($request) @@ -65,95 +53,93 @@ public function execute($request) $order = $payment->getOrder(); $billingAddress = $order->getBillingAddress(); - if ($billingAddress->getCompany() != null) { - $billingStreet = $billingAddress->getCompany() . ' ' . $billingAddress->getStreet(); + if (null !== $billingAddress->getCompany()) { + $billingStreet = $billingAddress->getCompany().' '.$billingAddress->getStreet(); } else { $billingStreet = $billingAddress->getStreet(); } $shippingAddress = $order->getShippingAddress(); - if ($shippingAddress->getCompany() != null) { - $shippingStreet = $shippingAddress->getCompany() . ' ' . $shippingAddress->getStreet(); + if (null !== $shippingAddress->getCompany()) { + $shippingStreet = $shippingAddress->getCompany().' '.$shippingAddress->getStreet(); } else { $shippingStreet = $shippingAddress->getStreet(); } - $description = 'Payment for order #' . $order->getNumber(); + $description = 'Payment for order #'.$order->getNumber(); $request = [ - "entryMethod" => "Ecommerce", - "transactionType" => "Payment", - "paymentMethod" => [ - "card" => [ - "merchantSessionKey" => $model['merchant-session-key'], - "cardIdentifier" => $model['card-identifier'] - ] + 'entryMethod' => 'Ecommerce', + 'transactionType' => 'Payment', + 'paymentMethod' => [ + 'card' => [ + 'merchantSessionKey' => $model['merchant-session-key'], + 'cardIdentifier' => $model['card-identifier'], + ], + ], + 'vendorTxCode' => $model['vendorTxCode'], + 'amount' => $model['amount'], + 'currency' => $payment->getCurrencyCode(), + 'description' => $description, + 'apply3DSecure' => 'UseMSPSetting', + 'customerFirstName' => $this->nameSanitizer->sanitize($billingAddress->getFirstName()), + 'customerLastName' => $this->nameSanitizer->sanitize($billingAddress->getLastName()), + 'billingAddress' => [ + 'address1' => $this->addressSanitizer->sanitize($billingStreet), + 'city' => $billingAddress->getCity(), + 'postalCode' => $billingAddress->getPostcode(), + 'country' => $billingAddress->getCountryCode(), ], - "vendorTxCode" => $model['vendorTxCode'], - "amount" => $model['amount'], - "currency" => $payment->getCurrencyCode(), - "description" => $description, - "apply3DSecure" => "UseMSPSetting", - "customerFirstName" => $this->nameSanitizer->sanitize($billingAddress->getFirstName()), - "customerLastName" => $this->nameSanitizer->sanitize($billingAddress->getLastName()), - "billingAddress" => [ - "address1" => $this->addressSanitizer->sanitize($billingStreet), - "city" => $billingAddress->getCity(), - "postalCode" => $billingAddress->getPostcode(), - "country" => $billingAddress->getCountryCode(), + 'shippingDetails' => [ + 'recipientFirstName' => $this->nameSanitizer->sanitize($shippingAddress->getFirstName()), + 'recipientLastName' => $this->nameSanitizer->sanitize($shippingAddress->getLastName()), + 'shippingAddress1' => $this->addressSanitizer->sanitize($shippingStreet), + 'shippingCity' => $shippingAddress->getCity(), + 'shippingPostalCode' => $shippingAddress->getPostcode(), + 'shippingCountry' => $shippingAddress->getCountryCode(), ], - "shippingDetails" => [ - "recipientFirstName" => $this->nameSanitizer->sanitize($shippingAddress->getFirstName()), - "recipientLastName" => $this->nameSanitizer->sanitize($shippingAddress->getLastName()), - "shippingAddress1" => $this->addressSanitizer->sanitize($shippingStreet), - "shippingCity" => $shippingAddress->getCity(), - "shippingPostalCode" => $shippingAddress->getPostcode(), - "shippingCountry" => $shippingAddress->getCountryCode(), - ] ]; - + if (static::US_CODE === $shippingAddress->getCountryCode()) { - $request["shippingDetails"]["shippingState"] = $shippingAddress->getProvinceCode(); + $request['shippingDetails']['shippingState'] = $this->api->getOption('stateCodeAbbreviated') + ? $this->provinceNamingProvider->getAbbreviation($shippingAddress) + : $shippingAddress->getProvinceCode(); } - + if (static::US_CODE === $billingAddress->getCountryCode()) { - $request["billingAddress"]["state"] = $billingAddress->getProvinceCode(); + $request['billingAddress']['state'] = $this->api->getOption('stateCodeAbbreviated') + ? $this->provinceNamingProvider->getAbbreviation($billingAddress) + : $billingAddress->getProvinceCode(); } - + $curl = curl_init(); - curl_setopt_array($curl, array( - CURLOPT_URL => $this->api->getApiEndpoint() . "transactions", + curl_setopt_array($curl, [ + CURLOPT_URL => $this->api->getApiEndpoint().'transactions', CURLOPT_RETURNTRANSFER => true, - CURLOPT_CUSTOMREQUEST => "POST", + CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode($request), - CURLOPT_HTTPHEADER => array( - "Authorization: " . $this->api->getBasicAuthenticationHeader(), - "Cache-Control: no-cache", - "Content-Type: application/json" - ), - )); + CURLOPT_HTTPHEADER => [ + 'Authorization: '.$this->api->getBasicAuthenticationHeader(), + 'Cache-Control: no-cache', + 'Content-Type: application/json', + ], + ]); $response = curl_exec($curl); $err = curl_error($curl); - + curl_close($curl); $model['payment_response'] = $response; $model['payment_error'] = $err; - + return $model; } - /** - * {@inheritDoc} - */ public function supports($request) { - return - $request instanceof ExecutePayment && + return $request instanceof ExecutePayment && $request->getModel() instanceof \ArrayAccess ; } - - } diff --git a/src/Action/Integrations/Direct/StatusAction.php b/src/Action/Integrations/Direct/StatusAction.php index fd06ffc..80e70df 100644 --- a/src/Action/Integrations/Direct/StatusAction.php +++ b/src/Action/Integrations/Direct/StatusAction.php @@ -4,47 +4,23 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct; -use Payum\Core\Action\ActionInterface; -use Payum\Core\Request\GetStatusInterface; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\ApiAwareInterface; -use Payum\Core\ApiAwareTrait; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; -use Payum\Core\Request\Convert; -use Payum\Core\Request\Capture; -use Payum\Core\Request\GetHttpRequest; use Payum\Core\Reply\HttpPostRedirect; -use Payum\Core\Reply\HttpResponse; +use Payum\Core\Request\GetHttpRequest; +use Payum\Core\Request\GetStatusInterface; use Payum\Core\Security\GenericTokenFactoryAwareInterface; use Payum\Core\Security\GenericTokenFactoryAwareTrait; -use Payum\Core\Request\RenderTemplate; - -use Sylius\Component\Core\Model\PaymentInterface; - -use Sbarbat\SyliusSagepayPlugin\SagepayDirectApi; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayResponse; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayStatusType; - use Sbarbat\SyliusSagepayPlugin\Action\Api\DirectApiAwareAction; +use Sbarbat\SyliusSagepayPlugin\Lib\SagepayStatusType; use Sbarbat\SyliusSagepayPlugin\Request\Api\ExecutePayment; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\ExecutePaymentAction; +use Sylius\Component\Core\Model\PaymentInterface; -class StatusAction extends DirectApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface, GenericTokenFactoryAwareInterface +class StatusAction extends DirectApiAwareAction implements GenericTokenFactoryAwareInterface { - use GatewayAwareTrait, - GenericTokenFactoryAwareTrait; - - - public function __construct() - { - $this->apiClass = SagepayDirectApi::class; - } + use GenericTokenFactoryAwareTrait; /** - * {@inheritDoc} - * * @param GetStatusInterface $request */ public function execute($request) @@ -57,10 +33,10 @@ public function execute($request) $details = $payment->getDetails(); $this->gateway->execute($httpRequest = new GetHttpRequest()); - + if ($this->api->is3DAuthResponse($httpRequest)) { /** - * If is the return of the 3D Authentication + * If is the return of the 3D Authentication. */ // Get the paRes from the response @@ -73,27 +49,29 @@ public function execute($request) $outcome = $this->api->getTransactionOutcome($transactionId); - if (isset($outcome->status) && SagepayStatusType::OK == strtoupper($outcome->status)) { + if (isset($outcome->status) && SagepayStatusType::OK === strtoupper($outcome->status)) { $this->resolvePaymentStatus($request, $outcome); } else { $request->markFailed(); } - } elseif (!$this->api->is3DAuthResponse($httpRequest) && ($request->isNew() || $request->isUnknown()) && isset($model['payment_response'])) { - /** - * See if need to redirect for 3DAuth - */ + } elseif (! $this->api->is3DAuthResponse( + $httpRequest + ) && ($request->isNew() || $request->isUnknown()) && isset($model['payment_response'])) { + // See if need to redirect for 3DAuth $this->get3DAuthRedirect($request, $model['payment_response'], $payment); - + $this->resolvePaymentStatus($request, json_decode($model['payment_response'])); return; - } elseif (!$this->api->is3DAuthResponse($httpRequest) && ($request->isNew() || $request->isUnknown()) && isset($model['card-identifier'])) { + } elseif (! $this->api->is3DAuthResponse( + $httpRequest + ) && ($request->isNew() || $request->isUnknown()) && isset($model['card-identifier'])) { $this->gateway->addAction(new ExecutePaymentAction()); $executePaymentRequest = new ExecutePayment($payment); $executePaymentRequest->setModel($model); $this->gateway->execute($executePaymentRequest); - - $response = json_decode($model["payment_response"]); + + $response = json_decode($model['payment_response']); if (isset($response->errors)) { $request->markFailed(); } else { @@ -103,18 +81,21 @@ public function execute($request) $request->markNew(); } - if (null != $details) { + if (null !== $details) { $payment->setDetails($details); } } - /** - * @param string $authResult - * @param GetStatusInterface $request - */ + public function supports($request) + { + return $request instanceof GetStatusInterface && + $request->getFirstModel() instanceof PaymentInterface + ; + } + private function resolvePaymentStatus(GetStatusInterface $request, $response): void { - if (!isset($response->status)) { + if (! isset($response->status)) { $request->markCanceled(); return; @@ -123,12 +104,15 @@ private function resolvePaymentStatus(GetStatusInterface $request, $response): v switch (strtoupper($response->status)) { case null: $request->markNew(); + break; case SagepayStatusType::OK: $request->markCaptured(); + break; case SagepayStatusType::ABORT: $request->markCanceled(); + break; case SagepayStatusType::NOTAUTHED: case SagepayStatusType::REJECTED: @@ -136,6 +120,7 @@ private function resolvePaymentStatus(GetStatusInterface $request, $response): v case SagepayStatusType::MALFORMED: case SagepayStatusType::INVALID: $request->markFailed(); + break; // case SagepayStatusType::CANCEL: // $request->markSuspended(); @@ -145,28 +130,20 @@ private function resolvePaymentStatus(GetStatusInterface $request, $response): v // break; default: $request->markUnknown(); + break; } } - /** - * {@inheritDoc} - */ - public function supports($request) - { - return - $request instanceof GetStatusInterface && - $request->getFirstModel() instanceof PaymentInterface - ; - } - private function get3DAuthRedirect(GetStatusInterface $request, $response, $payment) { $response = json_decode($response); - - if (isset($response->status) && SagepayStatusType::_3DAUTH == strtoupper($response->status)) { + + if (isset($response->status) && SagepayStatusType::_3DAUTH === strtoupper($response->status)) { /** @var GatewayConfigInterface $gatewayConfig */ - $gatewayConfig = $payment->getMethod()->getGatewayConfig(); + $gatewayConfig = $payment->getMethod() + ->getGatewayConfig() + ; $token = $this->tokenFactory->createToken( $gatewayConfig->getGatewayName(), @@ -177,15 +154,16 @@ private function get3DAuthRedirect(GetStatusInterface $request, $response, $paym throw new HttpPostRedirect($response->acsUrl, [ 'PaReq' => $response->paReq, 'TermUrl' => $token->getTargetUrl(), - 'MD' => $payment->getId() + 'MD' => $payment->getId(), ]); } } /** - * Gets the transaction id from the 3D Auth response + * Gets the transaction id from the 3D Auth response. * * @param PaymentInterface $payment + * * @return int */ private function getTransactionId($payment) diff --git a/src/Action/Integrations/Form/CancelAction.php b/src/Action/Integrations/Form/CancelAction.php index cd96412..85f373b 100755 --- a/src/Action/Integrations/Form/CancelAction.php +++ b/src/Action/Integrations/Form/CancelAction.php @@ -7,16 +7,11 @@ use Payum\Core\Action\ActionInterface; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\GatewayAwareTrait; use Payum\Core\Request\Cancel; class CancelAction implements ActionInterface { - use GatewayAwareTrait; - /** - * {@inheritDoc} - * * @param Cancel $request */ public function execute($request) @@ -28,13 +23,9 @@ public function execute($request) throw new \LogicException('Not implemented'); } - /** - * {@inheritDoc} - */ public function supports($request) { - return - $request instanceof Cancel && + return $request instanceof Cancel && $request->getModel() instanceof \ArrayAccess ; } diff --git a/src/Action/Integrations/Form/CaptureAction.php b/src/Action/Integrations/Form/CaptureAction.php index 6059a3c..fd62df6 100755 --- a/src/Action/Integrations/Form/CaptureAction.php +++ b/src/Action/Integrations/Form/CaptureAction.php @@ -4,34 +4,40 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form; -use Payum\Core\Action\ActionInterface; -use Payum\Core\ApiAwareInterface; -use Payum\Core\ApiAwareTrait; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; -use Payum\Core\Request\Convert; -use Payum\Core\Request\Capture; -use Payum\Core\Request\GetHttpRequest; use Payum\Core\Reply\HttpPostRedirect; -use Payum\Core\Reply\HttpRedirect; +use Payum\Core\Request\Capture; use Payum\Core\Security\GenericTokenFactoryAwareInterface; use Payum\Core\Security\GenericTokenFactoryAwareTrait; - -use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; -use Sylius\Component\Core\Model\PaymentInterface; - use Sbarbat\SyliusSagepayPlugin\Action\Api\FormApiAwareAction; +use Sbarbat\SyliusSagepayPlugin\Provider\AmountProvider; +use Sylius\Component\Addressing\Provider\ProvinceNamingProviderInterface; +use Sylius\Component\Core\Model\PaymentInterface; -class CaptureAction extends FormApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface, GenericTokenFactoryAwareInterface +class CaptureAction extends FormApiAwareAction implements GenericTokenFactoryAwareInterface { - use GatewayAwareTrait; use GenericTokenFactoryAwareTrait; /** - * {@inheritDoc} - * + * @var ProvinceNamingProviderInterface + */ + private $provinceNamingProvider; + /** + * @var AmountProvider + */ + private $amountProvider; + + public function __construct( + ProvinceNamingProviderInterface $provinceNamingProvider, + AmountProvider $amountProvider + ) { + parent::__construct(); + $this->provinceNamingProvider = $provinceNamingProvider; + $this->amountProvider = $amountProvider; + } + + /** * @param Capture $request */ public function execute($request) @@ -40,20 +46,19 @@ public function execute($request) $model = ArrayObject::ensureArrayObject($request->getModel()); $payment = $request->getFirstModel(); - - throw new HttpPostRedirect( - $this->api->getOffsiteEndpoint(), - $this->api->preparePayment($request, $model, $payment)->getRequest() - ); + + throw new HttpPostRedirect($this->api->getOffsiteEndpoint(), $this->api->preparePayment( + $request, + $model, + $payment, + $this->provinceNamingProvider, + $this->amountProvider + )->getRequest()); } - /** - * {@inheritDoc} - */ public function supports($request) { - return - $request instanceof Capture && + return $request instanceof Capture && $request->getModel() instanceof \ArrayAccess && $request->getFirstModel() instanceof PaymentInterface ; diff --git a/src/Action/Integrations/Form/ConvertPaymentAction.php b/src/Action/Integrations/Form/ConvertPaymentAction.php index 377c3ff..9c435b9 100755 --- a/src/Action/Integrations/Form/ConvertPaymentAction.php +++ b/src/Action/Integrations/Form/ConvertPaymentAction.php @@ -4,34 +4,20 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form; -use Payum\Core\Action\ActionInterface; -use Payum\Core\ApiAwareInterface; -use Payum\Core\ApiAwareTrait; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; use Payum\Core\Request\Convert; -use Payum\Core\Request\Capture; -use Payum\Core\Request\GetHttpRequest; -use Payum\Core\Reply\HttpPostRedirect; -use Payum\Core\Reply\HttpRedirect; use Payum\Core\Security\GenericTokenFactoryAwareInterface; use Payum\Core\Security\GenericTokenFactoryAwareTrait; +use Sbarbat\SyliusSagepayPlugin\Action\Api\FormApiAwareAction; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\PaymentInterface; -use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; -use Sbarbat\SyliusSagepayPlugin\Action\Api\FormApiAwareAction; - -class ConvertPaymentAction extends FormApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface, GenericTokenFactoryAwareInterface +class ConvertPaymentAction extends FormApiAwareAction implements GenericTokenFactoryAwareInterface { - use GatewayAwareTrait; use GenericTokenFactoryAwareTrait; /** - * {@inheritDoc} - * * @param Convert $request */ public function execute($request) @@ -57,15 +43,11 @@ public function execute($request) $request->setResult((array) $details); } - /** - * {@inheritDoc} - */ public function supports($request) { - return - $request instanceof Convert && + return $request instanceof Convert && $request->getSource() instanceof PaymentInterface && - $request->getTo() == 'array' + 'array' === $request->getTo() ; } } diff --git a/src/Action/Integrations/Form/NotifyAction.php b/src/Action/Integrations/Form/NotifyAction.php index 68db043..97132c2 100755 --- a/src/Action/Integrations/Form/NotifyAction.php +++ b/src/Action/Integrations/Form/NotifyAction.php @@ -15,8 +15,6 @@ class NotifyAction implements ActionInterface use GatewayAwareTrait; /** - * {@inheritDoc} - * * @param Notify $request */ public function execute($request) @@ -28,9 +26,6 @@ public function execute($request) throw new \LogicException('Not implemented'); } - /** - * {@inheritDoc} - */ public function supports($request) { return diff --git a/src/Action/Integrations/Form/RefundAction.php b/src/Action/Integrations/Form/RefundAction.php index 4e4c6c2..b536f84 100755 --- a/src/Action/Integrations/Form/RefundAction.php +++ b/src/Action/Integrations/Form/RefundAction.php @@ -15,8 +15,6 @@ class RefundAction implements ActionInterface use GatewayAwareTrait; /** - * {@inheritDoc} - * * @param Refund $request */ public function execute($request) @@ -28,9 +26,6 @@ public function execute($request) throw new \LogicException('Not implemented'); } - /** - * {@inheritDoc} - */ public function supports($request) { return diff --git a/src/Action/Integrations/Form/StatusAction.php b/src/Action/Integrations/Form/StatusAction.php index 083941e..2701214 100755 --- a/src/Action/Integrations/Form/StatusAction.php +++ b/src/Action/Integrations/Form/StatusAction.php @@ -4,36 +4,17 @@ namespace Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form; -use Payum\Core\Action\ActionInterface; -use Payum\Core\Request\GetStatusInterface; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\ApiAwareInterface; -use Payum\Core\ApiAwareTrait; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; -use Payum\Core\Request\Convert; -use Payum\Core\Request\Capture; -use Payum\Core\Request\GetHttpRequest; -use Payum\Core\Reply\HttpPostRedirect; -use Payum\Core\Reply\HttpRedirect; -use Payum\Core\Security\GenericTokenFactoryAwareInterface; -use Payum\Core\Security\GenericTokenFactoryAwareTrait; - -use Sylius\Component\Core\Model\PaymentInterface; - -use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; +use Payum\Core\Request\GetStatusInterface; +use Sbarbat\SyliusSagepayPlugin\Action\Api\FormApiAwareAction; use Sbarbat\SyliusSagepayPlugin\Lib\SagepayResponse; use Sbarbat\SyliusSagepayPlugin\Lib\SagepayStatusType; -use Sbarbat\SyliusSagepayPlugin\Action\Api\FormApiAwareAction; +use Sylius\Component\Core\Model\PaymentInterface; -class StatusAction extends FormApiAwareAction implements ActionInterface, ApiAwareInterface, GatewayAwareInterface +class StatusAction extends FormApiAwareAction { - use GatewayAwareTrait; - /** - * {@inheritDoc} - * * @param GetStatusInterface $request */ public function execute($request) @@ -45,7 +26,7 @@ public function execute($request) $payment = $request->getFirstModel(); $details = $payment->getDetails(); - if(isset($_GET['crypt'])) { + if (isset($_GET['crypt'])) { $sagepayResponse = (new SagepayResponse($this->api))->parseResponse(); $this->resolvePaymentStatus($sagepayResponse, $request); @@ -57,26 +38,34 @@ public function execute($request) $payment->setDetails($details); } - /** - * @param string $authResult - * @param GetStatusInterface $request - */ + public function supports($request) + { + return + $request instanceof GetStatusInterface && + $request->getFirstModel() instanceof PaymentInterface + ; + } + private function resolvePaymentStatus(SagepayResponse $response, GetStatusInterface $request): void { switch ($response->getStatus()) { case null: $request->markNew(); + break; case SagepayStatusType::OK: $request->markCaptured(); + break; case SagepayStatusType::ABORT: $request->markCanceled(); + break; case SagepayStatusType::NOTAUTHED: case SagepayStatusType::REJECTED: case SagepayStatusType::ERROR: $request->markFailed(); + break; // case SagepayStatusType::CANCEL: // $request->markSuspended(); @@ -86,18 +75,8 @@ private function resolvePaymentStatus(SagepayResponse $response, GetStatusInterf // break; default: $request->markUnknown(); + break; } } - - /** - * {@inheritDoc} - */ - public function supports($request) - { - return - $request instanceof GetStatusInterface && - $request->getFirstModel() instanceof PaymentInterface - ; - } } diff --git a/src/DependencyInjection/SbarbatSyliusSagepayExtension.php b/src/DependencyInjection/SbarbatSyliusSagepayExtension.php index 23e37c3..195fe5f 100644 --- a/src/DependencyInjection/SbarbatSyliusSagepayExtension.php +++ b/src/DependencyInjection/SbarbatSyliusSagepayExtension.php @@ -11,12 +11,9 @@ final class SbarbatSyliusSagepayExtension extends Extension { - /** - * {@inheritdoc} - */ public function load(array $config, ContainerBuilder $container): void { - $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); } -} \ No newline at end of file +} diff --git a/src/Form/Type/SagepayDirectGatewayConfigurationType.php b/src/Form/Type/SagepayDirectGatewayConfigurationType.php index e3e8c8e..29f7b18 100644 --- a/src/Form/Type/SagepayDirectGatewayConfigurationType.php +++ b/src/Form/Type/SagepayDirectGatewayConfigurationType.php @@ -9,14 +9,9 @@ use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Validator\Constraints\NotBlank; -use Sylius\Bundle\CurrencyBundle\Form\Type\CurrencyChoiceType; - final class SagepayDirectGatewayConfigurationType extends AbstractType { - /** - * {@inheritdoc} - */ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder @@ -33,16 +28,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.vendor_name.not_blank', 'groups' => ['sylius'], - ]) - ], - ]) - ->add('currency', TextType::class, [ - 'label' => 'sbarbat_sylius_sagepay_plugin.ui.currency', - 'constraints' => [ - new NotBlank([ - 'message' => 'sbarbat_sylius_sagepay_plugin.currency.not_blank', - 'groups' => ['sylius'], - ]) + ]), ], ]) ->add('integrationKeyLive', TextType::class, [ @@ -51,7 +37,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.integration_key_live.not_blank', 'groups' => ['sylius'], - ]) + ]), ], ]) ->add('integrationPasswordLive', TextType::class, [ @@ -60,7 +46,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.integration_password_live.not_blank', 'groups' => ['sylius'], - ]) + ]), ], ]) ->add('integrationKeyTest', TextType::class, [ @@ -69,7 +55,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.integration_key_test.not_blank', 'groups' => ['sylius'], - ]) + ]), ], ]) ->add('integrationPasswordTest', TextType::class, [ @@ -78,9 +64,17 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.integration_password_test.not_blank', 'groups' => ['sylius'], - ]) + ]), + ], + ]) + ->add('stateCodeAbbreviated', ChoiceType::class, [ + 'label' => 'sbarbat_sylius_sagepay_plugin.ui.state_code_abbreviated', + 'help' => 'sbarbat_sylius_sagepay_plugin.ui.state_code_abbreviated_help', + 'choices' => [ + 'sbarbat_sylius_sagepay_plugin.ui.province_abbreviation' => true, + 'sbarbat_sylius_sagepay_plugin.ui.province_code' => false, ], ]) ; } -} \ No newline at end of file +} diff --git a/src/Form/Type/SagepayFormGatewayConfigurationType.php b/src/Form/Type/SagepayFormGatewayConfigurationType.php index 6e83513..34a07a6 100644 --- a/src/Form/Type/SagepayFormGatewayConfigurationType.php +++ b/src/Form/Type/SagepayFormGatewayConfigurationType.php @@ -9,14 +9,9 @@ use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Validator\Constraints\NotBlank; -use Sylius\Bundle\CurrencyBundle\Form\Type\CurrencyChoiceType; - final class SagepayFormGatewayConfigurationType extends AbstractType { - /** - * {@inheritdoc} - */ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder @@ -33,16 +28,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.vendor_name.not_blank', 'groups' => ['sylius'], - ]) - ], - ]) - ->add('currency', TextType::class, [ - 'label' => 'sbarbat_sylius_sagepay_plugin.ui.currency', - 'constraints' => [ - new NotBlank([ - 'message' => 'sbarbat_sylius_sagepay_plugin.currency.not_blank', - 'groups' => ['sylius'], - ]) + ]), ], ]) ->add('encryptionPasswordTest', TextType::class, [ @@ -51,7 +37,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.encryptation_password_test.not_blank', 'groups' => ['sylius'], - ]) + ]), ], ]) ->add('encryptionPasswordLive', TextType::class, [ @@ -60,9 +46,17 @@ public function buildForm(FormBuilderInterface $builder, array $options): void new NotBlank([ 'message' => 'sbarbat_sylius_sagepay_plugin.encryptation_password_live.not_blank', 'groups' => ['sylius'], - ]) + ]), + ], + ]) + ->add('stateCodeAbbreviated', ChoiceType::class, [ + 'label' => 'sbarbat_sylius_sagepay_plugin.ui.state_code_abbreviated', + 'help' => 'sbarbat_sylius_sagepay_plugin.ui.state_code_abbreviated_help', + 'choices' => [ + 'sbarbat_sylius_sagepay_plugin.ui.province_abbreviation' => true, + 'sbarbat_sylius_sagepay_plugin.ui.province_code' => false, ], ]) ; } -} \ No newline at end of file +} diff --git a/src/Lib/SagepayApiException.php b/src/Lib/SagepayApiException.php index 2298096..feb7e14 100755 --- a/src/Lib/SagepayApiException.php +++ b/src/Lib/SagepayApiException.php @@ -5,13 +5,12 @@ namespace Sbarbat\SyliusSagepayPlugin\Lib; /** - * SagepayApi exceptions type + * SagepayApi exceptions type. * * @category Payment - * @package Sagepay + * * @copyright (c) 2013, Sage Pay Europe Ltd. */ class SagepayApiException extends \Exception { - } diff --git a/src/Lib/SagepayRequest.php b/src/Lib/SagepayRequest.php index ac25fe6..f0bf2df 100644 --- a/src/Lib/SagepayRequest.php +++ b/src/Lib/SagepayRequest.php @@ -5,22 +5,14 @@ namespace Sbarbat\SyliusSagepayPlugin\Lib; use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; -use Sbarbat\SyliusSagepayPlugin\Action\AuthorizeAction; -use Sbarbat\SyliusSagepayPlugin\Action\CancelAction; -use Sbarbat\SyliusSagepayPlugin\Action\ConvertPaymentAction; -use Sbarbat\SyliusSagepayPlugin\Action\CaptureAction; -use Sbarbat\SyliusSagepayPlugin\Action\NotifyAction; -use Sbarbat\SyliusSagepayPlugin\Action\RefundAction; -use Sbarbat\SyliusSagepayPlugin\Action\StatusAction; -use Payum\Core\Bridge\Spl\ArrayObject; -use Payum\Core\GatewayFactory; - use Sylius\Component\Core\Model\AddressInterface; class SagepayRequest { protected $api; + protected $query = []; + protected $request = []; protected $queryMandatoryValues = [ @@ -73,12 +65,10 @@ class SagepayRequest 'DeliveryPhone', 'CustomerName', 'CustomerEMail', - 'Profile' + 'Profile', ]; /** - * @param array $options - * * @throws \Payum\Core\Exception\InvalidArgumentException if an option is invalid */ public function __construct(SagepayFormApi $api) @@ -88,13 +78,11 @@ public function __construct(SagepayFormApi $api) $this->request['Vendor'] = $this->api->getOptions()['vendorName']; $this->request['VPSProtocol'] = $this->api->getOptions()['protocolVersion']; $this->request['TxType'] = SagepayTransactionType::PAYMENT; - - $this->addQuery('Currency', $this->api->getOption('currency')); } public function addQuery($key, $value): void { - if (!in_array($key, $this->querySupportedValues)) { + if (! in_array($key, $this->querySupportedValues, true)) { throw new SagepayApiException('Value ['.$key.'] not supported'); } @@ -114,25 +102,27 @@ public function setShippingAddress(AddressInterface $address): void public function getRequest() { $this->validateQuery(); - $this->request['Crypt'] = SagepayUtil::encrypt($this->query, $this->api->getFormEncryptionPassword()); + $this->request['Crypt'] = SagepayUtil::encrypt($this->query, $this->api->getFormEncryptionPassword()); return $this->request; } protected function validateQuery(): void { - if ("US" === $this->query['BillingCountry']) { + if ('US' === $this->query['BillingCountry']) { $this->queryMandatoryValues[] = 'BillingState'; } - foreach($this->queryMandatoryValues as $key) { - if (!isset($this->query[$key]) || isset($this->query[$key]) && !$this->validateField($this->query[$key])) { - throw new SagepayApiException($key . ' must be in the query'); + foreach ($this->queryMandatoryValues as $key) { + if (! isset($this->query[$key]) || (isset($this->query[$key]) && ! $this->validateField( + $this->query[$key] + ))) { + throw new SagepayApiException($key.' must be in the query'); } } - foreach($this->query as $key => $value) { - if (null == $value) { + foreach ($this->query as $key => $value) { + if (null === $value) { unset($this->query[$key]); } } @@ -140,26 +130,27 @@ protected function validateQuery(): void protected function validateField($value): bool { - return $value != null; + return null !== $value; } protected function setAddress($prefix, AddressInterface $address): void { - $this->addQuery($prefix . 'Surname', $address->getLastName()); - $this->addQuery($prefix . 'Firstnames', $address->getFirstName()); + $this->addQuery($prefix.'Surname', $address->getLastName()); + $this->addQuery($prefix.'Firstnames', $address->getFirstName()); - if (null == $address->getCompany()) { - $this->addQuery($prefix . 'Address1', $address->getStreet()); + if (null === $address->getCompany()) { + $this->addQuery($prefix.'Address1', $address->getStreet()); } else { - $this->addQuery($prefix . 'Address1', $address->getCompany()); - $this->addQuery($prefix . 'Address2', $address->getStreet()); + $this->addQuery($prefix.'Address1', $address->getCompany()); + $this->addQuery($prefix.'Address2', $address->getStreet()); } - $this->addQuery($prefix . 'City', $address->getCity()); - $this->addQuery($prefix . 'State', $address->getProvinceCode()); - $this->addQuery($prefix . 'PostCode', $address->getPostcode()); - $this->addQuery($prefix . 'Country', $address->getCountryCode()); - $this->addQuery($prefix . 'Phone', $address->getPhoneNumber()); + $this->addQuery($prefix.'City', $address->getCity()); + if ('US' === $address->getCountryCode()) { + $this->addQuery($prefix.'State', $this->api->getStateCode($address)); + } + $this->addQuery($prefix.'PostCode', $address->getPostcode()); + $this->addQuery($prefix.'Country', $address->getCountryCode()); + $this->addQuery($prefix.'Phone', $address->getPhoneNumber()); } - } diff --git a/src/Lib/SagepayResponse.php b/src/Lib/SagepayResponse.php index ff6fd6d..814f279 100644 --- a/src/Lib/SagepayResponse.php +++ b/src/Lib/SagepayResponse.php @@ -5,40 +5,42 @@ namespace Sbarbat\SyliusSagepayPlugin\Lib; use Sbarbat\SyliusSagepayPlugin\SagepayFormApi; -use Sbarbat\SyliusSagepayPlugin\Action\AuthorizeAction; -use Sbarbat\SyliusSagepayPlugin\Action\CancelAction; -use Sbarbat\SyliusSagepayPlugin\Action\ConvertPaymentAction; -use Sbarbat\SyliusSagepayPlugin\Action\CaptureAction; -use Sbarbat\SyliusSagepayPlugin\Action\NotifyAction; -use Sbarbat\SyliusSagepayPlugin\Action\RefundAction; -use Sbarbat\SyliusSagepayPlugin\Action\StatusAction; -use Payum\Core\Bridge\Spl\ArrayObject; -use Payum\Core\GatewayFactory; -use Sylius\Component\Core\Model\AddressInterface; class SagepayResponse { protected $api; protected $status; + protected $statusDetail; + protected $vendorTxCode; + protected $amount; + protected $txAuthNo; + protected $declineCode; + protected $AVSCV2; + protected $vpsTxId; + protected $addressResult; + protected $postCodeResult; + protected $cv2Result; + protected $giftAid; + protected $_3dSecureStatus; + protected $cardType; + protected $last4Digits; /** - * @param array $options - * * @throws \Payum\Core\Exception\InvalidArgumentException if an option is invalid */ public function __construct(SagepayFormApi $api) @@ -48,7 +50,7 @@ public function __construct(SagepayFormApi $api) public function parseResponse() { - if(!isset($_GET['crypt'])) { + if (! isset($_GET['crypt'])) { throw new SagepayApiException('No crypt return'); } $array = SagepayUtil::decrypt($_GET['crypt'], $this->api->getFormEncryptionPassword()); @@ -79,23 +81,25 @@ public function getArrayForDetails() { $all = get_object_vars($this); unset($all['api']); + return $all; } - /** - * Get the value of declineCode - */ + * Get the value of declineCode. + */ public function getDeclineCode() { return $this->declineCode; } /** - * Set the value of declineCode + * Set the value of declineCode. + * + * @param mixed $declineCode * - * @return self - */ + * @return self + */ public function setDeclineCode($declineCode) { $this->declineCode = $declineCode; @@ -104,18 +108,20 @@ public function setDeclineCode($declineCode) } /** - * Get the value of txAuthNo - */ + * Get the value of txAuthNo. + */ public function getTxAuthNo() { return $this->txAuthNo; } /** - * Set the value of txAuthNo + * Set the value of txAuthNo. * - * @return self - */ + * @param mixed $txAuthNo + * + * @return self + */ public function setTxAuthNo($txAuthNo) { $this->txAuthNo = $txAuthNo; @@ -124,18 +130,20 @@ public function setTxAuthNo($txAuthNo) } /** - * Get the value of status - */ + * Get the value of status. + */ public function getStatus() { return $this->status; } /** - * Set the value of status + * Set the value of status. + * + * @param mixed $status * - * @return self - */ + * @return self + */ public function setStatus($status) { $this->status = $status; @@ -144,18 +152,20 @@ public function setStatus($status) } /** - * Get the value of statusDetail - */ + * Get the value of statusDetail. + */ public function getStatusDetail() { return $this->statusDetail; } /** - * Set the value of statusDetail + * Set the value of statusDetail. * - * @return self - */ + * @param mixed $statusDetail + * + * @return self + */ public function setStatusDetail($statusDetail) { $this->statusDetail = $statusDetail; @@ -164,18 +174,20 @@ public function setStatusDetail($statusDetail) } /** - * Get the value of vendorTxCode - */ + * Get the value of vendorTxCode. + */ public function getVendorTxCode() { return $this->vendorTxCode; } /** - * Set the value of vendorTxCode + * Set the value of vendorTxCode. + * + * @param mixed $vendorTxCode * - * @return self - */ + * @return self + */ public function setVendorTxCode($vendorTxCode) { $this->vendorTxCode = $vendorTxCode; @@ -184,18 +196,20 @@ public function setVendorTxCode($vendorTxCode) } /** - * Get the value of amount - */ + * Get the value of amount. + */ public function getAmount() { return $this->amount; } /** - * Set the value of amount + * Set the value of amount. + * + * @param mixed $amount * - * @return self - */ + * @return self + */ public function setAmount($amount) { $this->amount = $amount; @@ -204,18 +218,20 @@ public function setAmount($amount) } /** - * Get the value of vpsTxId - */ + * Get the value of vpsTxId. + */ public function getVpsTxId() { return $this->vpsTxId; } /** - * Set the value of vpsTxId + * Set the value of vpsTxId. * - * @return self - */ + * @param mixed $vpsTxId + * + * @return self + */ public function setVpsTxId($vpsTxId) { $this->vpsTxId = $vpsTxId; @@ -224,18 +240,20 @@ public function setVpsTxId($vpsTxId) } /** - * Get the value of addressResult - */ + * Get the value of addressResult. + */ public function getAddressResult() { return $this->addressResult; } /** - * Set the value of addressResult + * Set the value of addressResult. + * + * @param mixed $addressResult * - * @return self - */ + * @return self + */ public function setAddressResult($addressResult) { $this->addressResult = $addressResult; @@ -244,18 +262,20 @@ public function setAddressResult($addressResult) } /** - * Get the value of postCodeResult - */ + * Get the value of postCodeResult. + */ public function getPostCodeResult() { return $this->postCodeResult; } /** - * Set the value of postCodeResult + * Set the value of postCodeResult. * - * @return self - */ + * @param mixed $postCodeResult + * + * @return self + */ public function setPostCodeResult($postCodeResult) { $this->postCodeResult = $postCodeResult; @@ -264,18 +284,20 @@ public function setPostCodeResult($postCodeResult) } /** - * Get the value of cv2Result - */ + * Get the value of cv2Result. + */ public function getCv2Result() { return $this->cv2Result; } /** - * Set the value of cv2Result + * Set the value of cv2Result. + * + * @param mixed $cv2Result * - * @return self - */ + * @return self + */ public function setCv2Result($cv2Result) { $this->cv2Result = $cv2Result; @@ -284,18 +306,20 @@ public function setCv2Result($cv2Result) } /** - * Get the value of giftAid - */ + * Get the value of giftAid. + */ public function getGiftAid() { return $this->giftAid; } /** - * Set the value of giftAid + * Set the value of giftAid. + * + * @param mixed $giftAid * - * @return self - */ + * @return self + */ public function setGiftAid($giftAid) { $this->giftAid = $giftAid; @@ -304,18 +328,20 @@ public function setGiftAid($giftAid) } /** - * Get the value of _3dSecureStatus - */ + * Get the value of _3dSecureStatus. + */ public function get_3dSecureStatus() { return $this->_3dSecureStatus; } /** - * Set the value of _3dSecureStatus + * Set the value of _3dSecureStatus. * - * @return self - */ + * @param mixed $_3dSecureStatus + * + * @return self + */ public function set_3dSecureStatus($_3dSecureStatus) { $this->_3dSecureStatus = $_3dSecureStatus; @@ -324,18 +350,20 @@ public function set_3dSecureStatus($_3dSecureStatus) } /** - * Get the value of cardType - */ + * Get the value of cardType. + */ public function getCardType() { return $this->cardType; } /** - * Set the value of cardType + * Set the value of cardType. + * + * @param mixed $cardType * - * @return self - */ + * @return self + */ public function setCardType($cardType) { $this->cardType = $cardType; @@ -344,18 +372,20 @@ public function setCardType($cardType) } /** - * Get the value of last4Digits - */ + * Get the value of last4Digits. + */ public function getLast4Digits() { return $this->last4Digits; } /** - * Set the value of last4Digits + * Set the value of last4Digits. * - * @return self - */ + * @param mixed $last4Digits + * + * @return self + */ public function setLast4Digits($last4Digits) { $this->last4Digits = $last4Digits; @@ -364,18 +394,20 @@ public function setLast4Digits($last4Digits) } /** - * Get the value of AVSCV2 - */ + * Get the value of AVSCV2. + */ public function getAVSCV2() { return $this->AVSCV2; } /** - * Set the value of AVSCV2 + * Set the value of AVSCV2. + * + * @param mixed $AVSCV2 * - * @return self - */ + * @return self + */ public function setAVSCV2($AVSCV2) { $this->AVSCV2 = $AVSCV2; diff --git a/src/Lib/SagepayStatusType.php b/src/Lib/SagepayStatusType.php index bc1205c..915dd5b 100644 --- a/src/Lib/SagepayStatusType.php +++ b/src/Lib/SagepayStatusType.php @@ -4,32 +4,30 @@ namespace Sbarbat\SyliusSagepayPlugin\Lib; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayException; - class SagepayStatusType { // Transaction ok - const OK = 'OK'; + public const OK = 'OK'; // If the authorisation was failed by the bank. - const NOTAUTHED = 'NOTAUTHED'; + public const NOTAUTHED = 'NOTAUTHED'; // If the user decided to click cancel whilst on the Sage Pay payment pages. - const ABORT = 'ABORT'; + public const ABORT = 'ABORT'; // If authorisation occurred but your fraud screening rules were not met, or 3DAuthetnication failed three times. - const REJECTED = 'REJECTED'; + public const REJECTED = 'REJECTED'; - // If an error has occurred at Sage Pay (these are very infrequent, but your site should handle them anyway. + // If an error has occurred at Sage Pay (these are very infrequent, but your site should handle them anyway. // They normally indicate a problem with authorisation). - const ERROR = 'ERROR'; + public const ERROR = 'ERROR'; // Missing properties or badly formed body - const MALFORMED = 'MALFORMED'; + public const MALFORMED = 'MALFORMED'; //Invalid property values supplied - const INVALID = 'INVALID'; + public const INVALID = 'INVALID'; //Needs 3D authentication - const _3DAUTH = '3DAUTH'; -} \ No newline at end of file + public const _3DAUTH = '3DAUTH'; +} diff --git a/src/Lib/SagepayTransactionType.php b/src/Lib/SagepayTransactionType.php index 1abf630..f4fe493 100755 --- a/src/Lib/SagepayTransactionType.php +++ b/src/Lib/SagepayTransactionType.php @@ -4,19 +4,27 @@ namespace Sbarbat\SyliusSagepayPlugin\Lib; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayException; - class SagepayTransactionType { - const PAYMENT = 'PAYMENT'; - const DEFERRED = 'DEFERRED'; - const AUTHORISE = 'AUTHORISE'; - const CANCEL = 'CANCEL'; - const VOID = 'VOID'; - const REFUND = 'REFUND'; - const REPEAT = 'REPEAT'; - const REPEATDEFERRED = 'REPEATDEFERRED'; - const ABORT = 'ABORT'; - const RELEASE = 'RELEASE'; - const COMPLETE = 'COMPLETE'; + public const PAYMENT = 'PAYMENT'; + + public const DEFERRED = 'DEFERRED'; + + public const AUTHORISE = 'AUTHORISE'; + + public const CANCEL = 'CANCEL'; + + public const VOID = 'VOID'; + + public const REFUND = 'REFUND'; + + public const REPEAT = 'REPEAT'; + + public const REPEATDEFERRED = 'REPEATDEFERRED'; + + public const ABORT = 'ABORT'; + + public const RELEASE = 'RELEASE'; + + public const COMPLETE = 'COMPLETE'; } diff --git a/src/Lib/SagepayUtil.php b/src/Lib/SagepayUtil.php index 51694b7..6a51625 100755 --- a/src/Lib/SagepayUtil.php +++ b/src/Lib/SagepayUtil.php @@ -4,109 +4,105 @@ namespace Sbarbat\SyliusSagepayPlugin\Lib; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayException; - class SagepayUtil { /** * Encrypt a string ready to send to SagePay using encryption key. * - * @param string $string The unencrypyted string. - * @param string $key The encryption key. + * @param string $key the encryption key * - * @return string The encrypted string. + * @return string the encrypted string */ - static public function encrypt(array $data, string $key): string + public static function encrypt(array $data, string $key): string { - $data = SagepayUtil::arrayToQueryString($data); - - return strtoupper("@" . bin2hex(openssl_encrypt($data, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $key))); + $data = self::arrayToQueryString($data); + + return strtoupper('@'.bin2hex(openssl_encrypt($data, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $key))); } /** * Decode a returned string from SagePay. * - * @param string $strIn The encrypted String. - * @param string $password The encyption password used to encrypt the string. - * - * @return string The unecrypted string. * @throws SagepayApiException + * + * @return string the unecrypted string */ - static public function decrypt(string $str, string $key): array + public static function decrypt(string $str, string $key): array { $str = substr($str, 1); $str = pack('H*', $str); + return self::queryStringToArray(openssl_decrypt($str, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $key)); } /** * Convert a data array to a query string ready to post. * - * @param array $data The data array. - * @param string $delimeter Delimiter used in query string - * @param boolean $urlencoded If true encode the final query string + * @param array $data the data array + * @param bool $urlencoded If true encode the final query string + * @param mixed $delimiter * - * @return string The array as a string. + * @return string the array as a string */ - static public function arrayToQueryString(array $data, $delimiter = '&', $urlencoded = false) + public static function arrayToQueryString(array $data, $delimiter = '&', $urlencoded = false) { $queryString = ''; $delimiterLength = strlen($delimiter); // Parse each value pairs and concate to query string - foreach ($data as $name => $value) - { + foreach ($data as $name => $value) { // Apply urlencode if it is required - if ($urlencoded) - { + if ($urlencoded) { $value = urlencode($value); } - $queryString .= $name . '=' . $value . $delimiter; + $queryString .= $name.'='.$value.$delimiter; } // remove the last delimiter return substr($queryString, 0, -1 * $delimiterLength); } - static public function arrayToQueryStringRemovingSensitiveData(array $data,array $nonSensitiveDataKey, $delimiter = '&', $urlencoded = false) - { + public static function arrayToQueryStringRemovingSensitiveData( + array $data, + array $nonSensitiveDataKey, + $delimiter = '&', + $urlencoded = false + ) { $queryString = ''; $delimiterLength = strlen($delimiter); // Parse each value pairs and concate to query string - foreach ($data as $name => $value) - { - if (!in_array($name, $nonSensitiveDataKey)){ - $value=MASK_FOR_HIDDEN_FIELDS; - } - else if ($urlencoded){ - $value = urlencode($value); - } - // Apply urlencode if it is required - - $queryString .= $name . '=' . $value . $delimiter; + foreach ($data as $name => $value) { + if (! in_array($name, $nonSensitiveDataKey, true)) { + $value = MASK_FOR_HIDDEN_FIELDS; + } elseif ($urlencoded) { + $value = urlencode($value); + } + // Apply urlencode if it is required + + $queryString .= $name.'='.$value.$delimiter; } // remove the last delimiter return substr($queryString, 0, -1 * $delimiterLength); } + /** * Convert string to data array. * - * @param string $data Query string - * @param string $delimeter Delimiter used in query string + * @param string $data Query string + * @param string $delimeter Delimiter used in query string * * @return array */ - static public function queryStringToArray($data, $delimeter = "&") + public static function queryStringToArray($data, $delimeter = '&') { // Explode query by delimiter $pairs = explode($delimeter, $data); - $queryArray = array(); + $queryArray = []; // Explode pairs by "=" - foreach ($pairs as $pair) - { + foreach ($pairs as $pair) { $keyValue = explode('=', $pair); // Use first value as key @@ -115,50 +111,48 @@ static public function queryStringToArray($data, $delimeter = "&") // Implode others as value for $key $queryArray[$key] = implode('=', $keyValue); } + return $queryArray; } - static public function queryStringToArrayRemovingSensitiveData($data, $delimeter = "&", $nonSensitiveDataKey) - { + public static function queryStringToArrayRemovingSensitiveData($data, $delimeter = '&', $nonSensitiveDataKey) + { // Explode query by delimiter $pairs = explode($delimeter, $data); - $queryArray = array(); + $queryArray = []; // Explode pairs by "=" - foreach ($pairs as $pair) - { + foreach ($pairs as $pair) { $keyValue = explode('=', $pair); // Use first value as key $key = array_shift($keyValue); - if (in_array($key, $nonSensitiveDataKey)){ - $keyValue = explode('=', $pair); - } - else{ - $keyValue = array(MASK_FOR_HIDDEN_FIELDS); - } - // Implode others as value for $key - $queryArray[$key] = implode('=', $keyValue); - + if (in_array($key, $nonSensitiveDataKey, true)) { + $keyValue = explode('=', $pair); + } else { + $keyValue = [MASK_FOR_HIDDEN_FIELDS]; + } + // Implode others as value for $key + $queryArray[$key] = implode('=', $keyValue); } + return $queryArray; } /** - * Extract last 4 digits from card number; + * Extract last 4 digits from card number;. * * @param string $cardNr * * @return string */ - static public function getLast4Digits($cardNr) + public static function getLast4Digits($cardNr) { // Apply RegExp to extract last 4 digits - $matches = array(); - if (preg_match('/\d{4}$/', $cardNr, $matches)) - { + $matches = []; + if (preg_match('/\d{4}$/', $cardNr, $matches)) { return $matches[0]; } + return ''; } - } diff --git a/src/Provider/AmountProvider.php b/src/Provider/AmountProvider.php new file mode 100644 index 0000000..eeb7a31 --- /dev/null +++ b/src/Provider/AmountProvider.php @@ -0,0 +1,15 @@ +getAmount() / 100); + } +} diff --git a/src/Request/Api/ExecutePayment.php b/src/Request/Api/ExecutePayment.php index ddfc44e..e9c4a2b 100644 --- a/src/Request/Api/ExecutePayment.php +++ b/src/Request/Api/ExecutePayment.php @@ -1,10 +1,11 @@ messageFactory = $messageFactory; } - /** - * @param array $fields - * - * @return array - */ - protected function doRequest($method, $path, array $fields = []) - { - $headers = [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ]; - - $request = $this->messageFactory->createRequest($method, $this->getApiEndpoint(), $headers, http_build_query($fields)); - - $response = $this->client->send($request); - - if (false == ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300)) { - throw HttpException::factory($request, $response); - } - - return $response; - } - /** * @return string */ @@ -95,6 +66,35 @@ public function getOptions() public function getTransactionCode(OrderInterface $order, PaymentInterface $payment) { - return $order->getNumber() . '_' . $payment->getId() . '_' . time(); + return $order->getNumber().'_'.$payment->getId().'_'.time(); + } + + /** + * @param mixed $method + * @param mixed $path + * + * @return ResponseInterface + */ + protected function doRequest($method, $path, array $fields = []) + { + $headers = [ + 'Content-Type' => 'application/x-www-form-urlencoded', + ]; + + $request = $this->messageFactory->createRequest( + $method, + $this->getApiEndpoint(), + $headers, + http_build_query($fields) + ); + + $response = $this->client->send($request); + + $statusCode = $response->getStatusCode(); + if (! ($statusCode >= 200 && $statusCode < 300)) { + throw HttpException::factory($request, $response); + } + + return $response; } } diff --git a/src/SagepayDirectApi.php b/src/SagepayDirectApi.php index 23eec80..a9ea6cb 100644 --- a/src/SagepayDirectApi.php +++ b/src/SagepayDirectApi.php @@ -4,70 +4,30 @@ namespace Sbarbat\SyliusSagepayPlugin; -use Http\Message\MessageFactory; - -use Payum\Core\HttpClientInterface; -use Payum\Core\Bridge\Spl\ArrayObject; -use Payum\Core\Request\RenderTemplate; use Payum\Core\Exception\Http\HttpException; -use Sylius\Component\Core\Model\OrderInterface; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayUtil; -use Sylius\Component\Core\Model\PaymentInterface; - -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayRequest; -use Sbarbat\SyliusSagepayPlugin\Sanitizers\NameSanitizer; -use Sbarbat\SyliusSagepayPlugin\Sanitizers\SanitizerInterface; +use Psr\Http\Message\ResponseInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class SagepayDirectApi extends SagepayApi { - /** - * @param array $fields - * - * @return array - */ - protected function doRequest($method, $path, array $fields = []) - { - $headers = [ - "Authorization" => $this->getBasicAuthenticationHeader(), - "Cache-Control" => 'no-cache', - "Content-Type" => "application/json" - ]; - - $fileds = array_merge($fields, [ - 'vendorName' => $this->options['vendorName'], - ]); - - $url = $this->getApiEndpoint() . $path; - $request = $this->messageFactory->createRequest($method, $url, $headers, http_build_query($fields)); - - $response = $this->client->send($request); - - if (false == ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300)) { - throw HttpException::factory($request, $response); - } - - return $response; - } - public function getMerchantSessionKey() { $curl = curl_init(); - curl_setopt_array($curl, array( - CURLOPT_URL => $this->getApiEndpoint() . "merchant-session-keys", - CURLOPT_RETURNTRANSFER => true, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => '{ "vendorName": "'.$this->options['vendorName'].'" }', - CURLOPT_HTTPHEADER => array( - "Authorization: " . $this->getBasicAuthenticationHeader(), - "Cache-Control: no-cache", - "Content-Type: application/json" - ), - )); - + curl_setopt_array($curl, [ + CURLOPT_URL => $this->getApiEndpoint().'merchant-session-keys', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ "vendorName": "'.$this->options['vendorName'].'" }', + CURLOPT_HTTPHEADER => [ + 'Authorization: '.$this->getBasicAuthenticationHeader(), + 'Cache-Control: no-cache', + 'Content-Type: application/json', + ], + ]); + $response = json_decode(curl_exec($curl)); $err = curl_error($curl); - + curl_close($curl); if (isset($response->code)) { @@ -80,18 +40,18 @@ public function getMerchantSessionKey() public function validate3DAuthResponse($transactionId, $paRes) { $curl = curl_init(); - - curl_setopt_array($curl, array( - CURLOPT_URL => $this->getApiEndpoint() . "transactions/" . $transactionId . "/3d-secure", + + curl_setopt_array($curl, [ + CURLOPT_URL => $this->getApiEndpoint().'transactions/'.$transactionId.'/3d-secure', CURLOPT_RETURNTRANSFER => true, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => '{ "paRes": "' . $paRes . '" }', - CURLOPT_HTTPHEADER => array( - "Authorization: " . $this->getBasicAuthenticationHeader(), - "Cache-Control: no-cache", - "Content-Type: application/json" - ), - )); + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ "paRes": "'.$paRes.'" }', + CURLOPT_HTTPHEADER => [ + 'Authorization: '.$this->getBasicAuthenticationHeader(), + 'Cache-Control: no-cache', + 'Content-Type: application/json', + ], + ]); $response = curl_exec($curl); @@ -103,18 +63,18 @@ public function validate3DAuthResponse($transactionId, $paRes) public function getTransactionOutcome($transactionId) { $curl = curl_init(); - - curl_setopt_array($curl, array( - CURLOPT_URL => $this->getApiEndpoint() . "transactions/" . $transactionId, + + curl_setopt_array($curl, [ + CURLOPT_URL => $this->getApiEndpoint().'transactions/'.$transactionId, CURLOPT_RETURNTRANSFER => true, - CURLOPT_HTTPHEADER => array( - "Authorization: " . $this->getBasicAuthenticationHeader(), - "Cache-Control: no-cache", - ), - )); - + CURLOPT_HTTPHEADER => [ + 'Authorization: '.$this->getBasicAuthenticationHeader(), + 'Cache-Control: no-cache', + ], + ]); + $response = curl_exec($curl); - + curl_close($curl); return json_decode($response); @@ -129,7 +89,7 @@ public function getBasicAuthenticationHeader() { $str = 'Basic %s'; - $token = base64_encode($this->getIntegrationKey() .':'. $this->getIntegrationPassword()); + $token = base64_encode($this->getIntegrationKey().':'.$this->getIntegrationPassword()); return sprintf($str, $token); } @@ -143,4 +103,35 @@ public function getIntegrationPassword() { return $this->options['sandbox'] ? $this->options['integrationPasswordTest'] : $this->options['integrationPasswordLive']; } + + /** + * @param mixed $method + * @param mixed $path + * + * @return ResponseInterface + */ + protected function doRequest($method, $path, array $fields = []) + { + $headers = [ + 'Authorization' => $this->getBasicAuthenticationHeader(), + 'Cache-Control' => 'no-cache', + 'Content-Type' => 'application/json', + ]; + + $fields = array_merge($fields, [ + 'vendorName' => $this->options['vendorName'], + ]); + + $url = $this->getApiEndpoint().$path; + $request = $this->messageFactory->createRequest($method, $url, $headers, http_build_query($fields)); + + $response = $this->client->send($request); + + $statusCode = $response->getStatusCode(); + if (! ($statusCode >= 200 && $statusCode < 300)) { + throw HttpException::factory($request, $response); + } + + return $response; + } } diff --git a/src/SagepayDirectGatewayFactory.php b/src/SagepayDirectGatewayFactory.php index 84f5ff1..bc37343 100644 --- a/src/SagepayDirectGatewayFactory.php +++ b/src/SagepayDirectGatewayFactory.php @@ -4,21 +4,14 @@ namespace Sbarbat\SyliusSagepayPlugin; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\AuthorizeAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\CancelAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\ConvertPaymentAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\CaptureAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\NotifyAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\RefundAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\StatusAction; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\GatewayFactory; +use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\CaptureAction; +use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\ConvertPaymentAction; +use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Direct\StatusAction; class SagepayDirectGatewayFactory extends GatewayFactory { - /** - * {@inheritDoc} - */ protected function populateConfig(ArrayObject $config) { $config->defaults([ @@ -36,7 +29,7 @@ protected function populateConfig(ArrayObject $config) ]); if (null === $config['payum.api'] || false === $config['payum.api']) { - $config['payum.default_options'] = array( + $config['payum.default_options'] = [ 'integration' => SagepayIntegrations::DIRECT, 'sandbox' => true, 'vendorName' => 'winebuyers', @@ -44,20 +37,25 @@ protected function populateConfig(ArrayObject $config) 'integrationPasswordLive' => '', 'integrationKeyTest' => '', 'integrationPasswordTest' => '', - ); + 'stateCodeAbbreviated' => false, + ]; $config->defaults($config['payum.default_options']); $config['payum.required_options'] = [ 'vendorName', 'integrationKeyLive', 'integrationPasswordLive', 'integrationKeyTest', - 'integrationPasswordTest' + 'integrationPasswordTest', ]; $config['payum.api'] = function (ArrayObject $config) { $config->validateNotEmpty($config['payum.required_options']); - return new SagepayDirectApi((array) $config, $config['payum.http_client'], $config['httplug.message_factory']); + return new SagepayDirectApi( + (array) $config, + $config['payum.http_client'], + $config['httplug.message_factory'] + ); }; } diff --git a/src/SagepayFormApi.php b/src/SagepayFormApi.php index d1f6216..f7e43bb 100755 --- a/src/SagepayFormApi.php +++ b/src/SagepayFormApi.php @@ -4,34 +4,46 @@ namespace Sbarbat\SyliusSagepayPlugin; -use Http\Message\MessageFactory; -use Payum\Core\Exception\Http\HttpException; -use Payum\Core\HttpClientInterface; use Payum\Core\Bridge\Spl\ArrayObject; -use Sbarbat\SyliusSagepayPlugin\Lib\SagepayUtil; use Sbarbat\SyliusSagepayPlugin\Lib\SagepayRequest; - -use Sylius\Component\Core\Model\PaymentInterface; +use Sbarbat\SyliusSagepayPlugin\Provider\AmountProvider; +use Sylius\Component\Addressing\Provider\ProvinceNamingProviderInterface; +use Sylius\Component\Core\Model\AddressInterface; use Sylius\Component\Core\Model\OrderInterface; +use Sylius\Component\Core\Model\PaymentInterface; -class SagepayFormApi extends SagepayApi +class SagepayFormApi extends SagepayApi { /** - * @param array $params + * @var ProvinceNamingProviderInterface + */ + private $provinceNamingProvider; + + /** + * @param mixed $request * * @return array */ - public function preparePayment($request, ArrayObject $model, PaymentInterface $payment): SagepayRequest - { - $afterUrl = $request->getToken()->getAfterUrl(); + public function preparePayment( + $request, + ArrayObject $model, + PaymentInterface $payment, + ProvinceNamingProviderInterface $provinceNamingProvider, + AmountProvider $amountProvider + ): SagepayRequest { + $this->provinceNamingProvider = $provinceNamingProvider; + $afterUrl = $request->getToken() + ->getAfterUrl() + ; $order = $payment->getOrder(); - $customer = $order->getCustomer(); + assert($order instanceof OrderInterface); $request = new SagepayRequest($this); $request->addQuery('VendorTxCode', $payment->getDetails()['txCode']); - $request->addQuery('Amount', (string) $payment->getAmount() / 100); - $request->addQuery('Description', 'Payment for order #'. $order->getNumber()); + $request->addQuery('Amount', $amountProvider->getAmount($payment)); + $request->addQuery('Description', 'Payment for order #'.$order->getNumber()); + $request->addQuery('Currency', $payment->getCurrencyCode()); $request->addQuery('SuccessURL', $afterUrl); $request->addQuery('FailureURL', $afterUrl); @@ -42,9 +54,15 @@ public function preparePayment($request, ArrayObject $model, PaymentInterface $p return $request; } - public function getFormEncryptionPassword() + public function getFormEncryptionPassword() { return $this->options['sandbox'] ? $this->options['encryptionPasswordTest'] : $this->options['encryptionPasswordLive']; } + public function getStateCode(AddressInterface $address) + { + return $this->options['stateCodeAbbreviated'] ? $this->provinceNamingProvider->getAbbreviation( + $address + ) : $address->getProvinceCode(); + } } diff --git a/src/SagepayFormGatewayFactory.php b/src/SagepayFormGatewayFactory.php index 7f93fac..acbe6ae 100755 --- a/src/SagepayFormGatewayFactory.php +++ b/src/SagepayFormGatewayFactory.php @@ -4,50 +4,52 @@ namespace Sbarbat\SyliusSagepayPlugin; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\AuthorizeAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\CancelAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\ConvertPaymentAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\CaptureAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\NotifyAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\RefundAction; -use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\StatusAction; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\GatewayFactory; +use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\CaptureAction; +use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\ConvertPaymentAction; +use Sbarbat\SyliusSagepayPlugin\Action\Integrations\Form\StatusAction; class SagepayFormGatewayFactory extends GatewayFactory { - /** - * {@inheritDoc} - */ protected function populateConfig(ArrayObject $config) { $config->defaults([ 'payum.factory_name' => 'sagepay', 'payum.factory_title' => 'Sagepay Form', - 'payum.action.capture' => new CaptureAction(), + // 'payum.action.capture' => new CaptureAction(), // No needed for form integration for now //'payum.action.notify' => new NotifyAction(), 'payum.action.status' => new StatusAction(), 'payum.action.convert' => new ConvertPaymentAction(), ]); - if (false == $config['payum.api']) { - $config['payum.default_options'] = array( + if (! $config['payum.api']) { + $config['payum.default_options'] = [ 'integration' => SagepayIntegrations::FORM, 'sandbox' => true, - 'currency' => 'GBP', 'vendorName' => '', 'protocolVersion' => '3.00', 'encryptionPasswordLive' => '', 'encryptionPasswordTest' => '', - ); + 'stateCodeAbbreviated' => false, + ]; $config->defaults($config['payum.default_options']); - $config['payum.required_options'] = [ 'vendorName', 'encryptionPasswordLive', 'encryptionPasswordTest', 'currency' ]; + $config['payum.required_options'] = [ + 'vendorName', + 'encryptionPasswordLive', + 'encryptionPasswordTest', + 'currency', + ]; $config['payum.api'] = function (ArrayObject $config) { $config->validateNotEmpty($config['payum.required_options']); - return new SagepayFormApi((array) $config, $config['payum.http_client'], $config['httplug.message_factory']); + return new SagepayFormApi( + (array) $config, + $config['payum.http_client'], + $config['httplug.message_factory'] + ); }; } } diff --git a/src/SagepayIntegrations.php b/src/SagepayIntegrations.php index beec1ee..516456f 100644 --- a/src/SagepayIntegrations.php +++ b/src/SagepayIntegrations.php @@ -4,19 +4,11 @@ namespace Sbarbat\SyliusSagepayPlugin; -use Sbarbat\SyliusSagepayPlugin\Action\AuthorizeAction; -use Sbarbat\SyliusSagepayPlugin\Action\CancelAction; -use Sbarbat\SyliusSagepayPlugin\Action\ConvertPaymentAction; -use Sbarbat\SyliusSagepayPlugin\Action\CaptureAction; -use Sbarbat\SyliusSagepayPlugin\Action\NotifyAction; -use Sbarbat\SyliusSagepayPlugin\Action\RefundAction; -use Sbarbat\SyliusSagepayPlugin\Action\StatusAction; -use Payum\Core\Bridge\Spl\ArrayObject; -use Payum\Core\GatewayFactory; - class SagepayIntegrations -{ - const FORM = 'FORM'; - const DIRECT = 'DIRECT'; - const SERVER = 'SERVER'; +{ + public const FORM = 'FORM'; + + public const DIRECT = 'DIRECT'; + + public const SERVER = 'SERVER'; } diff --git a/src/Sanitizers/AbstractSanitizer.php b/src/Sanitizers/AbstractSanitizer.php index b3074fd..99a9b2f 100644 --- a/src/Sanitizers/AbstractSanitizer.php +++ b/src/Sanitizers/AbstractSanitizer.php @@ -1,5 +1,7 @@ create(array('vendorName' => 'winebuyers')); + $gateway = $factory->create([ + 'vendorName' => 'winebuyers', + ]); $this->assertInstanceOf('Payum\Core\Gateway', $gateway); $this->assertAttributeNotEmpty('apis', $gateway); @@ -37,12 +42,12 @@ public function shouldConfigContainDefaultOptions() $this->assertInternalType('array', $config); $this->assertArrayHasKey('payum.default_options', $config); - $this->assertEquals(array( + $this->assertEquals([ 'sandbox' => true, 'currency' => 'GBP', 'vendorName' => '', - 'protocolVersion' => 3.00 - ), $config['payum.default_options']); + 'protocolVersion' => 3.00, + ], $config['payum.default_options']); } /** @@ -73,4 +78,4 @@ public function shouldThrowIfRequiredOptionsNotPassed() $factory = new SagepayGatewayFactory(); $factory->create(); } -} \ No newline at end of file +}