Gateway.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Signifyd\Model\SignifydGateway;
  7. use Magento\Sales\Api\OrderRepositoryInterface;
  8. use Magento\Signifyd\Api\CaseRepositoryInterface;
  9. use Magento\Signifyd\Model\SignifydGateway\Request\CreateCaseBuilderInterface;
  10. /**
  11. * Signifyd Gateway.
  12. *
  13. * Encapsulates interaction with Signifyd API.
  14. */
  15. class Gateway
  16. {
  17. /**#@+
  18. * Constants for case available statuses
  19. */
  20. const STATUS_OPEN = 'OPEN';
  21. const STATUS_PROCESSING = 'PROCESSING';
  22. const STATUS_FLAGGED = 'FLAGGED';
  23. const STATUS_DISMISSED = 'DISMISSED';
  24. /**#@-*/
  25. /**#@+
  26. * Constants for guarantee available statuses
  27. * @see https://www.signifyd.com/resources/manual/signifyd-guarantee/signifyd-guarantee/
  28. */
  29. const GUARANTEE_APPROVED = 'APPROVED';
  30. const GUARANTEE_DECLINED = 'DECLINED';
  31. const GUARANTEE_PENDING = 'PENDING';
  32. const GUARANTEE_CANCELED = 'CANCELED';
  33. const GUARANTEE_IN_REVIEW = 'IN_REVIEW';
  34. const GUARANTEE_UNREQUESTED = 'UNREQUESTED';
  35. /**#@-*/
  36. /**#@+
  37. * Constants for case available review dispositions
  38. */
  39. const DISPOSITION_GOOD = 'GOOD';
  40. const DISPOSITION_FRAUDULENT = 'FRAUDULENT';
  41. const DISPOSITION_UNSET = 'UNSET';
  42. /**
  43. * @var CreateCaseBuilderInterface
  44. */
  45. private $createCaseBuilder;
  46. /**
  47. * @var ApiClient
  48. */
  49. private $apiClient;
  50. /**
  51. * @var OrderRepositoryInterface
  52. */
  53. private $orderRepository;
  54. /**
  55. * @var CaseRepositoryInterface
  56. */
  57. private $caseRepository;
  58. /**
  59. * Gateway constructor.
  60. *
  61. * @param CreateCaseBuilderInterface $createCaseBuilder
  62. * @param ApiClient $apiClient
  63. * @param OrderRepositoryInterface $orderRepository
  64. * @param CaseRepositoryInterface $caseRepository
  65. */
  66. public function __construct(
  67. CreateCaseBuilderInterface $createCaseBuilder,
  68. ApiClient $apiClient,
  69. OrderRepositoryInterface $orderRepository,
  70. CaseRepositoryInterface $caseRepository
  71. ) {
  72. $this->createCaseBuilder = $createCaseBuilder;
  73. $this->apiClient = $apiClient;
  74. $this->orderRepository = $orderRepository;
  75. $this->caseRepository = $caseRepository;
  76. }
  77. /**
  78. * Returns id of created case (investigation) on Signifyd service
  79. * @see https://www.signifyd.com/docs/api/#/reference/cases/create-a-case
  80. *
  81. * @param int $orderId
  82. * @return int Signifyd case (investigation) identifier
  83. * @throws GatewayException
  84. */
  85. public function createCase($orderId)
  86. {
  87. $caseParams = $this->createCaseBuilder->build($orderId);
  88. $storeId = $this->getStoreIdFromOrder($orderId);
  89. $caseCreationResult = $this->apiClient->makeApiCall(
  90. '/cases',
  91. 'POST',
  92. $caseParams,
  93. $storeId
  94. );
  95. if (!isset($caseCreationResult['investigationId'])) {
  96. throw new GatewayException('Expected field "investigationId" missed.');
  97. }
  98. return (int)$caseCreationResult['investigationId'];
  99. }
  100. /**
  101. * Returns guaranty decision result
  102. * @see https://www.signifyd.com/docs/api/#/reference/guarantees/submit-a-case-for-guarantee
  103. *
  104. * @param int $signifydCaseId
  105. * @return string
  106. * @throws GatewayException
  107. */
  108. public function submitCaseForGuarantee($signifydCaseId)
  109. {
  110. $storeId = $this->getStoreIdFromCase($signifydCaseId);
  111. $guaranteeCreationResult = $this->apiClient->makeApiCall(
  112. '/guarantees',
  113. 'POST',
  114. [
  115. 'caseId' => $signifydCaseId,
  116. ],
  117. $storeId
  118. );
  119. $disposition = $this->processDispositionResult($guaranteeCreationResult);
  120. return $disposition;
  121. }
  122. /**
  123. * Sends request to cancel guarantee and returns disposition.
  124. *
  125. * @see https://www.signifyd.com/docs/api/#/reference/guarantees/submit-a-case-for-guarantee/cancel-guarantee
  126. * @param int $caseId
  127. * @return string
  128. * @throws GatewayException
  129. */
  130. public function cancelGuarantee($caseId)
  131. {
  132. $storeId = $this->getStoreIdFromCase($caseId);
  133. $result = $this->apiClient->makeApiCall(
  134. '/cases/' . $caseId . '/guarantee',
  135. 'PUT',
  136. [
  137. 'guaranteeDisposition' => self::GUARANTEE_CANCELED
  138. ],
  139. $storeId
  140. );
  141. $disposition = $this->processDispositionResult($result);
  142. if ($disposition !== self::GUARANTEE_CANCELED) {
  143. throw new GatewayException("API returned unexpected disposition: $disposition.");
  144. }
  145. return $disposition;
  146. }
  147. /**
  148. * Processes result from Signifyd API.
  149. * Throws the GatewayException is result does not contain guarantee disposition in response or
  150. * disposition has unknown status.
  151. *
  152. * @param array $result
  153. * @return string
  154. * @throws GatewayException
  155. */
  156. private function processDispositionResult(array $result)
  157. {
  158. if (!isset($result['disposition'])) {
  159. throw new GatewayException('Expected field "disposition" missed.');
  160. }
  161. $disposition = strtoupper($result['disposition']);
  162. if (!in_array($disposition, [
  163. self::GUARANTEE_APPROVED,
  164. self::GUARANTEE_DECLINED,
  165. self::GUARANTEE_PENDING,
  166. self::GUARANTEE_CANCELED,
  167. self::GUARANTEE_IN_REVIEW,
  168. self::GUARANTEE_UNREQUESTED
  169. ])) {
  170. throw new GatewayException(
  171. sprintf('API returns unknown guaranty disposition "%s".', $disposition)
  172. );
  173. }
  174. return $disposition;
  175. }
  176. /**
  177. * Returns store id by case.
  178. *
  179. * @param int $caseId
  180. * @return int|null
  181. */
  182. private function getStoreIdFromCase(int $caseId)
  183. {
  184. $case = $this->caseRepository->getByCaseId($caseId);
  185. $orderId = $case->getOrderId();
  186. return $this->getStoreIdFromOrder($orderId);
  187. }
  188. /**
  189. * Returns store id from order.
  190. *
  191. * @param int $orderId
  192. * @return int|null
  193. */
  194. private function getStoreIdFromOrder(int $orderId)
  195. {
  196. $order = $this->orderRepository->get($orderId);
  197. return $order->getStoreId();
  198. }
  199. }