PMProGateway_authorizenet

The Paid Memberships Pro PMProGateway authorizenet class.

Defined (1)

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

/classes/gateways/class.pmprogateway_authorizenet.php  
  1. class PMProGateway_authorizenet 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 Authorize.net is a gateway option 
  12. add_filter('pmpro_gateways', array('PMProGateway_authorizenet', 'pmpro_gateways')); 
  13.  
  14. //add fields to payment settings 
  15. add_filter('pmpro_payment_options', array('PMProGateway_authorizenet', 'pmpro_payment_options')); 
  16. add_filter('pmpro_payment_option_fields', array('PMProGateway_authorizenet', 'pmpro_payment_option_fields'), 10, 2); 
  17.  
  18. /** 
  19. * Make sure this gateway is in the gateways list 
  20. * @since 1.8 
  21. */ 
  22. static function pmpro_gateways($gateways) 
  23. if(empty($gateways['authorizenet'])) 
  24. $gateways['authorizenet'] = __('Authorize.net', 'paid-memberships-pro' ); 
  25.  
  26. return $gateways; 
  27.  
  28. /** 
  29. * Get a list of payment options that the this gateway needs/supports. 
  30. * @since 1.8 
  31. */ 
  32. static function getGatewayOptions() 
  33. $options = array( 
  34. 'sslseal',  
  35. 'nuclear_HTTPS',  
  36. 'gateway_environment',  
  37. 'loginname',  
  38. 'transactionkey',  
  39. 'currency',  
  40. 'use_ssl',  
  41. 'tax_state',  
  42. 'tax_rate',  
  43. 'accepted_credit_cards' 
  44. ); 
  45.  
  46. return $options; 
  47.  
  48. /** 
  49. * Set payment options for payment settings page. 
  50. * @since 1.8 
  51. */ 
  52. static function pmpro_payment_options($options) 
  53. //get stripe options 
  54. $authorizenet_options = PMProGateway_authorizenet::getGatewayOptions(); 
  55.  
  56. //merge with others. 
  57. $options = array_merge($authorizenet_options, $options); 
  58.  
  59. return $options; 
  60.  
  61. /** 
  62. * Display fields for this gateway's options. 
  63. * @since 1.8 
  64. */ 
  65. static function pmpro_payment_option_fields($values, $gateway) 
  66. ?> 
  67. <tr class="pmpro_settings_divider gateway gateway_authorizenet" <?php if($gateway != "authorizenet") { ?>style="display: none;"<?php } ?>> 
  68. <td colspan="2"> 
  69. <?php _e('Authorize.net Settings', 'paid-memberships-pro' ); ?> 
  70. </td> 
  71. </tr> 
  72. <tr class="gateway gateway_authorizenet" <?php if($gateway != "authorizenet") { ?>style="display: none;"<?php } ?>> 
  73. <th scope="row" valign="top"> 
  74. <label for="loginname"><?php _e('Login Name', 'paid-memberships-pro' );?>:</label> 
  75. </th> 
  76. <td> 
  77. <input type="text" id="loginname" name="loginname" size="60" value="<?php echo esc_attr($values['loginname'])?>" /> 
  78. </td> 
  79. </tr> 
  80. <tr class="gateway gateway_authorizenet" <?php if($gateway != "authorizenet") { ?>style="display: none;"<?php } ?>> 
  81. <th scope="row" valign="top"> 
  82. <label for="transactionkey"><?php _e('Transaction Key', 'paid-memberships-pro' );?>:</label> 
  83. </th> 
  84. <td> 
  85. <input type="text" id="transactionkey" name="transactionkey" size="60" value="<?php echo esc_attr($values['transactionkey'])?>" /> 
  86. </td> 
  87. </tr> 
  88. <tr class="gateway gateway_authorizenet" <?php if($gateway != "authorizenet") { ?>style="display: none;"<?php } ?>> 
  89. <th scope="row" valign="top"> 
  90. <label><?php _e('Silent Post URL', 'paid-memberships-pro' );?>:</label> 
  91. </th> 
  92. <td> 
  93. <p><?php _e('To fully integrate with Authorize.net, be sure to set your Silent Post URL to', 'paid-memberships-pro' );?> <pre><?php echo admin_url("admin-ajax.php") . "?action=authnet_silent_post";?></pre></p> 
  94. </td> 
  95. </tr> 
  96. <?php 
  97.  
  98. /** 
  99. * Process checkout. 
  100. */ 
  101. function process(&$order) 
  102. //check for initial payment 
  103. if(floatval($order->InitialPayment) == 0) 
  104. //auth first, then process 
  105. if($this->authorize($order)) 
  106. $this->void($order); 
  107. if(!pmpro_isLevelTrial($order->membership_level)) 
  108. //subscription will start today with a 1 period trial 
  109. $order->ProfileStartDate = date_i18n("Y-m-d") . "T0:0:0"; 
  110. $order->TrialBillingPeriod = $order->BillingPeriod; 
  111. $order->TrialBillingFrequency = $order->BillingFrequency; 
  112. $order->TrialBillingCycles = 1; 
  113. $order->TrialAmount = 0; 
  114.  
  115. //add a billing cycle to make up for the trial, if applicable 
  116. if(!empty($order->TotalBillingCycles)) 
  117. $order->TotalBillingCycles++; 
  118. elseif($order->InitialPayment == 0 && $order->TrialAmount == 0) 
  119. //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there 
  120. $order->ProfileStartDate = date_i18n("Y-m-d") . "T0:0:0"; 
  121. $order->TrialBillingCycles++; 
  122.  
  123. //add a billing cycle to make up for the trial, if applicable 
  124. if(!empty($order->TotalBillingCycles)) 
  125. $order->TotalBillingCycles++; 
  126. else 
  127. //add a period to the start date to account for the initial payment 
  128. $order->ProfileStartDate = date_i18n("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0"; 
  129.  
  130. $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order); 
  131. return $this->subscribe($order); 
  132. else 
  133. if(empty($order->error)) 
  134. $order->error = __("Unknown error: Authorization failed.", 'paid-memberships-pro' ); 
  135. return false; 
  136. else 
  137. //charge first payment 
  138. if($this->charge($order)) 
  139. //set up recurring billing 
  140. if(pmpro_isLevelRecurring($order->membership_level)) 
  141. if(!pmpro_isLevelTrial($order->membership_level)) 
  142. //subscription will start today with a 1 period trial 
  143. $order->ProfileStartDate = date_i18n("Y-m-d") . "T0:0:0"; 
  144. $order->TrialBillingPeriod = $order->BillingPeriod; 
  145. $order->TrialBillingFrequency = $order->BillingFrequency; 
  146. $order->TrialBillingCycles = 1; 
  147. $order->TrialAmount = 0; 
  148.  
  149. //add a billing cycle to make up for the trial, if applicable 
  150. if(!empty($order->TotalBillingCycles)) 
  151. $order->TotalBillingCycles++; 
  152. elseif($order->InitialPayment == 0 && $order->TrialAmount == 0) 
  153. //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there 
  154. $order->ProfileStartDate = date_i18n("Y-m-d") . "T0:0:0"; 
  155. $order->TrialBillingCycles++; 
  156.  
  157. //add a billing cycle to make up for the trial, if applicable 
  158. if(!empty($order->TotalBillingCycles)) 
  159. $order->TotalBillingCycles++; 
  160. else 
  161. //add a period to the start date to account for the initial payment 
  162. $order->ProfileStartDate = date_i18n("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0"; 
  163.  
  164. $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order); 
  165. if($this->subscribe($order)) 
  166. return true; 
  167. else 
  168. if($this->void($order)) 
  169. if(!$order->error) 
  170. $order->error = __("Unknown error: Payment failed.", 'paid-memberships-pro' ); 
  171. else 
  172. if(!$order->error) 
  173. $order->error = __("Unknown error: Payment failed.", 'paid-memberships-pro' ); 
  174. $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", 'paid-memberships-pro' ); 
  175.  
  176. return false; 
  177. else 
  178. //only a one time charge 
  179. $order->status = "success"; //saved on checkout page 
  180. return true; 
  181. else 
  182. if(empty($order->error)) 
  183. $order->error = __("Unknown error: Payment failed.", 'paid-memberships-pro' ); 
  184.  
  185. return false; 
  186.  
  187. function authorize(&$order) 
  188. if(empty($order->code)) 
  189. $order->code = $order->getRandomCode(); 
  190.  
  191. if(empty($order->gateway_environment)) 
  192. $gateway_environment = pmpro_getOption("gateway_environment"); 
  193. else 
  194. $gateway_environment = $order->gateway_environment; 
  195. if($gateway_environment == "live") 
  196. $host = "secure.authorize.net"; 
  197. else 
  198. $host = "test.authorize.net"; 
  199.  
  200. $path = "/gateway/transact.dll"; 
  201. $post_url = "https://" . $host . $path; 
  202.  
  203. $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment); 
  204.  
  205. //what amount to authorize? just $1 to test 
  206. $amount = "1.00"; 
  207.  
  208. //combine address 
  209. $address = $order->Address1; 
  210. if(!empty($order->Address2)) 
  211. $address .= "\n" . $order->Address2; 
  212.  
  213. //customer stuff 
  214. $customer_email = $order->Email; 
  215. $customer_phone = $order->billing->phone; 
  216.  
  217. if(!isset($order->membership_level->name)) 
  218. $order->membership_level->name = ""; 
  219.  
  220. $post_values = array( 
  221.  
  222. // the API Login ID and Transaction Key must be replaced with valid values 
  223. "x_login" => pmpro_getOption("loginname"),  
  224. "x_tran_key" => pmpro_getOption("transactionkey"),  
  225.  
  226. "x_version" => "3.1",  
  227. "x_delim_data" => "TRUE",  
  228. "x_delim_char" => "|",  
  229. "x_relay_response" => "FALSE",  
  230.  
  231. "x_type" => "AUTH_ONLY",  
  232. "x_method" => "CC",  
  233. "x_card_type" => $order->cardtype,  
  234. "x_card_num" => $order->accountnumber,  
  235. "x_exp_date" => $order->ExpirationDate,  
  236.  
  237. "x_amount" => $amount,  
  238. "x_description" => $order->membership_level->name . " " . __("Membership", 'paid-memberships-pro' ),  
  239.  
  240. "x_first_name" => $order->FirstName,  
  241. "x_last_name" => $order->LastName,  
  242. "x_address" => $address,  
  243. "x_city" => $order->billing->city,  
  244. "x_state" => $order->billing->state,  
  245. "x_zip" => $order->billing->zip,  
  246. "x_country" => $order->billing->country,  
  247. "x_invoice_num" => $order->code,  
  248. "x_phone" => $customer_phone,  
  249. "x_email" => $order->Email 
  250. // Additional fields can be added here as outlined in the AIM integration 
  251. // guide at: http://developer.authorize.net 
  252. ); 
  253.  
  254. if(!empty($order->CVV2)) 
  255. $post_values["x_card_code"] = $order->CVV2; 
  256.  
  257. // This section takes the input fields and converts them to the proper format 
  258. // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4" 
  259. $post_string = ""; 
  260. foreach( $post_values as $key => $value ) 
  261. { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; } 
  262. $post_string = rtrim( $post_string, "& " ); 
  263.  
  264. //curl 
  265. $request = curl_init($post_url); // initiate curl object 
  266. curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response 
  267. curl_setopt($request, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1) 
  268. curl_setopt($request, CURLOPT_POSTFIELDS, $post_string); // use HTTP POST to send form data 
  269. curl_setopt($request, CURLOPT_SSL_VERIFYPEER, FALSE); // uncomment this line if you get no gateway response. 
  270. curl_setopt($request, CURLOPT_USERAGENT, PMPRO_USER_AGENT); // setting the user agent 
  271. $post_response = curl_exec($request); // execute curl post and store results in $post_response 
  272. // additional options may be required depending upon your server configuration 
  273. // you can find documentation on curl options at http://www.php.net/curl_setopt 
  274. curl_close ($request); // close curl object 
  275.  
  276. // This line takes the response and breaks it into an array using the specified delimiting character 
  277. $response_array = explode($post_values["x_delim_char"], $post_response); 
  278.  
  279. if($response_array[0] == 1) 
  280. $order->payment_transaction_id = $response_array[6]; 
  281. $order->updateStatus("authorized"); 
  282.  
  283. return true; 
  284. else 
  285. //$order->status = "error"; 
  286. $order->errorcode = $response_array[2]; 
  287. $order->error = $response_array[3]; 
  288. $order->shorterror = $response_array[3]; 
  289. return false; 
  290.  
  291. function void(&$order) 
  292. if(empty($order->payment_transaction_id)) 
  293. return false; 
  294.  
  295. if(empty($order->gateway_environment)) 
  296. $gateway_environment = pmpro_getOption("gateway_environment"); 
  297. else 
  298. $gateway_environment = $order->gateway_environment; 
  299. if($gateway_environment == "live") 
  300. $host = "secure.authorize.net"; 
  301. else 
  302. $host = "test.authorize.net"; 
  303.  
  304. $path = "/gateway/transact.dll"; 
  305. $post_url = "https://" . $host . $path; 
  306.  
  307. $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment); 
  308.  
  309. $post_values = array( 
  310.  
  311. // the API Login ID and Transaction Key must be replaced with valid values 
  312. "x_login" => pmpro_getOption("loginname"),  
  313. "x_tran_key" => pmpro_getOption("transactionkey"),  
  314.  
  315. "x_version" => "3.1",  
  316. "x_delim_data" => "TRUE",  
  317. "x_delim_char" => "|",  
  318. "x_relay_response" => "FALSE",  
  319.  
  320. "x_type" => "VOID",  
  321. "x_trans_id" => $order->payment_transaction_id 
  322. // Additional fields can be added here as outlined in the AIM integration 
  323. // guide at: http://developer.authorize.net 
  324. ); 
  325.  
  326. // This section takes the input fields and converts them to the proper format 
  327. // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4" 
  328. $post_string = ""; 
  329. foreach( $post_values as $key => $value ) 
  330. { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; } 
  331. $post_string = rtrim( $post_string, "& " ); 
  332.  
  333. //curl 
  334. $request = curl_init($post_url); // initiate curl object 
  335. curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response 
  336. curl_setopt($request, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1) 
  337. curl_setopt($request, CURLOPT_POSTFIELDS, $post_string); // use HTTP POST to send form data 
  338. curl_setopt($request, CURLOPT_SSL_VERIFYPEER, FALSE); // uncomment this line if you get no gateway response. 
  339. $post_response = curl_exec($request); // execute curl post and store results in $post_response 
  340. // additional options may be required depending upon your server configuration 
  341. // you can find documentation on curl options at http://www.php.net/curl_setopt 
  342. curl_close ($request); // close curl object 
  343.  
  344. // This line takes the response and breaks it into an array using the specified delimiting character 
  345. $response_array = explode($post_values["x_delim_char"], $post_response); 
  346. if($response_array[0] == 1) 
  347. $order->payment_transaction_id = $response_array[4]; 
  348. $order->updateStatus("voided"); 
  349. return true; 
  350. else 
  351. //$order->status = "error"; 
  352. $order->errorcode = $response_array[2]; 
  353. $order->error = $response_array[3]; 
  354. $order->shorterror = $response_array[3]; 
  355. return false; 
  356.  
  357. function charge(&$order) 
  358. if(empty($order->code)) 
  359. $order->code = $order->getRandomCode(); 
  360.  
  361. if(!empty($order->gateway_environment)) 
  362. $gateway_environment = $order->gateway_environment; 
  363. if(empty($gateway_environment)) 
  364. $gateway_environment = pmpro_getOption("gateway_environment"); 
  365. if($gateway_environment == "live") 
  366. $host = "secure.authorize.net"; 
  367. else 
  368. $host = "test.authorize.net"; 
  369.  
  370. $path = "/gateway/transact.dll"; 
  371. $post_url = "https://" . $host . $path; 
  372.  
  373. $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment); 
  374.  
  375. //what amount to charge? 
  376. $amount = $order->InitialPayment; 
  377.  
  378. //tax 
  379. $order->subtotal = $amount; 
  380. $tax = $order->getTax(true); 
  381. $amount = round((float)$order->subtotal + (float)$tax, 2); 
  382.  
  383. //combine address 
  384. $address = $order->Address1; 
  385. if(!empty($order->Address2)) 
  386. $address .= "\n" . $order->Address2; 
  387.  
  388. //customer stuff 
  389. $customer_email = $order->Email; 
  390. $customer_phone = $order->billing->phone; 
  391.  
  392. if(!isset($order->membership_level->name)) 
  393. $order->membership_level->name = ""; 
  394.  
  395. $post_values = array( 
  396.  
  397. // the API Login ID and Transaction Key must be replaced with valid values 
  398. "x_login" => pmpro_getOption("loginname"),  
  399. "x_tran_key" => pmpro_getOption("transactionkey"),  
  400.  
  401. "x_version" => "3.1",  
  402. "x_delim_data" => "TRUE",  
  403. "x_delim_char" => "|",  
  404. "x_relay_response" => "FALSE",  
  405.  
  406. "x_type" => "AUTH_CAPTURE",  
  407. "x_method" => "CC",  
  408. "x_card_type" => $order->cardtype,  
  409. "x_card_num" => $order->accountnumber,  
  410. "x_exp_date" => $order->ExpirationDate,  
  411.  
  412. "x_amount" => $amount,  
  413. "x_tax" => $tax,  
  414. "x_description" => $order->membership_level->name . " Membership",  
  415.  
  416. "x_first_name" => $order->FirstName,  
  417. "x_last_name" => $order->LastName,  
  418. "x_address" => $address,  
  419. "x_city" => $order->billing->city,  
  420. "x_state" => $order->billing->state,  
  421. "x_zip" => $order->billing->zip,  
  422. "x_country" => $order->billing->country,  
  423. "x_invoice_num" => $order->code,  
  424. "x_phone" => $customer_phone,  
  425. "x_email" => $order->Email 
  426.  
  427. // Additional fields can be added here as outlined in the AIM integration 
  428. // guide at: http://developer.authorize.net 
  429. ); 
  430.  
  431. if(!empty($order->CVV2)) 
  432. $post_values["x_card_code"] = $order->CVV2; 
  433.  
  434. // This section takes the input fields and converts them to the proper format 
  435. // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4" 
  436. $post_string = ""; 
  437. foreach( $post_values as $key => $value ) 
  438. { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; } 
  439. $post_string = rtrim( $post_string, "& " ); 
  440.  
  441. //curl 
  442. $request = curl_init($post_url); // initiate curl object 
  443. curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response 
  444. curl_setopt($request, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1) 
  445. curl_setopt($request, CURLOPT_POSTFIELDS, $post_string); // use HTTP POST to send form data 
  446. curl_setopt($request, CURLOPT_SSL_VERIFYPEER, FALSE); // uncomment this line if you get no gateway response. 
  447. $post_response = curl_exec($request); // execute curl post and store results in $post_response 
  448. // additional options may be required depending upon your server configuration 
  449. // you can find documentation on curl options at http://www.php.net/curl_setopt 
  450. curl_close ($request); // close curl object 
  451.  
  452. // This line takes the response and breaks it into an array using the specified delimiting character 
  453. $response_array = explode($post_values["x_delim_char"], $post_response); 
  454. if($response_array[0] == 1) 
  455. $order->payment_transaction_id = $response_array[6]; 
  456. $order->updateStatus("success"); 
  457. return true; 
  458. else 
  459. //$order->status = "error"; 
  460. $order->errorcode = $response_array[2]; 
  461. $order->error = $response_array[3]; 
  462. $order->shorterror = $response_array[3]; 
  463. return false; 
  464.  
  465. function subscribe(&$order) 
  466. //define variables to send 
  467.  
  468. if(empty($order->code)) 
  469. $order->code = $order->getRandomCode(); 
  470.  
  471. //filter order before subscription. use with care. 
  472. $order = apply_filters("pmpro_subscribe_order", $order, $this); 
  473.  
  474. if(!empty($order->gateway_environment)) 
  475. $gateway_environment = $order->gateway_environment; 
  476. if(empty($gateway_environment)) 
  477. $gateway_environment = pmpro_getOption("gateway_environment"); 
  478. if($gateway_environment == "live") 
  479. $host = "api.authorize.net"; 
  480. else 
  481. $host = "apitest.authorize.net"; 
  482.  
  483. $path = "/xml/v1/request.api"; 
  484.  
  485. $loginname = pmpro_getOption("loginname"); 
  486. $transactionkey = pmpro_getOption("transactionkey"); 
  487.  
  488. $amount = $order->PaymentAmount; 
  489. $refId = $order->code; 
  490. $name = $order->membership_name; 
  491. $length = (int)$order->BillingFrequency; 
  492.  
  493. if($order->BillingPeriod == "Month") 
  494. $unit = "months"; 
  495. elseif($order->BillingPeriod == "Day") 
  496. $unit = "days"; 
  497. elseif($order->BillingPeriod == "Year" && $order->BillingFrequency == 1) 
  498. $unit = "months"; 
  499. $length = 12; 
  500. elseif($order->BillingPeriod == "Week") 
  501. $unit = "days"; 
  502. $length = $length * 7; //converting weeks to days 
  503. else 
  504. return false; //authorize.net only supports months and days 
  505.  
  506. $startDate = substr($order->ProfileStartDate, 0, 10); 
  507. if(!empty($order->TotalBillingCycles)) 
  508. $totalOccurrences = (int)$order->TotalBillingCycles; 
  509. if(empty($totalOccurrences)) 
  510. $totalOccurrences = 9999; 
  511. if(isset($order->TrialBillingCycles)) 
  512. $trialOccurrences = (int)$order->TrialBillingCycles; 
  513. else 
  514. $trialOccurrences = 0; 
  515. if(isset($order->TrialAmount)) 
  516. $trialAmount = $order->TrialAmount; 
  517. else 
  518. $trialAmount = NULL; 
  519.  
  520. //taxes 
  521. $amount_tax = $order->getTaxForPrice($amount); 
  522. $trial_tax = $order->getTaxForPrice($trialAmount); 
  523.  
  524. $amount = round((float)$amount + (float)$amount_tax, 2); 
  525. $trialAmount = round((float)$trialAmount + (float)$trial_tax, 2); 
  526.  
  527. //authorize.net doesn't support different periods between trial and actual 
  528.  
  529. if(!empty($order->TrialBillingPeriod) && $order->TrialBillingPeriod != $order->BillingPeriod) 
  530. echo "F"; 
  531. return false; 
  532.  
  533. $cardNumber = $order->accountnumber; 
  534. $expirationDate = $order->ExpirationDate_YdashM; 
  535. $cardCode = $order->CVV2; 
  536.  
  537. $firstName = $order->FirstName; 
  538. $lastName = $order->LastName; 
  539.  
  540. //do address stuff then? 
  541. $address = $order->Address1; 
  542. if(!empty($order->Address2)) 
  543. $address .= "\n" . $order->Address2; 
  544. $city = $order->billing->city; 
  545. $state = $order->billing->state; 
  546. $zip = $order->billing->zip; 
  547. $country = $order->billing->country; 
  548.  
  549. //customer stuff 
  550. $customer_email = $order->Email; 
  551. if(strpos($order->billing->phone, "+") === false) 
  552. $customer_phone = $order->billing->phone; 
  553. else 
  554. $customer_phone = ""; 
  555.  
  556. //make sure the phone is in an okay format 
  557. $customer_phone = preg_replace("/[^0-9]/", "", $customer_phone); 
  558. if(strlen($customer_phone) > 10) 
  559. $customer_phone = ""; 
  560.  
  561. //build xml to post 
  562. $this->content = 
  563. "<?xml version=\"1.0\" encoding=\"utf-8\"?>" . 
  564. "<ARBCreateSubscriptionRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">" . 
  565. "<merchantAuthentication>". 
  566. "<name>" . $loginname . "</name>". 
  567. "<transactionKey>" . $transactionkey . "</transactionKey>". 
  568. "</merchantAuthentication>". 
  569. "<refId><![CDATA[" . substr($refId, 0, 20) . "]]></refId>". 
  570. "<subscription>". 
  571. "<name><![CDATA[" . substr($name, 0, 50) . "]]></name>". 
  572. "<paymentSchedule>". 
  573. "<interval>". 
  574. "<length>". $length ."</length>". 
  575. "<unit>". $unit ."</unit>". 
  576. "</interval>". 
  577. "<startDate>" . $startDate . "</startDate>". 
  578. "<totalOccurrences>". $totalOccurrences . "</totalOccurrences>"; 
  579. if(!empty($trialOccurrences)) 
  580. $this->content .= 
  581. "<trialOccurrences>". $trialOccurrences . "</trialOccurrences>"; 
  582. $this->content .= 
  583. "</paymentSchedule>". 
  584. "<amount>". $amount ."</amount>"; 
  585. if(!empty($trialOccurrences)) 
  586. $this->content .= 
  587. "<trialAmount>" . $trialAmount . "</trialAmount>"; 
  588. $this->content .= 
  589. "<payment>". 
  590. "<creditCard>". 
  591. "<cardNumber>" . $cardNumber . "</cardNumber>". 
  592. "<expirationDate>" . $expirationDate . "</expirationDate>"; 
  593. if(!empty($cardCode)) 
  594. $this->content .= "<cardCode>" . $cardCode . "</cardCode>"; 
  595. $this->content .= 
  596. "</creditCard>". 
  597. "</payment>". 
  598. "<order><invoiceNumber>" . substr($order->code, 0, 20) . "</invoiceNumber></order>". 
  599. "<customer>". 
  600. "<email>". substr($customer_email, 0, 255) . "</email>". 
  601. "<phoneNumber>". substr($customer_phone, 0, 25) . "</phoneNumber>". 
  602. "</customer>". 
  603. "<billTo>". 
  604. "<firstName><![CDATA[". substr($firstName, 0, 50) . "]]></firstName>". 
  605. "<lastName><![CDATA[" . substr($lastName, 0, 50) . "]]></lastName>". 
  606. "<address><![CDATA[". substr($address, 0, 60) . "]]></address>". 
  607. "<city><![CDATA[" . substr($city, 0, 40) . "]]></city>". 
  608. "<state>". substr($state, 0, 2) . "</state>". 
  609. "<zip>" . substr($zip, 0, 20) . "</zip>". 
  610. "<country>". substr($country, 0, 60) . "</country>". 
  611. "</billTo>". 
  612. "</subscription>". 
  613. "</ARBCreateSubscriptionRequest>"; 
  614.  
  615. //send the xml via curl 
  616. $this->response = $this->send_request_via_curl($host, $path, $this->content); 
  617. //if curl is unavilable you can try using fsockopen 
  618. /** 
  619. $response = send_request_via_fsockopen($host, $path, $content); 
  620. */ 
  621.  
  622. if(!empty($this->response)) { 
  623. list ($refId, $resultCode, $code, $text, $subscriptionId) = $this->parse_return($this->response); 
  624. if($resultCode == "Ok") 
  625. $order->status = "success"; //saved on checkout page 
  626. $order->subscription_transaction_id = $subscriptionId; 
  627. return true; 
  628. else 
  629. $order->status = "error"; 
  630. $order->errorcode = $code; 
  631. $order->error = $text; 
  632. $order->shorterror = $text; 
  633. return false; 
  634. } else { 
  635. $order->status = "error"; 
  636. $order->error = "Could not connect to Authorize.net"; 
  637. $order->shorterror = "Could not connect to Authorize.net"; 
  638. return false; 
  639.  
  640. function update(&$order) 
  641. //define variables to send 
  642. $gateway_environment = $order->gateway_environment; 
  643. if(empty($gateway_environment)) 
  644. $gateway_environment = pmpro_getOption("gateway_environment"); 
  645. if($gateway_environment == "live") 
  646. $host = "api.authorize.net"; 
  647. else 
  648. $host = "apitest.authorize.net"; 
  649.  
  650. $path = "/xml/v1/request.api"; 
  651.  
  652. $loginname = pmpro_getOption("loginname"); 
  653. $transactionkey = pmpro_getOption("transactionkey"); 
  654.  
  655. //$amount = $order->PaymentAmount; 
  656. $refId = $order->code; 
  657. $subscriptionId = $order->subscription_transaction_id; 
  658.  
  659. $cardNumber = $order->accountnumber; 
  660. $expirationDate = $order->ExpirationDate_YdashM; 
  661. $cardCode = $order->CVV2; 
  662.  
  663. $firstName = $order->FirstName; 
  664. $lastName = $order->LastName; 
  665.  
  666. //do address stuff then? 
  667. $address = $order->Address1; 
  668. if(!empty($order->Address2)) 
  669. $address .= "\n" . $order->Address2; 
  670. $city = $order->billing->city; 
  671. $state = $order->billing->state; 
  672. $zip = $order->billing->zip; 
  673. $country = $order->billing->country; 
  674.  
  675. //customer stuff 
  676. $customer_email = $order->Email; 
  677. if(strpos($order->billing->phone, "+") === false) 
  678. $customer_phone = $order->billing->phone; 
  679.  
  680.  
  681. //build xml to post 
  682. $this->content = 
  683. "<?xml version=\"1.0\" encoding=\"utf-8\"?>" . 
  684. "<ARBUpdateSubscriptionRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">". 
  685. "<merchantAuthentication>". 
  686. "<name><![CDATA[" . $loginname . "]]></name>". 
  687. "<transactionKey>" . $transactionkey . "</transactionKey>". 
  688. "</merchantAuthentication>". 
  689. "<refId>" . substr($refId, 0, 20) . "</refId>". 
  690. "<subscriptionId>" . $subscriptionId . "</subscriptionId>". 
  691. "<subscription>". 
  692. "<payment>". 
  693. "<creditCard>". 
  694. "<cardNumber>" . $cardNumber . "</cardNumber>". 
  695. "<expirationDate>" . $expirationDate . "</expirationDate>"; 
  696. if(!empty($cardCode)) 
  697. $this->content .= "<cardCode>" . $cardCode . "</cardCode>"; 
  698. $this->content .= 
  699. "</creditCard>". 
  700. "</payment>". 
  701. "<customer>". 
  702. "<email>". substr($customer_email, 0, 255) . "</email>". 
  703. "<phoneNumber>". substr(str_replace("1 (", "(", formatPhone($customer_phone)), 0, 25) . "</phoneNumber>". 
  704. "</customer>". 
  705. "<billTo>". 
  706. "<firstName><![CDATA[". substr($firstName, 0, 50) . "]]></firstName>". 
  707. "<lastName><![CDATA[" . substr($lastName, 0, 50) . "]]></lastName>". 
  708. "<address><![CDATA[". substr($address, 0, 60) . "]]></address>". 
  709. "<city><![CDATA[" . substr($city, 0, 40) . "]]></city>". 
  710. "<state><![CDATA[". substr($state, 0, 2) . "]]></state>". 
  711. "<zip>" . substr($zip, 0, 20) . "</zip>". 
  712. "<country>". substr($country, 0, 60) . "</country>". 
  713. "</billTo>". 
  714. "</subscription>". 
  715. "</ARBUpdateSubscriptionRequest>"; 
  716.  
  717. //send the xml via curl 
  718. $this->response = $this->send_request_via_curl($host, $path, $this->content); 
  719. //if curl is unavilable you can try using fsockopen 
  720. /** 
  721. $response = send_request_via_fsockopen($host, $path, $order->content); 
  722. */ 
  723.  
  724.  
  725. if(!empty($this->response)) { 
  726. list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($this->response); 
  727.  
  728. if($resultCode == "Ok" || $code == "Ok") 
  729. return true; 
  730. else 
  731. $order->status = "error"; 
  732. $order->errorcode = $code; 
  733. $order->error = $text; 
  734. $order->shorterror = $text; 
  735. return false; 
  736. } else { 
  737. $order->status = "error"; 
  738. $order->error = "Could not connect to Authorize.net"; 
  739. $order->shorterror = "Could not connect to Authorize.net"; 
  740. return false; 
  741.  
  742. function cancel(&$order) 
  743. //define variables to send 
  744. if(!empty($order->subscription_transaction_id)) 
  745. $subscriptionId = $order->subscription_transaction_id; 
  746. else 
  747. $subscriptionId = ""; 
  748. $loginname = pmpro_getOption("loginname"); 
  749. $transactionkey = pmpro_getOption("transactionkey"); 
  750.  
  751. if(!empty($order->gateway_environment)) 
  752. $gateway_environment = $order->gateway_environment; 
  753. else 
  754. $gateway_environment = pmpro_getOption("gateway_environment"); 
  755.  
  756. if($gateway_environment == "live") 
  757. $host = "api.authorize.net"; 
  758. else 
  759. $host = "apitest.authorize.net"; 
  760.  
  761. $path = "/xml/v1/request.api"; 
  762.  
  763. if(!$subscriptionId || !$loginname || !$transactionkey) 
  764. return false; 
  765.  
  766. //build xml to post 
  767. $content = 
  768. "<?xml version=\"1.0\" encoding=\"utf-8\"?>". 
  769. "<ARBCancelSubscriptionRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">". 
  770. "<merchantAuthentication>". 
  771. "<name>" . $loginname . "</name>". 
  772. "<transactionKey>" . $transactionkey . "</transactionKey>". 
  773. "</merchantAuthentication>" . 
  774. "<subscriptionId>" . $subscriptionId . "</subscriptionId>". 
  775. "</ARBCancelSubscriptionRequest>"; 
  776.  
  777. //send the xml via curl 
  778. $response = $this->send_request_via_curl($host, $path, $content); 
  779. //if curl is unavilable you can try using fsockopen 
  780. /** 
  781. $response = send_request_via_fsockopen($host, $path, $content); 
  782. */ 
  783.  
  784. //if the connection and send worked $response holds the return from Authorize.net 
  785. if ($response) 
  786. list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($response); 
  787.  
  788. if($resultCode == "Ok" || $code == "Ok") 
  789. $order->updateStatus("cancelled"); 
  790. return true; 
  791. else 
  792. //$order->status = "error"; 
  793. $order->errorcode = $code; 
  794. $order->error = $text; 
  795. $order->shorterror = $text; 
  796. return false; 
  797. else 
  798. $order->status = "error"; 
  799. $order->error = __("Could not connect to Authorize.net", 'paid-memberships-pro' ); 
  800. $order->shorterror = __("Could not connect to Authorize.net", 'paid-memberships-pro' ); 
  801. return false; 
  802.  
  803. function getSubscriptionStatus(&$order) 
  804. //define variables to send 
  805. if(!empty($order->subscription_transaction_id)) 
  806. $subscriptionId = $order->subscription_transaction_id; 
  807. else 
  808. $subscriptionId = ""; 
  809. $loginname = pmpro_getOption("loginname"); 
  810. $transactionkey = pmpro_getOption("transactionkey"); 
  811.  
  812. if(!empty($order->gateway_environment)) 
  813. $gateway_environment = $order->gateway_environment; 
  814. else 
  815. $gateway_environment = pmpro_getOption("gateway_environment"); 
  816.  
  817. if($gateway_environment == "live") 
  818. $host = "api.authorize.net"; 
  819. else 
  820. $host = "apitest.authorize.net"; 
  821.  
  822. $path = "/xml/v1/request.api"; 
  823.  
  824. if(!$subscriptionId || !$loginname || !$transactionkey) 
  825. return false; 
  826.  
  827. //build xml to post 
  828. $content = 
  829. "<?xml version=\"1.0\" encoding=\"utf-8\"?>". 
  830. "<ARBGetSubscriptionStatusRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">". 
  831. "<merchantAuthentication>". 
  832. "<name>" . $loginname . "</name>". 
  833. "<transactionKey>" . $transactionkey . "</transactionKey>". 
  834. "</merchantAuthentication>" . 
  835. "<subscriptionId>" . $subscriptionId . "</subscriptionId>". 
  836. "</ARBGetSubscriptionStatusRequest>"; 
  837.  
  838. //send the xml via curl 
  839. $response = $this->send_request_via_curl($host, $path, $content); 
  840.  
  841. //if curl is unavilable you can try using fsockopen 
  842. /** 
  843. $response = send_request_via_fsockopen($host, $path, $content); 
  844. */ 
  845.  
  846. //if the connection and send worked $response holds the return from Authorize.net 
  847. if($response) 
  848. list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($response); 
  849.  
  850. $status = $this->substring_between($response, '<status>', '</status>'); 
  851.  
  852. if($resultCode == "Ok" || $code == "Ok") 
  853. return $status; 
  854. else 
  855. $order->status = "error"; 
  856. $order->errorcode = $resultCode; 
  857. $order->error = $message; 
  858. $order->shorterror = $text; 
  859. else 
  860. $order->status = "error"; 
  861. $order->errorcode = $resultCode; 
  862. $order->error = $message; 
  863. $order->shorterror = $text; 
  864.  
  865. //Authorize.net Function 
  866. //function to send xml request via fsockopen 
  867. function send_request_via_fsockopen($host, $path, $content) 
  868. $posturl = "ssl://" . $host; 
  869. $header = "Host: $host\r\n"; 
  870. $header .= "User-Agent: PHP Script\r\n"; 
  871. $header .= "Content-Type: text/xml\r\n"; 
  872. $header .= "Content-Length: ".strlen($content)."\r\n"; 
  873. $header .= "Connection: close\r\n\r\n"; 
  874. $fp = fsockopen($posturl, 443, $errno, $errstr, 30); 
  875. if (!$fp) 
  876. $response = false; 
  877. else 
  878. error_reporting(E_ERROR); 
  879. fputs($fp, "POST $path HTTP/1.1\r\n"); 
  880. fputs($fp, $header.$content); 
  881. fwrite($fp, $out); 
  882. $response = ""; 
  883. while (!feof($fp)) 
  884. $response = $response . fgets($fp, 128); 
  885. fclose($fp); 
  886. error_reporting(E_ALL ^ E_NOTICE); 
  887. return $response; 
  888.  
  889. //Authorize.net Function 
  890. //function to send xml request via curl 
  891. function send_request_via_curl($host, $path, $content) 
  892. $posturl = "https://" . $host . $path; 
  893. $posturl = apply_filters("pmpro_authorizenet_post_url", $posturl, pmpro_getOption("gateway_environment")); 
  894. $ch = curl_init(); 
  895. curl_setopt($ch, CURLOPT_URL, $posturl); 
  896. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  897. curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: text/xml")); 
  898. curl_setopt($ch, CURLOPT_HEADER, 1); 
  899. curl_setopt($ch, CURLOPT_POSTFIELDS, $content); 
  900. curl_setopt($ch, CURLOPT_POST, 1); 
  901. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
  902. curl_setopt($ch, CURLOPT_USERAGENT, PMPRO_USER_AGENT); //set user agent 
  903. $response = curl_exec($ch); 
  904. return $response; 
  905.  
  906.  
  907. //Authorize.net Function 
  908. //function to parse Authorize.net response 
  909. function parse_return($content) 
  910. $refId = $this->substring_between($content, '<refId>', '</refId>'); 
  911. $resultCode = $this->substring_between($content, '<resultCode>', '</resultCode>'); 
  912. $code = $this->substring_between($content, '<code>', '</code>'); 
  913. $text = $this->substring_between($content, '<text>', '</text>'); 
  914. $subscriptionId = $this->substring_between($content, '<subscriptionId>', '</subscriptionId>'); 
  915. return array ($refId, $resultCode, $code, $text, $subscriptionId); 
  916.  
  917. //Authorize.net Function 
  918. //helper function for parsing response 
  919. function substring_between($haystack, $start, $end) 
  920. if (strpos($haystack, $start) === false || strpos($haystack, $end) === false) 
  921. return false; 
  922. else 
  923. $start_position = strpos($haystack, $start)+strlen($start); 
  924. $end_position = strpos($haystack, $end); 
  925. return substr($haystack, $start_position, $end_position-$start_position);