PMProGateway_paypal

The Paid Memberships Pro PMProGateway paypal class.

Defined (1)

The class is defined in the following location(s).

/classes/gateways/class.pmprogateway_paypal.php  
  1. class PMProGateway_paypal extends PMProGateway 
  2. function __construct($gateway = NULL) 
  3. $this->gateway = $gateway; 
  4. return $this->gateway; 
  5.  
  6. /** 
  7. * Run on WP init 
  8. * @since 1.8 
  9. */ 
  10. static function init() 
  11. //make sure PayPal Website Payments Pro is a gateway option 
  12. add_filter('pmpro_gateways', array('PMProGateway_paypal', 'pmpro_gateways')); 
  13.  
  14. //add fields to payment settings 
  15. add_filter('pmpro_payment_options', array('PMProGateway_paypal', 'pmpro_payment_options')); 
  16.  
  17. /** 
  18. This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard 
  19. So we only load it if we haven't already. 
  20. */ 
  21. global $pmpro_payment_option_fields_for_paypal; 
  22. if(empty($pmpro_payment_option_fields_for_paypal)) 
  23. add_filter('pmpro_payment_option_fields', array('PMProGateway_paypal', 'pmpro_payment_option_fields'), 10, 2); 
  24. $pmpro_payment_option_fields_for_paypal = true; 
  25.  
  26. //code to add at checkout 
  27. $gateway = pmpro_getGateway(); 
  28. if($gateway == "paypal") 
  29. add_filter('pmpro_checkout_default_submit_button', array('PMProGateway_paypal', 'pmpro_checkout_default_submit_button')); 
  30. add_action('pmpro_checkout_after_form', array('PMProGateway_paypal', 'pmpro_checkout_after_form')); 
  31. add_action('http_api_curl', array('PMProGateway_paypal', 'http_api_curl'), 10, 3); 
  32.  
  33. /** 
  34. * Update the SSLVERSION for CURL to support PayPal Express moving to TLS 1.2 
  35. * @since 1.8.9.1 
  36. */ 
  37. static function http_api_curl($handle, $r, $url) { 
  38. if(strpos($url, 'paypal.com') !== false) 
  39. curl_setopt( $handle, CURLOPT_SSLVERSION, 6 ); 
  40.  
  41. /** 
  42. * Make sure this gateway is in the gateways list 
  43. * @since 1.8 
  44. */ 
  45. static function pmpro_gateways($gateways) 
  46. if(empty($gateways['paypal'])) 
  47. $gateways['paypal'] = __('PayPal Website Payments Pro', 'paid-memberships-pro' ); 
  48.  
  49. return $gateways; 
  50.  
  51. /** 
  52. * Get a list of payment options that the this gateway needs/supports. 
  53. * @since 1.8 
  54. */ 
  55. static function getGatewayOptions() 
  56. $options = array( 
  57. 'sslseal',  
  58. 'nuclear_HTTPS',  
  59. 'gateway_environment',  
  60. 'gateway_email',  
  61. 'apiusername',  
  62. 'apipassword',  
  63. 'apisignature',  
  64. 'currency',  
  65. 'use_ssl',  
  66. 'tax_state',  
  67. 'tax_rate',  
  68. 'accepted_credit_cards',  
  69. 'paypalexpress_skip_confirmation' 
  70. ); 
  71.  
  72. return $options; 
  73.  
  74. /** 
  75. * Set payment options for payment settings page. 
  76. * @since 1.8 
  77. */ 
  78. static function pmpro_payment_options($options) 
  79. //get stripe options 
  80. $paypal_options = PMProGateway_paypal::getGatewayOptions(); 
  81.  
  82. //merge with others. 
  83. $options = array_merge($paypal_options, $options); 
  84.  
  85. return $options; 
  86.  
  87. /** 
  88. * Display fields for this gateway's options. 
  89. * @since 1.8 
  90. */ 
  91. static function pmpro_payment_option_fields($values, $gateway) 
  92. ?> 
  93. <tr class="pmpro_settings_divider gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>> 
  94. <td colspan="2"> 
  95. <?php _e('PayPal Settings', 'paid-memberships-pro' ); ?> 
  96. </td> 
  97. </tr> 
  98. <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>> 
  99. <td colspan="2"> 
  100. <strong><?php _e('Note', 'paid-memberships-pro' );?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'paid-memberships-pro' );?> 
  101. </td> 
  102. </tr> 
  103. <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>> 
  104. <th scope="row" valign="top"> 
  105. <label for="gateway_email"><?php _e('Gateway Account Email', 'paid-memberships-pro' );?>:</label> 
  106. </th> 
  107. <td> 
  108. <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" /> 
  109. </td> 
  110. </tr> 
  111. <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>> 
  112. <th scope="row" valign="top"> 
  113. <label for="apiusername"><?php _e('API Username', 'paid-memberships-pro' );?>:</label> 
  114. </th> 
  115. <td> 
  116. <input type="text" id="apiusername" name="apiusername" size="60" value="<?php echo esc_attr($values['apiusername'])?>" /> 
  117. </td> 
  118. </tr> 
  119. <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>> 
  120. <th scope="row" valign="top"> 
  121. <label for="apipassword"><?php _e('API Password', 'paid-memberships-pro' );?>:</label> 
  122. </th> 
  123. <td> 
  124. <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" /> 
  125. </td> 
  126. </tr> 
  127. <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>> 
  128. <th scope="row" valign="top"> 
  129. <label for="apisignature"><?php _e('API Signature', 'paid-memberships-pro' );?>:</label> 
  130. </th> 
  131. <td> 
  132. <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" /> 
  133. </td> 
  134. </tr> 
  135. <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>> 
  136. <th scope="row" valign="top"> 
  137. <label for="paypalexpress_skip_confirmation"><?php _e('Confirmation Step', 'paid-memberships-pro' );?>:</label> 
  138. </th> 
  139. <td> 
  140. <select id="paypalexpress_skip_confirmation" name="paypalexpress_skip_confirmation"> 
  141. <option value="0" <?php selected(pmpro_getOption('paypalexpress_skip_confirmation'), 0);?>>Require an extra confirmation after users return from PayPal Express.</option> 
  142. <option value="1" <?php selected(pmpro_getOption('paypalexpress_skip_confirmation'), 1);?>>Skip the extra confirmation after users return from PayPal Express.</option> 
  143. </select> 
  144. </td> 
  145. </tr> 
  146. <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>> 
  147. <th scope="row" valign="top"> 
  148. <label><?php _e('IPN Handler URL', 'paid-memberships-pro' );?>:</label> 
  149. </th> 
  150. <td> 
  151. <p><?php _e('This URL is passed to PayPal for all new charges and subscriptions. You SHOULD NOT set this in your PayPal account settings.', 'paid-memberships-pro' );?><pre><?php echo admin_url("admin-ajax.php") . "?action=ipnhandler";?></pre></p> 
  152. </td> 
  153. </tr> 
  154. <?php 
  155.  
  156. /** 
  157. * Swap in our submit buttons. 
  158. * @since 1.8 
  159. */ 
  160. static function pmpro_checkout_default_submit_button($show) 
  161. global $gateway, $pmpro_requirebilling; 
  162.  
  163. //show our submit buttons 
  164. ?> 
  165. <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?> 
  166. <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>> 
  167. <input type="hidden" name="submit-checkout" value="1" /> 
  168. <input type="image" class="pmpro_btn-submit-checkout" value="<?php _e('Check Out with PayPal', 'paid-memberships-pro' );?> »" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" /> 
  169. </span> 
  170. <?php } ?> 
  171.  
  172. <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>> 
  173. <input type="hidden" name="submit-checkout" value="1" /> 
  174. <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'paid-memberships-pro' ); } else { _e('Submit and Confirm', 'paid-memberships-pro' );}?> »" /> 
  175. </span> 
  176. <?php 
  177.  
  178. //don't show the default 
  179. return false; 
  180.  
  181. /** 
  182. * Scripts for checkout page. 
  183. * @since 1.8 
  184. */ 
  185. static function pmpro_checkout_after_form() 
  186. ?> 
  187. <script> 
  188. <!-- 
  189. //choosing payment method 
  190. jQuery('input[name=gateway]').click(function() { 
  191. if(jQuery(this).val() == 'paypal') 
  192. jQuery('#pmpro_paypalexpress_checkout').hide(); 
  193. jQuery('#pmpro_billing_address_fields').show(); 
  194. jQuery('#pmpro_payment_information_fields').show(); 
  195. jQuery('#pmpro_submit_span').show(); 
  196. else 
  197. jQuery('#pmpro_billing_address_fields').hide(); 
  198. jQuery('#pmpro_payment_information_fields').hide(); 
  199. jQuery('#pmpro_submit_span').hide(); 
  200. jQuery('#pmpro_paypalexpress_checkout').show(); 
  201. }); 
  202.  
  203. //select the radio button if the label is clicked on 
  204. jQuery('a.pmpro_radio').click(function() { 
  205. jQuery(this).prev().click(); 
  206. }); 
  207. --> 
  208. </script> 
  209. <?php 
  210.  
  211. /** 
  212. * Process checkout. 
  213. */ 
  214. function process(&$order) 
  215. if(floatval($order->InitialPayment) == 0) 
  216. //auth first, then process 
  217. $authorization_id = $this->authorize($order); 
  218. if($authorization_id) 
  219. $this->void($order, $authorization_id); 
  220. $order->ProfileStartDate = date_i18n("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0"; 
  221. $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order); 
  222. return $this->subscribe($order); 
  223. else 
  224. if(empty($order->error)) 
  225. $order->error = __("Unknown error: Authorization failed.", 'paid-memberships-pro' ); 
  226. return false; 
  227. else 
  228. //charge first payment 
  229. if($this->charge($order)) 
  230. //set up recurring billing 
  231. if(pmpro_isLevelRecurring($order->membership_level)) 
  232. $order->ProfileStartDate = date_i18n("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0"; 
  233. $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order); 
  234. if($this->subscribe($order)) 
  235. return true; 
  236. else 
  237. if($this->refund($order, $order->payment_transaction_id)) 
  238. if(empty($order->error)) 
  239. $order->error = __("Unknown error: Payment failed.", 'paid-memberships-pro' ); 
  240. else 
  241. if(empty($order->error)) 
  242. $order->error = "Unknown error: Payment failed."; 
  243.  
  244. $order->error .= " " . __("A partial payment was made that we could not refund. Please contact the site owner immediately to correct this.", 'paid-memberships-pro' ); 
  245.  
  246. return false; 
  247. else 
  248. //only a one time charge 
  249. $order->status = "success"; //saved on checkout page 
  250. $order->saveOrder(); 
  251. return true; 
  252.  
  253. function authorize(&$order) 
  254. if(empty($order->code)) 
  255. $order->code = $order->getRandomCode(); 
  256.  
  257. //paypal profile stuff 
  258. $nvpStr = ""; 
  259. if(!empty($order->Token)) 
  260. $nvpStr .= "&TOKEN=" . $order->Token; 
  261. $nvpStr .="&AMT=1.00&CURRENCYCODE=" . pmpro_getOption("currency"); 
  262. $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler"); 
  263. //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount; 
  264.  
  265. $nvpStr .= "&PAYMENTACTION=Authorization&IPADDRESS=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code; 
  266.  
  267. //credit card fields 
  268. if($order->cardtype == "American Express") 
  269. $cardtype = "Amex"; 
  270. else 
  271. $cardtype = $order->cardtype; 
  272.  
  273. if(!empty($cardtype)) 
  274. $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2; 
  275.  
  276. //Maestro/Solo card fields. (Who uses these?) :) 
  277. if(!empty($order->StartDate)) 
  278. $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber; 
  279.  
  280. //billing address, etc 
  281. if(!empty($order->Address1)) 
  282. $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1; 
  283.  
  284. if($order->Address2) 
  285. $nvpStr .= "&STREET2=" . $order->Address2; 
  286.  
  287. $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone; 
  288.  
  289. //for debugging, let's attach this to the class object 
  290. $this->nvpStr = $nvpStr; 
  291.  
  292. $this->httpParsedResponseAr = $this->PPHttpPost('DoDirectPayment', $nvpStr); 
  293.  
  294. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) { 
  295. $order->authorization_id = $this->httpParsedResponseAr['TRANSACTIONID']; 
  296. $order->updateStatus("authorized"); 
  297. return $order->authorization_id; 
  298. } else { 
  299. $order->status = "error"; 
  300. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  301. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']); 
  302. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  303. return false; 
  304.  
  305. function void(&$order, $authorization_id = null) 
  306. if(empty($authorization_id)) 
  307. return false; 
  308.  
  309. //paypal profile stuff 
  310. $nvpStr="&AUTHORIZATIONID=" . $authorization_id . "&NOTE=Voiding an authorization for a recurring payment setup."; 
  311.  
  312. $this->httpParsedResponseAr = $this->PPHttpPost('DoVoid', $nvpStr); 
  313.  
  314. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) { 
  315. return true; 
  316. } else { 
  317. $order->status = "error"; 
  318. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  319. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']); 
  320. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  321. return false; 
  322.  
  323. function refund(&$order, $transaction_id) 
  324. if(empty($transaction_id)) 
  325. return false; 
  326.  
  327. //paypal profile stuff 
  328. $nvpStr="&TRANSACTIONID=" . $transaction_id . "&NOTE=Refunding a charge."; 
  329.  
  330. $this->httpParsedResponseAr = $this->PPHttpPost('RefundTransaction', $nvpStr); 
  331.  
  332. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) { 
  333. return true; 
  334. } else { 
  335. $order->status = "error"; 
  336. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  337. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']); 
  338. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  339. return false; 
  340.  
  341. function charge(&$order) 
  342. global $pmpro_currency; 
  343.  
  344. if(empty($order->code)) 
  345. $order->code = $order->getRandomCode(); 
  346.  
  347. //taxes on the amount 
  348. $amount = $order->InitialPayment; 
  349. $amount_tax = $order->getTaxForPrice($amount); 
  350. $order->subtotal = $amount; 
  351. $amount = round((float)$amount + (float)$amount_tax, 2); 
  352.  
  353. //paypal profile stuff 
  354. $nvpStr = ""; 
  355. if(!empty($order->Token)) 
  356. $nvpStr .= "&TOKEN=" . $order->Token; 
  357. $nvpStr .="&AMT=" . $amount . "&ITEMAMT=" . $order->InitialPayment . "&TAXAMT=" . $amount_tax . "&CURRENCYCODE=" . $pmpro_currency; 
  358. $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler"); 
  359. //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount; 
  360.  
  361. $nvpStr .= "&PAYMENTACTION=Sale&IPADDRESS=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code; 
  362.  
  363. //credit card fields 
  364. if($order->cardtype == "American Express") 
  365. $cardtype = "Amex"; 
  366. else 
  367. $cardtype = $order->cardtype; 
  368.  
  369. if(!empty($cardtype)) 
  370. $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2; 
  371.  
  372. //Maestro/Solo card fields. (Who uses these?) :) 
  373. if(!empty($order->StartDate)) 
  374. $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber; 
  375.  
  376. //billing address, etc 
  377. if($order->Address1) 
  378. $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1; 
  379.  
  380. if($order->Address2) 
  381. $nvpStr .= "&STREET2=" . $order->Address2; 
  382.  
  383. $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone; 
  384.  
  385. $this->httpParsedResponseAr = $this->PPHttpPost('DoDirectPayment', $nvpStr); 
  386.  
  387. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) { 
  388. $order->payment_transaction_id = $this->httpParsedResponseAr['TRANSACTIONID']; 
  389. $order->updateStatus("success"); 
  390. return true; 
  391. } else { 
  392. $order->status = "error"; 
  393. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  394. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']); 
  395. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  396. return false; 
  397.  
  398. function subscribe(&$order) 
  399. global $pmpro_currency; 
  400.  
  401. if(empty($order->code)) 
  402. $order->code = $order->getRandomCode(); 
  403.  
  404. //filter order before subscription. use with care. 
  405. $order = apply_filters("pmpro_subscribe_order", $order, $this); 
  406.  
  407. //taxes on the amount 
  408. $amount = $order->PaymentAmount; 
  409. $amount_tax = $order->getTaxForPrice($amount); 
  410. $amount = round((float)$amount + (float)$amount_tax, 2); 
  411.  
  412. //paypal profile stuff 
  413. $nvpStr = ""; 
  414.  
  415. if(!empty($order->Token)) 
  416. $nvpStr .= "&TOKEN=" . $order->Token; 
  417. $nvpStr .="&AMT=" . $order->PaymentAmount . "&TAXAMT=" . $amount_tax . "&CURRENCYCODE=" . $pmpro_currency . "&PROFILESTARTDATE=" . $order->ProfileStartDate; 
  418. $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLOUTAMT=AddToNextBilling"; 
  419. $nvpStr .= "&DESC=" . urlencode( apply_filters( 'pmpro_paypal_level_description', substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127), $order->membership_level->name, $order, get_bloginfo("name")) ); 
  420. $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler"); 
  421. //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount; 
  422.  
  423. //if billing cycles are defined 
  424. if(!empty($order->TotalBillingCycles)) 
  425. $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles; 
  426.  
  427. //if a trial period is defined 
  428. if(!empty($order->TrialBillingPeriod)) 
  429. $trial_amount = $order->TrialAmount; 
  430. $trial_tax = $order->getTaxForPrice($trial_amount); 
  431. $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2); 
  432.  
  433. $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount; 
  434. if(!empty($order->TrialBillingCycles)) 
  435. $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles; 
  436.  
  437. //credit card fields 
  438. if($order->cardtype == "American Express") 
  439. $cardtype = "Amex"; 
  440. else 
  441. $cardtype = $order->cardtype; 
  442.  
  443. if($cardtype) 
  444. $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2; 
  445.  
  446. //Maestro/Solo card fields. (Who uses these?) :) 
  447. if(!empty($order->StartDate)) 
  448. $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber; 
  449.  
  450. //billing address, etc 
  451. if($order->Address1) 
  452. $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1; 
  453.  
  454. if($order->Address2) 
  455. $nvpStr .= "&STREET2=" . $order->Address2; 
  456.  
  457. $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone; 
  458.  
  459. //for debugging let's add this to the class object 
  460. $this->nvpStr = $nvpStr; 
  461.  
  462. $this->httpParsedResponseAr = $this->PPHttpPost('CreateRecurringPaymentsProfile', $nvpStr); 
  463.  
  464. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) { 
  465. $order->status = "success"; 
  466. $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']); 
  467. return true; 
  468. //exit('CreateRecurringPaymentsProfile Completed Successfully: '.print_r($this->httpParsedResponseAr, true)); 
  469. } else { 
  470. $order->status = "error"; 
  471. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  472. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']); 
  473. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  474. return false; 
  475. //exit('CreateRecurringPaymentsProfile failed: ' . print_r($httpParsedResponseAr, true)); 
  476.  
  477. function update(&$order) 
  478. //paypal profile stuff 
  479. $nvpStr = ""; 
  480. $nvpStr .= "&PROFILEID=" . $order->subscription_transaction_id; 
  481.  
  482. //credit card fields 
  483. if($order->cardtype == "American Express") 
  484. $cardtype = "Amex"; 
  485. else 
  486. $cardtype = $order->cardtype; 
  487.  
  488. //credit card fields 
  489. if($cardtype) 
  490. $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2; 
  491.  
  492. //Maestro/Solo card fields. (Who uses these?) :) 
  493. if($order->StartDate) 
  494. $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber; 
  495.  
  496. //billing address, etc 
  497. if($order->Address1) 
  498. $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1; 
  499.  
  500. if($order->Address2) 
  501. $nvpStr .= "&STREET2=" . $order->Address2; 
  502.  
  503. $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip; 
  504.  
  505. $this->httpParsedResponseAr = $this->PPHttpPost('UpdateRecurringPaymentsProfile', $nvpStr); 
  506.  
  507. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) { 
  508. $order->status = "success"; 
  509. $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']); 
  510. return true; 
  511. //exit('CreateRecurringPaymentsProfile Completed Successfully: '.print_r($this->httpParsedResponseAr, true)); 
  512. } else { 
  513. $order->status = "error"; 
  514. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  515. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']); 
  516. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  517. return false; 
  518. //exit('CreateRecurringPaymentsProfile failed: ' . print_r($httpParsedResponseAr, true)); 
  519.  
  520. function cancel(&$order) 
  521. //paypal profile stuff 
  522. $nvpStr = ""; 
  523. $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel."); 
  524.  
  525. $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr); 
  526.  
  527. if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) 
  528. $order->updateStatus("cancelled"); 
  529. return true; 
  530. else 
  531. $order->status = "error"; 
  532. $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0']; 
  533. $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", 'paid-memberships-pro' ); 
  534. $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']); 
  535.  
  536. return false; 
  537.  
  538. /** 
  539. * PAYPAL Function 
  540. * Send HTTP POST Request 
  541. * @param string The API method name 
  542. * @param string The POST Message fields in &name=value pair format 
  543. * @return array Parsed HTTP Response body 
  544. */ 
  545. function PPHttpPost($methodName_, $nvpStr_) { 
  546. global $gateway_environment; 
  547. $environment = $gateway_environment; 
  548.  
  549. $API_UserName = pmpro_getOption("apiusername"); 
  550. $API_Password = pmpro_getOption("apipassword"); 
  551. $API_Signature = pmpro_getOption("apisignature"); 
  552. $API_Endpoint = "https://api-3t.paypal.com/nvp"; 
  553. if("sandbox" === $environment || "beta-sandbox" === $environment) { 
  554. $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp"; 
  555.  
  556. $version = urlencode('72.0'); 
  557.  
  558. // NVPRequest for submitting to server 
  559. $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_; 
  560.  
  561. //post to PayPal 
  562. $response = wp_remote_post( $API_Endpoint, array( 
  563. 'timeout' => 60,  
  564. 'sslverify' => FALSE,  
  565. 'httpversion' => '1.1',  
  566. 'body' => $nvpreq 
  567. ); 
  568.  
  569. if ( is_wp_error( $response ) ) { 
  570. $error_message = $response->get_error_message(); 
  571. die( "methodName_ failed: $error_message" ); 
  572. } else { 
  573. //extract the response details 
  574. $httpParsedResponseAr = array(); 
  575. parse_str(wp_remote_retrieve_body($response), $httpParsedResponseAr); 
  576.  
  577. //check for valid response 
  578. if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) { 
  579. exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint."); 
  580.  
  581. return $httpParsedResponseAr;