DLocalGoGateway.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. // Copyright 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 DLocalGoGateway 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', '/v1/payments', $bodyParams);
  23. $responseBody = $this->purchaseProcessResponse($response);
  24. $paymentUuid = $this->purchaseInsertPayment(
  25. $bodyParams,
  26. $responseBody,
  27. $origin
  28. );
  29. return [
  30. 'uuid' => $paymentUuid,
  31. 'redirect_url' => $responseBody->redirect_url
  32. ];
  33. }
  34. private function purchaseAddDefaultParams(
  35. array $bodyParams,
  36. string $origin
  37. ): array {
  38. $uuid = (string) Str::uuid();
  39. $returnUrl = HttpSupport::appendQueryParams(
  40. config("payment.origins.$origin.return_url"),
  41. ['uuid' => $uuid]
  42. );
  43. return array_merge($bodyParams, [
  44. 'order_id' => $uuid,
  45. 'payer' => ['email' =>
  46. User::findByEmailOrCreate($bodyParams['payer']['email'])->email],
  47. 'success_url' => $returnUrl,
  48. 'back_url' => $returnUrl,
  49. 'notification_url' => url(route(
  50. 'gateways.notify',
  51. ['gateway' => 'dlocalgo']
  52. )),
  53. ]);
  54. }
  55. /**
  56. * Validate and process $response
  57. * @returns object parsed body
  58. */
  59. private function purchaseProcessResponse(
  60. ResponseInterface $response
  61. ): object {
  62. if ($response->getStatusCode() === 200) {
  63. $responseBody = HttpSupport::getJsonBody($response);
  64. if (property_exists($responseBody, 'id')) {
  65. return $responseBody;
  66. }
  67. }
  68. throw new UnexpectedResponseException($response);
  69. }
  70. /**
  71. * @returns string Payment primary key value
  72. */
  73. private function purchaseInsertPayment(
  74. array $bodyParams,
  75. object $responseBody,
  76. string $origin
  77. ): string {
  78. return (new Payment([
  79. 'uuid' => $bodyParams['order_id'],
  80. 'user_uid' => $bodyParams['payer']['email'],
  81. 'gateway' => 'dlocalgo',
  82. 'currency' => $bodyParams['currency'] ?? 'USD',
  83. 'amount' => $bodyParams['amount'],
  84. 'description' => $bodyParams['description'],
  85. 'detail' => [
  86. 'id' => $responseBody->id,
  87. 'country' => $responseBody->country,
  88. ],
  89. 'status' => Payment::STATUS_PENDING,
  90. 'origin' => $origin,
  91. ]))->insert();
  92. }
  93. public function acceptNotification(array $bodyParams)
  94. {
  95. $response = $this->request(
  96. 'GET',
  97. '/v1/payments/' . $bodyParams['payment_id']
  98. );
  99. $responseBody = HttpSupport::getJsonBody($response);
  100. $payment = Payment::find($responseBody->order_id);
  101. if (
  102. Money::of($responseBody->amount, $responseBody->currency)
  103. ->isAmountAndCurrencyEqualTo($payment->amountAsMoney)
  104. ) {
  105. if ($payment->status === Payment::STATUS_COMPLETED) {
  106. return response('Already processed', 400);
  107. } else {
  108. // REJECTED CANCELLED or EXPIRED set Payment::STATUS_ABORTED.
  109. $payment->validateAndUpdateStatus(
  110. $responseBody->status,
  111. ['PAID'],
  112. ['PENDING']
  113. );
  114. return response('All right DLocalGo!', 200);
  115. }
  116. }
  117. return response('Incorrect amount', 400);
  118. }
  119. }