postaffiliatepro
Last commit date
Form
1 week ago
Shortcode
1 week ago
Template
1 month ago
Util
1 month ago
Widget
1 month ago
resources
2 months ago
Base.class.php
1 month ago
PapApi.class.php
1 week ago
postaffiliatepro.php
1 week ago
readme.txt
1 week ago
screenshot-1.png
3 years ago
screenshot-2.png
3 years ago
screenshot-3.png
3 years ago
screenshot-4.png
3 years ago
screenshot-5.png
3 years ago
screenshot-6.png
3 years ago
screenshot-7.png
3 years ago
Base.class.php
379 lines
| 1 | <?php |
| 2 | if (!class_exists('postaffiliatepro_Base')) { |
| 3 | class postaffiliatepro_Base { |
| 4 | const IMG_PATH = 'resources/img/'; |
| 5 | const URL_SEPARATOR = '/'; |
| 6 | const CSS_PATH = 'resources/css/'; |
| 7 | const UNSUCCESSFUL_LOGIN_COUNT = 'pap-unsuccessful-login-counter'; |
| 8 | const FIRST_UNSUCCESSFUL_LOGIN = 'pap-first-unsuccessful-login'; |
| 9 | const UNSUCCESSFUL_LOGIN_TIME_LIMIT = 900; |
| 10 | private static $session = null; |
| 11 | private static $campaignHelper = null; |
| 12 | private $error = ''; |
| 13 | |
| 14 | public static function _log($message) { |
| 15 | global $wp_filesystem; |
| 16 | |
| 17 | if (get_option(postaffiliatepro_Form_Settings_Debugging::DEBUGGING_ENABLED) === 'true') { |
| 18 | if (empty($wp_filesystem)) { |
| 19 | require_once ABSPATH.'/wp-admin/includes/file.php'; |
| 20 | WP_Filesystem(); |
| 21 | } |
| 22 | |
| 23 | if (is_array($message) || is_object($message)) { |
| 24 | $message = print_r($message, true); |
| 25 | } |
| 26 | |
| 27 | $logFile = WP_PLUGIN_DIR.postaffiliatepro_Form_Settings_Debugging::DEBUG_FILE; |
| 28 | |
| 29 | $logs = ''; |
| 30 | if ($wp_filesystem->exists($logFile)) { |
| 31 | $logs = $wp_filesystem->get_contents($logFile); |
| 32 | } |
| 33 | |
| 34 | $newLog = gmdate('Y.m.d H:i:s', time()) . ' ' . $message . "\n"; |
| 35 | |
| 36 | $wp_filesystem->put_contents($logFile, $logs.$newLog, FS_CHMOD_FILE); |
| 37 | } |
| 38 | return true; |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * @return postaffiliatepro_Util_CampaignHelper |
| 43 | */ |
| 44 | protected function getCampaignHelper() { |
| 45 | if (self::$campaignHelper) { |
| 46 | return self::$campaignHelper; |
| 47 | } |
| 48 | self::$campaignHelper = new postaffiliatepro_Util_CampaignHelper(); |
| 49 | return self::$campaignHelper; |
| 50 | } |
| 51 | |
| 52 | public static function getAccountName() { |
| 53 | if (get_option(postaffiliatepro::CLICK_TRACKING_ACCOUNT_SETTING_NAME) == '') { |
| 54 | return postaffiliatepro::DEFAULT_ACCOUNT_NAME; |
| 55 | } |
| 56 | return get_option(postaffiliatepro::CLICK_TRACKING_ACCOUNT_SETTING_NAME); |
| 57 | } |
| 58 | |
| 59 | public function getError() { |
| 60 | return $this->error; |
| 61 | } |
| 62 | |
| 63 | protected function getPapVersion() { |
| 64 | $url = get_option(postaffiliatepro::PAP_URL_SETTING_NAME); |
| 65 | if ($url == '') { |
| 66 | return false; |
| 67 | } |
| 68 | |
| 69 | $result = $this->sendRequest($url.'api/version.php'); |
| 70 | if (!$result ) { |
| 71 | self::_log('Unable to parse application version number'); |
| 72 | } |
| 73 | |
| 74 | if (isset($result['response']['code']) && $result['response']['code'] !== 200) { |
| 75 | self::_log('API connection error ('.$result['response']['code'].'): '.$result['response']['message']); |
| 76 | } |
| 77 | |
| 78 | libxml_use_internal_errors(true); |
| 79 | $xml = simplexml_load_string($result['body']); |
| 80 | if (!$xml) { |
| 81 | $msg = ''; |
| 82 | foreach (libxml_get_errors() as $error) { |
| 83 | $msg .= $error->message; |
| 84 | } |
| 85 | self::_log('Unable to parse application version number, error: ' . $msg); |
| 86 | return __('unknown (possibly below 4.5.48.1)', 'postaffiliatepro') . $msg; |
| 87 | } |
| 88 | |
| 89 | update_option(postaffiliatepro::PAP_VERSION, (string) $xml->applications->pap->versionNumber); |
| 90 | return (string) $xml->applications->pap->versionNumber; |
| 91 | } |
| 92 | |
| 93 | protected function getApiSessionUrl() { |
| 94 | return get_option(postaffiliatepro::PAP_URL_SETTING_NAME) . 'scripts/server.php'; |
| 95 | } |
| 96 | |
| 97 | /** |
| 98 | * @return Pap_Api_Session |
| 99 | */ |
| 100 | protected function getApiSession($isFromConfigurationScreen = false) { |
| 101 | if (self::$session !== null && !$isFromConfigurationScreen) { |
| 102 | return self::$session; |
| 103 | } |
| 104 | $unsuccessfulLogins = get_option(self::UNSUCCESSFUL_LOGIN_COUNT); |
| 105 | if (!$isFromConfigurationScreen && $this->isLoginLimitExceeded($unsuccessfulLogins)) { |
| 106 | self::_log('Invalid session counter exceeded. Fix credentials in plugin configuration.'); |
| 107 | return null; |
| 108 | } |
| 109 | $session = new Pap_Api_Session($this->getApiSessionUrl()); |
| 110 | |
| 111 | // temporarily set custom error handler to catch possible NOTICE about non-corresponding API version |
| 112 | set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool { |
| 113 | // Only NOTICE error level |
| 114 | if (!(error_reporting(8) & $errno)) { |
| 115 | return false; |
| 116 | } |
| 117 | throw new \ErrorException(esc_attr($errstr), 0, esc_attr($errno), esc_attr($errfile), esc_attr($errline)); |
| 118 | }); |
| 119 | |
| 120 | $errorExceptionHappened = false; |
| 121 | try { |
| 122 | $login = $session->login(get_option(postaffiliatepro::PAP_MERCHANT_NAME_SETTING_NAME), get_option(postaffiliatepro::PAP_MERCHANT_PASSWORD_SETTING_NAME)); |
| 123 | } catch(ErrorException $e) { |
| 124 | self::_log('API call error: '.$e->getMessage()); |
| 125 | $errorExceptionHappened = true; |
| 126 | } catch(Exception $e) { |
| 127 | self::_log('API call error: '.$e->getMessage()); |
| 128 | } finally { |
| 129 | restore_error_handler(); |
| 130 | } |
| 131 | |
| 132 | if ($errorExceptionHappened) { |
| 133 | try { |
| 134 | $login = $session->login(get_option(postaffiliatepro::PAP_MERCHANT_NAME_SETTING_NAME), get_option(postaffiliatepro::PAP_MERCHANT_PASSWORD_SETTING_NAME)); |
| 135 | } catch(Exception $e) { |
| 136 | self::_log('API call error: '.$e->getMessage()); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | try { |
| 141 | if ($login == false) { |
| 142 | if (!$isFromConfigurationScreen) { |
| 143 | $firstUnsuccessfulLoginTimestamp = get_option(self::FIRST_UNSUCCESSFUL_LOGIN); |
| 144 | if ($unsuccessfulLogins == 0 || $firstUnsuccessfulLoginTimestamp == 0 || (time() - $firstUnsuccessfulLoginTimestamp) > self::UNSUCCESSFUL_LOGIN_TIME_LIMIT) { |
| 145 | update_option(self::FIRST_UNSUCCESSFUL_LOGIN, time()); |
| 146 | } |
| 147 | update_option(self::UNSUCCESSFUL_LOGIN_COUNT, $unsuccessfulLogins + 1); |
| 148 | } |
| 149 | $this->error = $session->getMessage(); |
| 150 | if (strpos($this->error, 'Response decoding failed') !== false) { |
| 151 | $this->error = substr($this->error, 0, strpos($this->error, 'Received text')-1); |
| 152 | } |
| 153 | self::_log(__('Unable to login into PAP installation with given credentials: ', 'postaffiliatepro') . $session->getMessage()); |
| 154 | self::$session = '0'; |
| 155 | return null; |
| 156 | } |
| 157 | self::_log('Login with API was successful'); |
| 158 | // enable hashing if available |
| 159 | if (get_option(postaffiliatepro::HASHED_TRACKING_SCRIPT) == '') { |
| 160 | $request = new Gpf_Rpc_DataRequest('Pap_Merchants_Tools_IntegrationMethods', 'getHashScriptNameParams', $session); |
| 161 | |
| 162 | try { |
| 163 | $request->sendNow(); |
| 164 | $data = $request->getData(); |
| 165 | update_option(postaffiliatepro::HASHED_TRACKING_SCRIPT, $data->getValue('hashTrackingScriptsValue')); |
| 166 | self::_log('Hashing will be used, hashed script is '.$data->getValue('hashTrackingScriptsValue')); |
| 167 | } |
| 168 | catch(Exception $e) { |
| 169 | self::_log("API call error for 'getHashScriptNameParams': ".$e->getMessage()); |
| 170 | update_option(postaffiliatepro::HASHED_TRACKING_SCRIPT, '0'); |
| 171 | } |
| 172 | } |
| 173 | } catch (Gpf_Api_IncompatibleVersionException $e) { |
| 174 | $this->error = __('Unable to login into PAP installation because of incompatible versions (probably your API file here in WP installation is older than your PAP installation)', 'postaffiliatepro'); |
| 175 | self::_log($this->error); |
| 176 | return null; |
| 177 | } |
| 178 | update_option(self::UNSUCCESSFUL_LOGIN_COUNT, 0); |
| 179 | update_option(self::FIRST_UNSUCCESSFUL_LOGIN, 0); |
| 180 | self::$session = $session; |
| 181 | return $session; |
| 182 | } |
| 183 | |
| 184 | private function isLoginLimitExceeded($unsuccessfulLogins) { |
| 185 | $firstUnsuccessfulLoginTimestamp = get_option(self::FIRST_UNSUCCESSFUL_LOGIN); |
| 186 | if ($firstUnsuccessfulLoginTimestamp == 0) { |
| 187 | return false; |
| 188 | } |
| 189 | if ($unsuccessfulLogins > 4 && (time() - $firstUnsuccessfulLoginTimestamp) < self::UNSUCCESSFUL_LOGIN_TIME_LIMIT) { |
| 190 | return true; |
| 191 | } |
| 192 | return false; |
| 193 | } |
| 194 | |
| 195 | public function changeAffiliateStatus($email, $status) { |
| 196 | $session = $this->getApiSession(); |
| 197 | if ($session === null || $session === '0') { |
| 198 | self::_log(__('We have no session to PAP installation! Affiliate status change failed.', 'postaffiliatepro')); |
| 199 | return false; |
| 200 | } |
| 201 | $affiliate = new Pap_Api_Affiliate($session); |
| 202 | $affiliate->setUsername($email); |
| 203 | try { |
| 204 | $affiliate->load(); |
| 205 | } catch (Exception $e) { |
| 206 | // try notification email as well |
| 207 | $affiliate->setUsername(''); |
| 208 | $affiliate->setNotificationEmail($email); |
| 209 | try { |
| 210 | $affiliate->load(); |
| 211 | } catch (Exception $e) { |
| 212 | self::_log('Affiliate not found by email: '.$email); |
| 213 | return false; |
| 214 | } |
| 215 | } |
| 216 | $affiliate->setStatus($status); |
| 217 | try { |
| 218 | $affiliate->save(); |
| 219 | self::_log('Affiliate status changed'); |
| 220 | return true; |
| 221 | } catch (Exception $e) { |
| 222 | self::_log('Error changing affiliate status: ').$e->getMessage(); |
| 223 | return false; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | public function changeOrderStatus($orderId, $status) { |
| 228 | self::_log('Changing commission status for order ' . $orderId . ' to ' . $status); |
| 229 | $session = $this->getApiSession(); |
| 230 | if ($session === null || $session === '0') { |
| 231 | self::_log('We have no session to PAP installation! Transaction status change failed.'); |
| 232 | return false; |
| 233 | } |
| 234 | if (method_exists('Pap_Api_Transaction', 'approveByOrderId')) { |
| 235 | $transaction = new Pap_Api_Transaction($session); |
| 236 | $transaction->setOrderId($orderId); |
| 237 | if ($status === 'A') { // for approval |
| 238 | $transaction->approveByOrderId(); |
| 239 | return true; |
| 240 | } |
| 241 | if ($status === 'D') { // for declining |
| 242 | $transaction->declineByOrderId(); |
| 243 | return true; |
| 244 | } |
| 245 | self::_log('Status change failed, status ' . $status . ' is not supported.'); |
| 246 | return false; |
| 247 | } |
| 248 | $ids = $this->getTransactionIDsByOrderID($orderId, $session, $status); |
| 249 | if (empty($ids)) { |
| 250 | self::_log('No existing transactions found for order ID ' .$orderId . '. Since your API version is old (you can update it), we cannot change status of unprocessed transactions with it. Ending.'); |
| 251 | return false; |
| 252 | } |
| 253 | $request = new Gpf_Rpc_FormRequest('Pap_Merchants_Transaction_TransactionsForm', 'changeStatus', $session); |
| 254 | $request->addParam('ids', new Gpf_Rpc_Array($ids)); |
| 255 | $request->addParam('status', $status); |
| 256 | try { |
| 257 | $request->sendNow(); |
| 258 | self::_log('Status of transactions with IDs: "' . implode(', ', $ids) . '" have been changed to ' . $status); |
| 259 | } catch (Exception $e) { |
| 260 | self::_log('Status change failed with error: ' . $e->getMessage()); |
| 261 | return false; |
| 262 | } |
| 263 | return true; |
| 264 | } |
| 265 | |
| 266 | public function getTransactionIDsByOrderID($orderId, $session, $status, $limit = 100) { |
| 267 | $ids = array(); |
| 268 | if (($orderId == '') || $orderId == null) { |
| 269 | return $ids; |
| 270 | } |
| 271 | $request = new Pap_Api_TransactionsGrid($session); |
| 272 | $request->addFilter('orderid', Gpf_Data_Filter::LIKE, $orderId . '(%'); |
| 273 | $request->setLimit(0, $limit); |
| 274 | if ($status === 'A') { |
| 275 | $request->addFilter('rstatus', '=', 'P'); // load only pending for approval |
| 276 | } |
| 277 | if ($status === 'P') { |
| 278 | $request->addFilter('rstatus', '=', 'A'); // load only approved to change to pending (this should not ever happen) |
| 279 | } |
| 280 | if ($limit === 1) { |
| 281 | $request->addParam('sort_col', 'dateinserted'); |
| 282 | $request->addParam('sort_asc', 'false'); |
| 283 | $request->addFilter('rstatus', 'IN', $status); |
| 284 | } |
| 285 | |
| 286 | try { |
| 287 | $request->sendNow(); |
| 288 | $grid = $request->getGrid(); |
| 289 | $recordset = $grid->getRecordset(); |
| 290 | |
| 291 | if ($recordset->getSize() == 0) { |
| 292 | return $ids; |
| 293 | } |
| 294 | |
| 295 | if ($limit == 1) { |
| 296 | // load the transaction and use it's 'dateinserted' to filter all commissions of that |
| 297 | // day for the orderID - this way we will load also tier commission of subscription |
| 298 | foreach ($recordset as $rec) { |
| 299 | $dateinserted = $rec->get('dateinserted'); |
| 300 | } |
| 301 | $request2 = new Pap_Api_TransactionsGrid($session); |
| 302 | $request2->addFilter('orderid', Gpf_Data_Filter::LIKE, $orderId . '(%'); |
| 303 | $request2->addFilter('dateinserted', Gpf_Data_Filter::EQUALS, $dateinserted); |
| 304 | $request2->sendNow(); |
| 305 | $grid = $request2->getGrid(); |
| 306 | $recordset = $grid->getRecordset(); |
| 307 | } |
| 308 | |
| 309 | foreach ($recordset as $rec) { |
| 310 | $ids[] = $rec->get('id'); |
| 311 | } |
| 312 | } catch (Exception $e) { |
| 313 | self::_log('A problem occurred while loading transactions with API: ' . $e->getMessage()); |
| 314 | } |
| 315 | return $ids; |
| 316 | } |
| 317 | |
| 318 | public function loadTransactionsByOrderID($orderId, $session, $status = 'A') { |
| 319 | if (($orderId == '') || $orderId == null) { |
| 320 | return null; |
| 321 | } |
| 322 | $request = new Pap_Api_TransactionsGrid($session); |
| 323 | $request->addFilter('orderid', Gpf_Data_Filter::LIKE, $orderId . '(%'); |
| 324 | $request->addParam('columns', new Gpf_Rpc_Array(array(array('id'), array('transid'), array('orderid'), array('commission'), array('userid')))); |
| 325 | $request->sendNow(); |
| 326 | $grid = $request->getGrid(); |
| 327 | return $grid->getRecordset(); |
| 328 | } |
| 329 | |
| 330 | public function fireRecurringCommissions($session, $orderId, $total = false, $currency = false) { |
| 331 | $recurringCommission = new Pap_Api_RecurringCommission($session); |
| 332 | $recurringCommission->setOrderId($orderId); |
| 333 | if ($total !== false) { |
| 334 | $recurringCommission->setTotalCost($total); |
| 335 | } |
| 336 | if ($currency) { |
| 337 | $recurringCommission->setCurrency($currency); |
| 338 | } |
| 339 | try { |
| 340 | $recurringCommission->createCommissions(); |
| 341 | } catch (Exception $e) { |
| 342 | self::_log('Can not process recurring commission: ' . $e->getMessage()); |
| 343 | return false; |
| 344 | } |
| 345 | return true; |
| 346 | } |
| 347 | |
| 348 | public function isPluginSet() { |
| 349 | return (get_option(postaffiliatepro::PAP_MERCHANT_NAME_SETTING_NAME) != '' && get_option(postaffiliatepro::PAP_MERCHANT_PASSWORD_SETTING_NAME) != ''); |
| 350 | } |
| 351 | |
| 352 | protected function getImgUrl() { |
| 353 | return plugins_url() . self::URL_SEPARATOR . PAP_PLUGIN_NAME . self::URL_SEPARATOR . self::IMG_PATH; |
| 354 | } |
| 355 | |
| 356 | protected static function getCssUrl() { |
| 357 | return plugins_url() . self::URL_SEPARATOR . PAP_PLUGIN_NAME . self::URL_SEPARATOR . self::CSS_PATH; |
| 358 | } |
| 359 | |
| 360 | public static function sendRequest($url, $query = null) { |
| 361 | if (is_array($query)) { |
| 362 | $query = http_build_query($query); |
| 363 | } |
| 364 | $destination = $url . '?' . $query; |
| 365 | self::_log("Calling URL $destination"); |
| 366 | $response = wp_safe_remote_get($destination, [ |
| 367 | 'timeout' => 10, |
| 368 | 'sslverify' => true |
| 369 | ]); |
| 370 | |
| 371 | if (is_wp_error($response)) { |
| 372 | self::_log($response->get_error_message()); |
| 373 | return false; |
| 374 | } |
| 375 | |
| 376 | return $response; |
| 377 | } |
| 378 | } |
| 379 | } |