FlowGateway.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. // Copyright 2019-2022 Hackware SpA <human@hackware.cl>
  3. // This file is part of "Hackware Web Services Payment" and licensed under
  4. // the terms of the GNU Affero General Public License version 3, or (at your
  5. // option) a later version. You should have received a copy of this license
  6. // along with the software. If not, see <https://www.gnu.org/licenses/>.
  7. namespace Hawese\Payment\Gateways;
  8. use Hawese\Payment\Payment;
  9. use Hawese\Payment\Exceptions\UnexpectedResponseException;
  10. use Hawese\Payment\Support\Http as HttpSupport;
  11. use Hawese\Core\User;
  12. use Brick\Money\Money;
  13. use Illuminate\Support\Str;
  14. use Psr\Http\Message\ResponseInterface;
  15. class FlowGateway extends AbstractGateway
  16. {
  17. public function purchase(
  18. array $bodyParams,
  19. string $origin = 'wallet'
  20. ): array {
  21. $bodyParams = $this->purchaseAddDefaultParams($bodyParams, $origin);
  22. $response = $this->request('POST', '/payment/create', $bodyParams);
  23. $responseBody = $this->purchaseProcessResponse($response);
  24. $payment_uuid = $this->purchaseInsertPayment(
  25. $bodyParams,
  26. $responseBody,
  27. $origin
  28. );
  29. $redirectUrl = $responseBody->url . '?token=' . $responseBody->token;
  30. return ['uuid' => $payment_uuid, 'redirect_url' => $redirectUrl];
  31. }
  32. private function purchaseAddDefaultParams(
  33. array $bodyParams,
  34. string $origin
  35. ): array {
  36. $uuid = (string) Str::uuid();
  37. return array_merge($bodyParams, [
  38. 'urlReturn' => HttpSupport::appendQueryParams(
  39. config("payment.origins.$origin.return_url"),
  40. ['uuid' => $uuid]
  41. ),
  42. 'urlConfirmation' => url(route(
  43. 'gateways.notify',
  44. ['gateway' => 'flow']
  45. )),
  46. 'commerceOrder' => $uuid,
  47. ]);
  48. }
  49. /**
  50. * Validate and process $response
  51. * @returns object parsed body
  52. */
  53. private function purchaseProcessResponse(
  54. ResponseInterface &$response
  55. ): object {
  56. if ($response->getStatusCode() == 200) {
  57. $responseBody = HttpSupport::getJsonBody($response);
  58. if (property_exists($responseBody, 'token')) {
  59. return $responseBody;
  60. }
  61. }
  62. throw new UnexpectedResponseException($response);
  63. }
  64. /**
  65. * @returns string Payment primary key value
  66. */
  67. private function purchaseInsertPayment(
  68. array &$bodyParams,
  69. object &$responseBody,
  70. string &$origin
  71. ): string {
  72. return (new Payment([
  73. 'uuid' => $bodyParams['commerceOrder'],
  74. 'user_uid' => User::findByEmailOrCreate($bodyParams['email'])->uid,
  75. 'gateway' => 'flow',
  76. 'currency' => $bodyParams['currency'] ?? 'CLP',
  77. 'amount' => $bodyParams['amount'], // Integers only!!
  78. 'description' => $bodyParams['subject'],
  79. 'detail' => [
  80. 'flowOrder' => $responseBody->flowOrder,
  81. 'paymentMethod' => $bodyParams['paymentMethod'],
  82. ],
  83. 'status' => Payment::STATUS_PENDING,
  84. 'origin' => $origin,
  85. ]))->insert();
  86. }
  87. public function acceptNotification(array $bodyParams)
  88. {
  89. $queryParams = ['token' => $bodyParams['token']];
  90. $response = $this->request(
  91. 'GET',
  92. '/payment/getStatus?' . HttpSupport::buildUriQuery($queryParams)
  93. );
  94. $responseBody = HttpSupport::getJsonBody($response);
  95. $payment = Payment::find($responseBody->commerceOrder);
  96. if (
  97. Money::of($responseBody->amount, $responseBody->currency)
  98. ->isAmountAndCurrencyEqualTo($payment->amountAsMoney)
  99. ) {
  100. if ($payment->status === Payment::STATUS_COMPLETED) {
  101. return response('Already processed', 400);
  102. } else {
  103. // 1 pendiente de pago, 2 pagada, 3 rechazada, 4 anulada
  104. $payment->validateAndUpdateStatus($responseBody->status, [2], [1]);
  105. return response('OK, Flow', 200);
  106. }
  107. }
  108. return response('Incorrect amount', 400);
  109. }
  110. }