PluginProbe ʕ •ᴥ•ʔ
Post Affiliate Pro / trunk
Post Affiliate Pro vtrunk
1.29.5 1.29.4 1.29.3 1.29.0 1.29.1 1.29.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.5.0 1.5.1 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.1 1.6.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.9.0 1.9.1 1.9.2 1.9.3 1.9.4 trunk 1.0.1 1.0.10 1.0.11 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.10.1 1.10.2 1.10.3 1.10.4 1.11.1 1.11.2 1.12.1 1.12.2 1.12.3 1.12.4 1.12.5 1.13.0 1.13.1 1.13.2 1.13.3 1.13.4 1.13.5 1.13.6 1.14.0 1.14.1 1.14.2 1.15.0 1.15.1 1.15.2 1.15.3 1.15.4 1.15.5 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.17.0 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.19.0 1.19.1 1.19.10 1.19.11 1.19.12 1.19.13 1.19.14 1.19.15 1.19.16 1.19.17 1.19.2 1.19.3 1.19.4 1.19.5 1.19.6 1.19.7 1.19.8 1.19.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.28 1.2.3 1.2.31 1.2.32 1.2.33 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.20.0 1.20.1 1.21.0 1.21.1 1.21.2 1.21.3 1.21.4 1.21.5 1.21.6 1.21.7 1.22.0 1.22.1 1.22.2 1.23.0 1.23.1 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.24.1 1.24.2 1.24.3 1.24.4 1.24.5 1.24.6 1.24.7 1.24.8 1.24.9 1.25.0 1.26.0 1.26.1 1.26.10 1.26.11 1.26.2 1.26.3 1.26.4 1.26.5 1.26.6 1.26.7 1.26.8 1.26.9 1.27.0 1.27.1 1.27.10 1.27.11 1.27.12 1.27.13 1.27.14 1.27.15 1.27.2 1.27.3 1.27.5 1.27.6 1.27.7 1.27.8 1.27.9 1.28.0 1.28.1 1.28.2 1.28.3
postaffiliatepro / Base.class.php
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 }