mirror of https://github.com/4xmen/xshop.git
Payment gateway added
parent
2bb6bf6931
commit
169196317d
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Contracts;
|
||||||
|
|
||||||
|
interface Payment
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Payment Service Provider
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public static function registerService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Payment name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getName(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get payment type must be one of: ONLINE, CHEQUE, CARD, CASH, CASH_ON_DELIVERY
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getType(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is Active To Show user
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isActive(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway Logo
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getLogo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request online payment
|
||||||
|
*
|
||||||
|
* @param int $amount transaction amount
|
||||||
|
* @param string $callbackUrl a url that callback user after transaction
|
||||||
|
* @param array $additionalData additional data to send back
|
||||||
|
*
|
||||||
|
* @return array request data like token and order id
|
||||||
|
* @throws \Throwable
|
||||||
|
*/
|
||||||
|
public function request(int $amount, string $callbackUrl, array $additionalData = []): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect customer to bank payment page
|
||||||
|
*/
|
||||||
|
public function goToBank();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify payment
|
||||||
|
*
|
||||||
|
* @return array successful payment have two keys: reference_id , card_number
|
||||||
|
* @throws \Throwable if payment fail
|
||||||
|
*/
|
||||||
|
public function verify(): array;
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Contracts;
|
||||||
|
|
||||||
|
|
||||||
|
interface PaymentStore
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Store payment request
|
||||||
|
*
|
||||||
|
* @param int $orderId Payment unique order id
|
||||||
|
* @param null $token
|
||||||
|
* @param string $type One of 'ONLINE', 'CHEQUE', 'CASH', 'CARD', 'CASH_ON_DELIVERY'
|
||||||
|
*
|
||||||
|
* @return \App\Models\Payment
|
||||||
|
*/
|
||||||
|
public function storePaymentRequest($orderId,$amount, $token = null, $type = 'ONLINE',$bank=null): \App\Models\Payment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store success payment and update invoice status
|
||||||
|
*
|
||||||
|
* @param int $paymentId Payment unique order id
|
||||||
|
* @param string|int $referenceId Transaction reference id
|
||||||
|
* @param null $cardNumber
|
||||||
|
*
|
||||||
|
* @return \App\Models\Payment
|
||||||
|
*/
|
||||||
|
public function storeSuccessPayment($paymentId, $referenceId, $cardNumber = null): \App\Models\Payment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store failed payment and update invoice status
|
||||||
|
*
|
||||||
|
* @param int $orderId Payment unique order id
|
||||||
|
* @param null $message Fail reason text to store
|
||||||
|
*
|
||||||
|
* @return \App\Models\Payment
|
||||||
|
*/
|
||||||
|
public function storeFailPayment($orderId, $message = null): \App\Models\Payment;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class InvoiceCompleted
|
||||||
|
{
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Invoice
|
||||||
|
*/
|
||||||
|
public $invoice;
|
||||||
|
|
||||||
|
public function __construct(Invoice $invoice)
|
||||||
|
{
|
||||||
|
$this->invoice = $invoice;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class InvoiceFailed
|
||||||
|
{
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Invoice
|
||||||
|
*/
|
||||||
|
public $invoice;
|
||||||
|
/**
|
||||||
|
* @var Payment
|
||||||
|
*/
|
||||||
|
public $payment;
|
||||||
|
|
||||||
|
public function __construct(Invoice $invoice,Payment $payment)
|
||||||
|
{
|
||||||
|
$this->invoice = $invoice;
|
||||||
|
$this->payment = $payment;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class InvoiceSucceed
|
||||||
|
{
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Invoice
|
||||||
|
*/
|
||||||
|
public $invoice;
|
||||||
|
/**
|
||||||
|
* @var Payment
|
||||||
|
*/
|
||||||
|
public $payment;
|
||||||
|
|
||||||
|
public function __construct(Invoice $invoice,Payment $payment)
|
||||||
|
{
|
||||||
|
$this->invoice = $invoice;
|
||||||
|
$this->payment = $payment;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Payment;
|
||||||
|
|
||||||
|
use App\Contracts\Payment;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
|
||||||
|
class GatewayVerifyController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Invoice $invoice
|
||||||
|
* @param Payment $gateway
|
||||||
|
*/
|
||||||
|
public function __invoke($invoice_hash, $gateway)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$invoice = Invoice::whereHash($invoice_hash)->firstOrFail();
|
||||||
|
$payment = null;
|
||||||
|
$message = null;
|
||||||
|
$result = true;
|
||||||
|
$paymentId = self::getPayment($invoice);
|
||||||
|
$response = $gateway->verify();
|
||||||
|
$payment = $invoice->storeSuccessPayment($paymentId, $response['reference_id'], $response['card_number']);
|
||||||
|
session(['card'=>serialize([])]);
|
||||||
|
} catch (\Throwable $exception) {
|
||||||
|
$result = false;
|
||||||
|
$invoice->storeFailPayment($paymentId, $exception->getMessage());
|
||||||
|
$message = $exception->getMessage();
|
||||||
|
\Log::debug("Payment RESPONSE Fail For Gateway {$gateway->getName()} :" . $exception->getMessage() . " On Line {$exception->getLine()} Of File {$exception->getFile()}", ['request' => request()->all(), 'session' => request()->session()->all(), 'user' => request()->user(), 'payment_id' => $paymentId]);
|
||||||
|
\Log::warning($exception->getTraceAsString());
|
||||||
|
return redirect()->route('client.card')->withErrors(__("error in payment.").$message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('client.profile')->with('message' , __("payment success"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Invoice $invoice
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public static function getPayment($invoice)
|
||||||
|
{
|
||||||
|
$paymentId = session('payment_id');
|
||||||
|
if (empty($paymentId)) {
|
||||||
|
$paymentId = $invoice->payments->last()->id;
|
||||||
|
}
|
||||||
|
return $paymentId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Payment;
|
||||||
|
|
||||||
|
use App\Contracts\Payment;
|
||||||
|
|
||||||
|
class Zarinpal implements Payment
|
||||||
|
{
|
||||||
|
public $token;
|
||||||
|
/**
|
||||||
|
* @var \Pishran\Zarinpal\RequestResponse
|
||||||
|
*/
|
||||||
|
public $result;
|
||||||
|
/**
|
||||||
|
* @var \Pishran\Zarinpal\Zarinpal
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
public function __construct(\Pishran\Zarinpal\Zarinpal $gateway)
|
||||||
|
{
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Payment name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getName(): string
|
||||||
|
{
|
||||||
|
return 'zarinpal';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getType(): string
|
||||||
|
{
|
||||||
|
return 'ONLINE';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request online payment
|
||||||
|
*
|
||||||
|
* @param int $amount transaction amount
|
||||||
|
* @param string $callbackUrl return user after transaction to this url
|
||||||
|
* @param array $additionalData additional data to send back
|
||||||
|
*
|
||||||
|
* @return array request data like token,order_id
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function request(int $amount, string $callbackUrl, array $additionalData = []): array
|
||||||
|
{
|
||||||
|
$result = $this->gateway->amount($amount )->request()->callbackUrl($callbackUrl)->description(config('app.name'))->send();
|
||||||
|
|
||||||
|
throw_unless($result->success(), \Exception::class, $result->error()->message());
|
||||||
|
|
||||||
|
\Session::put('zarinpal_amount', $amount);
|
||||||
|
\Session::put('zarinpal_token', $result->authority());
|
||||||
|
\Session::save();
|
||||||
|
|
||||||
|
$this->token = $result->authority();
|
||||||
|
$this->result = $result;
|
||||||
|
return [
|
||||||
|
'order_id' => $result->authority(),
|
||||||
|
'token' => null
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect customer to bank payment page
|
||||||
|
*/
|
||||||
|
public function goToBank()
|
||||||
|
{
|
||||||
|
return redirect()->away($this->result->url());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify payment
|
||||||
|
* @return array successful payment result.The array contain 2 keys: card_number, reference_id. The reference_id is reference number in banking network
|
||||||
|
* @throws \Throwable if payment fail
|
||||||
|
*/
|
||||||
|
public function verify(): array
|
||||||
|
{
|
||||||
|
$result = $this->gateway->amount(session('zarinpal_amount'))
|
||||||
|
->verification()
|
||||||
|
->authority(session('zarinpal_token'))
|
||||||
|
->send();
|
||||||
|
throw_if(
|
||||||
|
!$result->success(),
|
||||||
|
\Exception::class,
|
||||||
|
$result->error()->message()
|
||||||
|
);
|
||||||
|
return [
|
||||||
|
'reference_id' => $result->referenceId(),
|
||||||
|
'card_number' => $result->cardPan(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function registerService()
|
||||||
|
{
|
||||||
|
app()->singleton(
|
||||||
|
sprintf('%s-gateway', self::getName()),
|
||||||
|
function () {
|
||||||
|
$gateway = zarinpal()
|
||||||
|
->merchantId(config('xshop.payment.config.zarinpal.merchant'));
|
||||||
|
return new Zarinpal($gateway);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isActive(): bool
|
||||||
|
{
|
||||||
|
return !empty(config('xshop.payment.config.zarinpal.merchant'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getLogo()
|
||||||
|
{
|
||||||
|
return asset('payment/image/shaparak.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Payment;
|
||||||
|
|
||||||
|
use App\Contracts\Payment;
|
||||||
|
|
||||||
|
class Zibal implements Payment
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Dpsoft\Zibal\Zibal
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
public function __construct(\Dpsoft\Zibal\Zibal $gateway)
|
||||||
|
{
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Payment name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getName(): string
|
||||||
|
{
|
||||||
|
return 'zibal';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getType(): string
|
||||||
|
{
|
||||||
|
return 'ONLINE';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request online payment
|
||||||
|
*
|
||||||
|
* @param int $amount transaction amount
|
||||||
|
* @param string $callbackUrl a url that callback user after transaction
|
||||||
|
* @param array $additionalData additional data to send back
|
||||||
|
* @return array request data like token,order_id
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function request(int $amount, string $callbackUrl, array $additionalData = []): array
|
||||||
|
{
|
||||||
|
$result = $this->gateway->request($callbackUrl, $amount);
|
||||||
|
\Session::put('zibal_amount', $amount);
|
||||||
|
\Session::put('zibal_invoice_id', $result['invoice_id']);
|
||||||
|
\Session::put('zibal_token', $result['token']);
|
||||||
|
return [
|
||||||
|
'order_id' => $result['invoice_id'],
|
||||||
|
'token' => $result['token']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect customer to bank payment page
|
||||||
|
*/
|
||||||
|
public function goToBank()
|
||||||
|
{
|
||||||
|
return redirect()->away($this->gateway->redirectUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify payment
|
||||||
|
* @return array successful payment result.The array contain 3 key: card_number, invoice_id & reference_id. The reference_id is reference number in banking network
|
||||||
|
* @throws \Exception if payment fail
|
||||||
|
*/
|
||||||
|
public function verify(): array
|
||||||
|
{
|
||||||
|
$result = $this->gateway->verify(session('zibal_amount'), session('zibal_token'));
|
||||||
|
return [
|
||||||
|
'reference_id' => $result['transaction_id'],
|
||||||
|
'card_number' => $result['card_number'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function registerService()
|
||||||
|
{
|
||||||
|
app()->singleton(
|
||||||
|
sprintf('%s-gateway',self::getName()),
|
||||||
|
function () {
|
||||||
|
$gateway = new \Dpsoft\Zibal\Zibal(config('xshop.payment.config.zibal.merchant'));
|
||||||
|
|
||||||
|
return new Zibal($gateway);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isActive():bool
|
||||||
|
{
|
||||||
|
return !empty(config('xshop.payment.config.zibal.merchant'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getLogo()
|
||||||
|
{
|
||||||
|
return asset('payment/image/shaparak.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
"payment" => [
|
||||||
|
'active_gateway' => env('PAY_GATEWAY', \App\Payment\Zarinpal::getName()),
|
||||||
|
'gateways' => [
|
||||||
|
\App\Payment\Zibal::class,
|
||||||
|
\App\Payment\Zarinpal::class,
|
||||||
|
],
|
||||||
|
'config' => [
|
||||||
|
'zibal' => [
|
||||||
|
'merchant' => env('ZIBAL_MERCHANT', 'zibal'),
|
||||||
|
],
|
||||||
|
'zarinpal' => [
|
||||||
|
'merchant' => env('ZARINPAL_MERCHANT'),
|
||||||
|
'test' => env('ZARINPAL_TEST')
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
];
|
Loading…
Reference in New Issue