JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbrlaravel_paytabs/composer.json000064400000001257150364336770012462 0ustar00{ "name": "paytabscom/laravel_paytabs", "version": "1.4.1", "type": "composer-package", "description": "Official laravel package to implement PayTabs integration with laravel apps", "authors": [ { "name": "Walaa Elsaeed", "email": "w.elsaeed@paytabs.com" } ], "homepage": "https://site.paytabs.com/en/", "minimum-stability": "dev", "keywords": [ "Laravel", "Paytabs", "Payments", "E-comerce" ], "license": "MIT", "require": { "php": "^7.0|^8.0" }, "autoload": { "psr-4": { "Paytabscom\\Laravel_paytabs\\": "src/" } } } laravel_paytabs/src/paypage.php000064400000016307150364336770012670 0ustar00paytabsinit = new paytabs_core(); $this->paytabs_core = new PaytabsRequestHolder(); $this->paytabs_core_token = new PaytabsTokenHolder(); $this->paytabs_api = PaytabsApi::getInstance(config('paytabs.region'), config('paytabs.profile_id'), config('paytabs.server_key')); $this->follow_transaction = new PaytabsFollowupHolder(); $this->laravel_version = app()::VERSION; $this->package_version = '1.4.0'; } public function sendPaymentCode($code) { $this->paytabs_core->set01PaymentCode($code); return $this; } public function sendTransaction($transaction) { $this->paytabs_core->set02Transaction($transaction); return $this; } public function sendCart($cart_id, $amount, $cart_description) { $this->paytabs_core->set03Cart($cart_id, config('paytabs.currency'), $amount, $cart_description); return $this; } public function sendCustomerDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip) { $this->paytabs_core->set04CustomerDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip); return $this; } public function sendShippingDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip) { $this->paytabs_core->set05ShippingDetails(false, $name, $email, $phone, $address, $city, $state, $country, $zip, $ip); return $this; } public function shipping_same_billing() { $this->paytabs_core->set05ShippingDetails(true); return $this; } public function sendHideShipping($on = false) { $this->paytabs_core->set06HideShipping($on); return $this; } public function sendURLs($return_url, $callback_url) { $this->paytabs_core->set07URLs($return_url, $callback_url); return $this; } public function sendLanguage($language) { $this->paytabs_core->set08Lang($language); return $this; } public function sendFramed($on = false) { $this->paytabs_core->set09Framed($on); return $this; } public function sendTokinse($on = false) { $this->paytabs_core->set10Tokenise($on); return $this; } public function sendToken($token, $tran_ref) { $this->paytabs_core_token->set20Token($token, $tran_ref); return $this; } public function sendUserDefined(array $user_defined = []) { $this->paytabs_core->set100userDefined($user_defined); return $this; } public function create_pay_page() { $this->paytabs_core->set99PluginInfo('Laravel',8,'1.4.0'); $pp_params = $this->paytabs_core->pt_build(); $response = $this->paytabs_api->create_pay_page($pp_params); if ($response->success) { $redirect_url = $response->redirect_url; if (isset($pp_params['framed']) && $pp_params['framed'] == true) { return $redirect_url; } return Redirect::to($redirect_url); } else { Log::channel('PayTabs')->info(json_encode($response)); print_r(json_encode($response)); } } public function refund($tran_ref,$order_id,$amount,$refund_reason) { $this->follow_transaction->set02Transaction(PaytabsEnum::TRAN_TYPE_REFUND) ->set03Cart($order_id, config('paytabs.currency'), $amount, $refund_reason) ->set30TransactionInfo($tran_ref) ->set99PluginInfo('Laravel', $this->laravel_version, $this->package_version); $refund_params = $this->follow_transaction->pt_build(); $result = $this->paytabs_api->request_followup($refund_params); $success = $result->success; $message = $result->message; $pending_success = $result->pending_success; if ($success) { $payment = $this->paytabs_api->verify_payment($tran_ref); if ((float)$amount < (float)$payment->cart_amount) { $status = 'partially_refunded'; } else { $status = 'refunded'; } return response()->json(['status' => $status], 200); } else if ($pending_success) { Log::channel('PayTabs')->info(json_encode($result)); print_r('some thing went wrong with integration' . $message); } } public function capture($tran_ref,$order_id,$amount,$capture_description) { $this->follow_transaction->set02Transaction(PaytabsEnum::TRAN_TYPE_CAPTURE) ->set03Cart($order_id, config('paytabs.currency'), $amount, $capture_description) ->set30TransactionInfo($tran_ref) ->set99PluginInfo('Laravel', $this->laravel_version, $this->package_version); $capture_params = $this->follow_transaction->pt_build(); $result = $this->paytabs_api->request_followup($capture_params); $success = $result->success; $message = $result->message; $pending_success = $result->pending_success; if ($success) { $payment = $this->paytabs_api->verify_payment($tran_ref); if ((float)$amount < (float)$payment->cart_amount) { $status = 'partially_captured'; } else { $status = 'captured'; } return response()->json(['status' => $status], 200); } else if ($pending_success) { Log::channel('PayTabs')->info(json_encode($result)); print_r('some thing went wrong with integration' . $message); } } public function void($tran_ref,$order_id,$amount,$void_description) { $this->follow_transaction->set02Transaction(PaytabsEnum::TRAN_TYPE_VOID) ->set03Cart($order_id, config('paytabs.currency'), $amount, $void_description) ->set30TransactionInfo($tran_ref) ->set99PluginInfo('Laravel', $this->laravel_version, $this->package_version); $void_params = $this->follow_transaction->pt_build(); $result = $this->paytabs_api->request_followup($void_params); $success = $result->success; $message = $result->message; $pending_success = $result->pending_success; if ($success) { $payment = $this->paytabs_api->verify_payment($tran_ref); if ((float)$amount < (float)$payment->cart_amount) { $status = 'partially_voided'; } else { $status = 'voided'; } return response()->json(['status' => $status], 200); } else if ($pending_success) { Log::channel('PayTabs')->info(json_encode($result)); print_r('some thing went wrong with integration' . $message); } } public function queryTransaction($tran_ref) { $transaction = $this->paytabs_api->verify_payment($tran_ref); return $transaction; } } laravel_paytabs/src/Controllers/PaytabsLaravelListenerApi.php000064400000002020150364336770020605 0ustar00updateCartByIPN($ipnRequest); } $response= 'valid IPN request. Cart updated'; return response($response, 200) ->header('Content-Type', 'text/plain'); }catch(\Exception $e){ return response($e, 400) ->header('Content-Type', 'text/plain'); } } }laravel_paytabs/src/config/config.php000064400000003301150364336770013742 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ /* |-------------------------------------------------------------------------- | Merchant profile id |-------------------------------------------------------------------------- | | Your merchant profile id , you can find the profile id on your PayTabs Merchant’s Dashboard- profile. | */ 'profile_id' => env('paytabs_profile_id', null), /* |-------------------------------------------------------------------------- | Server Key |-------------------------------------------------------------------------- | | You can find the Server key on your PayTabs Merchant’s Dashboard - Developers - Key management. | */ 'server_key' => env('paytabs_server_key', null), /* |-------------------------------------------------------------------------- | Currency |-------------------------------------------------------------------------- | | The currency you registered in with PayTabs account you must pass value from this array ['AED','EGP','SAR','OMR','JOD','US'] | */ 'currency' => env('paytabs_currency', null), /* |-------------------------------------------------------------------------- | Region |-------------------------------------------------------------------------- | | The region you registered in with PayTabs you must pass value from this array ['ARE','EGY','SAU','OMN','JOR','GLOBAL'] | */ 'region' => env('paytabs_region', null), ]; laravel_paytabs/src/Services/IpnRequest.php000064400000005635150364336770015126 0ustar00createIpnRequest($httpRequest); } /** * create an object by extracting params received from: callback request or IPN Default Web request from the payment gateway after payment is processed */ private function createIpnRequest($httpRequest){ //verify that it is a valid callback request\IPN Default Web request if($this->isValidIPNRequest($httpRequest)){ //update the cart payment status $content= $httpRequest->getContent(); $this->request= json_decode($content, false, 3); $this->clientKey= $httpRequest->header('client-key'); }else{ throw new BadRequestException('invalid callback\IPN request'); } } /** * process of validating an IPN basic web request is the same as process of validating a IPN default web request */ public static function isValidIPNBasicRequest($httpRequest){ $this->isValidIPNRequest($httpRequest); } /** * verify that it is a valid callback request or IPN Default Web request */ private function isValidIPNRequest($httpRequest){ $signature= $httpRequest->header('signature'); $content= $httpRequest->getContent(); //get the request raw content new \Paytabscom\Laravel_paytabs\paytabs_core(); //this is a hack just to be able to use `PaytabsApi` class from paytabs_core.php !!! $paytabs_api= \Paytabscom\Laravel_paytabs\PaytabsApi::getInstance(config('paytabs.region'), config('paytabs.profile_id'), config('paytabs.server_key')); if($paytabs_api->is_valid_ipn($content, $signature)){ return true; }else{ return false; } } /** * get all the IPN request info */ public function getIpnRequestDetails(){ return $this->request; } /** * return client-key header parameter */ public function getIpnRequestClientKey(){ return $this->clientKey; } public function getCartId() { return $this->request->cart_id; } public function getStatus() { return $this->request->payment_result->response_status; } public function getCode() { return $this->request->payment_result->response_code; } public function getMessage() { return $this->request->payment_result->response_message; } public function getTranRef() { return $this->request->tran_ref; } } /** * for wrong request exceptions */ class BadRequestException extends \Exception{ protected $message; public function __construct($message) { $this->message= $message; } public function __toString(): string { return $this->message; } } laravel_paytabs/src/paytabs_core.php000064400000055012150364336770013711 0ustar00 $value) { if ($value['name'] === $code) { $row = $value; break; } } if (!$row) { return false; } $list = $row['currencies']; if ($list == null) { return true; } $currencyCode = strtoupper($currencyCode); return in_array($currencyCode, $list); } static function isPayTabsPayment($code) { foreach (PaytabsApi::PAYMENT_TYPES as $key => $value) { if ($value['name'] === $code) { return true; } } return false; } /** * @return the first non-empty var from the vars list * @return null if all params are empty */ public static function getNonEmpty(...$vars) { foreach ($vars as $var) { if (!empty($var)) return $var; } return null; } /** * convert non-english digits to English * used for fileds that accepts only English digits like: "postal_code" */ public static function convertAr2En($string) { $nonEnglish = [ // Arabic [ '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩' ], // Persian [ '۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹' ] ]; $num = range(0, 9); $englishNumbersOnly = $string; foreach ($nonEnglish as $oldNum) { $englishNumbersOnly = str_replace($oldNum, $num, $englishNumbersOnly); } return $englishNumbersOnly; } /** * check Strings that require to be a valid Word, not [. (dot) or digits ...] * if the parameter is not a valid "Word", convert it to "NA" */ public static function pt_fillIfEmpty(&$string) { if (empty(preg_replace('/[\W]/', '', $string))) { $string .= 'NA'; } } static function pt_fillIP(&$string) { $string = $_SERVER['REMOTE_ADDR']; } /** * paytabs_error_log should be defined, * Main functionality: use the platform logger to log the error messages * If not found: create a new log file and log the messages */ public static function log($msg, $severity = 1) { try { paytabs_error_log($msg, $severity); } catch (\Throwable $th) { try { $_prefix = date('c') . ' PayTabs: '; $_msg = ($_prefix . $msg . PHP_EOL); file_put_contents('debug_paytabs.log', $_msg, FILE_APPEND); } catch (\Throwable $th) { // var_export($th); } } } static function getTokenInfo($return_values) { $fields = [ 'pt_token', 'pt_customer_email', 'pt_customer_password' ]; $tokenInfo = []; foreach ($fields as $field) { if (!isset($return_values[$field])) return false; $tokenInfo[$field] = $return_values[$field]; } return $tokenInfo; } } /** * @abstract class: Enum for static values of PayTabs requests */ abstract class PaytabsEnum { const TRAN_TYPE_AUTH = 'auth'; const TRAN_TYPE_CAPTURE = 'capture'; const TRAN_TYPE_SALE = 'sale'; const TRAN_TYPE_VOID = 'void'; const TRAN_TYPE_REFUND = 'refund'; // const TRAN_CLASS_ECOM = 'ecom'; const TRAN_CLASS_MOTO = 'moto'; const TRAN_CLASS_RECURRING = 'recurring'; // static function TranIsAuth($tran_type) { return strcasecmp($tran_type, PaytabsEnum::TRAN_TYPE_AUTH) == 0; } static function TranIsSale($tran_type) { return strcasecmp($tran_type, PaytabsEnum::TRAN_TYPE_SALE) == 0; } } /** * Holder class: Holds & Generates the parameters array that pass to PayTabs' API */ class PaytabsHolder { /** * tran_type * tran_class */ private $transaction; /** * cart_id * cart_currency * cart_amount * cart_descriptions */ private $cart; /** * cart_name * cart_version * plugin_version */ private $plugin_info; // /** * @return array */ public function pt_build() { $all = array_merge( $this->transaction, $this->cart, $this->plugin_info ); return $all; } protected function pt_merges(&$all, ...$arrays) { foreach ($arrays as $array) { if ($array) { $all = array_merge($all, $array); } } } // public function set02Transaction($tran_type, $tran_class = PaytabsEnum::TRAN_CLASS_ECOM) { $this->transaction = [ 'tran_type' => $tran_type, 'tran_class' => $tran_class, ]; return $this; } public function set03Cart($cart_id, $currency, $amount, $cart_description) { $this->cart = [ 'cart_id' => "$cart_id", 'cart_currency' => "$currency", 'cart_amount' => (float)$amount, 'cart_description' => $cart_description, ]; return $this; } public function set99PluginInfo($platform_name, $platform_version, $plugin_version) { $this->plugin_info = [ 'plugin_info' => [ 'cart_name' => $platform_name, 'cart_version' => "{$platform_version}", 'plugin_version' => "{$plugin_version}", ] ]; return $this; } } /** * Holder class, Inherit class PaytabsHolder * Holds & Generates the parameters array that pass to PayTabs' API */ class PaytabsRequestHolder extends PaytabsHolder { /** * payment_type */ private $payment_code; /** * name * email * phone * street1 * city * state * country * zip * ip */ private $customer_details; /** * name * email * phone * street1 * city * state * country * zip * ip */ private $shipping_details; /** * hide_shipping */ private $hide_shipping; /** * pan * expiry_month * expiry_year * cvv */ private $card_details; /** * return * callback */ private $urls; /** * paypage_lang */ private $lang; /** * framed */ private $framed; /** * tokenise * show_save_card */ private $tokenise; /** * custom values passed from the merchant */ private $user_defined; // /** * @return array */ public function pt_build() { $all = parent::pt_build(); $this->pt_merges( $all, $this->payment_code, $this->urls, $this->customer_details, $this->shipping_details, $this->hide_shipping, $this->lang, $this->framed, $this->tokenise, $this->user_defined ); return $all; } private function setCustomerDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip) { // PaytabsHelper::pt_fillIfEmpty($name); // $this->_fill($address, 'NA'); // PaytabsHelper::pt_fillIfEmpty($city); // $this->_fill($state, $city, 'NA'); if ($zip) { $zip = PaytabsHelper::convertAr2En($zip); } if (!$ip) { PaytabsHelper::pt_fillIP($ip); } // $info = [ 'name' => $name, 'email' => $email, 'phone' => $phone, 'street1' => $address, 'city' => $city, 'state' => $state, 'country' => $country, 'zip' => $zip, 'ip' => $ip ]; return $info; } // public function set01PaymentCode($code) { $this->payment_code = ['payment_methods' => [$code]]; return $this; } public function set04CustomerDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip) { $infos = $this->setCustomerDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip); // $this->customer_details = [ 'customer_details' => $infos ]; return $this; } public function set05ShippingDetails($same_as_billing, $name = null, $email = null, $phone = null, $address = null, $city = null, $state = null, $country = null, $zip = null, $ip = null) { $infos = $same_as_billing ? $this->customer_details['customer_details'] : $this->setCustomerDetails($name, $email, $phone, $address, $city, $state, $country, $zip, $ip); // $this->shipping_details = [ 'shipping_details' => $infos ]; return $this; } public function set06HideShipping($on = false) { $this->hide_shipping = [ 'hide_shipping' => $on, ]; return $this; } public function set07URLs($return_url, $callback_url) { $this->urls = [ 'return' => $return_url, 'callback' => $callback_url, ]; return $this; } public function set08Lang($lang_code) { $this->lang = [ 'paypage_lang' => $lang_code ]; return $this; } /** * @param string $redirect_target "parent" or "top" or "iframe" */ public function set09Framed($on = false, $redirect_target = 'iframe') { $this->framed = [ 'framed' => $on, 'framed_return_parent' => $redirect_target == 'parent', 'framed_return_top' => $redirect_target == 'top' ]; return $this; } /** * @param int $token_format integer between 2 and 6, Set the Token format * @param bool $optional Display the save card option on the payment page */ public function set10Tokenise($on = false, $token_format = 2, $optional = false) { if ($on) { $this->tokenise = [ 'tokenise' => $token_format, 'show_save_card' => $optional ]; } return $this; } public function set100userDefined($user_defined = []) { $this->user_defined = [ 'user_defined' => $user_defined ]; return $this; } } /** * Holder class, Inherit class PaytabsHolder * Holds & Generates the parameters array for the Tokenised payments */ class PaytabsTokenHolder extends PaytabsHolder { /** * token * tran_ref */ private $token_info; public function set20Token($token, $tran_ref) { $this->token_info = [ 'token' => $token, 'tran_ref' => $tran_ref ]; return $this; } public function pt_build() { $all = parent::pt_build(); $all = array_merge($all, $this->token_info); return $all; } } /** * Holder class, Inherit class PaytabsHolder * Holder & Generates the parameters array for the Followup requests * Followup requests: * - Capture (follows Auth) * - Void (follows Auth) * - Refund (follows Capture or Sale) */ class PaytabsFollowupHolder extends PaytabsHolder { /** * transaction_id */ private $transaction_id; // /** * @return array */ public function pt_build() { $all = parent::pt_build(); $all = array_merge($all, $this->transaction_id); return $all; } // public function set30TransactionInfo($transaction_id) { $this->transaction_id = [ 'tran_ref' => $transaction_id, ]; return $this; } } /** * API class which contacts PayTabs server's API */ class PaytabsApi { const PAYMENT_TYPES = [ '0' => ['name' => 'all', 'title' => 'PayTabs - All', 'currencies' => null], '1' => ['name' => 'stcpay', 'title' => 'PayTabs - StcPay', 'currencies' => ['SAR']], '2' => ['name' => 'stcpayqr', 'title' => 'PayTabs - StcPay(QR)', 'currencies' => ['SAR']], '3' => ['name' => 'applepay', 'title' => 'PayTabs - ApplePay', 'currencies' => ['AED', 'SAR']], '4' => ['name' => 'omannet', 'title' => 'PayTabs - OmanNet', 'currencies' => ['OMR']], '5' => ['name' => 'mada', 'title' => 'PayTabs - Mada', 'currencies' => ['SAR']], '6' => ['name' => 'creditcard', 'title' => 'PayTabs - CreditCard', 'currencies' => null], '7' => ['name' => 'sadad', 'title' => 'PayTabs - Sadad', 'currencies' => ['SAR']], '8' => ['name' => 'atfawry', 'title' => 'PayTabs - @Fawry', 'currencies' => ['EGP']], '9' => ['name' => 'knet', 'title' => 'PayTabs - KnPay', 'currencies' => ['KWD']], '10' => ['name' => 'amex', 'title' => 'PayTabs - Amex', 'currencies' => ['AED', 'SAR']], '11' => ['name' => 'valu', 'title' => 'PayTabs - valU', 'currencies' => ['EGP']], ]; const BASE_URLS = [ 'ARE' => [ 'title' => 'United Arab Emirates', 'endpoint' => 'https://secure.paytabs.com/' ], 'SAU' => [ 'title' => 'Saudi Arabia', 'endpoint' => 'https://secure.paytabs.sa/' ], 'OMN' => [ 'title' => 'Oman', 'endpoint' => 'https://secure-oman.paytabs.com/' ], 'JOR' => [ 'title' => 'Jordan', 'endpoint' => 'https://secure-jordan.paytabs.com/' ], 'EGY' => [ 'title' => 'Egypt', 'endpoint' => 'https://secure-egypt.paytabs.com/' ], 'GLOBAL' => [ 'title' => 'Global', 'endpoint' => 'https://secure-global.paytabs.com/' ], // 'DEMO' => [ // 'title' => 'Demo', // 'endpoint' => 'https://secure-demo.paytabs.com/' // ], ]; // const BASE_URL = 'https://secure.paytabs.com/'; const URL_REQUEST = 'payment/request'; const URL_QUERY = 'payment/query'; const URL_TOKEN_QUERY = 'payment/token'; const URL_TOKEN_DELETE = 'payment/token/delete'; // private $base_url; private $profile_id; private $server_key; // private static $instance = null; // public static function getEndpoints() { $endpoints = []; foreach (PaytabsApi::BASE_URLS as $key => $value) { $endpoints[$key] = $value['title']; } return $endpoints; } public static function getInstance($region, $merchant_id, $key) { if (self::$instance == null) { self::$instance = new PaytabsApi($region, $merchant_id, $key); } // self::$instance->setAuth($merchant_email, $secret_key); return self::$instance; } private function __construct($region, $profile_id, $server_key) { $this->base_url = self::BASE_URLS[$region]['endpoint']; $this->setAuth($profile_id, $server_key); } private function setAuth($profile_id, $server_key) { $this->profile_id = $profile_id; $this->server_key = $server_key; } /** start: API calls */ function create_pay_page($values) { // $serverIP = getHostByName(getHostName()); // $values['ip_merchant'] = PaytabsHelper::getNonEmpty($serverIP, $_SERVER['SERVER_ADDR'], 'NA'); $isTokenize = array_key_exists('token', $values); $response = $this->sendRequest(self::URL_REQUEST, $values); $res = json_decode($response); $paypage = $isTokenize ? $this->enhanceTokenization($res) : $this->enhance($res); return $paypage; } function verify_payment($tran_reference) { $values['tran_ref'] = $tran_reference; $verify = json_decode($this->sendRequest(self::URL_QUERY, $values)); $verify = $this->enhanceVerify($verify); return $verify; } function request_followup($values) { $res = json_decode($this->sendRequest(self::URL_REQUEST, $values)); $refund = $this->enhanceRefund($res); return $refund; } function token_query($token) { $values = ['token' => $token]; $res = json_decode($this->sendRequest(self::URL_TOKEN_QUERY, $values)); return $res; } function token_delete($token) { $values = ['token' => $token]; $res = json_decode($this->sendRequest(self::URL_TOKEN_DELETE, $values)); return $res; } // function is_valid_redirect($post_values) { $serverKey = $this->server_key; // Request body include a signature post Form URL encoded field // 'signature' (hexadecimal encoding for hmac of sorted post form fields) $requestSignature = $post_values["signature"]; unset($post_values["signature"]); $fields = array_filter($post_values); // Sort form fields ksort($fields); // Generate URL-encoded query string of Post fields except signature field. $query = http_build_query($fields); return $this->is_genuine($query, $requestSignature, $serverKey); } function is_valid_ipn($data, $signature, $serverkey = false) { $server_key = $serverKey ?? $this->server_key; return $this->is_genuine($data, $signature, $server_key); } private function is_genuine($data, $requestSignature, $serverKey) { $signature = hash_hmac('sha256', $data, $serverKey); if (hash_equals($signature, $requestSignature) === TRUE) { // VALID Redirect return true; } else { // INVALID Redirect return false; } } /** end: API calls */ /** start: Local calls */ /** * */ private function enhance($paypage) { $_paypage = $paypage; if (!$paypage) { $_paypage = new stdClass(); $_paypage->success = false; $_paypage->message = 'Create paytabs payment failed'; } else { $_paypage->success = isset($paypage->tran_ref, $paypage->redirect_url) && !empty($paypage->redirect_url); $_paypage->payment_url = @$paypage->redirect_url; } return $_paypage; } private function enhanceVerify($verify) { $_verify = $verify; if (!$verify) { $_verify = new stdClass(); $_verify->success = false; $_verify->message = 'Verifying paytabs payment failed'; } else if (isset($verify->code, $verify->message)) { $_verify->success = false; } else { if (isset($verify->payment_result)) { $_verify->success = $verify->payment_result->response_status == "A"; } else { $_verify->success = false; } $_verify->message = $verify->payment_result->response_message; } $_verify->reference_no = @$verify->cart_id; $_verify->transaction_id = @$verify->tran_ref; return $_verify; } private function enhanceRefund($refund) { $_refund = $refund; if (!$refund) { $_refund = new stdClass(); $_refund->success = false; $_refund->message = 'Verifying paytabs Refund failed'; } else { if (isset($refund->payment_result)) { $_refund->success = $refund->payment_result->response_status == "A"; $_refund->message = $refund->payment_result->response_message; } else { $_refund->success = false; } $_refund->pending_success = false; } return $_refund; } private function enhanceTokenization($paypage) { $_paypage = $paypage; if (!$paypage) { $_paypage = new stdClass(); $_paypage->success = false; $_paypage->message = 'Create paytabs tokenization payment failed'; } else { $is_redirect = isset($paypage->tran_ref, $paypage->redirect_url) && !empty($paypage->redirect_url); $is_completed = isset($paypage->payment_result); if ($is_redirect) { $_paypage->success = true; $_paypage->payment_url = $paypage->redirect_url; } else if ($is_completed) { $_paypage = $this->enhanceVerify($paypage); } else { $_paypage = $this->enhance($paypage); } $_paypage->is_redirect = $is_redirect; $_paypage->is_completed = $is_completed; } return $_paypage; } /** end: Local calls */ private function sendRequest($request_url, $values) { $auth_key = $this->server_key; $gateway_url = $this->base_url . $request_url; $headers = [ 'Content-Type: application/json', "Authorization: {$auth_key}" ]; $values['profile_id'] = (int)$this->profile_id; $post_params = json_encode($values); $ch = @curl_init(); @curl_setopt($ch, CURLOPT_URL, $gateway_url); @curl_setopt($ch, CURLOPT_POST, true); @curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params); @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_HEADER, false); @curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); @curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); @curl_setopt($ch, CURLOPT_VERBOSE, true); // @curl_setopt($ch, CURLOPT_TIMEOUT, 30); $result = @curl_exec($ch); $error_num = curl_errno($ch); if ($error_num) { $error_msg = curl_error($ch); PaytabsHelper::log("Paytabs Admin: Response [($error_num) $error_msg], [$result]", 3); $result = json_encode([ 'message' => 'Sorry, unable to process your transaction, Contact the site Administrator' ]); } @curl_close($ch); return $result; } } laravel_paytabs/src/Facades/paypage.php000064400000000332150364336770014205 0ustar00app->bind('paypage', function($app) { return new paypage(); }); $this->mergeConfigFrom( __DIR__ . '/config/config.php', 'paytabs' ); $this->app->make(\Paytabscom\Laravel_paytabs\Controllers\PaytabsLaravelListenerApi::class); } /** * Bootstrap services. * * @return void */ public function boot() { $this->publishes([ __DIR__ . '/config/config.php' => config_path('paytabs.php'), ],'paytabs'); include __DIR__.'/../routes/routes.php'; } } laravel_paytabs/README.md000064400000015371150364336770011221 0ustar00Laravel PayTabs PT2 Description ----------- This Package provides integration with the PayTabs payment gateway. CONTENTS OF THIS FILE --------------------- * Introduction * Requirements * Installation * Configuration * usage INTRODUCTION ------------ This Package integrates PayTabs online payments into the Laravel Framework starts from version 5.8 - 8.x. REQUIREMENTS ------------ This Package requires no external dependencies. INSTALLATION ------------ - composer require paytabscom/laravel_paytabs CONFIGURATION ------------- * composer dump-autoload * Go to _config/app.php_ and in the providers array add Paytabscom\Laravel_paytabs\PaypageServiceProvider::class, * Create the package config file: php artisan vendor:publish --tag=paytabs * Go to _config/logging.php_ and in the channels array add 'PayTabs' => [ 'driver' => 'single', 'path' => storage_path('logs/paytabs.log'), 'level' => 'info', ], * In _config/paytabs.php_ add your merchant info. **Important Hint:** you can pass your merchant info in the environment file with the same key names mentioned in the _config/paytabs.php_ file. This value will be returned if no environment variable exists for the given key. Usage ------------- * create pay page use Paytabscom\Laravel_paytabs\Facades\paypage; $pay= paypage::sendPaymentCode('all') ->sendTransaction('sale') ->sendCart(10,1000,'test') ->sendCustomerDetails('Walaa Elsaeed', 'w.elsaeed@paytabs.com', '0101111111', 'test', 'Nasr City', 'Cairo', 'EG', '1234','100.279.20.10') ->sendShippingDetails('Walaa Elsaeed', 'w.elsaeed@paytabs.com', '0101111111', 'test', 'Nasr City', 'Cairo', 'EG', '1234','100.279.20.10') ->sendURLs('return_url', 'callback_url') ->sendLanguage('en') ->create_pay_page(); return $pay; * if you want to pass the shipping address as same as billing address you can use >shipping_same_billing() and make sure to remove calling ->sendShippingDetails. * if you want to hide the shipping address you can use ->sendHideShipping(true); * if you want to use iframe option instead of redirection you can use ->sendFramed(true); * if you want to pass the payment methods you can use ::sendPaymentCode("['creditcard','fawry']") * if you want to pass the Tokenization option you can use ->sendTokinse(true) * if you want to make a payment via token you can use ->sendTransaction('transaction_type','recurring') ->sendToken('token returned from the first payment page created with Tokenization option','transRef returned to you in the same first payment page') * if you want to make a payment with user defined you can use ->sendUserDefined(["udf1"=>"UDF1 Test", "udf2"=>"UDF2 Test", "udf3"=>"UDF3 Test"]) * refund (you can use this function to both refund and partially refund) $refund = Paypage::refund('tran_ref','order_id','amount','refund_reason'); return $refund; * Auth pay= Paypage::sendPaymentCode('all') ->sendTransaction('Auth') ->sendCart(10,1000,'test') ->sendCustomerDetails('Walaa Elsaeed', 'w.elsaeed@paytabs.com', '0101111111', 'test', 'Nasr City', 'Cairo', 'EG', '1234','100.279.20.10') ->sendShippingDetails('Walaa Elsaeed', 'w.elsaeed@paytabs.com', '0101111111', 'test', 'Nasr City', 'Cairo', 'EG', '1234','100.279.20.10') ->sendURLs('return_url', 'callback_url') ->sendLanguage('en') ->create_pay_page(); return $pay; * capture (the tran_ref is the tran_ref of the Auth transaction you need to capture it. you can use this function to both capture and partially capture.) $capture = Paypage::capture('tran_ref','order_id','amount','capture description'); return $capture; * void (the tran_ref is the tran_ref of the Auth transaction you need to void it. you can use this function to both capture and partially capture) $void = Paypage::void('tran_ref','order_id','amount','void description'); return $void * transaction details $transaction = Paypage::queryTransaction('tran_ref'); return $transaction; * if you face any error you will find it logged in: _storage/logs/paytabs.log_ PAYMENT RESULT NOTIFICATION -------------------------------- PayTabs payment gateway provides means to notify your system with payment result once transaction processing was completed so that your system can update the transaction respective cart. To get use of this feature do the following: 1- Defining a route (Optional) -------------------------- Laravel PayTabs PT2 package comes with a default route for incoming IPN requests. The route URI is _/paymentIPN_ , if you don't like it this URI just ignore it and define your own. Look at _routes/routes.php_ to get a clue. 2- Implementing a means to receive notification ------------------------------------------ To receive notification, do one of the following: * While creating a pay page, passed this route as a Callback URL to _sendURLs_ method, that URL will receive an HTTP Post request with the payment result. For more about callback check: **merchant dashboard** > **Developers** > **Transaction API**. * Second means is to configure IPN notification from merchant dashboard. For more details about how to configure IPN request and its different formats check: **merchant dashboard** > **Developers** > **Service Types**. 3- Configuring a callback method -------------------------------- Now, you need to configure the plugin with the class\method that will grab the payment details and perform your custom logic (updating cart in DB, notifying the customer ...etc ). * In your website _config/paytabs.php_ file, add the following: 'callback' => env('paytabs_ipn_callback', new namespace\your_class() ), * In your class add new method, it must named: **updateCartByIPN** updateCartByIPN( $requestData){ $cartId= $requestData->getCartId(); $status= $requestData->getStatus(); //your logic .. updating cart in DB, notifying the customer ...etc //Hold On Reject support // if $status = "H" this is mean the transaction is hold on reject. // you can't make capture for it from your system. // you must make the capture from paytabs dashboard side. // make sure to add your ipn value to paytabs dashboard from here: "{paytabs portal}/merchant/developers/ipnconfig". } you can also get transaction reference number. To get the list of available properties check: _Paytabscom\Laravel__paytabs\IpnRequest_ class. laravel_paytabs/config/config.php000064400000003301150364336770013153 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ /* |-------------------------------------------------------------------------- | Merchant profile id |-------------------------------------------------------------------------- | | Your merchant profile id , you can find the profile id on your PayTabs Merchant’s Dashboard- profile. | */ 'profile_id' => env('paytabs_profile_id', null), /* |-------------------------------------------------------------------------- | Server Key |-------------------------------------------------------------------------- | | You can find the Server key on your PayTabs Merchant’s Dashboard - Developers - Key management. | */ 'server_key' => env('paytabs_server_key', null), /* |-------------------------------------------------------------------------- | Currency |-------------------------------------------------------------------------- | | The currency you registered in with PayTabs account you must pass value from this array ['AED','EGP','SAR','OMR','JOD','US'] | */ 'currency' => env('paytabs_currency', null), /* |-------------------------------------------------------------------------- | Region |-------------------------------------------------------------------------- | | The region you registered in with PayTabs you must pass value from this array ['ARE','EGY','SAU','OMN','JOR','GLOBAL'] | */ 'region' => env('paytabs_region', null), ]; laravel_paytabs/routes/routes.php000064400000000222150364336770013302 0ustar00name('payment_ipn');