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 / Form / Settings / WooComm.class.php
postaffiliatepro / Form / Settings Last commit date
AdditionalOptions.class.php 2 months ago CampaignInfo.class.php 2 months ago Campaigns.class.php 2 months ago ClickTracking.class.php 2 months ago ContactForm7.class.php 2 months ago Debugging.class.php 3 weeks ago EDD.class.php 3 weeks ago General.class.php 3 weeks ago Integrations.class.php 2 months ago LifterLMS.class.php 2 months ago Marketpress.class.php 3 weeks ago MemberPress.class.php 2 months ago Membership2.class.php 2 months ago PMPro.class.php 2 months ago PPBuyNowButton.class.php 2 months ago RestrictContentPro.class.php 2 months ago S2Member.class.php 2 months ago Signup.class.php 2 months ago SimplePayPro.class.php 2 months ago StripePayments.class.php 3 weeks ago SureCart.class.php 2 months ago WPEasyCart.class.php 2 months ago WPPayForms.class.php 2 months ago WishListMember.class.php 2 months ago WooComm.class.php 3 weeks ago
WooComm.class.php
1230 lines
1 <?php
2 if (!defined('ABSPATH')) exit;
3
4 class postaffiliatepro_Form_Settings_WooComm extends postaffiliatepro_Form_Base {
5 const WOOCOMM_COMMISSION_ENABLED = 'woocomm-commission-enabled';
6 const WOOCOMM_CONFIG_PAGE = 'woocomm-config-page';
7 const WOOCOMM_ORDERID_SETTING = 'woocomm-orderid';
8 const WOOCOMM_PERPRODUCT = 'woocomm-per-product';
9 const WOOCOMM_PRODUCT_ID = 'woocomm-product-id';
10 const WOOCOMM_DATA1 = 'woocomm-data1';
11 const WOOCOMM_DATA2 = 'woocomm-data2';
12 const WOOCOMM_DATA3 = 'woocomm-data3';
13 const WOOCOMM_DATA4 = 'woocomm-data4';
14 const WOOCOMM_DATA5 = 'woocomm-data5';
15 const WOOCOMM_CAMPAIGN = 'woocomm-campaign';
16 const WOOCOMM_STATUS_UPDATE = 'woocomm-status-update';
17 const WOOCOMM_AFFILIATE_APPROVAL = 'woocomm-affiliate-approval';
18 const WOOCOMM_TRACK_RECURRING_TOTAL = 'woocomm-track-recurring-total';
19 const WOOCOMM_TRACK_RECURRING_SEPARATELY = 'woocomm-track-recurring-separately';
20 const WOOCOMM_DEDUCT_FEES = 'woocomm-deduct-fees';
21
22 const WOOCOMM_ORDER_ID = 'Order ID';
23 const WOOCOMM_ORDER_NUMBER = 'Order number';
24
25 private $saleTrackingCodeAdded = false;
26
27 public function __construct() {
28 parent::__construct(self::WOOCOMM_CONFIG_PAGE, 'options.php');
29 }
30
31 protected function getTemplateFile() {
32 return WP_PLUGIN_DIR . '/postaffiliatepro/Template/WooCommConfig.xtpl';
33 }
34
35 protected function initForm() {
36 $this->addSelect(self::WOOCOMM_ORDERID_SETTING, array(
37 self::WOOCOMM_ORDER_ID => self::WOOCOMM_ORDER_ID,
38 self::WOOCOMM_ORDER_NUMBER => self::WOOCOMM_ORDER_NUMBER
39 ));
40 $this->addCheckbox(self::WOOCOMM_PERPRODUCT);
41 $this->addCheckbox(self::WOOCOMM_TRACK_RECURRING_TOTAL);
42 $this->addCheckbox(self::WOOCOMM_TRACK_RECURRING_SEPARATELY);
43 $this->addCheckbox(self::WOOCOMM_DEDUCT_FEES);
44 $this->addSelect(self::WOOCOMM_PRODUCT_ID, array(
45 '0' => ' ',
46 'id' => 'product ID',
47 'title' => 'product name',
48 'var' => 'variation ID',
49 'sku' => 'SKU',
50 'categ' => 'product category',
51 'tag' => 'product tag',
52 'role' => 'user role'
53 ));
54 $this->addCheckbox(self::WOOCOMM_STATUS_UPDATE);
55
56 $productOptions = array(
57 '0' => ' ',
58 'id' => 'customer ID',
59 'email' => 'customer email',
60 'name' => 'customer name', // $billing_first_name $billing_last_name
61 'phone' => 'customer phone',
62 'pmethod' => 'payment method', // $payment_method_title
63 'discount' => 'cart discount', // $cart_discount
64 'coupon' => 'coupon code',
65 'title' => 'product name',
66 'order' => 'order name',
67 'order_note' => 'order note'
68
69 );
70 $this->addSelect(self::WOOCOMM_DATA1, $productOptions);
71 $this->addSelect(self::WOOCOMM_DATA2, $productOptions);
72 $this->addSelect(self::WOOCOMM_DATA3, $productOptions);
73 $this->addSelect(self::WOOCOMM_DATA4, $productOptions);
74 $this->addSelect(self::WOOCOMM_DATA5, $productOptions);
75 $this->addTextBox(self::WOOCOMM_AFFILIATE_APPROVAL);
76
77 $campaignHelper = new postaffiliatepro_Util_CampaignHelper();
78 $campaignList = $campaignHelper->getCampaignsList();
79
80 $campaigns = array(
81 '0' => ' '
82 );
83 foreach ($campaignList as $row) {
84 $campaigns[$row->get('campaignid')] = htmlspecialchars($row->get('name'));
85 }
86 $this->addSelect(self::WOOCOMM_CAMPAIGN, $campaigns);
87
88 $this->addSubmit();
89
90 $this->addHtml('currentOrderIdSetting', get_option(self::WOOCOMM_ORDERID_SETTING));
91 $this->addHtml('currentStatusUpdateSetting', get_option(self::WOOCOMM_STATUS_UPDATE));
92 }
93
94 public function initSettings() {
95 register_setting(postaffiliatepro::INTEGRATIONS_SETTINGS_PAGE_NAME, self::WOOCOMM_COMMISSION_ENABLED);
96 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_ORDERID_SETTING);
97 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_PERPRODUCT);
98 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_PRODUCT_ID);
99 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_STATUS_UPDATE);
100 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_DATA1);
101 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_DATA2);
102 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_DATA3);
103 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_DATA4);
104 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_DATA5);
105 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_CAMPAIGN);
106 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_AFFILIATE_APPROVAL, ['sanitize_callback' => 'sanitize_text_field']);
107 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_TRACK_RECURRING_TOTAL);
108 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_TRACK_RECURRING_SEPARATELY);
109 register_setting(self::WOOCOMM_CONFIG_PAGE, self::WOOCOMM_DEDUCT_FEES);
110 }
111
112 public function addPrimaryConfigMenu() {
113 if (get_option(self::WOOCOMM_COMMISSION_ENABLED) == 'true') {
114 add_submenu_page('integrations-config-page-handle', 'WooCommerce', 'WooCommerce', 'manage_options', 'woocommintegration-settings-page', array(
115 $this,
116 'printConfigPage'
117 ));
118 }
119 }
120
121 public function printConfigPage() {
122 $this->render();
123 }
124
125 public function wooHandleCustomThankYouPages($content) {
126 if (get_option(self::WOOCOMM_COMMISSION_ENABLED) !== 'true') {
127 return $content;
128 }
129 if (!function_exists('wc_get_order')) {
130 return $content;
131 }
132 if (isset($_GET['ctpw'], $_GET['key'], $_GET['order']) && $_GET['ctpw'] !== '' && $_GET['key'] !== '' && $_GET['order'] !== '') {
133 $this->wooAddThankYouPageTrackSale(sanitize_text_field(wp_unslash($_GET['order'])));
134 return $content;
135 }
136 if (isset($_GET['ctpw'], $_GET['key'], $_GET['order-received']) && $_GET['ctpw'] !== '' && $_GET['key'] !== '' && $_GET['order-received'] !== '') {
137 $this->wooAddThankYouPageTrackSale(sanitize_text_field(wp_unslash($_GET['order-received'])));
138 return $content;
139 }
140 if (isset($_GET['order']) && $_GET['order'] !== '') { // Thanks Redirect 3.0
141 $this->wooAddThankYouPageTrackSale(sanitize_text_field(wp_unslash($_GET['order'])));
142 return $content;
143 }
144 if (isset($_GET['wcf-order'], $_GET['wcf-key'], $_GET['wcf-sk']) && $_GET['wcf-order'] !== '' && $_GET['wcf-key'] !== '' && $_GET['wcf-sk'] !== '') {
145 $this->wooAddThankYouPageTrackSale(sanitize_text_field(wp_unslash($_GET['wcf-order'])));
146 return $content;
147 }
148 if (isset($_GET['ctp_order_id'], $_GET['ctp_order_key']) && $_GET['ctp_order_id'] !== '' && $_GET['ctp_order_key'] !== '') {
149 $this->wooAddThankYouPageTrackSale(sanitize_text_field(wp_unslash($_GET['ctp_order_id'])));
150 return $content;
151 }
152 if (isset($_SERVER['REQUEST_URI']) && sanitize_url(wp_unslash($_SERVER['REQUEST_URI'])) !== '') { // ELEMENTOR
153 $reqUri = explode('?', sanitize_url(wp_unslash($_SERVER['REQUEST_URI'])));
154 $reqUri = explode('/', substr($reqUri[0], 1, -1)); // e.g. custom-name/order-received/771
155 if (isset($_GET['key']) && $_GET['key'] !== ''
156 && $reqUri[1] == 'order-received' && $reqUri[0] != 'checkout' // as this is the original form
157 && isset($reqUri[2]) && $reqUri[2] !== '') {
158 $this->wooAddThankYouPageTrackSale($reqUri[2]);
159 return $content;
160 }
161 }
162 // funnelkit
163 if (isset($_GET['wfocu-si']) && sanitize_text_field(wp_unslash($_GET['wfocu-si'])) !== '' &&
164 function_exists('WFOCU_Core') && WFOCU_Core()->data->has_valid_session()) {
165 $this->_log('FunnelKit - adding sale tracking code for new order');
166 $this->wooAddFunnelKitSaleTracker();
167 }
168 return $content;
169 }
170
171 public function wooAddFunnelKitSaleTracker() {
172 echo "<!-- Post Affiliate Pro sale tracking (FunnelKit) -->\n";
173 $contentToAsync = 'PostAffTracker.setAccountId(\'' . postaffiliatepro::getAccountName() . "');\n";
174 $contentToAsync .= 'var papOrderId = wfocu_tracking_data.order_id;'."\n";
175 $contentToAsync .= "if (typeof papOrderId == 'undefined' || papOrderId == '') {papOrderId = wfocu_tracking_data.ga_transaction_id}\n";
176 $contentToAsync .= "var papTotal = wfocu_tracking_data.total - wfocu_tracking_data.shipping - wfocu_tracking_data.tax;\n";
177
178 $productAttrib = 'id';
179 switch (get_option(self::WOOCOMM_PRODUCT_ID)) {
180 case 'sku':
181 $productAttrib = 'sku';
182 break;
183 case 'title':
184 $productAttrib = 'name';
185 break;
186 case 'categ':
187 $productAttrib = 'category';
188 }
189
190 if (get_option(self::WOOCOMM_PERPRODUCT) === 'true') {
191 // compute discount value
192 $contentToAsync .= "var discount = 1;\n";
193 $contentToAsync .= "if (typeof wfocu_tracking_data.additional.coupon_name !== 'undefined') {\n";
194 $contentToAsync .= "var fullProductPrice = 0;\n";
195 $contentToAsync .= "wfocu_tracking_data.products.forEach(function(prod, i){\n";
196 $contentToAsync .= "fullProductPrice += prod.item_total;\n";
197 $contentToAsync .= "})};\n";
198 $contentToAsync .= "if (fullProductPrice != 1) {\n";
199 $contentToAsync .= "discount = papTotal / fullProductPrice;\n";
200 $contentToAsync .= "}\n";
201 } else {
202 // prepare one product only
203 $contentToAsync .= "var papProd = '';\n";
204 $contentToAsync .= "wfocu_tracking_data.products.forEach(function(prod, i){\n";
205 $contentToAsync .= "if (i == 0) {var papProd = prod.$productAttrib}";
206 $contentToAsync .= "});\n";
207 }
208
209 $campaign = '';
210 if (get_option(self::WOOCOMM_CAMPAIGN) !== ''
211 && get_option(self::WOOCOMM_CAMPAIGN) !== null
212 && get_option(self::WOOCOMM_CAMPAIGN) !== 0
213 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
214 $campaign = get_option(self::WOOCOMM_CAMPAIGN);
215 }
216
217 if (get_option(self::WOOCOMM_PERPRODUCT) === 'true') {
218 $contentToAsync .= "wfocu_tracking_data.products.forEach(function(prod, i){\n";
219 $contentToAsync .= "var sale = PostAffTracker.createSale();\n";
220 $contentToAsync .= "sale.setTotalCost(prod.item_total * discount);\n";
221 $contentToAsync .= "sale.setProductID(prod.$productAttrib);\n";
222 $contentToAsync .= 'sale.setOrderID(papOrderId + "(" + (i+1) +")");' . "\n";
223 $contentToAsync .= "sale.setCurrency(wfocu_tracking_data.currency);\n";
224 $contentToAsync .= "sale.setData1(wfocu_tracking_data.email);\n";
225 $contentToAsync .= "if (typeof wfocu_tracking_data.additional.coupon_name !== 'undefined') {sale.setCoupon(wfocu_tracking_data.additional.coupon_name);}\n";
226 if ($campaign != '') $contentToAsync .= "sale.setCampaignID('$campaign');\n";
227 $contentToAsync .= "PostAffTracker.register();";
228 $contentToAsync .= "});\n";
229 } else {
230 $contentToAsync .= "var sale = PostAffTracker.createSale();\n";
231 $contentToAsync .= "sale.setTotalCost(papTotal);\n";
232 $contentToAsync .= "sale.setProductID(papProd);\n";
233 $contentToAsync .= 'sale.setOrderID(papOrderId + "(1)");'."\n";
234 $contentToAsync .= "sale.setCurrency(wfocu_tracking_data.currency);\n";
235 $contentToAsync .= "sale.setData1(wfocu_tracking_data.email);\n";
236 $contentToAsync .= "if (typeof wfocu_tracking_data.additional.coupon_name !== 'undefined') {sale.setCoupon(wfocu_tracking_data.additional.coupon_name);}\n";
237 $contentToAsync .= $campaign;
238 $contentToAsync .= "PostAffTracker.register();";
239 }
240
241 if (get_option(postaffiliatepro::ASYNC_ENABLED) != 'true') {
242 $result = postaffiliatepro::getPAPTrackJSDynamicCode().'<script type="text/javascript">';
243 $result .= $contentToAsync . "</script>\n";
244 } else {
245 $result = postaffiliatepro::getPAPTrackJSAsyncCode($contentToAsync);
246 }
247
248 echo $result;
249 }
250
251 public function wooAddThankYouPageTrackSale($order_id) {
252 if (get_option(self::WOOCOMM_COMMISSION_ENABLED) !== 'true') {
253 echo "<!-- Post Affiliate Pro sale tracking error - tracking not enabled -->\n";
254 return $order_id;
255 }
256 $order = wc_get_order($order_id);
257 if (empty($order)) {
258 echo '<!-- Post Affiliate Pro sale tracking error - no order loaded for order ID ' . $order_id . " -->\n";
259 return $order_id;
260 }
261 if (function_exists('WFOCU_Core') && WFOCU_Core()->data->has_valid_session()) {
262 // ignore thank you page to prevent duplicates (funnelkit integration)
263 $this->saleTrackingCodeAdded = true;
264 }
265 if ($this->saleTrackingCodeAdded === true) {
266 $this->_log('Custom thank you page already tracked the sale.');
267 echo "<!-- Post Affiliate Pro sale tracking - already tracked -->\n";
268 return $order_id;
269 }
270
271 if (isset($_GET['customGateway'])) {
272 if (empty($_REQUEST['cm']) || empty($_REQUEST['tx']) || empty($_REQUEST['st'])) {
273 // SKIP THANK YOU PAGE, SALE WILL BE TRACKED FROM PAYPAL IPN
274 echo "<!-- Post Affiliate Pro sale tracking - no sale tracker needed -->\n";
275 $this->_log('Thank you page sale tracking is skipped (customGateway).');
276 return $order_id;
277 } else {
278 // THIS IS A PDT RESPONSE, NO IPN WILL BE USED/VALIDATED/TRIGGERED, CONTINUE TO THANK YOU PAGE
279 }
280 }
281 // RevCent integration
282 $paymentMethod = $order->get_payment_method();
283 if ($paymentMethod == 'revcent_payments' || strpos($paymentMethod, 'revcent') !== false) {
284 // SKIP THANK YOU PAGE, SALE WILL BE TRACKED FROM REVCENT WEBHOOK
285 echo "<!-- Post Affiliate Pro sale tracking - no sale tracker needed -->\n";
286 $this->_log('Thank you page sale tracking is skipped (RevCent).');
287 return $order_id;
288 }
289 $this->trackWooOrder($order);
290 $this->saleTrackingCodeAdded = true; // in case footer was triggered before custom thank you page
291 return $order_id;
292 }
293
294 private function trackWooOrder($order) {
295 $orderId = $this->getOrderId($order);
296
297 echo "<!-- Post Affiliate Pro sale tracking -->\n";
298 $contentToAsync = 'PostAffTracker.setAccountId(\'' . postaffiliatepro::getAccountName() . '\');';
299
300 $status = '';
301 if (get_option(self::WOOCOMM_STATUS_UPDATE) === 'true') {
302 $orderStatus = $order->get_status();
303 switch ($orderStatus) {
304 case 'completed': $status = 'A'; break;
305 case 'cancelled':
306 case 'refunded':
307 case 'failed': $status = 'D'; break;
308 default: $status = '';
309 }
310 }
311 if ($status === 'D') {
312 $this->_log('The order was not successful, no commissions will be created.');
313 return false;
314 }
315
316 try {
317 if (method_exists($order, 'get_coupon_codes')) { // for newer versions
318 $coupons = $order->get_coupon_codes();
319 } else {
320 $coupons = $order->get_used_coupons();
321 }
322 $couponCode = implode(',', $coupons);
323 } catch (Exception $e) {
324 //
325 }
326
327 if (get_option(self::WOOCOMM_PERPRODUCT) === 'true') {
328 $parentOrderId = $order->get_parent_id();
329 if (get_class($order) == 'AWCDP_Order' && !empty($parentOrderId)) {
330 $order = wc_get_order($order->get_parent_id());
331 $orderId = $this->getOrderId($order);
332 // as the order uses the deposit plugin, the original order is definitely not paid so we will set pending status here
333 $status = 'P';
334 }
335
336 $i = 1;
337 $count = count($order->get_items());
338 foreach ($order->get_items() as $item) {
339 $itemprice = $item['line_total'];
340
341 $contentToAsync .= "var sale$i = PostAffTracker.createSale();\n";
342 $contentToAsync .= "sale$i.setTotalCost('" . $itemprice . "');\n";
343 $contentToAsync .= "sale$i.setOrderID('$orderId($i)');\n";
344 $contentToAsync .= "sale$i.setProductID('" . str_replace("'","\'",$this->getTrackingProductID($order, $item)) . "');\n";
345 $contentToAsync .= "sale$i.setCurrency('" . $order->get_currency() . "');\n";
346 $contentToAsync .= "sale$i.setCoupon('" . $couponCode . "');\n";
347
348 for ($d = 1; $d <=5; $d++) {
349 $contentToAsync .= "sale$i.setData$d('" . str_replace("'","\'",$this->getTrackingData($order, $d, $item, $couponCode)) . "');\n";
350 }
351 if (get_option(self::WOOCOMM_CAMPAIGN) !== '' && get_option(self::WOOCOMM_CAMPAIGN) !== null && get_option(self::WOOCOMM_CAMPAIGN) !== 0 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
352 $contentToAsync .= "sale$i.setCampaignID('" . get_option(self::WOOCOMM_CAMPAIGN) . "');\n";
353 }
354 if ($status != '') {
355 $contentToAsync .= "sale$i.setStatus('" . $status . "');\n";
356 }
357
358 if ($i != $count) { // delete cookie after sale fix
359 $contentToAsync .= "if (typeof sale$i.doNotDeleteCookies=== 'function') {sale$i.doNotDeleteCookies();}
360 PostAffTracker.register();";
361 } else {
362 $contentToAsync .= "if (typeof PostAffTracker.registerOnAllFinished === 'function') {
363 PostAffTracker.registerOnAllFinished();
364 } else {
365 PostAffTracker.register();
366 }";
367 }
368 $i++;
369 }
370 } else {
371 $contentToAsync .= "var sale = PostAffTracker.createSale();\n";
372 $contentToAsync .= "sale.setTotalCost('" . $this->getSubtotal($order) . "');\n";
373 $contentToAsync .= "sale.setOrderID('$orderId(1)');\n";
374 $contentToAsync .= "sale.setCurrency('" . $order->get_currency() . "');\n";
375 $contentToAsync .= "sale.setProductID('" . str_replace("'","\'",$this->getTrackingProductIDsLine($order)) . "');\n";
376 for ($d = 1; $d <=5; $d++) {
377 $contentToAsync .= "sale.setData$d('" . str_replace("'","\'",$this->getTrackingData($order, $d, null, $couponCode)) . "');\n";
378 }
379 $contentToAsync .= "sale.setCoupon('" . $couponCode . "');\n";
380
381 if (get_option(self::WOOCOMM_CAMPAIGN) !== '' && get_option(self::WOOCOMM_CAMPAIGN) !== null && get_option(self::WOOCOMM_CAMPAIGN) !== 0 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
382 $contentToAsync .= "sale.setCampaignID('" . get_option(self::WOOCOMM_CAMPAIGN) . "');\n";
383 }
384 if ($status != '') {
385 $contentToAsync .= "sale.setStatus('" . $status . "');\n";
386 }
387
388 $contentToAsync .= 'PostAffTracker.register();';
389 }
390
391 if (get_option(postaffiliatepro::ASYNC_ENABLED) != 'true') {
392 $result = postaffiliatepro::getPAPTrackJSDynamicCode().'<script type="text/javascript">';
393 $result .= $contentToAsync . "</script>\n";
394 } else {
395 $result = postaffiliatepro::getPAPTrackJSAsyncCode($contentToAsync);
396 }
397
398 echo $result;
399
400 // affiliate approval?
401 if (get_option(self::WOOCOMM_AFFILIATE_APPROVAL) != '') {
402 $approvalProducts = explode(';', get_option(self::WOOCOMM_AFFILIATE_APPROVAL));
403 $orderedProducts = explode(', ', $this->getTrackingProductIDsLine($order));
404 foreach ($orderedProducts as $item) {
405 if (in_array($item, $approvalProducts)) {
406 // approve the customer/affiliate
407 $this->changeAffiliateStatus($order->get_billing_email(), 'A');
408 break;
409 }
410 }
411 }
412
413 return true;
414 }
415
416 private function trackWooOrderRemote($order, $affiliateId = null, $orderRefunds = null) {
417 $orderId = $this->getOrderId($order, false);
418
419 if (get_option(self::WOOCOMM_PERPRODUCT) === 'true') {
420 $i = 1;
421 $count = count($order->get_items());
422
423 $status = '';
424 if (get_option(self::WOOCOMM_STATUS_UPDATE) === 'true') {
425 $orderStatus = $order->get_status();
426 switch ($orderStatus) {
427 case 'completed': $status = 'A'; break;
428 case 'cancelled':
429 case 'refunded':
430 case 'failed': $status = 'D'; break;
431 default: $status = '';
432 }
433 }
434 if ($status === 'D') {
435 $this->_log('The order was not successful, no commissions will be created.');
436 return false;
437 }
438
439 $parentOrderId = $order->get_parent_id();
440 if (get_class($order) == 'AWCDP_Order' && !empty($parentOrderId)) {
441 $order = wc_get_order($order->get_parent_id());
442 $orderId = $this->getOrderId($order);
443 }
444
445 foreach ($order->get_items() as $item) {
446 if (!empty($orderRefunds)) {
447 if (in_array($item['product_id'], $orderRefunds)) {
448 // this item was refunded, ignore it
449 continue;
450 }
451 }
452 $itemprice = $item['line_total'];
453 $couponCode = '';
454
455 try { //if coupon has been used, set the last one in the setCoupon() parameter
456 if (method_exists($order, 'get_coupon_codes')) { // for newer versions
457 $coupons = $order->get_coupon_codes();
458 } else {
459 $coupons = $order->get_used_coupons();
460 }
461
462 $couponCode = urlencode(implode(',', $coupons));
463 } catch (Exception $e) {
464 $this->_log('Getting coupon failed, error: '.$e->getMessage());
465 }
466
467 $query = 'AccountID='.postaffiliatepro::getAccountName()."&TotalCost=$itemprice&OrderID=" . $orderId . "($i)";
468 $query .= '&ProductID=' . urlencode($this->getTrackingProductID($order, $item));
469 $query .= '&Currency=' . $order->get_currency() . "&Coupon=$couponCode";
470
471 for ($d = 1; $d <=5; $d++) {
472 $query .= "&Data$d=".urlencode($this->getTrackingData($order, $d, $item, $couponCode));
473 }
474
475 if (get_option(self::WOOCOMM_CAMPAIGN) !== '' && get_option(self::WOOCOMM_CAMPAIGN) !== null && get_option(self::WOOCOMM_CAMPAIGN) !== 0 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
476 $query .= '&CampaignID='.get_option(self::WOOCOMM_CAMPAIGN);
477 }
478
479 if ($affiliateId != null) {
480 $query .= "&AffiliateID=$affiliateId";
481 }
482
483 if ($i != $count) { // delete cookie after sale fix
484 $query .= '&DoNotDeleteCookies=Y';
485 }
486 self::sendRequest(postaffiliatepro::parseSaleScriptPath(), $query);
487 $i++;
488 }
489 } else {
490 if (method_exists($order, 'get_coupon_codes')) { // for newer versions
491 $coupons = $order->get_coupon_codes();
492 } else {
493 $coupons = $order->get_used_coupons();
494 }
495 $couponCode = urlencode(implode(',', $coupons));
496 $query = 'AccountID='.postaffiliatepro::getAccountName().'&TotalCost=' . $this->getSubtotal($order, $orderRefunds) . '&OrderID=' . $orderId . '(1)';
497 $query .= '&ProductID=' . urlencode($this->getTrackingProductIDsLine($order));
498 $query .= '&Currency=' . $order->get_currency() . '&Coupon=' . $couponCode;
499
500 for ($d = 1; $d <=5; $d++) {
501 $query .= "&Data$d=" . urlencode($this->getTrackingData($order, $d, null, $couponCode));
502 }
503
504 if (get_option(self::WOOCOMM_CAMPAIGN) !== '' && get_option(self::WOOCOMM_CAMPAIGN) !== null && get_option(self::WOOCOMM_CAMPAIGN) !== 0 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
505 $query .= '&CampaignID=' . get_option(self::WOOCOMM_CAMPAIGN);
506 }
507
508 if ($affiliateId != null) {
509 $query .= "&AffiliateID=$affiliateId";
510 }
511
512 self::sendRequest(postaffiliatepro::parseSaleScriptPath(), $query);
513 }
514 }
515
516 private function getSubtotal($order, $orderRefunds = 0) {
517 $subtotal = $order->get_total() - $order->get_total_tax() - $order->get_shipping_total();
518
519 if (!empty($orderRefunds) && !is_array($orderRefunds)) {
520 $subtotal -= $orderRefunds;
521 }
522
523 if (get_option(self::WOOCOMM_DEDUCT_FEES) === 'true') {
524 foreach ($order->get_fees() as $fee) {
525 $subtotal -= $fee->get_total();
526 }
527 }
528 return $subtotal;
529 }
530
531 private function getTrackingProductID($order, $item) {
532 $product = $item->get_product();
533 try {
534 $productId = $item->get_product_id();
535 } catch (Exception $e) {
536 $productId = $product->get_id();
537 }
538
539 switch (get_option(self::WOOCOMM_PRODUCT_ID)) {
540 case 'id':
541 return $productId;
542 case 'sku':
543 if (!empty($product->get_sku())) {
544 return $product->get_sku();
545 } else {
546 return $productId;
547 }
548 case 'var':
549 $variationId = $productId;
550 try {
551 $variationId = $item->get_variation_id();
552 } catch (Exception $e) {
553 if ($product->is_type('variation')) {
554 $variationId = $product->get_variation_id();
555 }
556 }
557 return ($variationId === 0) ? $productId : $variationId;
558 case 'categ':
559 $categories = explode(',', wc_get_product_category_list($productId,','));
560 return wp_strip_all_tags($categories[0]);
561 case 'tag':
562 $tags = explode(',', wc_get_product_tag_list($productId,','));
563 return wp_strip_all_tags($tags[0]);
564 case 'role':
565 try {
566 $user = new WP_User($order->get_user_id());
567 if (isset($user->roles[0])) {
568 return $user->roles[0];
569 } else {
570 break;
571 }
572 } catch (Exception $e) {
573 break;
574 }
575 case 'title':
576 return $product->get_name();
577 }
578 return '';
579 }
580
581 private function getTrackingProductIDsLine($order) {
582 $productSelection = get_option(self::WOOCOMM_PRODUCT_ID);
583 if (empty($productSelection)) {
584 return '';
585 }
586
587 $line = '';
588 foreach ($order->get_items() as $item) {
589 $line .= $this->getTrackingProductID($order, $item) . ', ';
590 }
591 if (!empty($line)) {
592 $line = substr($line, 0, -2);
593 }
594 return $line;
595 }
596
597 private function getTrackingData($order, $n, $item = null, $coupon = '') {
598 $product = null;
599 if ($item != null) {
600 $product = $item->get_product();
601 }
602 $data = get_option(constant('self::WOOCOMM_DATA'.$n));
603 switch ($data) {
604 case 'id':
605 if ($order->get_user_id() != '') {
606 return $order->get_user_id();
607 }
608 return crc32($order->get_billing_email());
609 case 'email':
610 return $order->get_billing_email();
611 case 'name':
612 return $order->get_billing_first_name().' '.$order->get_billing_last_name();
613 case 'phone':
614 return $order->get_billing_phone();
615 case 'pmethod':
616 return $order->get_payment_method_title();
617 case 'discount':
618 return $order->get_total_discount();
619 case 'coupon':
620 return $coupon;
621 case 'title':
622 if ($product != null) {
623 return get_the_title($product->get_id());
624 } else {
625 return '';
626 }
627 case 'order':
628 return '#'.$order->get_order_number();
629 case 'order_note':
630 return $this->getOrderNote($order->get_id());
631 default: return '';
632 }
633 }
634
635 private function getOrderNote($orderId) {
636 $post = get_post($orderId);
637 if (!$post) {
638 return '';
639 }
640 return substr($post->post_excerpt, 0, 255);
641 }
642
643 public function wooOrderStatusChanged($orderId, $old_status, $new_status) {
644 if (get_option(self::WOOCOMM_STATUS_UPDATE) !== 'true') {
645 return false;
646 }
647
648 $this->_log('Received status: ' . $new_status);
649
650 switch ($new_status) {
651 case 'completed':
652 $status = 'A';
653 break;
654 case 'processing':
655 case 'on-hold':
656 $status = 'P';
657 break;
658 case 'cancelled':
659 case 'failed':
660 $status = 'D';
661 break;
662 case 'refunded':
663 return $this->refundTransaction($orderId);
664 default:
665 $status = '';
666 }
667
668 if ($status == '') {
669 $this->_log('Unsupported status ' . $new_status);
670 return false;
671 }
672
673 $orderId = $this->getOrderId(wc_get_order($orderId));
674
675 return $this->changeOrderStatus($orderId, $status);
676 }
677
678 private function refundTransaction($orderId) {
679 $limit = 100;
680 $isSubscription = false;
681 if (function_exists('wcs_get_subscriptions_for_order') &&
682 get_option(self::WOOCOMM_TRACK_RECURRING_SEPARATELY) !== 'true') { // we will have to refund one of the recurring commissions
683 $subscriptions = wcs_get_subscriptions_for_order($orderId);
684 if (!empty($subscriptions)) {
685 foreach ($subscriptions as $key => $value) { // take the first and leave
686 $orderId = $key;
687 $limit = 1;
688 $isSubscription = true;
689 break;
690 }
691 }
692 }
693 if (!$isSubscription && get_option(self::WOOCOMM_ORDERID_SETTING) === self::WOOCOMM_ORDER_NUMBER) {
694 $order = wc_get_order($orderId);
695 $orderId = $order->get_order_number();
696 }
697
698 $session = $this->getApiSession();
699 if ($session === null || $session === '0') {
700 $this->_log('We have no session to PAP installation! Transaction status change failed.');
701 return false;
702 }
703 $ids = $this->getTransactionIDsByOrderID($orderId, $session, 'A,P', $limit);
704 if (empty($ids)) {
705 $this->_log('Nothing to change, the commission does not exist in PAP');
706 return true;
707 }
708
709 $request = new Gpf_Rpc_FormRequest('Pap_Merchants_Transaction_TransactionsForm', 'makeRefundChargeback', $session);
710 $request->addParam('ids', new Gpf_Rpc_Array($ids));
711 $request->addParam('status', 'R');
712 $request->addParam('merchant_note', 'Refunded automatically from WooCommerce');
713 $request->addParam('refund_multitier', 'Y');
714 try {
715 $request->sendNow();
716 } catch (Exception $e) {
717 $this->_log('A problem occurred while transaction status change with API: ' . $e->getMessage());
718 return false;
719 }
720
721 return true;
722 }
723
724 public function wooSubscriptionStatusChanged($orderId, $old_status, $new_status) {
725 if ($new_status !== 'cancelled') {
726 return false;
727 }
728 $session = $this->getApiSession();
729 if ($session === null || $session === '0') {
730 $this->_log('We have no session to PAP installation! Transaction status change failed.');
731 return;
732 }
733 // load recurring order ID
734 $request = new Gpf_Rpc_GridRequest('Pap_Features_RecurringCommissions_RecurringCommissionsGrid', 'getRows', $session);
735 $request->addFilter('orderid', 'L', $orderId . '(%');
736 $recurringIds = array();
737 try {
738 $request->sendNow();
739 $grid = $request->getGrid();
740 $recordset = $grid->getRecordset();
741 foreach ($recordset as $rec) {
742 $recurringIds[] = $rec->get('orderid');
743 }
744 } catch (Exception $e) {
745 $this->_log('A problem occurred while loading recurring commissions: ' . $e->getMessage());
746 return false;
747 }
748
749 if (empty($recurringIds)) {
750 $this->_log('Nothing to change, the commission does not exist in PAP');
751 return false;
752 }
753
754 $request = new Gpf_Rpc_FormRequest('Pap_Features_RecurringCommissions_RecurringCommissionsForm', 'changeStatus', $session);
755 $request->addParam('ids', new Gpf_Rpc_Array($recurringIds));
756 $request->addParam('status', 'D');
757 try {
758 $request->sendNow();
759 } catch (Exception $e) {
760 $this->_log('A problem occurred while transaction status change with API: ' . $e->getMessage());
761 return false;
762 }
763
764 return true;
765 }
766
767 public function wooRecurringCommission($renewal_order, $subscription) {
768 if (!is_object($subscription)) {
769 $subscription = wcs_get_subscription($subscription);
770 }
771
772 if (!is_object($renewal_order)) {
773 $renewal_order = wc_get_order($renewal_order);
774 }
775
776 // try to recur a commission with order ID $subscription->id
777 $session = $this->getApiSession();
778 if ($session === null || $session === '0') {
779 $this->_log('We have no session to PAP installation! Recurring commission failed.');
780 return $renewal_order;
781 }
782
783 $recurringSubtotal = false;
784 if (get_option(self::WOOCOMM_TRACK_RECURRING_TOTAL) === 'true') {
785 $recurringSubtotal = $renewal_order->get_total() - $renewal_order->get_total_tax() - $renewal_order->get_shipping_total();
786 }
787 if (!$this->fireRecurringCommissions($session, $subscription->id . '(1)', $recurringSubtotal)) {
788 // creating recurring commissions failed, create a new commission instead
789 $this->_log('Creating new commissions with order ID ' . $renewal_order->id . '(1)');
790 $this->trackWooOrderRemote($renewal_order);
791 }
792
793 return $renewal_order;
794 }
795
796 public function wooAutoshipCommission($order_id, $schedule_id) {
797 // can work only with lifetime relations, no way to use recurring commissions
798 $renewal_order = wc_get_order($order_id);
799 $this->_log('Creating new commissions with order ID ' . $renewal_order->id . '(1)');
800 $this->trackWooOrderRemote($renewal_order);
801 return $renewal_order;
802 }
803
804 public function wooModifyPaypalArgs($array) {
805 if (strpos($array['notify_url'], '?')) {
806 $array['notify_url'] .= '&';
807 } else {
808 $array['notify_url'] .= '?';
809 }
810 if (isset($_REQUEST['pap_custom'])) {
811 $array['notify_url'] .= 'pap_custom=' . sanitize_text_field(wp_unslash($_REQUEST['pap_custom']));
812 }
813 if (isset($_REQUEST['pap_IP']) && ($ip = filter_var(wp_unslash($_REQUEST['pap_IP']), FILTER_VALIDATE_IP))) {
814 $array['notify_url'] .= '&pap_IP=' . $ip;
815 }
816 if (strpos($array['return'], '?')) {
817 $array['return'] .= '&';
818 } else {
819 $array['return'] .= '?';
820 }
821 $array['return'] .= 'customGateway=paypal';
822 return $array;
823 }
824
825 public function wooProcessPaypalIPN($post_data) {
826 $this->_log('PayPal IPN received: '.print_r($post_data,true));
827 $post_data['payment_status'] = strtolower($post_data['payment_status']);
828 if (empty($post_data['custom'])) {
829 $this->_log('PayPal IPN received but didn\'t find anything in custom, expected WooCommerce order details, stopping.');
830 return false;
831 }
832 if (!$order = $this->get_paypal_order($post_data['custom'])) {
833 $this->_log('PayPal IPN received but couldn\'t load the WooCommerce order for the IPN, stopping. Content of custom was '.$post_data['custom']);
834 return false;
835 }
836
837 if ($post_data['payment_status'] === 'completed') {
838 $orderId = $this->getOrderId($order, false);
839 if (get_option(self::WOOCOMM_PERPRODUCT) === 'true') {
840 $i = 1;
841 $count = count($order->get_items());
842 foreach ($order->get_items() as $item) {
843 $itemprice = $item['line_total'];
844 $couponCode = '';
845
846 try { //if coupon has been used, set the last one in the setCoupon() parameter
847 if (method_exists($order, 'get_coupon_codes')) { // for newer versions
848 $coupons = $order->get_coupon_codes();
849 } else {
850 $coupons = $order->get_used_coupons();
851 }
852 $couponCode = $this->resolveCoupons($coupons);
853 } catch (Exception $e) {
854 //echo "<!--Error: ".$e->getMessage()."-->";
855 }
856
857 $query = '';
858 if (isset($_GET['pap_custom'])) {
859 $query = 'AccountId=' . substr(sanitize_text_field(wp_unslash($_GET['pap_custom'])), 0, 8) . '&visitorId=' . substr(sanitize_text_field(wp_unslash($_GET['pap_custom'])), -32);
860 }
861 if (isset($_GET['pap_IP']) && ($ip = filter_var(wp_unslash($_GET['pap_IP']), FILTER_VALIDATE_IP))) {
862 $query .= '&ip=' . $ip;
863 }
864 $query .= "&TotalCost=$itemprice&OrderID=" . $orderId . "($i)";
865 $query .= '&ProductID=' . urlencode($this->getTrackingProductID($order, $item));
866 $query .= '&Currency=' . $order->get_currency() . "&Coupon=$couponCode";
867
868 for ($d = 1; $d <= 5; $d++) {
869 $query .= "&Data$d=" . urlencode($this->getTrackingData($order, $d, $item, $couponCode));
870 }
871
872 if (get_option(self::WOOCOMM_CAMPAIGN) !== '' && get_option(self::WOOCOMM_CAMPAIGN) !== null && get_option(self::WOOCOMM_CAMPAIGN) !== 0 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
873 $query .= '&CampaignID=' . get_option(self::WOOCOMM_CAMPAIGN);
874 }
875
876 if ($i != $count) { // delete cookie after sale fix
877 $query .= '&DoNotDeleteCookies=Y';
878 }
879 $this->_log('PayPal sending tracking request to PAP for '.$query);
880 self::sendRequest(postaffiliatepro::parseSaleScriptPath(), $query);
881 $i++;
882 }
883 } else {
884 if (method_exists($order, 'get_coupon_codes')) { // for newer versions
885 $coupons = $order->get_coupon_codes();
886 } else {
887 $coupons = $order->get_used_coupons();
888 }
889 $couponCode = implode(',', $coupons);
890
891 $query = '';
892 if (isset($_GET['pap_custom'])) {
893 $query = 'AccountId=' . substr(sanitize_text_field(wp_unslash($_GET['pap_custom'])), 0, 8) . '&visitorId='.
894 substr(sanitize_text_field(wp_unslash($_GET['pap_custom'])), -32);
895 }
896 if (isset($_GET['pap_IP']) && ($ip = filter_var(wp_unslash($_GET['pap_IP']), FILTER_VALIDATE_IP))) {
897 $query .= '&ip=' . $ip;
898 }
899 $query .= '&TotalCost=' . $this->getSubtotal($order) . '&OrderID=' . $orderId . '(1)';
900 $query .= '&ProductID=' . urlencode($this->getTrackingProductIDsLine($order));
901 $query .= '&Currency=' . $order->get_currency() . '&Coupon=' . $couponCode;
902
903 for ($d = 1; $d <= 5; $d++) {
904 $query .= "&Data$d=" . urlencode($this->getTrackingData($order, $d, null, $couponCode));
905 }
906
907 if (get_option(self::WOOCOMM_CAMPAIGN) !== '' && get_option(self::WOOCOMM_CAMPAIGN) !== null && get_option(self::WOOCOMM_CAMPAIGN) !== 0 && get_option(self::WOOCOMM_CAMPAIGN) !== '0') {
908 $query .= '&CampaignID=' . get_option(self::WOOCOMM_CAMPAIGN);
909 }
910 $this->_log('PayPal sending tracking request to PAP for '.$query);
911 self::sendRequest(postaffiliatepro::parseSaleScriptPath(), $query);
912 }
913
914 // affiliate approval?
915 if (get_option(self::WOOCOMM_AFFILIATE_APPROVAL) != '') {
916 $approvalProducts = explode(';', get_option(self::WOOCOMM_AFFILIATE_APPROVAL));
917 $orderedProducts = explode(', ', $this->getTrackingProductIDsLine($order));
918 foreach ($orderedProducts as $item) {
919 if (in_array($item, $approvalProducts)) {
920 // approve the customer/affiliate
921 $this->changeAffiliateStatus($order->get_billing_email(), 'A');
922 break;
923 }
924 }
925 }
926 return true;
927 }
928 return false;
929 }
930
931 private function get_paypal_order($raw_custom) {
932 if (($custom = json_decode($raw_custom)) && is_object($custom)) {
933 $order_id = $custom->order_id;
934 $order_key = $custom->order_key;
935 } elseif (preg_match('/^a:2:{/', $raw_custom) && !preg_match('/[CO]:\+?[0-9]+:"/', $raw_custom) && ($custom = maybe_unserialize($raw_custom))) {
936 $order_id = $custom[0];
937 $order_key = $custom[1];
938 } else {
939 $this->_log('PayPal IPN handling: Order ID and key were not found in "custom".');
940 return false;
941 }
942
943 if (!$order = wc_get_order($order_id)) {
944 // We have an invalid $order_id, probably because invoice_prefix has changed.
945 $order_id = wc_get_order_id_by_order_key($order_key);
946 $order = wc_get_order($order_id);
947 }
948
949 if (!$order || $order->get_order_key() !== $order_key) {
950 $this->_log('PayPal IPN handling: Order keys do not match.');
951 return false;
952 }
953
954 return $order;
955 }
956
957 private function resolveCoupons(array $coupons) {
958 $version = get_option(postaffiliatepro::PAP_VERSION);
959 $versionArray = explode('.', $version);
960 $minVersion = array(0 => '5', 1 => '9', 2 => '8', 3 => '8');
961 $problem = false;
962
963 if ($version != '') {
964 if ($versionArray[0] < $minVersion[0]) {
965 $problem = true;
966 } elseif ($versionArray[0] == $minVersion[0]) {
967 if ($versionArray[1] < $minVersion[1]) {
968 $problem = true;
969 } elseif ($versionArray[1] == $minVersion[1]) {
970 if ($versionArray[2] < $minVersion[2]) {
971 $problem = true;
972 } elseif ($versionArray[2] == $minVersion[2]) {
973 if ($versionArray[3] < $minVersion[3]) {
974 $problem = true;
975 }
976 }
977 }
978 }
979 } else {
980 $problem = true;
981 }
982
983 if ($problem) {
984 $couponToBeUsed = (count($coupons) > 1 ? count($coupons) - 1 : 0);
985 return $coupons[$couponToBeUsed];
986 }
987 return implode(',', $coupons);
988 }
989
990 private function getOrderId($order, $checkSubscription = true) {
991 $orderId = $order->get_id();
992 if ($checkSubscription && function_exists('wcs_get_subscriptions_for_order') &&
993 get_option(self::WOOCOMM_TRACK_RECURRING_SEPARATELY) !== 'true') {
994 $subscriptions = wcs_get_subscriptions_for_order($orderId);
995 if (!empty($subscriptions)) {
996 foreach ($subscriptions as $key => $value) { // take the first and leave
997 return $key;
998 }
999 }
1000 }
1001 if (get_option(self::WOOCOMM_ORDERID_SETTING) === self::WOOCOMM_ORDER_NUMBER) {
1002 $orderId = $order->get_order_number();
1003 }
1004 return $orderId;
1005 }
1006
1007 public function addHiddenFieldToPaymentForm($return = false) {
1008 postaffiliatepro::addHiddenFieldToPaymentForm($return);
1009 postaffiliatepro::addHiddenFieldToRegistrationForm(); // to support parent affiliate for signup
1010 }
1011
1012 public function wooAddRefIdToOrderMetaData($orderId, $postedData, $order) {
1013 if (isset($_POST['pap_parent']) && (wp_unslash($_POST['pap_parent']) != '')) {
1014 add_post_meta($orderId, 'Affiliate', sanitize_text_field(wp_unslash($_POST['pap_parent'])));
1015 }
1016 if (isset($_POST['pap_custom']) && (wp_unslash($_POST['pap_custom']) != '')) {
1017 add_post_meta($orderId, 'Visitor ID', sanitize_text_field(wp_unslash($_POST['pap_custom'])));
1018 }
1019 }
1020
1021 public function wooAddMetaToRevCent($saleArray) {
1022 if ($saleArray['type'] == 'sale'
1023 && $saleArray['method'] == 'create'
1024 && isset($_REQUEST['pap_custom'])
1025 && $_REQUEST['pap_custom'] != 'null'
1026 && $_REQUEST['pap_custom'] != 'default1null') {
1027 $visitorObj = new stdClass();
1028 $visitorObj->name = 'visitorid';
1029 $visitorObj->value = strval(sanitize_text_field(wp_unslash($_REQUEST['pap_custom'])));
1030 array_push($saleArray['metadata'], $visitorObj);
1031 }
1032 return $saleArray;
1033 }
1034
1035 public function addRecomputionMetaBox($post_type, $post) {
1036 if ($post_type !== 'shop_order') {
1037 return;
1038 }
1039
1040 $papwc = new postaffiliatepro_Form_Settings_WooComm();
1041 add_meta_box('wc-pap-recompute-commissions',
1042 'Post Affiliate Pro',
1043 array(
1044 $papwc,
1045 'papRecomputeCommissions'
1046 ),
1047 'shop_order',
1048 'side',
1049 'high'
1050 );
1051
1052 wp_enqueue_script('jquery');
1053 wp_add_inline_script('jquery', "jQuery(function($) {
1054 $('#pap-recompute').on('click', function() {
1055 $('#papRecomputionNote.p').hide();
1056 $('#pap-recompute').val('...".__('working', 'postaffiliatepro')."');
1057 papRecomputeCommissions($('#pap-recompute-orderid').val());
1058 });
1059
1060 function papRecomputeCommissions(orderid) {
1061 var d = {
1062 action: 'pap_recompute_ajax',
1063 order_id: orderid,
1064 nonce: $('#pap_recompute_nonce').val()
1065 };
1066
1067 $.post(ajaxurl, d, function(response) {
1068 if (response.success === true) {
1069 $('#pap-recompute').css('background-color','#DDFFAA');
1070 $('#pap-recompute').css('color','#44AA55');
1071 $('#pap-recompute').css('border-color','#AAFF44');
1072 $('#pap-recompute').val('Done');
1073 } else {
1074 $('#pap-recompute').val('Error');
1075 $('#papRecomputionNote').html(response.data.error);
1076 $('#papRecomputionNote').show();
1077 }
1078 });
1079 }
1080 });");
1081 }
1082
1083 public function papRecomputeCommissions(WP_Post $post) {
1084 echo '
1085 <div id="papRecomputionContent">
1086 <div id="papRecomputionText">
1087 '.__('If number of products, their cost or order cost changed, you can recompute commission for the order. Clicking the button will load, decline/refund and re-create the commission.', 'postaffiliatepro')
1088 .'</div>
1089 <div class="note_content" id="papRecomputionNote">
1090 </div>
1091 <input type="hidden" id="pap-recompute-orderid" name="pap-recompute-orderid" value="'.$post->ID.'" />';
1092 wp_nonce_field('pap_recompute_commission', 'pap_recompute_nonce');
1093 echo '<input id="pap-recompute" type="button" class="button" value="Recompute Commission" />
1094 </div>';
1095 }
1096
1097 public function recomputeCommissionAjaxCallback() {
1098 if (!check_ajax_referer('pap_recompute_commission', 'pap_recompute_nonce', false)) {
1099 wp_send_json_error(['error' => __('Invalid nonce.', 'postaffiliatepro')]);
1100 wp_die();
1101 }
1102
1103 try {
1104 if (!current_user_can('edit_shop_orders')) {
1105 throw new Exception(__('You do not have enough permissions to manipulate orders!', 'postaffiliatepro'));
1106 }
1107
1108 if (!isset($_POST['order_id']) || ($_POST['order_id'] == '')) {
1109 throw new Exception(__('Order ID is missing in the request. Something is wrong! Contact the plugin developer.', 'postaffiliatepro'));
1110 }
1111 $orderId = sanitize_text_field(wp_unslash($_POST['order_id']));
1112
1113 // try to load commission
1114 $session = $this->getApiSession();
1115 if ($session === null || $session === '0') {
1116 throw new Exception(__('We have no session to PAP installation! Recomputing is not possible right now.', 'postaffiliatepro'));
1117 }
1118
1119 $order = wc_get_order($orderId);
1120 $orderIdForLoadingFromPap = $this->getOrderId($order, false);
1121 $ids = $this->getTransactionIDsByOrderID($orderIdForLoadingFromPap, $session, 'A,P');
1122 if (empty($ids)) {
1123 throw new Exception(__('There is no approved or pending commission for this order. Nothing to recompute.', 'postaffiliatepro'));
1124 }
1125
1126 $commissionRecordset = $this->loadTransactionsByOrderID($orderIdForLoadingFromPap, $session, 'A,P');
1127
1128 $affiliateId = null;
1129 foreach ($commissionRecordset as $row) {
1130 $affiliateId = $row->get('userid');
1131 break;
1132 }
1133 if ($affiliateId == null) {
1134 throw new Exception(__('Could not load affiliate info from commission.', 'postaffiliatepro'));
1135 }
1136
1137 // refund and track again
1138 if ($this->refundTransaction($orderId)) {
1139 $orderRefunds = null;
1140 if (get_option(self::WOOCOMM_PERPRODUCT) !== 'true') {
1141 $orderRefunds = $order->get_total_refunded();
1142 } else { // per product
1143 $orderRefunds = array();
1144 foreach ($order->get_refunds() as $refund) {
1145 // Loop through the order refund line items
1146 foreach ($refund->get_items() as $item_id => $item) {
1147 $orderRefunds[] = $item_id;
1148 }
1149 }
1150 }
1151
1152 $this->trackWooOrderRemote($order, $affiliateId, $orderRefunds);
1153 } else {
1154 throw new Exception('Refunding was not successful!', 'postaffiliatepro');
1155 }
1156
1157 wp_send_json_success();
1158 } catch (Exception $e) {
1159 wp_send_json_error(array('error' => $e->getMessage()));
1160 }
1161 wp_die();
1162 }
1163 }
1164
1165 $papSubmenuPriority = 52;
1166 $papIntegrationWooComm = new postaffiliatepro_Form_Settings_WooComm();
1167 add_action('admin_init', array(
1168 $papIntegrationWooComm,
1169 'initSettings'
1170 ), 99);
1171 add_action('admin_menu', array(
1172 $papIntegrationWooComm,
1173 'addPrimaryConfigMenu'
1174 ), $papSubmenuPriority);
1175 add_filter('wp_footer', array(
1176 $papIntegrationWooComm,
1177 'wooHandleCustomThankYouPages'
1178 ), 99);
1179 add_action('woocommerce_thankyou', array(
1180 $papIntegrationWooComm,
1181 'wooAddThankYouPageTrackSale'
1182 ));
1183 add_action('woocommerce_checkout_before_order_review', array(
1184 $papIntegrationWooComm,
1185 'addHiddenFieldToPaymentForm'
1186 ));
1187 add_action('woocommerce_order_status_changed', array(
1188 $papIntegrationWooComm,
1189 'wooOrderStatusChanged'
1190 ), 99, 3);
1191 add_action('woocommerce_subscription_status_changed', array(
1192 $papIntegrationWooComm,
1193 'wooSubscriptionStatusChanged'
1194 ), 99, 3);
1195 add_filter('wcs_renewal_order_created', array(
1196 $papIntegrationWooComm,
1197 'wooRecurringCommission'
1198 ), 99, 2);
1199 add_filter('wc_autoship_payment_complete', array(
1200 $papIntegrationWooComm,
1201 'wooAutoshipCommission'
1202 ), 99, 2);
1203 add_action('add_meta_boxes', array(
1204 $papIntegrationWooComm,
1205 'addRecomputionMetaBox'
1206 ), 99, 2);
1207 add_action('woocommerce_checkout_order_processed', array(
1208 $papIntegrationWooComm,
1209 'wooAddRefIdToOrderMetaData'
1210 ), 99, 3);
1211 // WooCommerce PayPal
1212 add_filter('woocommerce_paypal_args', array(
1213 $papIntegrationWooComm,
1214 'wooModifyPaypalArgs'
1215 ), 99);
1216 add_action('valid-paypal-standard-ipn-request', array(
1217 $papIntegrationWooComm,
1218 'wooProcessPaypalIPN'
1219 ));
1220 // WooCommerce RevCent
1221 add_filter('revcent_payload_request_args', array(
1222 $papIntegrationWooComm,
1223 'wooAddMetaToRevCent'
1224 ), 99);
1225 // AJAX
1226 add_action('wp_ajax_pap_recompute_ajax', array(
1227 $papIntegrationWooComm,
1228 'recomputeCommissionAjaxCallback'
1229 ), 99);
1230