KhipuGateway.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. // Copyright 2019 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 Illuminate\Support\{Arr, Str};
  12. use Psr\Http\Message\ResponseInterface;
  13. class KhipuGateway extends AbstractGateway
  14. {
  15. public function purchase(array $bodyParams): array
  16. {
  17. // payment_method is processed on this side
  18. $payment_method = Arr::pull($bodyParams, 'payment_method');
  19. $bodyParams = $this->purchaseAddDefaultParams($bodyParams);
  20. $response = $this->request('POST', '/payments', $bodyParams);
  21. $responseBody = $this->purchaseProcessResponse($response);
  22. $this->purchaseInsertPayment(
  23. $bodyParams,
  24. $responseBody,
  25. $payment_method
  26. );
  27. return $this->purchaseReturnResponse($responseBody, $payment_method);
  28. }
  29. private function purchaseAddDefaultParams(array $bodyParams): array
  30. {
  31. $uuid = (string) Str::uuid();
  32. $returnUrl = HttpSupport::appendQueryParams(
  33. config('payment.return_url'),
  34. ['uuid' => $uuid]
  35. );
  36. return array_merge($bodyParams, [
  37. 'transaction_id' => $uuid,
  38. 'currency' => 'CLP',
  39. 'return_url' => $returnUrl,
  40. 'cancel_url' => $returnUrl,
  41. 'notify_url' => url(route(
  42. 'gateways.notify',
  43. ['gateway' => 'khipu'],
  44. )),
  45. ]);
  46. }
  47. /**
  48. * Validate and process $response
  49. * @returns object parsed body
  50. */
  51. private function purchaseProcessResponse(
  52. ResponseInterface &$response
  53. ): object {
  54. if ($response->getStatusCode() == 201) {
  55. $responseBody = HttpSupport::getJsonBody($response);
  56. if (property_exists($responseBody, 'payment_id')) {
  57. return $responseBody;
  58. }
  59. }
  60. throw new UnexpectedResponseException($response);
  61. }
  62. /**
  63. * @returns string Payment primary key value
  64. */
  65. private function purchaseInsertPayment(
  66. array &$bodyParams,
  67. object &$responseBody,
  68. string &$payment_method
  69. ): string {
  70. return (new Payment([
  71. 'uuid' => $bodyParams['transaction_id'],
  72. 'user_uid' => $bodyParams['payer_email'],
  73. 'gateway' => 'khipu',
  74. 'currency' => $bodyParams['currency'],
  75. 'amount' => $bodyParams['amount'], // Integers only!!
  76. 'description' => $bodyParams['subject'],
  77. 'detail' => json_encode([
  78. 'payment_id' => $responseBody->payment_id,
  79. 'payment_method' => $payment_method,
  80. ]),
  81. 'status' => Payment::STATUS_PENDING,
  82. ]))->insert();
  83. }
  84. private function purchaseReturnResponse(
  85. object &$responseBody,
  86. string &$payment_method
  87. ): array {
  88. switch ($payment_method) {
  89. case 'transfer':
  90. $redirectTo = 'transfer_url';
  91. break;
  92. case 'simplified_transfer':
  93. $redirectTo = 'simplified_transfer_url';
  94. break;
  95. default:
  96. $redirectTo = 'payment_url';
  97. }
  98. return ['redirect_url' => $responseBody->{$redirectTo}];
  99. }
  100. public function acceptNotification(array $bodyParams)
  101. {
  102. $response = $this->request(
  103. 'GET',
  104. '/payments?' . HttpSupport::buildUriQuery([
  105. 'notification_token' => $bodyParams['notification_token'],
  106. ])
  107. );
  108. $responseBody = HttpSupport::getJsonBody($response);
  109. $payment = Payment::find($responseBody->transaction_id);
  110. if ($payment->status === Payment::STATUS_COMPLETED) {
  111. return response('Already processed', 400);
  112. } else {
  113. $payment->validateAndUpdateStatus(
  114. $responseBody->status_detail,
  115. ['normal', 'marked-paid-by-receiver'],
  116. ['pending'],
  117. $responseBody->status === 'done'
  118. );
  119. if ($payment->status === Payment::STATUS_COMPLETED) {
  120. return response('Well done Khipu!', 200);
  121. }
  122. }
  123. }
  124. }