paymentgateway/src/Base/Gateways/PaymobPay.php

625 lines
21 KiB
PHP

<?php
namespace Xgenious\Paymentgateway\Base\Gateways;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Xgenious\Paymentgateway\Base\GlobalCurrency;
use Xgenious\Paymentgateway\Base\PaymentGatewayBase;
use Xgenious\Paymentgateway\Base\PaymentGatewayHelpers;
use Xgenious\Paymentgateway\Traits\ConvertUsdSupport;
use Xgenious\Paymentgateway\Traits\CurrencySupport;
use Xgenious\Paymentgateway\Traits\PaymentEnvironment;
class PaymobPay extends PaymentGatewayBase
{
use PaymentEnvironment, CurrencySupport, ConvertUsdSupport;
private $apiKey;
private $hmacSecret;
private $integrationId;
private $gatewayType;
private $iframeId;
private $secretKay;
private $publicKey;
private $walletMobileNumber;
/**
Available Gateway Type
*
"accept-online" //card payment
"accept-kiosk"
"accept-wallet"
"accept-valu"
"accept-installments"
"accept-sympl"
"accept-premium"
"accept-souhoola"
"accept-shahry"
"accept-get_go"
"accept-lucky"
"accept-forsa"
"accept-tabby"
"accept-nowpay"
* */
public function setWalletMobileNumber($walletMobileNumber)
{
$this->walletMobileNumber = $walletMobileNumber;
return $this;
}
public function getWalletMobileNumber()
{
return $this->walletMobileNumber;
}
public function setPublicKey($publicKey)
{
$this->publicKey = $publicKey;
return $this;
}
public function getPublicKey()
{
return $this->publicKey;
}
public function setSecretKey($secretKay)
{
$this->secretKay = $secretKay;
return $this;
}
public function getSecretKey()
{
return $this->secretKay;
}
public function setIframeId($iframeId)
{
$this->iframeId = $iframeId;
return $this;
}
public function getIframeId()
{
return $this->iframeId;
}
public function setGatewayType($gatewayType)
{
$this->gatewayType = $gatewayType;
return $this;
}
public function getGatewayType()
{
return $this->gatewayType;
}
public function setApiKey($apiKey)
{
$this->apiKey = $apiKey;
return $this;
}
public function getApiKey()
{
return $this->apiKey;
}
public function setHmacSecret($hmacSecret)
{
$this->hmacSecret = $hmacSecret;
return $this;
}
public function getHmacSecret()
{
return $this->hmacSecret;
}
public function setIntegrationId($integrationId)
{
$this->integrationId = $integrationId;
return $this;
}
public function getIntegrationId()
{
return $this->integrationId;
}
/*
* charge_amount();
* @required param list
* $amount
*
*
* */
public function charge_amount($amount)
{
if (in_array($this->getCurrency(), $this->supported_currency_list())) {
return $amount * 100;
}
return $this->get_amount_in_usd($amount) * 100;
}
/**
* @required param list
* $args['amount']
* $args['description']
* $args['item_name']
* $args['ipn_url']
* $args['cancel_url']
* $args['payment_track']
* return redirect url for
* */
public function charge_customer($args)
{
$authorize_token = $this->authentication_request();
/* make eCommerce Order */
$order_request = $this->order_registration_request($authorize_token,$args);
/* work on payment key request */
$payment_key_request_token = $this->payment_key_request($authorize_token,$args,($order_request['order_id'] ?? ""));
$payment_url = '';
/**
Available Gateway Type
*
"accept-online" //card payment
"accept-kiosk"
"accept-wallet"
"accept-valu"
"accept-installments"
"accept-sympl"
"accept-premium"
"accept-souhoola"
"accept-shahry"
"accept-get_go"
"accept-lucky"
"accept-forsa"
"accept-tabby"
"accept-nowpay"
* */
/* get payment page url based on the payment gateway type */
if ($this->getGatewayType() === 'accept-online'){
$payment_url = 'https://accept.paymobsolutions.com/api/acceptance/iframes/'.$this->getIframeId().'?payment_token='.$payment_key_request_token;
}elseif ($this->getGatewayType() === 'accept-valu'){
/* iframe id should be fore valU */
$payment_url = 'https://accept.paymobsolutions.com/api/acceptance/iframes/'.$this->getIframeId().'?payment_token='.$payment_key_request_token;
}elseif ($this->getGatewayType() === 'accept-kiosk'){
// api request for kiosk, need to show bill_reference to the user for pay it from koisok
$bill_reference = $this->process_kiosk_payment_request($payment_key_request_token,$authorize_token,$args);
return "your kiosk payment bill reference id:". $bill_reference;
}elseif ($this->getGatewayType() === 'accept-wallet'){
//todo:: call wallet api and redirect them to redirect_url
$redirect_url = $this->process_wallet_payment_request($payment_key_request_token,$authorize_token,$args);
return redirect()->away($redirect_url);
}
return view('paymentgateway::paymob',[
"payment_url" => $payment_url
]);
}
/**
* @required param list
* $args['request']
* $args['cancel_url']
* $args['success_url']
*
* return @void
* */
public function ipn_response($args = [])
{
$request = request();
//todo:: need to check it is is post or get request,
//post request mean == transaction process callback
//get request mean == transaction response callback
//todo:: need to verify hmac
$request_method = strtolower($request->method());
$hmac_type = $request_method === 'get' ? 'TRANSACTION' : 'TRANSACTION';
$hash_value = $this->getHasvalue();
$order_id = request()->get('merchant_order_id');
$callback_type = 'TRANSACTION';
if (strtolower(request()->method()) === 'post') {
$callback_type = request()->type;
}
if(hash_equals($hash_value,$request->hmac)){
if ($request_method === 'post'){
//handle post request
if ($callback_type == 'TRANSACTION') {
if (
$request->success === true &&
$request->is_voided === false &&
$request->is_refunded === false &&
$request->pending === false &&
$request->is_void === false &&
$request->is_refund === false &&
$request->error_occured === false
) {
return $this->verified_data([
'status' => 'processing',
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
} else if (
$request->success === true &&
$request->is_refunded === true &&
$request->is_voided === false &&
$request->pending === false &&
$request->is_void === false &&
$request->is_refund === false
) {
return $this->verified_data([
'status' => 'refunded',
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
} else if (
$request->success === true &&
$request->is_voided === true &&
$request->is_refunded === false &&
$request->pending === false &&
$request->is_void === false &&
$request->is_refund === false
) {
return $this->verified_data([
'status' => 'cancelled',
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
} else if (
$request->success === false &&
$request->is_voided === false &&
$request->is_refunded === false &&
$request->is_void === false &&
$request->is_refund === false
) {
return $this->verified_data([
'status' => 'pending-payment',
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
}
}else if ($callback_type == 'TOKEN'){
//handle if token accept
}
}elseif ($request_method === 'get'){
//handle get request
if (
$request->success === "true" &&
$request->is_voided === "false" &&
$request->is_refunded === "false" &&
$request->pending === "false" &&
$request->is_void === "false" &&
$request->is_refund === "false" &&
$request->error_occured === "false"
) {
return $this->verified_data([
'status' => 'complete',
'transaction_id' => request()->get('id'),
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
}
elseif($request->data_message ==="Approved" ) {
return $this->verified_data([
'status' => 'complete',
'transaction_id' => request()->get('id'),
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
}
}
}
return $this->verified_data([
'status' => 'failed',
'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id),
'order_type' => null
]);
}
/**
* geteway_name();
* return @string
* */
public function gateway_name()
{
return 'paymob';
}
/**
* charge_currency();
* return @string
* */
public function charge_currency()
{
if (in_array($this->getCurrency(), $this->supported_currency_list())) {
return $this->getCurrency();
}
return "EGP";
}
/**
* supported_currency_list();
* it will returl all of supported currency for the payment gateway
* return array
* */
public function supported_currency_list()
{
$supported_currency = ['EGP'];
if ($this->getGatewayType() === "accept-online"){
$supported_currency = ['EGP', 'USD', 'EUR', 'GBP'];
}
return $supported_currency;
}
private function base_api_url() {
return 'https://accept.paymob.com/api/';
}
private function authentication_request() {
$url = $this->base_api_url().'auth/tokens';
//todo:: post request
$response = Http::post($url,[
"api_key" => $this->getApiKey()
]);
if ($response->status() === 201){
$result = $response->object();
$authorise_token = $result->token;
if(!empty($authorise_token)){
return $authorise_token;
}
abort(500,'authentication request token generate failed');
}
abort(500,'authentication_request failed');
}
private function order_registration_request($authorize_token,$args) {
$response = Http::post($this->base_api_url().'ecommerce/orders',[
"auth_token" => $authorize_token,
"delivery_needed" => "false",
"amount_cents" => $this->charge_amount($args['amount']),
"currency" => $this->getCurrency(),
"merchant_order_id" => PaymentGatewayHelpers::wrapped_id($args['order_id']),
"items" => [
[
"name" => $args['title'],
"amount_cents" => $this->charge_amount($args['amount']),
"description" => $args['description'],
"quantity" => "1"
]
]
]);
if($response->status() === 201){
return [
'order_id' => $response->object()?->id,
'token' => $response->object()?->token
];
}
abort(500,'order_registration_request failed');
}
private function payment_key_request($authorize_token, array $args,$order_request_id)
{
$response = Http::post($this->base_api_url().'acceptance/payment_keys',[
"auth_token" => $authorize_token,
"amount_cents" => $this->charge_amount($args['amount']),
"expiration" => 3600,
"order_id" => $order_request_id,
"billing_data" => [
"first_name" => "Clifford",
"last_name" => "Nicolas",
"email" => "claudette09@exa.com",
"phone_number" => "+86(8)9135210487",
"apartment" => "NA",
"floor" => "NA",
"street" => "NA",
"building" => "NA",
"shipping_method" => "NA",
"postal_code" => "NA",
"city" => "NA",
"country" => "NA",
"state" => "NA"
],
"currency" => $this->getCurrency(),
"integration_id" => $this->getIntegrationId(),
"lock_order_when_paid" => "false"
]);
if($response->status() === 201){
return $response->object()?->token;
}
abort(500,'payment_key_request failed');
}
private function process_kiosk_payment_request($payment_key_request_token,$authorize_token,$args)
{
//todo api request
$response = Http::asJson()->post($this->base_api_url().'acceptance/payment_keys',[
"payment_token" => $payment_key_request_token,
"auth_token" => $authorize_token,
"source" => [
"identifier" => "AGGREGATOR",
"subtype" => "AGGREGATOR"
],
'amount_cents' => $this->charge_amount($args['amount']),
'currency' => $this->getCurrency()
]);
if($response->status() === 201){
return $response->object()?->data?->bill_reference;
}
abort(500,'process_kiosk_payment_request bill_reference generate failed');
}
private function process_wallet_payment_request($payment_key_request_token,$authorize_token,$args)
{
//todo api request
$response = Http::asJson()->post($this->base_api_url().'acceptance/payment_keys',[
"payment_token" => $payment_key_request_token,
"auth_token" => $authorize_token,
"source" => [
"identifier" => $this->getWalletMobileNumber(),
"subtype" => "WALLET"
],
'amount_cents' => $this->charge_amount($args['amount']),
'currency' => $this->getCurrency()
]);
if($response->status() === 201){
return $response->object()->redirect_url;
}
abort(500,'process_wallet_payment_request redirect_url generate failed');
}
private function getHmacStringArray()
{
$return_string = request()->all();
if (strtolower(request()->method()) === 'post'){
$return_string = '';
$callback_type = request()->type;
$object = request()->obj;
$return_string = request()->obj;
if ($callback_type === 'TRANSACTION'){
$return_string->order = $object->order?->id;
$return_string->order = $object->order?->id;
$return_string->is_3d_secure = ($object->is_3d_secure === true) ? 'true' : 'false';
$return_string->is_auth = ($object->is_auth === true) ? 'true' : 'false';
$return_string->is_capture = ($object->is_capture === true) ? 'true' : 'false';
$return_string->is_refunded = ($object->is_refunded === true) ? 'true' : 'false';
$return_string->is_standalone_payment = ($object->is_standalone_payment === true) ? 'true' : 'false';
$return_string->is_voided = ($object->is_voided === true) ? 'true' : 'false';
$return_string->success = ($object->success === true) ? 'true' : 'false';
$return_string->error_occured = ($object->error_occured === true) ? 'true' : 'false';
$return_string->has_parent_transaction = ($object->has_parent_transaction === true) ? 'true' : 'false';
$return_string->pending = ($object->pending === true) ? 'true' : 'false';
$return_string->source_data_pan = $object->source_data?->pan;
$return_string->source_data_type = $object->source_data?->type;
$return_string->source_data_sub_type = $object->source_data?->sub_type;
/*
amount_cents
created_at
currency
error_occured
has_parent_transaction
id
integration_id
is_3d_secure
is_auth
is_capture
is_refunded
is_standalone_payment
is_voided
order.id
owner
pending
source_data.pan
source_data.sub_type
source_data.type
success
*/
}elseif ($callback_type === 'DELIVERY_STATUS'){
$return_string->order = $object->order?->id;
}
}elseif(strtolower(request()->method()) === 'get'){
//handle if the callback if get request transaction callback.
$callback_type = 'TRANSACTION';
$return_string = request()->all();
}
return $return_string;
}
private function getHasvalue()
{
$callback_type = 'TRANSACTION';
if (strtolower(request()->method()) === 'post') {
$callback_type = request()->type;
}
$hmac_string = $this->getHmacStringArray();
$str = '';
switch ($callback_type) {
case 'TRANSACTION':
$str =
$hmac_string['amount_cents'] .
$hmac_string['created_at'] .
$hmac_string['currency'] .
$hmac_string['error_occured'] .
$hmac_string['has_parent_transaction'] .
$hmac_string['id'] .
$hmac_string['integration_id'] .
$hmac_string['is_3d_secure'] .
$hmac_string['is_auth'] .
$hmac_string['is_capture'] .
$hmac_string['is_refunded'] .
$hmac_string['is_standalone_payment'] .
$hmac_string['is_voided'] .
$hmac_string['order'] .
$hmac_string['owner'] .
$hmac_string['pending'] .
$hmac_string['source_data_pan'] .
$hmac_string['source_data_sub_type'] .
$hmac_string['source_data_type'] .
$hmac_string['success'];
break;
case 'TOKEN':
$str =
$hmac_string['card_subtype'] .
$hmac_string['created_at'] .
$hmac_string['email'] .
$hmac_string['id'] .
$hmac_string['masked_pan'] .
$hmac_string['merchant_id'] .
$hmac_string['order_id'] .
$hmac_string['token'];
break;
case 'DELIVERY_STATUS':
$str =
$hmac_string['created_at'] .
$hmac_string['extra_description'] .
$hmac_string['gps_lat'] .
$hmac_string['gps_long'] .
$hmac_string['id'] .
$hmac_string['merchant'] .
$hmac_string['order'] .
$hmac_string['status'];
break;
}
$hash = hash_hmac('sha512', $str, $this->getHmacSecret());
return $hash;
}
}