diff --git a/includes/paytabs_core.php b/includes/paytabs_core.php index d1e5ed1..2f79214 100755 --- a/includes/paytabs_core.php +++ b/includes/paytabs_core.php @@ -2,11 +2,11 @@ /** * PayTabs v2 PHP SDK - * Version: 2.17.0 + * Version: 2.20.1 * PHP >= 7.0.0 */ -define('PAYTABS_SDK_VERSION', '2.17.0'); +define('PAYTABS_SDK_VERSION', '2.20.1'); define('PAYTABS_DEBUG_FILE_NAME', 'debug_paytabs.log'); define('PAYTABS_DEBUG_SEVERITY', ['Info', 'Warning', 'Error']); @@ -84,6 +84,14 @@ static function getCardPayments($international_only = false, $currency = null) return $methods; } + /** + * @return true if the payment method can use the Card methods features + */ + static function canUseCardFeatures($code) + { + return ($code == 'all') || static::isCardPayment($code); + } + static function supportTokenization($code) { foreach (PaytabsApi::PAYMENT_TYPES as $key => $value) { @@ -124,6 +132,16 @@ static function supportRefund($code) return false; } + static function supportPending($code) + { + foreach (PaytabsApi::PAYMENT_TYPES as $key => $value) { + if ($value['name'] === $code) { + return in_array(PaytabsApi::GROUP_PENDING, $value['groups']); + } + } + return false; + } + // static function read_ipn_response() @@ -230,6 +248,30 @@ public static function log($msg, $severity = 1) } } } + + static function isValidDiscountPattern($pattern) + { + return preg_match(PaytabsEnum::DISCOUNT_PATTERN_REGEX, $pattern); + } + + /** + * Validate the patterns for discount option + * @param $patterns_str string, comma separated + */ + static function isValidDiscountPatterns($patterns_str) + { + $patterns = explode(',', $patterns_str); + + if (empty($patterns)) return false; + + foreach ($patterns as $prefix) { + if (!static::isValidDiscountPattern($prefix)) { + return false; + } + } + + return true; + } } @@ -242,6 +284,9 @@ abstract class PaytabsEnum const TRAN_TYPE_CAPTURE = 'capture'; const TRAN_TYPE_SALE = 'sale'; const TRAN_TYPE_REGISTER = 'register'; + // Auth Extension is used to refresh the hold on the funds + // Followup an Auth transaction + const TRAN_TYPE_AUTH_EXT = 'authext'; const TRAN_TYPE_PAYMENT_REQUEST = 'payment request'; @@ -267,15 +312,35 @@ abstract class PaytabsEnum // + const TOKEN_TYPE_REGISTERED = 'registered'; + const TOKEN_TYPE_UNSCHEDULED = 'unscheduled'; + const TOKEN_TYPE_RECURRING_FIXED = 'recurring_fixed'; + const TOKEN_TYPE_RECURRING_VARIABLE = 'recurring_variable'; + + // + const PP_ERR_DUPLICATE = 4; // + const DISCOUNT_PERCENTAGE = "percentage"; + const DISCOUNT_FIXED = "fixed"; + + const DISCOUNT_PATTERN_REGEX = '/^[0-9]{4,10}$/'; + + // + + static function TranIsAuth($tran_type) { return strcasecmp($tran_type, PaytabsEnum::TRAN_TYPE_AUTH) == 0; } + static function TranIsAuthExt($tran_type) + { + return strcasecmp($tran_type, PaytabsEnum::TRAN_TYPE_AUTH_EXT) == 0; + } + static function TranIsSale($tran_type) { return strcasecmp($tran_type, PaytabsEnum::TRAN_TYPE_SALE) == 0; @@ -375,6 +440,7 @@ static function PPIsDuplicate($paypage) * Members: * - Transaction Info (Type & Class) * - Cart Info (id, desc, amount, currency) + * - URLs (return & callback) * - Plugin Info (platform name, platform version, plugin version) */ class PaytabsHolder @@ -393,6 +459,12 @@ class PaytabsHolder */ private $cart; + /** + * return + * callback + */ + private $urls; + /** * cart_name * cart_version @@ -409,9 +481,12 @@ class PaytabsHolder */ public function pt_build() { - $all = array_merge( + $all = []; + $this->pt_merges( + $all, $this->transaction, $this->cart, + $this->urls, $this->plugin_info ); @@ -451,6 +526,16 @@ public function set03Cart($cart_id, $currency, $amount, $cart_description) return $this; } + public function set07URLs($return_url, $callback_url) + { + $this->urls = [ + 'return' => $return_url, + 'callback' => $callback_url, + ]; + + return $this; + } + public function set99PluginInfo($platform_name, $platform_version, $plugin_version = null) { if (!$plugin_version) { @@ -470,6 +555,47 @@ public function set99PluginInfo($platform_name, $platform_version, $plugin_versi } +/** + * Holder class: Holds & Generates the paramters array. + * Holds & Generates the parameters array for the payments + * Members: + * - airline_data + * -- pnr_code + */ +abstract class PaytabsExtraDataHolder extends PaytabsHolder +{ + private $airline_data; + + /** + * @return array + */ + public function pt_build() + { + $all = parent::pt_build(); + + $this->pt_merges( + $all, + $this->airline_data, + ); + + return $all; + } + + public function set60AirlineData($pnr_code) + { + if (!is_null($pnr_code)) { + $this->airline_data = [ + 'airline_data' => [ + 'pnr_code' => $pnr_code, + ], + ]; + } + + return $this; + } +} + + /** * Holder class, Inherit class PaytabsHolder * Holds & Generates the parameters array that pass to PayTabs' API @@ -477,12 +603,11 @@ public function set99PluginInfo($platform_name, $platform_version, $plugin_versi * - Payment method (payment_code) * - Customer Details * - Shipping Details - * - URLs (return & callback) * - Language (paypage_lang) * - Tokenise * - User defined */ -abstract class PaytabsBasicHolder extends PaytabsHolder +abstract class PaytabsBasicHolder extends PaytabsExtraDataHolder { /** * payment_type @@ -515,12 +640,6 @@ abstract class PaytabsBasicHolder extends PaytabsHolder */ private $shipping_details; - /** - * return - * callback - */ - private $urls; - /** * paypage_lang */ @@ -532,6 +651,15 @@ abstract class PaytabsBasicHolder extends PaytabsHolder */ private $tokenise; + /** + * tokenise + * token_type + * counter + * total_count + * show_save_card + */ + private $token_info; + /** * udf[1-9] */ @@ -549,11 +677,11 @@ public function pt_build() $this->pt_merges( $all, $this->payment_code, - $this->urls, $this->customer_details, $this->shipping_details, $this->lang, $this->tokenise, + $this->token_info, $this->user_defined ); @@ -655,22 +783,29 @@ public function set05ShippingDetails($same_as_billing, $name = null, $email = nu } - public function set07URLs($return_url, $callback_url) + public function set08Lang($lang_code) { - $this->urls = [ - 'return' => $return_url, - 'callback' => $callback_url, + $this->lang = [ + 'paypage_lang' => $lang_code ]; return $this; } - public function set08Lang($lang_code) + /** + * @deprecated + * @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) { - $this->lang = [ - 'paypage_lang' => $lang_code - ]; + if ($on) { + $this->tokenise = [ + 'tokenise' => $token_format, + 'show_save_card' => $optional + ]; + } return $this; } @@ -678,13 +813,27 @@ public function set08Lang($lang_code) /** * @param int $token_format integer between 2 and 6, Set the Token format + * @param string $token_type + * @param int $counter + * @param int $total_count * @param bool $optional Display the save card option on the payment page */ - public function set10Tokenise($on = false, $token_format = 2, $optional = false) + public function set11TokeniseInfo($on, $token_format = 2, $token_type = PaytabsEnum::TOKEN_TYPE_UNSCHEDULED, $counter = null, $total_count = null, $optional = false) { if ($on) { - $this->tokenise = [ + $_info = [ 'tokenise' => $token_format, + 'token_type' => $token_type, + ]; + if (!is_null($counter)) { + $_info['counter'] = $counter; + } + if (!is_null($total_count)) { + $_info['total_count'] = $total_count; + } + + $this->token_info = [ + 'token_info' => $_info, 'show_save_card' => $optional ]; } @@ -742,6 +891,11 @@ class PaytabsRequestHolder extends PaytabsBasicHolder */ private $alt_currency; + /** + * card_discounts + */ + private $card_discounts; + // /** @@ -756,7 +910,8 @@ public function pt_build() $this->hide_shipping, $this->framed, $this->config_id, - $this->alt_currency + $this->alt_currency, + $this->card_discounts ); return $all; @@ -809,6 +964,58 @@ public function set12AltCurrency($alt_currency) } return $this; } + + public function set13CardDiscounts($discount_patterns, $discount_amounts, $discount_types) + { + if (empty($discount_patterns)) { + PaytabsHelper::log('Paytabs admin: Discount arrays must be not empty', 3); + return $this; + } + + $count = count($discount_patterns); + + if ($count != count($discount_amounts) || $count != count($discount_types)) { + PaytabsHelper::log('Paytabs admin: Discount arrays must have the same length', 3); + return $this; + } + + $cards = []; + + for ($i = 0; $i < $count; $i++) { + $pattern = $discount_patterns[$i]; + $amount = $discount_amounts[$i]; + $type = $discount_types[$i]; + + if (!PaytabsHelper::isValidDiscountPattern($pattern)) { + PaytabsHelper::log('Paytabs admin: Discount pattern not valid', 2); + // uncomment if you want to stop the request, otherwise send the reqeust + // return $this; + } + + if ($type == PaytabsEnum::DISCOUNT_PERCENTAGE) { + $type_key = 'discount_percent'; + $title = "$discount_amounts[$i]% discount applied on cards starting with $discount_patterns[$i]"; + } elseif ($type == PaytabsEnum::DISCOUNT_FIXED) { + $type_key = 'discount_amount'; + $title = "$discount_amounts[$i] fixed discount applied on cards starting with $discount_patterns[$i]"; + } else { + PaytabsHelper::log('Paytabs admin: Discount type does not exist', 3); + return $this; + } + + $cards[$i]['discount_cards'] = $pattern; + $cards[$i][$type_key] = $amount; + $cards[$i]['discount_title'] = $title; + } + + if (count($cards) > 0) { + $this->card_discounts = [ + 'card_discounts' => $cards + ]; + } + + return $this; + } } @@ -818,7 +1025,7 @@ public function set12AltCurrency($alt_currency) * Members: * - Token Info (token & tran_ref) */ -class PaytabsTokenHolder extends PaytabsHolder +class PaytabsTokenHolder extends PaytabsExtraDataHolder { /** * token @@ -826,6 +1033,15 @@ class PaytabsTokenHolder extends PaytabsHolder */ private $token_info; + /** + * token + * tran_ref + * token_type + * counter + * total_count + */ + private $token_details; + public function set20Token($tran_ref, $token = null) { @@ -840,11 +1056,46 @@ public function set20Token($tran_ref, $token = null) return $this; } + public function set21TokenInfo($tran_ref, $token, $token_type, $counter, $total_count) + { + $this->token_details = []; + + $details = []; + + if ($tran_ref) { + $details = ['tran_ref' => $tran_ref]; + } + + if ($token) { + $details['token'] = $token; + } + + if ($token_type) { + $details['token_type'] = $token_type; + } + if (!is_null($counter)) { + $details['counter'] = $counter; + } + if (!is_null($total_count)) { + $details['total_count'] = $total_count; + } + + if (count($details) > 0) { + $this->token_details['token_info'] = $details; + } + + return $this; + } + public function pt_build() { $all = parent::pt_build(); - $all = array_merge($all, $this->token_info); + if ($this->token_details) { + $all = array_merge($all, $this->token_details); + } else if ($this->token_info) { + $all = array_merge($all, $this->token_info); + } return $all; } @@ -1021,17 +1272,18 @@ class PaytabsApi const GROUP_AUTH_CAPTURE = 'auth_capture'; const GROUP_REFUND = 'refund'; const GROUP_IFRAME = 'iframe'; + const GROUP_PENDING = 'payment_request'; const PAYMENT_TYPES = [ - '0' => ['name' => 'all', 'title' => 'PayTabs - All', 'currencies' => null, 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_AUTH_CAPTURE, PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], + '0' => ['name' => 'all', 'title' => 'PayTabs - All', 'currencies' => null, 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_AUTH_CAPTURE, PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND, PaytabsApi::GROUP_PENDING]], '1' => ['name' => 'stcpay', 'title' => 'PayTabs - StcPay', 'currencies' => ['SAR'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], '2' => ['name' => 'stcpayqr', 'title' => 'PayTabs - StcPay(QR)', 'currencies' => ['SAR'], 'groups' => []], '3' => ['name' => 'applepay', 'title' => 'PayTabs - ApplePay', 'currencies' => null, 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_AUTH_CAPTURE, PaytabsApi::GROUP_REFUND]], '4' => ['name' => 'omannet', 'title' => 'PayTabs - OmanNet', 'currencies' => ['OMR'], 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], '5' => ['name' => 'mada', 'title' => 'PayTabs - mada', 'currencies' => ['SAR'], 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_AUTH_CAPTURE, PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], '6' => ['name' => 'creditcard', 'title' => 'PayTabs - CreditCard', 'currencies' => null, 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_CARDS_INTERNATIONAL, PaytabsApi::GROUP_AUTH_CAPTURE, PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], - '7' => ['name' => 'sadad', 'title' => 'PayTabs - Sadad', 'currencies' => ['SAR'], 'groups' => [PaytabsApi::GROUP_IFRAME]], - '8' => ['name' => 'fawry', 'title' => 'PayTabs - @Fawry', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], + '7' => ['name' => 'sadad', 'title' => 'PayTabs - Sadad', 'currencies' => ['SAR'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_PENDING]], + '8' => ['name' => 'fawry', 'title' => 'PayTabs - @Fawry', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND, PaytabsApi::GROUP_PENDING]], '9' => ['name' => 'knet', 'title' => 'PayTabs - KnPay', 'currencies' => ['KWD'], 'groups' => [PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_REFUND]], '10' => ['name' => 'amex', 'title' => 'PayTabs - Amex', 'currencies' => ['AED', 'SAR', 'USD'], 'groups' => [PaytabsApi::GROUP_TOKENIZE, PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_CARDS_INTERNATIONAL, PaytabsApi::GROUP_AUTH_CAPTURE, PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], '11' => ['name' => 'valu', 'title' => 'PayTabs - valU', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], @@ -1041,13 +1293,13 @@ class PaytabsApi '15' => ['name' => 'samsungpay', 'title' => 'PayTabs - SamsungPay', 'currencies' => ['AED', 'SAR'], 'groups' => [PaytabsApi::GROUP_REFUND]], '16' => ['name' => 'knetdebit', 'title' => 'PayTabs - KnPay (Debit)', 'currencies' => ['KWD'], 'groups' => [PaytabsApi::GROUP_REFUND]], '17' => ['name' => 'knetcredit', 'title' => 'PayTabs - KnPay (Credit)', 'currencies' => ['KWD'], 'groups' => [PaytabsApi::GROUP_REFUND]], - '18' => ['name' => 'aman', 'title' => 'PayTabs - Aman', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME]], + '18' => ['name' => 'aman', 'title' => 'PayTabs - Aman', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_PENDING]], '19' => ['name' => 'urpay', 'title' => 'PayTabs - UrPay', 'currencies' => ['SAR'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], '20' => ['name' => 'paypal', 'title' => 'PayTabs - PayPal', 'currencies' => ['AED', 'EGP', 'USD', 'EUR', 'GPB', 'HKD', 'JPY'], 'groups' => [PaytabsApi::GROUP_REFUND]], '21' => ['name' => 'installment', 'title' => 'PayTabs - Installment', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_IFRAME]], '22' => ['name' => 'touchpoints', 'title' => 'PayTabs - Touchpoints', 'currencies' => ['AED'], 'groups' => [PaytabsApi::GROUP_CARDS, PaytabsApi::GROUP_IFRAME]], '23' => ['name' => 'forsa', 'title' => 'PayTabs - Forsa', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME]], - '24' => ['name' => 'tabby', 'title' => 'PayTabs - Tabby', 'currencies' => ['AED'], 'groups' => []], + '24' => ['name' => 'tabby', 'title' => 'PayTabs - Tabby', 'currencies' => ['AED', 'SAR'], 'groups' => []], '25' => ['name' => 'souhoola', 'title' => 'PayTabs - Souhoola', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], '26' => ['name' => 'amaninstallments', 'title' => 'PayTabs - Aman installments', 'currencies' => ['EGP'], 'groups' => [PaytabsApi::GROUP_IFRAME, PaytabsApi::GROUP_REFUND]], @@ -1121,6 +1373,23 @@ public static function getEndpoints() return $endpoints; } + /** + * Merge and return all Currency codes available in the payment methods list + */ + public static function getCurrencies() + { + $currencies = []; + foreach (PaytabsApi::PAYMENT_TYPES as $key => $value) { + $_currencies = $value['currencies']; + if ($_currencies) { + $_currencies = array_filter($_currencies); + $currencies = array_merge($currencies, $_currencies); + } + } + $currencies = array_unique($currencies); + return $currencies; + } + public static function getEndpoint($region) { $endpoint = self::BASE_URLS[$region]['endpoint']; @@ -1138,7 +1407,11 @@ public static function getInstance($region, $merchant_id, $key) private function __construct($region, $profile_id, $server_key) { - $this->base_url = self::BASE_URLS[$region]['endpoint']; + if (array_key_exists($region, self::BASE_URLS)) { + $this->base_url = self::BASE_URLS[$region]['endpoint']; + } else { + PaytabsHelper::log("Paytabs Admin: Region {$region} is not valid", 2); + } $this->setAuth($profile_id, $server_key); } @@ -1160,8 +1433,8 @@ function create_pay_page($values) $values['tran_class'] == PaytabsEnum::TRAN_CLASS_RECURRING || array_key_exists('payment_token', $values) || array_key_exists('apple_pay_token', $values) - || array_key_exists('card_details', $values); - + || array_key_exists('card_details', $values) + || (array_key_exists('token', $values) || array_key_exists('token_info', $values)); $response = $this->sendRequest(self::URL_REQUEST, $values); $res = json_decode($response); @@ -1328,7 +1601,7 @@ private function enhance($paypage) $_paypage->success = false; } else { $_paypage->success = isset($paypage->tran_ref, $paypage->redirect_url) && !empty($paypage->redirect_url); - + $_paypage->is_redirect = isset($paypage->tran_ref, $paypage->redirect_url) && !empty($paypage->redirect_url); $_paypage->payment_url = @$paypage->redirect_url; } diff --git a/paytabs-woocommerce.php b/paytabs-woocommerce.php index 88c3afe..7d3a482 100644 --- a/paytabs-woocommerce.php +++ b/paytabs-woocommerce.php @@ -9,7 +9,7 @@ * Plugin URI: https://paytabs.com/ * Description: PayTabs is a 3rd party payment gateway. Ideal payment solutions for your internet business. - * Version: 4.22.0 + * Version: 4.22.1 * Requires PHP: 7.0 * Author: PayTabs * Author URI: integration@paytabs.com @@ -20,7 +20,7 @@ } -define('PAYTABS_PAYPAGE_VERSION', '4.22.0'); +define('PAYTABS_PAYPAGE_VERSION', '4.22.1'); define('PAYTABS_PAYPAGE_DIR', plugin_dir_path(__FILE__)); define('PAYTABS_PAYPAGE_ICONS_URL', plugins_url("icons/", __FILE__)); define('PAYTABS_PAYPAGE_IMAGES_URL', plugins_url("images/", __FILE__));