Created
January 19, 2024 11:03
-
-
Save akalongman/d58e9eb292e1e230d0a50c8a589bd7eb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Http\Controllers\Api\V1; | |
use App\Models\Order; | |
use App\Services\OrdersService; | |
use App\Services\PurchaseService; | |
use Illuminate\Http\Request; | |
use Illuminate\Http\Response; | |
use Throwable; | |
use function implode; | |
use function jencode; | |
use function logger; | |
use function preg_replace; | |
use function report; | |
use function response; | |
use const PHP_EOL; | |
class PaymentsController extends ApiV1Controller | |
{ | |
public function check(Request $request, OrdersService $service) | |
{ | |
// Log request | |
logger()->info('Payment check request', ['request' => $request->toArray()]); | |
$orderId = (int) $request->get('o_order_id'); | |
if (empty($orderId)) { | |
return $this->paymentAvailableError('Order ID does not found'); | |
} | |
$order = $service->findOne($orderId); | |
if (empty($order)) { | |
return $this->paymentAvailableError('Order does not found'); | |
} | |
if (! $order->canBeProceedByBank()) { | |
return $this->paymentAvailableError('This order can not be proceed'); | |
} | |
$trxId = $request->get('trx_id'); | |
if (empty($trxId)) { | |
return $this->paymentAvailableError('trx_id is not provided'); | |
} | |
$service->update($order, ['bank_trx_id' => $trxId]); | |
return $this->paymentAvailableSuccess($order); | |
} | |
public function register(Request $request, OrdersService $ordersService, PurchaseService $purchaseService) | |
{ | |
// Log request | |
logger()->info('Payment register request', ['request' => $request->toArray()]); | |
$orderId = (int) $request->get('o_order_id'); | |
if (empty($orderId)) { | |
return $this->paymentRegisterResponse('Order ID does not found', 2); | |
} | |
$order = $ordersService->findOne($orderId); | |
if (empty($order)) { | |
return $this->paymentRegisterResponse('Order does not found', 2); | |
} | |
$trxId = $request->get('trx_id'); | |
if (empty($trxId) || $order->getBankTrxId() !== $trxId) { | |
return $this->paymentRegisterResponse('Invalid trx_id passed', 2); | |
} | |
// Check if order can be proceed | |
if (! $order->canBeProceedByBank()) { | |
return $this->paymentRegisterResponse('This order can not be proceed', 2); | |
} | |
$resultCode = (int) $request->get('result_code'); | |
if (empty($resultCode)) { | |
return $this->paymentRegisterResponse('result_code parameter does not found', 2); | |
} | |
// Payment failed | |
if ($resultCode !== Order::BANK_RESULT_CODE_SUCCESS) { | |
$data = [ | |
'status' => Order::STATUS_BANK_DECLINED, | |
'bank_result_code' => $resultCode, | |
'bank_ext_result_code' => $request->get('ext_result_code'), | |
]; | |
$purchaseService->bankDeclined($order, $data); | |
return $this->paymentRegisterResponse('Failure was registered from bank side', 1); | |
} | |
// Save payment method if requested | |
if ($order->getSavePayMethod()) { | |
$cardRegistered = $request->get('card_registered'); | |
// Save card, if all necessary fields are present | |
if ($cardRegistered === 'Y') { | |
$cardId = $request->get('card_id'); | |
if (empty($cardId)) { | |
return $this->paymentRegisterResponse('card_id does not found in request', 2); | |
} | |
$cardExpiry = $request->get('card_expiry'); | |
if (empty($cardExpiry)) { | |
return $this->paymentRegisterResponse('card_expiry does not found in request', 2); | |
} | |
$cardHolder = $request->get('p_cardholder'); | |
$maskedPan = $request->get('p_maskedPan'); | |
$purchaseService->savePayMethodIfNotExists($order, [ | |
'card_id' => $cardId, | |
'card_number' => $maskedPan, | |
'card_holder' => $cardHolder, | |
'card_expires' => $cardExpiry, | |
'trx_id' => $trxId, | |
]); | |
} else { | |
logger()->info('Card data is missing. Looks like did nod checked "save card" on bank\'s page'); | |
} | |
} | |
// Bank payment successful | |
// Send result to Socar | |
try { | |
$purchaseService->sendPurchaseData($order); | |
} catch (Throwable $e) { | |
$data = [ | |
'status_msg' => jencode($e), | |
'status' => Order::STATUS_BANK_SUCCESS, | |
'bank_result_code' => $resultCode, | |
'bank_ext_result_code' => $request->get('ext_result_code'), | |
]; | |
$purchaseService->sgpDeclined($order, $data); | |
report($e); | |
return $this->paymentRegisterResponse('Gateway error occurred', 2); | |
} | |
$data = [ | |
'status' => Order::STATUS_COMPLETED, | |
'bank_result_code' => $resultCode, | |
'bank_ext_result_code' => $request->get('ext_result_code'), | |
]; | |
$purchaseService->completed($order, $data); | |
return $this->paymentRegisterResponse('OK', 1); | |
} | |
private function paymentAvailableError(string $message, int $code = 2): Response | |
{ | |
$xml = <<<XML | |
<payment-avail-response> | |
<result> | |
<code>$code</code> | |
<desc>$message</desc> | |
</result> | |
</payment-avail-response> | |
XML; | |
// Log response | |
logger()->info('Payment check response', ['response' => $this->cleanXml($xml)]); | |
return response($xml, 200, [ | |
'Content-Type' => 'application/xml', | |
]); | |
} | |
private function paymentAvailableSuccess(Order $order, string $message = 'OK', int $code = 1): Response | |
{ | |
$xmlArray = []; | |
$xmlArray[] = '<payment-avail-response>'; | |
$xmlArray[] = '<result>'; | |
$xmlArray[] = '<code>' . $code . '</code>'; | |
$xmlArray[] = '<desc>' . $message . '</desc>'; | |
$xmlArray[] = '</result>'; | |
// Use saved card | |
if (! empty($order->payMethod)) { | |
$xmlArray[] = '<card>'; | |
$xmlArray[] = '<id>' . $order->payMethod->getCardId() . '</id>'; | |
$xmlArray[] = '</card>'; | |
} | |
$xmlArray[] = '<purchase>'; | |
$xmlArray[] = '<shortDesc>ტრანზაქციის ნომერი ' . $order->getId() . '</shortDesc>'; | |
$xmlArray[] = '<longDesc>P:' . $order->user->getPn() . ',O:' . $order->getId() . '</longDesc>'; | |
$xmlArray[] = '<account-amount>'; | |
$xmlArray[] = '<amount>' . $order->getAmount() . '</amount>'; | |
$xmlArray[] = '<currency>981</currency>'; | |
$xmlArray[] = '<exponent>2</exponent>'; | |
$xmlArray[] = '<id>POS18396</id>'; | |
$xmlArray[] = '</account-amount>'; | |
$xmlArray[] = '</purchase>'; | |
// Save card | |
if ($order->getSavePayMethod() || ! empty($order->payMethod)) { | |
$xmlArray[] = '<order-params>'; | |
$xmlArray[] = '<param>'; | |
$xmlArray[] = '<name>card_on_file</name>'; | |
$xmlArray[] = '<value>CIT</value>'; | |
$xmlArray[] = '</param>'; | |
$xmlArray[] = '</order-params>'; | |
} | |
$xmlArray[] = '</payment-avail-response>'; | |
$xml = implode(PHP_EOL, $xmlArray); | |
// Log response | |
logger()->info('Payment check response', ['response' => $this->cleanXml($xml)]); | |
return response($xml, 200, [ | |
'Content-Type' => 'application/xml', | |
]); | |
} | |
private function paymentRegisterResponse(string $message, int $code): Response | |
{ | |
$xmlArray = []; | |
$xmlArray[] = '<register-payment-response>'; | |
$xmlArray[] = '<result>'; | |
$xmlArray[] = '<code>' . $code . '</code>'; | |
$xmlArray[] = '<desc>' . $message . '</desc>'; | |
$xmlArray[] = '</result>'; | |
$xmlArray[] = '</register-payment-response>'; | |
$xml = implode(PHP_EOL, $xmlArray); | |
// Log response | |
logger()->info('Payment register response', ['response' => $this->cleanXml($xml)]); | |
return response($xml, 200, [ | |
'Content-Type' => 'application/xml', | |
]); | |
} | |
private function cleanXml(string $xml): string | |
{ | |
$xml = preg_replace('#\s+#isu', ' ', $xml); | |
return $xml; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment