VaultDetailsHandler.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Braintree\Gateway\Response;
  7. use Braintree\Transaction;
  8. use Magento\Braintree\Gateway\Config\Config;
  9. use Magento\Braintree\Gateway\SubjectReader;
  10. use Magento\Framework\App\ObjectManager;
  11. use Magento\Framework\Serialize\Serializer\Json;
  12. use Magento\Payment\Gateway\Response\HandlerInterface;
  13. use Magento\Payment\Model\InfoInterface;
  14. use Magento\Sales\Api\Data\OrderPaymentExtensionInterface;
  15. use Magento\Sales\Api\Data\OrderPaymentExtensionInterfaceFactory;
  16. use Magento\Vault\Api\Data\PaymentTokenFactoryInterface;
  17. use Magento\Vault\Api\Data\PaymentTokenInterface;
  18. /**
  19. * Vault Details Handler
  20. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  21. */
  22. class VaultDetailsHandler implements HandlerInterface
  23. {
  24. /**
  25. * @var PaymentTokenFactoryInterface
  26. */
  27. protected $paymentTokenFactory;
  28. /**
  29. * @var OrderPaymentExtensionInterfaceFactory
  30. */
  31. protected $paymentExtensionFactory;
  32. /**
  33. * @var SubjectReader
  34. */
  35. protected $subjectReader;
  36. /**
  37. * @var Config
  38. */
  39. protected $config;
  40. /**
  41. * @var Json
  42. */
  43. private $serializer;
  44. /**
  45. * VaultDetailsHandler constructor.
  46. *
  47. * @param PaymentTokenFactoryInterface $paymentTokenFactory
  48. * @param OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory
  49. * @param Config $config
  50. * @param SubjectReader $subjectReader
  51. * @param Json|null $serializer
  52. * @throws \RuntimeException
  53. */
  54. public function __construct(
  55. PaymentTokenFactoryInterface $paymentTokenFactory,
  56. OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory,
  57. Config $config,
  58. SubjectReader $subjectReader,
  59. Json $serializer = null
  60. ) {
  61. $this->paymentTokenFactory = $paymentTokenFactory;
  62. $this->paymentExtensionFactory = $paymentExtensionFactory;
  63. $this->config = $config;
  64. $this->subjectReader = $subjectReader;
  65. $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
  66. }
  67. /**
  68. * @inheritdoc
  69. */
  70. public function handle(array $handlingSubject, array $response)
  71. {
  72. $paymentDO = $this->subjectReader->readPayment($handlingSubject);
  73. $transaction = $this->subjectReader->readTransaction($response);
  74. $payment = $paymentDO->getPayment();
  75. // add vault payment token entity to extension attributes
  76. $paymentToken = $this->getVaultPaymentToken($transaction);
  77. if (null !== $paymentToken) {
  78. $extensionAttributes = $this->getExtensionAttributes($payment);
  79. $extensionAttributes->setVaultPaymentToken($paymentToken);
  80. }
  81. }
  82. /**
  83. * Get vault payment token entity
  84. *
  85. * @param \Braintree\Transaction $transaction
  86. * @return PaymentTokenInterface|null
  87. */
  88. protected function getVaultPaymentToken(Transaction $transaction)
  89. {
  90. // Check token existing in gateway response
  91. $token = $transaction->creditCardDetails->token;
  92. if (empty($token)) {
  93. return null;
  94. }
  95. /** @var PaymentTokenInterface $paymentToken */
  96. $paymentToken = $this->paymentTokenFactory->create(PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD);
  97. $paymentToken->setGatewayToken($token);
  98. $paymentToken->setExpiresAt($this->getExpirationDate($transaction));
  99. $paymentToken->setTokenDetails($this->convertDetailsToJSON([
  100. 'type' => $this->getCreditCardType($transaction->creditCardDetails->cardType),
  101. 'maskedCC' => $transaction->creditCardDetails->last4,
  102. 'expirationDate' => $transaction->creditCardDetails->expirationDate
  103. ]));
  104. return $paymentToken;
  105. }
  106. /**
  107. * @param Transaction $transaction
  108. * @return string
  109. */
  110. private function getExpirationDate(Transaction $transaction)
  111. {
  112. $expDate = new \DateTime(
  113. $transaction->creditCardDetails->expirationYear
  114. . '-'
  115. . $transaction->creditCardDetails->expirationMonth
  116. . '-'
  117. . '01'
  118. . ' '
  119. . '00:00:00',
  120. new \DateTimeZone('UTC')
  121. );
  122. $expDate->add(new \DateInterval('P1M'));
  123. return $expDate->format('Y-m-d 00:00:00');
  124. }
  125. /**
  126. * Convert payment token details to JSON
  127. * @param array $details
  128. * @return string
  129. */
  130. private function convertDetailsToJSON($details)
  131. {
  132. $json = $this->serializer->serialize($details);
  133. return $json ? $json : '{}';
  134. }
  135. /**
  136. * Get type of credit card mapped from Braintree
  137. *
  138. * @param string $type
  139. * @return array
  140. */
  141. private function getCreditCardType($type)
  142. {
  143. $replaced = str_replace(' ', '-', strtolower($type));
  144. $mapper = $this->config->getCcTypesMapper();
  145. return $mapper[$replaced];
  146. }
  147. /**
  148. * Get payment extension attributes
  149. * @param InfoInterface $payment
  150. * @return OrderPaymentExtensionInterface
  151. */
  152. private function getExtensionAttributes(InfoInterface $payment)
  153. {
  154. $extensionAttributes = $payment->getExtensionAttributes();
  155. if (null === $extensionAttributes) {
  156. $extensionAttributes = $this->paymentExtensionFactory->create();
  157. $payment->setExtensionAttributes($extensionAttributes);
  158. }
  159. return $extensionAttributes;
  160. }
  161. }