From b74ade3deb0fbefc8e69e417879d16207072d2e0 Mon Sep 17 00:00:00 2001 From: Benjamin BOUDIER Date: Wed, 30 Nov 2022 11:56:25 +0100 Subject: [PATCH] Update: add getReturnResponse on payment gateway --- Gateway/AbstractPaymentGateway.php | 10 ++++- Gateway/AlmaPaymentGateway.php | 36 ++++++++++++++++- Gateway/AtosSipsBinPaymentGateway.php | 25 ++++++------ Gateway/AtosSipsJsonPaymentGateway.php | 28 ++++++------- Gateway/AtosSipsPostPaymentGateway.php | 23 ++++++----- Gateway/EurekaPaymentGateway.php | 37 ++++++------------ Gateway/MoneticoPaymentGateway.php | 19 +++++---- Gateway/OgonePaymentGateway.php | 19 +++++---- Gateway/PayPlugPaymentGateway.php | 12 +++++- Gateway/PayboxPaymentGateway.php | 29 +++++++------- Gateway/PaymentGatewayInterface.php | 33 +++++----------- Gateway/PaypalPaymentGateway.php | 20 ++++++---- Gateway/SofincoCACFPaymentGateway.php | 24 ++++++------ Gateway/SofincoPaymentGateway.php | 39 +++++++------------ Gateway/StripePaymentGateway.php | 12 +++++- Gateway/SystemPayPaymentGateway.php | 26 ++++++------- Payment/PaymentContext.php | 30 ++++++++++++-- Payment/PaymentContextInterface.php | 2 + Resources/docs/create-your-payment-gateway.md | 28 +++++++++++-- Resources/docs/uml-schema.xmi | 2 +- Resources/views/PaymentStep/pending.html.twig | 2 +- .../ManageTransactionStepEventAction.php | 6 ++- .../AtosSipsJsonPaymentGatewayTest.php | 14 +++---- .../AtosSipsPostPaymentGatewayTest.php | 14 +++---- .../Gateway/PayPlugPaymentGatewayTest.php | 12 +++--- .../Unit/Gateway/PayboxPaymentGatewayTest.php | 2 +- .../Unit/Gateway/PaypalPaymentGatewayTest.php | 2 +- .../Unit/Gateway/StripePaymentGatewayTest.php | 6 +-- Tests/Unit/Payment/PaymentContextTest.php | 10 ++--- 29 files changed, 296 insertions(+), 226 deletions(-) diff --git a/Gateway/AbstractPaymentGateway.php b/Gateway/AbstractPaymentGateway.php index cf03a2f..ee5b868 100644 --- a/Gateway/AbstractPaymentGateway.php +++ b/Gateway/AbstractPaymentGateway.php @@ -47,7 +47,15 @@ abstract public function buildHTMLView( /** * {@inheritdoc} */ - abstract public function getResponse( + abstract public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse; + + /** + * {@inheritdoc} + */ + abstract public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse; diff --git a/Gateway/AlmaPaymentGateway.php b/Gateway/AlmaPaymentGateway.php index b22277b..ff03b35 100644 --- a/Gateway/AlmaPaymentGateway.php +++ b/Gateway/AlmaPaymentGateway.php @@ -83,12 +83,46 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + $gatewayResponse = new GatewayResponse(); + + if (!$request->query->has('pid')) { + return $gatewayResponse; + } + + try { + $payment = $this->getClient($paymentGatewayConfiguration)->payments->fetch($request->query->get('pid')); + + $gatewayResponse + ->setTransactionUuid($payment->orders[0]->merchant_reference) + ->setAmount($payment->purchase_amount) + ->setRaw(get_object_vars($payment)) + ; + + if (!in_array($payment->state, [AlmaStatusCode::STATUS_IN_PROGRESS, AlmaStatusCode::STATUS_PAID])) { + return $gatewayResponse->setStatus(PaymentStatus::STATUS_FAILED); + } + + return $gatewayResponse->setStatus(PaymentStatus::STATUS_APPROVED); + } catch (\Exception $e) { + $this->logger->error(sprintf('Error: %s. Context: %s', $e->getMessage(), json_encode($e->response->json))); + } + + return $gatewayResponse; + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/AtosSipsBinPaymentGateway.php b/Gateway/AtosSipsBinPaymentGateway.php index efdf949..f75f407 100644 --- a/Gateway/AtosSipsBinPaymentGateway.php +++ b/Gateway/AtosSipsBinPaymentGateway.php @@ -47,17 +47,13 @@ public function __construct( * Build notification response parameters. * * @method buildResponseParams - * - * @param Request $request - * - * @return array */ private function buildResponseParams(Request $request): array { - $shellOptions = array( + $shellOptions = [ 'pathfile' => $this->pathfile, 'message' => $request->request->get('DATA'), - ); + ]; $args = implode(' ', array_map( function ($k, $v) { return sprintf('%s=%s', $k, $v); }, @@ -129,11 +125,6 @@ function ($k, $v) { return sprintf('%s=%s', $k, $v); }, * Build payment gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -208,12 +199,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/AtosSipsJsonPaymentGateway.php b/Gateway/AtosSipsJsonPaymentGateway.php index 4df252a..fe1fc04 100644 --- a/Gateway/AtosSipsJsonPaymentGateway.php +++ b/Gateway/AtosSipsJsonPaymentGateway.php @@ -34,8 +34,6 @@ public function __construct( * Get Atos Sips Json server url. * * @method getServerUrl - * - * @return string */ protected function getServerUrl(): string { @@ -46,11 +44,6 @@ protected function getServerUrl(): string * Build payment gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -75,11 +68,6 @@ private function buildOptions( * Build payment gateway signature hash. * * @method buildSeal - * - * @param array $options - * @param string $secretKey - * - * @return string */ private function buildSeal(array $options, string $secretKey): string { @@ -120,9 +108,7 @@ public function initialize( } if ('00' != $returnParams['redirectionStatusCode']) { - throw new UnexpectedAtosSipsResponseCodeException( - AtosSipsStatusCode::getStatusMessage($returnParams['redirectionStatusCode']) - ); + throw new UnexpectedAtosSipsResponseCodeException(AtosSipsStatusCode::getStatusMessage($returnParams['redirectionStatusCode'])); } return $returnParams; @@ -142,12 +128,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/AtosSipsPostPaymentGateway.php b/Gateway/AtosSipsPostPaymentGateway.php index 52558cf..3495828 100644 --- a/Gateway/AtosSipsPostPaymentGateway.php +++ b/Gateway/AtosSipsPostPaymentGateway.php @@ -32,8 +32,6 @@ public function __construct( * Get Atos Sips POST server url. * * @method getServerUrl - * - * @return string */ private function getServerUrl(): string { @@ -44,11 +42,6 @@ private function getServerUrl(): string * Build payment gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -71,10 +64,6 @@ private function buildOptions( * Build payment gateway signature hash. * * @method buildSeal - * - * @param array $options - * - * @return string */ private function buildSeal(array $options): string { @@ -126,12 +115,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/EurekaPaymentGateway.php b/Gateway/EurekaPaymentGateway.php index d888d09..349373c 100644 --- a/Gateway/EurekaPaymentGateway.php +++ b/Gateway/EurekaPaymentGateway.php @@ -37,11 +37,6 @@ public function __construct( * * @method buildOptions * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array - * * @throws \UnexpectedValueException If required transaction metadata is not set */ private function buildOptions( @@ -50,9 +45,7 @@ private function buildOptions( ): array { foreach ($this->getRequiredTransactionMetadata() as $requiredTransactionMetadata) { if (!$transaction->hasMetadata($requiredTransactionMetadata)) { - throw new \UnexpectedValueException( - sprintf('The transaction metadata "%s" must be set', $requiredTransactionMetadata) - ); + throw new \UnexpectedValueException(sprintf('The transaction metadata "%s" must be set', $requiredTransactionMetadata)); } } @@ -83,11 +76,6 @@ private function buildOptions( * Request payment gateway request token. * * @method requestScoringToken - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return string */ private function requestScoringToken( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -218,11 +206,6 @@ private function requestScoringToken( * Build payment gateway HMAC signature according to its type (IN|OUT). * * @method buildHmac - * - * @param array $options - * @param string $hmacType - * - * @return string */ private function buildHmac(array $options, string $hmacType): string { @@ -278,12 +261,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { @@ -353,10 +346,6 @@ public static function getParameterNames(): ?array * Get the HMAC build parameters names according to its type (IN|OUT). * * @method getHmacBuildParameters - * - * @param string $hmacType - * - * @return array */ private function getHmacBuildParameters(string $hmacType): array { @@ -414,8 +403,6 @@ private function getHmacBuildParameters(string $hmacType): array * Get required transaction metadata names. * * @method getRequiredTransactionMetadata - * - * @return array */ private function getRequiredTransactionMetadata(): array { diff --git a/Gateway/MoneticoPaymentGateway.php b/Gateway/MoneticoPaymentGateway.php index 161cb18..f70aadf 100644 --- a/Gateway/MoneticoPaymentGateway.php +++ b/Gateway/MoneticoPaymentGateway.php @@ -13,8 +13,6 @@ class MoneticoPaymentGateway extends AbstractPaymentGateway * Get Monetico server url. * * @method getServerUrl - * - * @return string */ private function getServerUrl(): string { @@ -25,11 +23,6 @@ private function getServerUrl(): string * Build payment gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -122,7 +115,17 @@ public function buildHTMLView( /** * {@inheritdoc} */ - public function getResponse( + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + + /** + * {@inheritdoc} + */ + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/OgonePaymentGateway.php b/Gateway/OgonePaymentGateway.php index 92e6f10..f0ce22b 100644 --- a/Gateway/OgonePaymentGateway.php +++ b/Gateway/OgonePaymentGateway.php @@ -13,8 +13,6 @@ class OgonePaymentGateway extends AbstractPaymentGateway * Get Ogone server url. * * @method getServerUrl - * - * @return string */ private function getServerUrl(): string { @@ -25,11 +23,6 @@ private function getServerUrl(): string * Build payment gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -96,7 +89,17 @@ public function buildHTMLView( /** * {@inheritdoc} */ - public function getResponse( + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + + /** + * {@inheritdoc} + */ + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/PayPlugPaymentGateway.php b/Gateway/PayPlugPaymentGateway.php index 0f911c4..8a8f278 100644 --- a/Gateway/PayPlugPaymentGateway.php +++ b/Gateway/PayPlugPaymentGateway.php @@ -57,12 +57,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/PayboxPaymentGateway.php b/Gateway/PayboxPaymentGateway.php index b00b5a5..2b4cec1 100644 --- a/Gateway/PayboxPaymentGateway.php +++ b/Gateway/PayboxPaymentGateway.php @@ -36,8 +36,6 @@ public function __construct( * Get Paybox server url. * * @method getServerUrl - * - * @return string */ private function getServerUrl(): string { @@ -48,10 +46,6 @@ private function getServerUrl(): string * Get Paybox key file path accoding to client site id. * * @method getKeyPath - * - * @param string $clientSite - * - * @return string */ private function getKeyPath(string $clientSite): string { @@ -62,12 +56,10 @@ private function getKeyPath(string $clientSite): string * Get Paybox requested parameters for notification response. * * @method getPayboxReturnString - * - * @return string */ private function getPayboxReturnString(): string { - $codeMap = array( + $codeMap = [ 'M' => 'amount', 'R' => 'reference', 'A' => 'authorisation_id', @@ -91,7 +83,7 @@ private function getPayboxReturnString(): string 'I' => 'country', 'Y' => 'bank_country', 'K' => 'hash', - ); + ]; return implode(';', array_map( function ($k, $v) { return sprintf('%s:%s', $v, $k); }, @@ -104,11 +96,6 @@ function ($k, $v) { return sprintf('%s:%s', $v, $k); }, * Build payment gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -179,12 +166,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not post */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/PaymentGatewayInterface.php b/Gateway/PaymentGatewayInterface.php index 02f0601..a296e96 100644 --- a/Gateway/PaymentGatewayInterface.php +++ b/Gateway/PaymentGatewayInterface.php @@ -11,13 +11,6 @@ interface PaymentGatewayInterface { /** * Initialize payment gateway configuration. - * - * @method initialize - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ public function initialize( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -26,30 +19,24 @@ public function initialize( /** * Build payment gateway HTML view. - * - * @method buildHTMLView - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return string */ public function buildHTMLView( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, Transaction $transaction ): string; + /** + * Get payment gateway return response. + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse; + /** * Get payment gateway callback/notification response. - * - * @method getResponse - * - * @param Request $request - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * - * @return GatewayResponse */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse; @@ -58,8 +45,6 @@ public function getResponse( * Get payment gateway authorized parameters names used in configuration. * * @method getParameterNames - * - * @return array|null */ public static function getParameterNames(): ?array; } diff --git a/Gateway/PaypalPaymentGateway.php b/Gateway/PaypalPaymentGateway.php index a883474..3e23fe8 100644 --- a/Gateway/PaypalPaymentGateway.php +++ b/Gateway/PaypalPaymentGateway.php @@ -47,13 +47,7 @@ public function buildHTMLView( $initializationData = $this->initialize($paymentGatewayConfiguration, $transaction); if (!array_key_exists($paymentGatewayConfiguration->get('checkout_flow'), self::PAYPAL_CHECKOUT_FLOW_TEMPLATE_MAPPING)) { - throw new \UnexpectedValueException( - sprintf( - 'The checkout flow "%s" is not yet implemented in %s', - $paymentGatewayConfiguration->get('checkout_flow'), - self::class - ) - ); + throw new \UnexpectedValueException(sprintf('The checkout flow "%s" is not yet implemented in %s', $paymentGatewayConfiguration->get('checkout_flow'), self::class)); } return $this->templating->render( @@ -67,12 +61,22 @@ public function buildHTMLView( ); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/SofincoCACFPaymentGateway.php b/Gateway/SofincoCACFPaymentGateway.php index 315e17e..f3519e2 100644 --- a/Gateway/SofincoCACFPaymentGateway.php +++ b/Gateway/SofincoCACFPaymentGateway.php @@ -130,12 +130,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { @@ -154,13 +164,7 @@ public function getResponse( } if (strtoupper($request->query->get('transactionId')) !== $requestData['ORDER_ID']) { - throw new \UnexpectedValueException( - sprintf( - 'The transaction/order id mismatch in the data (query: %s, body: %s).', - $request->query->get('transactionId'), - $requestData['ORDER_ID'] - ) - ); + throw new \UnexpectedValueException(sprintf('The transaction/order id mismatch in the data (query: %s, body: %s).', $request->query->get('transactionId'), $requestData['ORDER_ID'])); } $gatewayResponse = (new GatewayResponse()) @@ -206,10 +210,6 @@ public static function getParameterNames(): ?array /** * Build exchange url with transactionId query parameter. - * - * @param string $url - * - * @return string */ private function buildExchangeUrl(string $url, string $transactionId): string { diff --git a/Gateway/SofincoPaymentGateway.php b/Gateway/SofincoPaymentGateway.php index ee59afc..eaa576f 100644 --- a/Gateway/SofincoPaymentGateway.php +++ b/Gateway/SofincoPaymentGateway.php @@ -38,11 +38,6 @@ public function __construct( * Build options for WSACCROCHE Sofinco module. * * @method buildOfferVerifyOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOfferVerifyOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -59,11 +54,6 @@ private function buildOfferVerifyOptions( * Build gateway form options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -84,11 +74,6 @@ private function buildOptions( * * @method verifyIfOfferExist * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return bool - * * @throws \UnexpectedValueException If the offer doesn't exists */ private function verifyIfOfferExist( @@ -104,15 +89,7 @@ private function verifyIfOfferExist( $data = json_decode(json_encode(new \SimpleXMLElement($response->getBody()->getContents())), true); if ('00' !== $data['C_RETOUR']) { - throw new \UnexpectedValueException( - sprintf( - 'Error code %s: No offer exists for the contract code "%s" and the amount "%s". Result of the request: %s', - $data['C_RETOUR'], - $options['q6'], - $options['p4'], - json_encode($data) - ) - ); + throw new \UnexpectedValueException(sprintf('Error code %s: No offer exists for the contract code "%s" and the amount "%s". Result of the request: %s', $data['C_RETOUR'], $options['q6'], $options['p4'], json_encode($data))); } return true; @@ -147,12 +124,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not GET */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { @@ -187,4 +174,4 @@ public static function getParameterNames(): ?array ] ); } -} \ No newline at end of file +} diff --git a/Gateway/StripePaymentGateway.php b/Gateway/StripePaymentGateway.php index 405267c..3a95870 100644 --- a/Gateway/StripePaymentGateway.php +++ b/Gateway/StripePaymentGateway.php @@ -62,12 +62,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { diff --git a/Gateway/SystemPayPaymentGateway.php b/Gateway/SystemPayPaymentGateway.php index a99f3eb..3cc76ff 100644 --- a/Gateway/SystemPayPaymentGateway.php +++ b/Gateway/SystemPayPaymentGateway.php @@ -37,11 +37,6 @@ public function __construct( * Build gateway options. * * @method buildOptions - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param Transaction $transaction - * - * @return array */ private function buildOptions( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -80,11 +75,6 @@ private function buildOptions( * Build SystemPay HMAC signature accoding to payment gateway coniguration. * * @method buildSignature - * - * @param PaymentGatewayConfigurationInterface $paymentGatewayConfiguration - * @param array $options - * - * @return string */ private function buildSignature( PaymentGatewayConfigurationInterface $paymentGatewayConfiguration, @@ -134,12 +124,22 @@ public function buildHTMLView( ]); } + /** + * {@inheritdoc} + */ + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + return new GatewayResponse(); + } + /** * {@inheritdoc} * * @throws \UnexpectedValueException If the request method is not POST */ - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { @@ -217,10 +217,6 @@ public static function getParameterNames(): ?array * Clean and sort alphabetically options array. * * @method cleanOptions - * - * @param array $options - * - * @return array */ protected function cleanOptions(array $options = []): array { diff --git a/Payment/PaymentContext.php b/Payment/PaymentContext.php index 8595459..ce6004e 100644 --- a/Payment/PaymentContext.php +++ b/Payment/PaymentContext.php @@ -8,8 +8,8 @@ use IDCI\Bundle\PaymentBundle\Model\PaymentGatewayConfigurationInterface; use IDCI\Bundle\PaymentBundle\Model\Transaction; use Psr\Log\LoggerInterface; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class PaymentContext implements PaymentContextInterface { @@ -60,11 +60,34 @@ public function createTransaction(array $parameters): Transaction return $this->transaction; } + public function handleReturnCallback(Request $request): ?Transaction + { + $gatewayResponse = $this + ->paymentGateway + ->getReturnResponse($request, $this->paymentGatewayConfiguration) + ; + + if (null === $gatewayResponse->getTransactionUuid()) { + return null; + } + + $transaction = $this + ->transactionManager + ->retrieveTransactionByUuid($gatewayResponse->getTransactionUuid()) + ; + + if (null !== $gatewayResponse->getStatus()) { + $transaction->setStatus($gatewayResponse->getStatus()); + } + + return $transaction; + } + public function handleGatewayCallback(Request $request): Transaction { $gatewayResponse = $this ->paymentGateway - ->getResponse($request, $this->paymentGatewayConfiguration) + ->getCallbackResponse($request, $this->paymentGatewayConfiguration) ; if (null === $gatewayResponse->getTransactionUuid()) { @@ -92,7 +115,8 @@ public function handleGatewayCallback(Request $request): Transaction $this->logger->info('Gateway response: ', [ 'response' => json_encode($gatewayResponse->toArray()), ]); - } catch (\Exception $e) {} + } catch (\Exception $e) { + } } return $transaction diff --git a/Payment/PaymentContextInterface.php b/Payment/PaymentContextInterface.php index 389f25c..bb8774a 100644 --- a/Payment/PaymentContextInterface.php +++ b/Payment/PaymentContextInterface.php @@ -11,6 +11,8 @@ interface PaymentContextInterface { public function createTransaction(array $parameters): Transaction; + public function handleReturnCallback(Request $request): ?Transaction; + public function handleGatewayCallback(Request $request): ?Transaction; public function hasTransaction(): bool; diff --git a/Resources/docs/create-your-payment-gateway.md b/Resources/docs/create-your-payment-gateway.md index 5f6f993..00dd3d8 100644 --- a/Resources/docs/create-your-payment-gateway.md +++ b/Resources/docs/create-your-payment-gateway.md @@ -3,10 +3,10 @@ How to create your own payment gateway ## Introduction -Q: What's a payment gateway ? +Q: What's a payment gateway ? A: That's what that prepare the form and the management of the transaction for a specific payment method (ex: paypal, stripe, ...) -Q: How does it work ? +Q: How does it work ? A: (schema) ## Learn by example @@ -53,8 +53,28 @@ class ExemplePaymentGateway extends AbstractPaymentGateway ]); } + // If you want to pre-validate the transaction on customer return + public function getReturnResponse( + Request $request, + PaymentGatewayConfigurationInterface $paymentGatewayConfiguration + ): GatewayResponse { + $gatewayResponse = new GatewayResponse(); + + if (null === $request->get('transactionID')) { + return $gatewayResponse; + } + + $gatewayResponse->setTransactionUuid($request->get('transactionID')); + + if ('failed' === $result->getState()) { + return $gatewayResponse->setStatus(PaymentStatus::STATUS_FAILED); + } + + return $gatewayResponse->setStatus(PaymentStatus::STATUS_APPROVED); + } + // Return the bank response in formalized GatewayResponse format to let PaymentContext verify that the transaction is correct - public function getResponse( + public function getCallbackResponse( Request $request, PaymentGatewayConfigurationInterface $paymentGatewayConfiguration ): GatewayResponse { @@ -104,7 +124,7 @@ MyBundle\Gateway\ExemplePaymentGateway: - { name: idci_payment.gateways, alias: exemple } ``` -Warning : The payment gateway ```getResponse()``` method will never be call by the client but by the bank itself in backend controller for security reason. +Warning : The payment gateway ```getCallbackResponse()``` method will never be call by the client but by the bank itself in backend controller for security reason. ## How to create a payment gateway configuration for your own gateway diff --git a/Resources/docs/uml-schema.xmi b/Resources/docs/uml-schema.xmi index 261f93f..96543c8 100644 --- a/Resources/docs/uml-schema.xmi +++ b/Resources/docs/uml-schema.xmi @@ -502,7 +502,7 @@ - + diff --git a/Resources/views/PaymentStep/pending.html.twig b/Resources/views/PaymentStep/pending.html.twig index f14a3b5..0e6f230 100644 --- a/Resources/views/PaymentStep/pending.html.twig +++ b/Resources/views/PaymentStep/pending.html.twig @@ -7,7 +7,7 @@ nextBtn.hidden = true; - var maxAttempt = 40; + var maxAttempt = 25; var endAttempt = function () { if (--maxAttempt > 0) { diff --git a/Step/Event/Action/ManageTransactionStepEventAction.php b/Step/Event/Action/ManageTransactionStepEventAction.php index 8163f00..d8191a4 100644 --- a/Step/Event/Action/ManageTransactionStepEventAction.php +++ b/Step/Event/Action/ManageTransactionStepEventAction.php @@ -206,7 +206,11 @@ private function prepareReturnTransaction(StepEventInterface $event, array $para $transactionId = $event->getStepEventData()['id'] ?? $request->query->get('transaction_id'); - $transaction = $this->transactionManager->retrieveTransactionByUuid($transactionId); + $transaction = $paymentContext->handleReturnCallback($request); + if (null === $transaction) { + $transaction = $this->transactionManager->retrieveTransactionByUuid($transactionId); + } + $paymentContext->setTransaction($transaction); if (PaymentStatus::STATUS_CREATED === $transaction->getStatus()) { diff --git a/Tests/Unit/Gateway/AtosSipsJsonPaymentGatewayTest.php b/Tests/Unit/Gateway/AtosSipsJsonPaymentGatewayTest.php index 00c559e..83b60c5 100644 --- a/Tests/Unit/Gateway/AtosSipsJsonPaymentGatewayTest.php +++ b/Tests/Unit/Gateway/AtosSipsJsonPaymentGatewayTest.php @@ -26,14 +26,14 @@ public function testInvalidMethod() { $request = Request::create('dummy_uri', Request::METHOD_GET); - $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); } public function testRequestNoData() { $request = Request::create('dummy_uri', Request::METHOD_POST); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('The request do not contains "Data"', $gatewayResponse->getMessage()); } @@ -47,7 +47,7 @@ public function testRequestSealCheckFail() ] ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('Seal check failed', $gatewayResponse->getMessage()); } @@ -65,7 +65,7 @@ public function testRequestResponseCodeError() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(AtosSipsStatusCode::getStatusMessage($testedStatusCode), $gatewayResponse->getMessage()); } } @@ -82,7 +82,7 @@ public function testCancelRequestResponseCode() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(PaymentStatus::STATUS_CANCELED, $gatewayResponse->getStatus()); } @@ -98,7 +98,7 @@ public function testUnauthorizedTransactionRequestResponse() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('Transaction unauthorized', $gatewayResponse->getMessage()); } @@ -114,7 +114,7 @@ public function testSuccessRequestResponse() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(PaymentStatus::STATUS_APPROVED, $gatewayResponse->getStatus()); } } diff --git a/Tests/Unit/Gateway/AtosSipsPostPaymentGatewayTest.php b/Tests/Unit/Gateway/AtosSipsPostPaymentGatewayTest.php index 65ab6cf..74cf211 100644 --- a/Tests/Unit/Gateway/AtosSipsPostPaymentGatewayTest.php +++ b/Tests/Unit/Gateway/AtosSipsPostPaymentGatewayTest.php @@ -48,14 +48,14 @@ public function testInvalidMethod() { $request = Request::create('dummy_uri', Request::METHOD_GET); - $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); } public function testRequestNoData() { $request = Request::create('dummy_uri', Request::METHOD_POST); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('The request do not contains "Data"', $gatewayResponse->getMessage()); } @@ -69,7 +69,7 @@ public function testRequestSealCheckFail() ] ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('Seal check failed', $gatewayResponse->getMessage()); } @@ -87,7 +87,7 @@ public function testRequestResponseCodeError() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(AtosSipsStatusCode::getStatusMessage($testedStatusCode), $gatewayResponse->getMessage()); } } @@ -104,7 +104,7 @@ public function testCancelRequestResponseCode() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(PaymentStatus::STATUS_CANCELED, $gatewayResponse->getStatus()); } @@ -120,7 +120,7 @@ public function testUnauthorizedTransactionRequestResponse() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('Transaction unauthorized', $gatewayResponse->getMessage()); } @@ -136,7 +136,7 @@ public function testSuccessRequestResponse() ); $request->request->set('Seal', hash('sha256', $data)); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(PaymentStatus::STATUS_APPROVED, $gatewayResponse->getStatus()); } } diff --git a/Tests/Unit/Gateway/PayPlugPaymentGatewayTest.php b/Tests/Unit/Gateway/PayPlugPaymentGatewayTest.php index 1c983d7..6deba10 100644 --- a/Tests/Unit/Gateway/PayPlugPaymentGatewayTest.php +++ b/Tests/Unit/Gateway/PayPlugPaymentGatewayTest.php @@ -33,17 +33,17 @@ public function testInvalidMethod() { $request = Request::create('dumy_uri', Request::METHOD_GET); - $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); } - public function testGetResponseEmptyPostDataRequest() + public function testGetCallbackResponseEmptyPostDataRequest() { $request = Request::create( 'dummy_uri', Request::METHOD_POST ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('The request do not contains required post data', $gatewayResponse->getMessage()); } @@ -62,11 +62,11 @@ public function testUnauthorizedTransactionResponse() ] ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals('Transaction unauthorized', $gatewayResponse->getMessage()); } - public function testGetResponseApproved() + public function testGetCallbackResponseApproved() { $request = Request::create( 'dummy_uri', @@ -81,7 +81,7 @@ public function testGetResponseApproved() ] ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(PaymentStatus::STATUS_APPROVED, $gatewayResponse->getStatus()); } } diff --git a/Tests/Unit/Gateway/PayboxPaymentGatewayTest.php b/Tests/Unit/Gateway/PayboxPaymentGatewayTest.php index f47dbd4..55ca488 100644 --- a/Tests/Unit/Gateway/PayboxPaymentGatewayTest.php +++ b/Tests/Unit/Gateway/PayboxPaymentGatewayTest.php @@ -54,6 +54,6 @@ public function testInvalidMethod() { $request = Request::create('dummy_uri', Request::METHOD_GET); - $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); } } diff --git a/Tests/Unit/Gateway/PaypalPaymentGatewayTest.php b/Tests/Unit/Gateway/PaypalPaymentGatewayTest.php index 98f9dc3..b692410 100644 --- a/Tests/Unit/Gateway/PaypalPaymentGatewayTest.php +++ b/Tests/Unit/Gateway/PaypalPaymentGatewayTest.php @@ -37,6 +37,6 @@ public function testInvalidMethod() { $request = Request::create('dumy_uri', Request::METHOD_GET); - $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); } } diff --git a/Tests/Unit/Gateway/StripePaymentGatewayTest.php b/Tests/Unit/Gateway/StripePaymentGatewayTest.php index 0a044c1..f6e8fec 100644 --- a/Tests/Unit/Gateway/StripePaymentGatewayTest.php +++ b/Tests/Unit/Gateway/StripePaymentGatewayTest.php @@ -56,7 +56,7 @@ public function testInvalidMethod() { $request = Request::create('dummy_uri', Request::METHOD_GET); - $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); } public function testRequestError() @@ -74,7 +74,7 @@ public function testRequestError() ] ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals($request->get('error')['message'], $gatewayResponse->getMessage()); } @@ -91,7 +91,7 @@ public function testRequestApproved() ] ); - $gatewayResponse = $this->gateway->getResponse($request, $this->paymentGatewayConfiguration); + $gatewayResponse = $this->gateway->getCallbackResponse($request, $this->paymentGatewayConfiguration); $this->assertEquals(PaymentStatus::STATUS_APPROVED, $gatewayResponse->getStatus()); } } diff --git a/Tests/Unit/Payment/PaymentContextTest.php b/Tests/Unit/Payment/PaymentContextTest.php index 5722bca..ed2aa93 100644 --- a/Tests/Unit/Payment/PaymentContextTest.php +++ b/Tests/Unit/Payment/PaymentContextTest.php @@ -55,7 +55,7 @@ public function setUp() $this->paymentGateway = $this->getMockBuilder(AbstractPaymentGateway::class) ->setConstructorArgs([$this->twig]) - ->setMethods(['initialize', 'getResponse', 'buildHTMLView']) + ->setMethods(['initialize', 'getCallbackResponse', 'buildHTMLView']) ->getMock() ; @@ -150,7 +150,7 @@ public function testHandleGatewayCallback( $this->paymentGateway ->expects($this->once()) - ->method('getResponse') + ->method('getCallbackResponse') ->with($this->equalTo($request), $this->equalTo($this->paymentGatewayConfiguration)) ->will($this->returnValue($gatewayResponse)) ; @@ -181,7 +181,7 @@ public function testHandleGatewayCallbackWithDifferentAmount( $this->paymentGateway ->expects($this->once()) - ->method('getResponse') + ->method('getCallbackResponse') ->with($this->equalTo($request), $this->equalTo($this->paymentGatewayConfiguration)) ->will($this->returnValue($gatewayResponse)) ; @@ -214,7 +214,7 @@ public function testHandleGatewayCallbackWithDifferentCurrencyCode( $this->paymentGateway ->expects($this->once()) - ->method('getResponse') + ->method('getCallbackResponse') ->with($this->equalTo($request), $this->equalTo($this->paymentGatewayConfiguration)) ->will($this->returnValue($gatewayResponse)) ; @@ -243,7 +243,7 @@ public function testHandleGatewayCallbackWithNoTransactionUuid( ) { $this->paymentGateway ->expects($this->once()) - ->method('getResponse') + ->method('getCallbackResponse') ->with($this->equalTo($request), $this->equalTo($this->paymentGatewayConfiguration)) ->will($this->returnValue($gatewayResponse)) ;