1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8// NB, all PayPal supported "HTML Variables" will be passed on to the button, even if not mentioned here 9 10function wikiplugin_paypal_info() 11{ 12 13 global $prefs; 14 15 return [ 16 'name' => tra('PayPal Button'), 17 'documentation' => 'Payment', 18 'description' => tra('Embed a PayPal button'), 19 'introduced' => 11, 20 'prefs' => ['wikiplugin_paypal'], // not dependent on 'payment_feature', would be annoying if you just want one donate button for instance 21 'iconname' => 'paypal', 22 'format' => 'html', 23 'extraparams' => true, 24 'validate' => 'all', 25 'params' => [ 26 'cmd' => [ 27 'required' => false, 28 'name' => tra('Type'), 29 'description' => tra('Type of PayPal button'), 30 'since' => '11.0', 31 'filter' => 'word', 32 'options' => [ 33 ['text' => '', 'value' => ''], 34 ['text' => tra('Shopping cart'), 'value' => '_cart'], 35 ['text' => tra('Buy Now'), 'value' => '_xclick'], 36 ['text' => tra('Donations'), 'value' => 'donations'], 37// array('text' => tra('Gift vouchers'), 'value' => 'gift_certs'), TODO? 38// array('text' => tra('Subscriptions'), 'value' => 'subscriptions'), 39// array('text' => tra('Automatic Billing'), 'value' => 'auto_billing'), 40// array('text' => tra('Instalment Plan'), 'value' => 'payment_plan'), 41 ], 42 'default' => '_cart', 43 ], 44 'cart_action' => [ 45 'required' => false, 46 'name' => tra('Cart Action'), 47 'description' => tra('Action if Shopping Cart selected for type'), 48 'since' => '11.0', 49 'filter' => 'word', 50 'options' => [ 51 ['text' => '', 'value' => ''], 52 ['text' => tra('Add to Cart'), 'value' => 'add'], 53 ['text' => tra('View Cart'), 'value' => 'display'], 54 //array('text' => tra('Cart Upload'), 'value' => 'upload'), // N/A 55 ], 56 'default' => 'add', 57 ], 58 'item_name' => [ 59 'required' => false, 60 'name' => tra('Item Name'), 61 'description' => tra('Item name or description. Required for Shopping cart'), 62 'since' => '11.0', 63 'filter' => 'text', 64 'default' => '', 65 ], 66 'amount' => [ 67 'required' => false, 68 'name' => tra('Price'), 69 'description' => tra('Item price'), 70 'since' => '11.0', 71 'filter' => 'text', 72 'default' => '', 73 ], 74 'paypal_button' => [ 75 'required' => false, 76 'name' => tra('PayPal Button'), 77 'description' => tra('Button appearance'), 78 'since' => '11.0', 79 'filter' => 'text', 80 'options' => [ 81 ['text' => tra('Normal'), 'value' => ''], 82 ['text' => tra('Smaller'), 'value' => 'small_button'], 83 ['text' => tra('Custom'), 'value' => 'custom'], 84 ], 85 'default' => '', 86 ], 87 'custom_image_url' => [ 88 'required' => false, 89 'name' => tra('Custom Button'), 90 'description' => tra('Custom button image URL'), 91 'since' => '11.0', 92 'filter' => 'url', 93 'default' => '', 94 ], 95 'item_number' => [ 96 'required' => false, 97 'name' => tra('Product ID'), 98 'description' => tra('Optional item identifier, often a tracker itemId'), 99 'since' => '11.0', 100 'filter' => 'text', 101 'default' => '', 102 ], 103 'quantity' => [ 104 'required' => false, 105 'name' => tra('Quantity'), 106 'description' => tra('Number of items, empty or 0 to have an input the user can fill in'), 107 'since' => '11.0', 108 'filter' => 'text', 109 'default' => '', 110 ], 111 'shipping' => [ 112 'required' => false, 113 'name' => tra('Shipping Cost'), 114 'description' => tra('The cost of shipping this item'), 115 'since' => '11.0', 116 'filter' => 'text', 117 'default' => '', 118 'advanced' => true, 119 ], 120 'shipping2' => [ 121 'required' => false, 122 'name' => tra('Additional Shipping Cost'), 123 'description' => tra('The cost of shipping each additional unit of this item'), 124 'since' => '11.0', 125 'filter' => 'text', 126 'default' => '', 127 'advanced' => true, 128 ], 129 'weight' => [ 130 'required' => false, 131 'name' => tra('Weight'), 132 'description' => tra('Weight of item'), 133 'since' => '11.0', 134 'filter' => 'text', 135 'default' => '', 136 'advanced' => true, 137 ], 138 'weight_unit' => [ 139 'required' => false, 140 'name' => tra('Weight Unit'), 141 'description' => tra('The unit of measure if weight is specified'), 142 'since' => '11.0', 143 'filter' => 'word', 144 'options' => [ 145 ['text' => '', 'value' => ''], 146 ['text' => tra('Kilos'), 'value' => 'kgs'], 147 ['text' => tra('Pounds'), 'value' => 'lbs'], 148 ], 149 'default' => 'kgs', 150 'advanced' => true, 151 ], 152 'business' => [ 153 'required' => false, 154 'name' => tra('Business ID'), 155 'description' => tra('PayPal business name/ID') . ' ' . tra('(Uses value in admin/payment if not set here)'), 156 'since' => '11.0', 157 'filter' => 'text', 158 'default' => $prefs['payment_paypal_business'], 159 'advanced' => ! empty($prefs['payment_paypal_business']), // if set in prefs shouldn't need to change it here 160 ], 161 'minicart' => [ 162 'required' => false, 163 'name' => tra('Use MiniCart'), 164 'description' => tra('See https://github.com/jeffharrell/MiniCart'), 165 'since' => '11.0', 166 'filter' => 'alpha', 167 'options' => [ 168 ['text' => '', 'value' => ''], 169 ['text' => tra('Yes'), 'value' => 'y'], 170 ['text' => tra('No'), 'value' => 'n'], 171 ], 172 'default' => 'y', 173 'advanced' => true, 174 ], 175 'no_shipping' => [ 176 'required' => false, 177 'name' => tra('Shipping Address Prompt'), 178 'description' => tra('Indicate whether to prompt for and require an address'), 179 'since' => '11.0', 180 'filter' => 'digits', 181 'options' => [ 182 ['text' => '', 'value' => ''], 183 ['text' => tra('Prompt for address'), 'value' => 0], 184 ['text' => tra('Do not prompt for address'), 'value' => 1], 185 ['text' => tra('Prompt for and require address'), 'value' => 2], 186 ], 187 'default' => 2, 188 'advanced' => true, 189 ], 190 'return' => [ 191 'required' => false, 192 'name' => tra('Completed payment return URL'), 193 'description' => tr('Empty for current page, %0n%1 to disable', '<code>', '</code>'), 194 'since' => '11.0', 195 'filter' => 'text', 196 'default' => '', 197 'advanced' => true, 198 ], 199 'shopping_url' => [ 200 'required' => false, 201 'name' => tra('Continue Shopping URL'), 202 'description' => tr('Empty for current page, %0n%1 to disable', '<code>', '</code>'), 203 'since' => '11.0', 204 'filter' => 'text', 205 'default' => '', 206 'advanced' => true, 207 ], 208 'cancel_return' => [ 209 'required' => false, 210 'name' => tra('Cancel payment URL'), 211 'description' => tr('Empty for current page, %0n%1 to disable', '<code>', '</code>'), 212 'since' => '11.0', 213 'filter' => 'text', 214 'default' => '', 215 'advanced' => true, 216 ], 217 'title' => [ 218 'required' => false, 219 'name' => tra('Form title'), 220 'description' => tra('Tooltip for the form and alt attribute for the image'), 221 'since' => '11.0', 222 'filter' => 'text', 223 'default' => tra('PayPal — The safer, easier way to pay online.'), 224 'advanced' => true, 225 ], 226 'stringButton' => [ 227 'required' => false, 228 'name' => tra('Button text'), 229 'description' => tra('The checkout button text'), 230 'since' => '11.0', 231 'filter' => 'text', 232 'default' => 'Checkout', 233 'advanced' => true, 234 ], 235 'stringSubtotal' => [ 236 'required' => false, 237 'name' => tra('Subtotal text'), 238 'description' => tra('The subtotal text'), 239 'since' => '11.0', 240 'filter' => 'text', 241 'default' => 'Subtotal: ', 242 'advanced' => true, 243 ], 244 'stringDiscount' => [ 245 'required' => false, 246 'name' => tra('Discount text'), 247 'description' => tra('The discount text'), 248 'since' => '11.0', 249 'filter' => 'text', 250 'default' => 'Discount: ', 251 'advanced' => true, 252 ], 253 'stringShipping' => [ 254 'required' => false, 255 'name' => tra('Shipping text'), 256 'description' => tra('The shipping text'), 257 'since' => '11.0', 258 'filter' => 'text', 259 'default' => 'does not include shipping & tax', 260 'advanced' => true, 261 ], 262 'stringProcessing' => [ 263 'required' => false, 264 'name' => tra('Processing text'), 265 'description' => tra('The processing text'), 266 'since' => '11.0', 267 'filter' => 'text', 268 'default' => 'Processing...', 269 'advanced' => true, 270 ], 271 ], 272 ]; 273} 274 275function wikiplugin_paypal($data, $params) 276{ 277 global $prefs, $language, $base_uri, $base_host; 278 static $id = 0; 279 280 $unique = 'wppaypal-' . ++$id; 281 $smarty = TikiLib::lib('smarty'); 282 283 // process default 284 $plugininfo = wikiplugin_paypal_info(); 285 foreach ($plugininfo['params'] as $key => $p) { 286 $default[$key] = $p['default']; 287 } 288 $params = array_merge($default, $params); 289 290 // check required params 291 if (empty($params['business'])) { 292 $access = TikiLib::lib('access'); 293 $access->check_feature('payment_paypal_business'); 294 } 295 296 if ($params['cmd'] === '_cart') { 297 if (empty($params['item_name'])) { 298 return '<span class="alert-warning">' . tra('PayPal button:') . ' ' . tra('Item name (item_name) required') . '</span>'; 299 } 300 if (empty($params['amount'])) { 301 return '<span class="alert-warning">' . tra('PayPal button:') . ' ' . tra('Price (amount) required') . '</span>'; 302 } 303 304 $params[$params['cart_action']] = 1; 305 unset($params['cart_action']); 306 } 307 308 // process others 309 if ($prefs['payment_feature'] === 'y' && ! empty($prefs['payment_currency'])) { 310 $params['currency_code'] = $prefs['payment_currency']; 311 } 312 313 if (empty($params['weight'])) { 314 unset($params['weight_unit']); 315 } 316 317 // logic handled in the tpl 318 $smarty->assign('wppaypal_quantity', $params['quantity']); 319 unset($params['quantity']); 320 $smarty->assign('wppaypal_title', $params['title']); 321 unset($params['title']); 322 323 global $paypallib; 324 include_once('lib/payment/paypallib.php'); 325 $locale = $paypallib->localeMap($language); // 'lc' locale param TODO maybe 326 327 // button image 328 if (! empty($params['custom_image_url']) && $params['paypal_button'] === 'custom') { 329 $button_url = $params['custom_image_url']; 330 } else { 331 switch ($params['cmd']) { 332 case '_cart': 333 if (isset($params['add'])) { 334 $button_type = 'cart'; 335 } elseif (isset($params['display'])) { 336 $button_type = 'viewcart'; 337 } 338 break; 339 case '_xclick': 340 $button_type = 'buynow'; 341 break; 342 case 'donations': 343 $button_type = 'donate'; 344 break; 345 default: 346 $button_type = 'paynow'; 347 } 348 $size = $params['paypal_button'] === 'small_button' ? 'SM' : 'LG'; 349 $button_url = "https://www.paypalobjects.com/{$locale}/i/btn/btn_{$button_type}_{$size}.gif"; 350 } 351 $pixel_url = "https://www.paypalobjects.com/{$locale}/i/scr/pixel.gif"; 352 353 $smarty->assign('wppaypal_button', $button_url); 354 $smarty->assign('wppaypal_pixel', $pixel_url); 355 unset($params['custom_image_url']); 356 unset($params['paypal_button']); 357 358 // return params 359 if (! empty($_SERVER['REQUEST_URI'])) { 360 $returnUrl = $base_host . $_SERVER['REQUEST_URI']; 361 } else { 362 $returnUrl = $base_uri; 363 } 364 if (strpos($returnUrl, 'tiki-ajax_services.php') !== false || 365 (isset($_REQUEST['controller']) && $_REQUEST['controller'] === 'search_customsearch')) { 366 $csearchEvent = 'pageSearchReady'; 367 if (! empty($_SERVER['HTTP_REFERER'])) { 368 $returnUrl = $_SERVER['HTTP_REFERER']; 369 } 370 $csearchInit = 'paypal = {}; $("#PPMiniCart").fadeOut().remove();'; 371 } else { 372 $csearchEvent = 'ready'; 373 $csearchInit = ''; 374 } 375 foreach (['return', 'shopping_url', 'cancel_return'] as $ret) { 376 if (empty($params[$ret])) { 377 $params[$ret] = $returnUrl; 378 } elseif ($params[$ret] === 'n') { 379 unset($params[$ret]); 380 } 381 } 382 383 // just add javascript? 384 $jsfile = 'vendor_bundled/vendor/jquery/minicart/dist/minicart' . ($prefs['tiki_minify_javascript'] === 'y' ? '.min' : '') . '.js'; 385 if ($params['minicart'] === 'y' && file_exists($jsfile)) { 386 // it appears currently if you set any of these all must be set 387 $miniParams = ['strings' => []]; 388 $miniParams['strings']['button'] = tra($params['stringButton']); 389 $miniParams['strings']['subtotal'] = tra($params['stringSubtotal']); 390 $miniParams['strings']['discount'] = tra($params['stringDiscount']); 391 $miniParams['strings']['shipping'] = tra($params['stringShipping']); 392 $miniParams['strings']['processing'] = tra($params['stringProcessing']); 393 // this seems to be the only secure URL for these assets, minicart.com uses github's SSL certificate 394 $miniParams['assetURL'] = 'https://github.com/jeffharrell/minicart/raw/3.0.6/'; 395 $miniParamStr = json_encode($miniParams); 396 397 TikiLib::lib('header')->add_js( 398 ' 399$(document).on("' . $csearchEvent . '", function () { 400 ' . $csearchInit . ' $.getScript("' . $jsfile . '", function() { 401 paypal.minicart.render(' . $miniParamStr . '); 402 }); 403});' 404 )->add_css('#PPMiniCart {z-index: 1040;}'); // make sure it clears the fixed page-header 405 } 406 unset($params['minicart']); 407 408 409 //$params['item_name'] = htmlentities($params['item_name']); // FIXME encoding problems! 410 411 // all remaining non-empty params get turned into hidden form inputs 412 $params = array_filter($params); 413 $smarty->assign_by_ref('wppaypal_hiddens', $params); 414 415 return $smarty->fetch('wiki-plugins/wikiplugin_paypal.tpl'); 416} 417