362 lines
9.5 KiB
PHP
362 lines
9.5 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\OnlinePayment\Repositories;
|
|
|
|
use App\Modules\Makeable;
|
|
use App\Modules\OnlinePayment\Contracts\PaymentProviderContract;
|
|
use App\Modules\OnlinePayment\Models\OnlinePayment;
|
|
use Illuminate\Contracts\View\View;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Http\Client\Response;
|
|
use Illuminate\Support\Facades\Config;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class OnlinePaymentRepository
|
|
{
|
|
use Makeable;
|
|
|
|
/**
|
|
* Pending online payments
|
|
*/
|
|
public const PENDING = 'pending';
|
|
|
|
/**
|
|
* Failed online payments
|
|
*/
|
|
public const FAILED = 'failed';
|
|
|
|
/**
|
|
* Paid online payments
|
|
*/
|
|
public const PAID = 'paid';
|
|
|
|
/**
|
|
* Related model
|
|
*/
|
|
protected ?Model $relatedModel;
|
|
|
|
/**
|
|
* Payment provider
|
|
*/
|
|
protected PaymentProviderContract $provider;
|
|
|
|
/**
|
|
* Response
|
|
*/
|
|
protected Response $response;
|
|
|
|
/**
|
|
* Online payment
|
|
*/
|
|
protected OnlinePayment $onlinePayment;
|
|
|
|
/**
|
|
* API client
|
|
*/
|
|
protected string $apiClient;
|
|
|
|
/**
|
|
* If payment is successful
|
|
*/
|
|
protected bool $successful;
|
|
|
|
/**
|
|
* If payment has failed
|
|
*/
|
|
protected bool $failed;
|
|
|
|
/**
|
|
* Payment order id
|
|
*/
|
|
protected string $orderId;
|
|
|
|
/**
|
|
* Online payment link
|
|
*/
|
|
protected string $paymentLink;
|
|
|
|
public function __construct(?Model $relatedModel = null, string $apiClient = '')
|
|
{
|
|
$this->relatedModel = $relatedModel;
|
|
$this->apiClient = $apiClient;
|
|
}
|
|
|
|
/**
|
|
* Status Values
|
|
*
|
|
* @return array<null|string, string>
|
|
*/
|
|
public static function statusValues(): array
|
|
{
|
|
return [
|
|
null => '-',
|
|
self::PENDING => __('Pending'),
|
|
self::PAID => __('Paid'),
|
|
self::FAILED => __('Cancelled'),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Generate order number for payment
|
|
*/
|
|
public function generateOrderNumber(): string
|
|
{
|
|
return date('dmyHis');
|
|
}
|
|
|
|
/**
|
|
* Payment provder
|
|
*/
|
|
public function setPaymentProvider(PaymentProviderContract $provider): self
|
|
{
|
|
$this->provider = $provider;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Payment provider
|
|
*/
|
|
public function paymentProvider(): PaymentProviderContract
|
|
{
|
|
return $this->provider;
|
|
}
|
|
|
|
/**
|
|
* Online payment
|
|
*/
|
|
public function onlinePayment(): OnlinePayment
|
|
{
|
|
return $this->onlinePayment;
|
|
}
|
|
|
|
/**
|
|
* If payment has been successfull
|
|
*/
|
|
public function successful(): bool
|
|
{
|
|
return $this->successful;
|
|
}
|
|
|
|
/**
|
|
* If payment has been a failure
|
|
*/
|
|
public function failed(): bool
|
|
{
|
|
return $this->failed;
|
|
}
|
|
|
|
/**
|
|
* Set respond results
|
|
*/
|
|
public function setResponseResults(bool $result): void
|
|
{
|
|
$this->successful = $result;
|
|
$this->failed = ! $result;
|
|
}
|
|
|
|
/**
|
|
* Send request via provider
|
|
*/
|
|
public function sendRequest(): self
|
|
{
|
|
$this->response = $this->provider->sendRequest();
|
|
|
|
$this->failed = $this->response->failed();
|
|
$this->successful = $this->response->successful();
|
|
|
|
if ($this->response['errorCode'] != 0) {
|
|
$this->setResponseResults(false);
|
|
}
|
|
|
|
if ($this->successful) {
|
|
$this->orderId = string($this->response['orderId']);
|
|
$this->paymentLink = string($this->response['formUrl']);
|
|
|
|
$this->createHistory();
|
|
} else {
|
|
Config::set('logging.channels.halkbank_payment_error', [
|
|
'driver' => 'single',
|
|
'path' => storage_path('logs/halkbank_payment_error.log'),
|
|
'level' => 'debug',
|
|
]);
|
|
|
|
Log::channel('halkbank_payment_error')
|
|
->error('Payment error', [
|
|
'response' => [
|
|
'title' => 'REGISTER',
|
|
'error' => $this->response->body(),
|
|
'file_line' => __FILE__.':'.__LINE__,
|
|
],
|
|
]);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Payment link
|
|
*/
|
|
public function paymentLink(): string
|
|
{
|
|
return $this->paymentLink;
|
|
}
|
|
|
|
/**
|
|
* Create online payment history
|
|
*/
|
|
public function createHistory(): void
|
|
{
|
|
$data = [
|
|
'amount' => $this->provider->amount(),
|
|
'orderNumber' => $this->provider->orderNumber(),
|
|
'description' => $this->provider->description(),
|
|
'orderId' => $this->orderId,
|
|
'formUrl' => $this->paymentLink,
|
|
'successUrl' => $this->provider->returnUrl(),
|
|
'errorUrl' => $this->provider->returnUrl(),
|
|
'username' => $this->provider->username(),
|
|
'paymentStatus' => self::PENDING,
|
|
'api_client' => $this->apiClient,
|
|
];
|
|
|
|
if ($this->relatedModel) {
|
|
$data['online_paymantable_id'] = $this->relatedModel->id; // @phpstan-ignore-line
|
|
$data['online_paymantable_type'] = $this->relatedModel::class;
|
|
}
|
|
|
|
$this->onlinePayment = OnlinePayment::create($data);
|
|
}
|
|
|
|
/**
|
|
* Check payment
|
|
*
|
|
* @return array<string, string|bool|int>
|
|
*/
|
|
public function checkPayment(string $orderId): array
|
|
{
|
|
// Find payment order from history
|
|
/** @var \App\Modules\OnlinePayment\Models\OnlinePayment */
|
|
$paymentHistory = OnlinePayment::where('orderId', $orderId)->first();
|
|
|
|
// Resolve related resource model dynamically
|
|
/** @var \Illuminate\Database\Eloquent\Model Find related resource */
|
|
$modelClass = $paymentHistory->online_paymantable_type;
|
|
$modelId = $paymentHistory->online_paymantable_id;
|
|
|
|
if (! class_exists($modelClass)) {
|
|
return $this->paymentFailed('(RELATED RESOURCE CLASS NOT FOUND)');
|
|
}
|
|
|
|
$relatedResource = (new $modelClass)->find(id: $modelId);
|
|
|
|
// Check if resource could not be found or does not exist
|
|
if (! $relatedResource) {
|
|
return $this->paymentFailed('(RESOURCE NOT FOUND)');
|
|
}
|
|
|
|
$relatedResource->loadMissing('branch');
|
|
|
|
/** @var \App\Modules\Branch\Models\Branch */
|
|
$bankBranch = $relatedResource->branch;
|
|
|
|
$username = $bankBranch->offsetExists($paymentHistory->api_client.'_username') ? $bankBranch->{$paymentHistory->api_client.'_username'} : '';
|
|
$password = $bankBranch->offsetExists($paymentHistory->api_client.'_password') ? $bankBranch->{$paymentHistory->api_client.'_password'} : '';
|
|
|
|
if ($username === '' || $password === '') {
|
|
return $this->paymentFailed('(USERNAME OR PASSWORD NOT FOUND)');
|
|
}
|
|
|
|
$this->provider->setUsername($username);
|
|
$this->provider->setPassword($password);
|
|
$response = $this->provider->checkPayment($orderId);
|
|
|
|
if ($response['errorCode'] != '0') {
|
|
return $this->paymentFailed($response['errorMessage']);
|
|
}
|
|
|
|
return $response['paymentAmountInfo']['depositedAmount'] > 0 // @phpstan-ignore-line
|
|
? $this->paymentSuccessful($relatedResource, $paymentHistory, $bankBranch->name)
|
|
: $this->paymentFailed(__('Payment has failed'), $paymentHistory, $bankBranch->name);
|
|
}
|
|
|
|
/**
|
|
* Successful payment
|
|
*
|
|
* @return array<string, string|bool|int>
|
|
*/
|
|
public function paymentSuccessful(Model $relatedResource, OnlinePayment $paymentHistory, string $branchName = ''): array
|
|
{
|
|
$relatedResource->update([
|
|
'paid' => true,
|
|
]);
|
|
|
|
$paymentHistory->update([
|
|
'paymentStatus' => OnlinePaymentRepository::PAID,
|
|
]);
|
|
|
|
return $this->paymentCheckResponseTemplate(
|
|
success: true,
|
|
pnr: $paymentHistory->online_paymantable_id,
|
|
branch_name: $branchName,
|
|
price_amount: $paymentHistory->amount.' TMT'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Failed payment
|
|
*
|
|
* @return array<string, string|bool|int>
|
|
*/
|
|
public function paymentFailed(string $title = '', ?OnlinePayment $paymentHistory = null, string $branchName = ''): array
|
|
{
|
|
if ($paymentHistory) {
|
|
$paymentHistory->update([
|
|
'paymentStatus' => OnlinePaymentRepository::FAILED,
|
|
]);
|
|
|
|
return $this->paymentCheckResponseTemplate(
|
|
success: false,
|
|
pnr: $paymentHistory->online_paymantable_id,
|
|
branch_name: $branchName,
|
|
price_amount: $paymentHistory->amount.' TMT'
|
|
);
|
|
}
|
|
|
|
return $this->paymentCheckResponseTemplate(false, $title);
|
|
}
|
|
|
|
/**
|
|
* Check payment response
|
|
*
|
|
* @return array<string, string|bool|int>
|
|
*/
|
|
public function paymentCheckResponseTemplate(
|
|
bool $success,
|
|
string $title = '',
|
|
int|string $pnr = '',
|
|
string $branch_name = '',
|
|
int|string $price_amount = '',
|
|
string $return_url = ''
|
|
): array {
|
|
return [
|
|
'success' => $success,
|
|
'title' => $title !== '' ? $title : ($success ? __('Payment is successful') : __('Payment has failed')),
|
|
'pnr' => $pnr,
|
|
'branch_name' => $branch_name,
|
|
'price_amount' => $price_amount,
|
|
'return_url' => $return_url !== '' ? $return_url : url('/'),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Show payment status
|
|
*
|
|
* @param array<string, string|bool|int> $data
|
|
*/
|
|
public function paymentStatusView(array $data): View
|
|
{
|
|
return view('module.online-payment::payment-status', $data);
|
|
}
|
|
}
|