PMProGateway_Twocheckout

The Paid Memberships Pro PMProGateway Twocheckout class.

Defined (1)

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

/classes/gateways/class.pmprogateway_twocheckout.php  
  1. class PMProGateway_Twocheckout extends PMProGateway 
  2. function __construct($gateway = NULL) 
  3. if(!class_exists("Twocheckout")) 
  4. require_once(dirname(__FILE__) . "/../../includes/lib/Twocheckout/Twocheckout.php"); 
  5.  
  6. //set API connection vars 
  7. Twocheckout::sellerId(pmpro_getOption('twocheckout_accountnumber'));  
  8. Twocheckout::username(pmpro_getOption('twocheckout_apiusername')); 
  9. Twocheckout::password(pmpro_getOption('twocheckout_apipassword')); 
  10. Twocheckout::$verifySSL = false; 
  11.  
  12. $this->gateway = $gateway; 
  13. return $this->gateway; 
  14. }  
  15.  
  16. /** 
  17. * Run on WP init 
  18. *  
  19. * @since 1.8 
  20. */ 
  21. static function init() 
  22. {  
  23. //make sure PayPal Express is a gateway option 
  24. add_filter('pmpro_gateways', array('PMProGateway_twocheckout', 'pmpro_gateways')); 
  25.  
  26. //add fields to payment settings 
  27. add_filter('pmpro_payment_options', array('PMProGateway_twocheckout', 'pmpro_payment_options'));  
  28. add_filter('pmpro_payment_option_fields', array('PMProGateway_twocheckout', 'pmpro_payment_option_fields'), 10, 2); 
  29.  
  30. //code to add at checkout 
  31. $gateway = pmpro_getGateway(); 
  32. if($gateway == "twocheckout") 
  33. {  
  34. add_filter('pmpro_include_billing_address_fields', '__return_false'); 
  35. add_filter('pmpro_include_payment_information_fields', '__return_false'); 
  36. add_filter('pmpro_required_billing_fields', array('PMProGateway_twocheckout', 'pmpro_required_billing_fields')); 
  37. add_filter('pmpro_checkout_default_submit_button', array('PMProGateway_twocheckout', 'pmpro_checkout_default_submit_button')); 
  38. add_filter('pmpro_checkout_before_change_membership_level', array('PMProGateway_twocheckout', 'pmpro_checkout_before_change_membership_level'), 10, 2); 
  39.  
  40. /** 
  41. * Make sure this gateway is in the gateways list 
  42. *  
  43. * @since 1.8 
  44. */ 
  45. static function pmpro_gateways($gateways) 
  46. if(empty($gateways['twocheckout'])) 
  47. $gateways['twocheckout'] = __('2Checkout', 'paid-memberships-pro' ); 
  48.  
  49. return $gateways; 
  50.  
  51. /** 
  52. * Get a list of payment options that the this gateway needs/supports. 
  53. *  
  54. * @since 1.8 
  55. */ 
  56. static function getGatewayOptions() 
  57. {  
  58. $options = array( 
  59. 'sslseal',  
  60. 'nuclear_HTTPS',  
  61. 'gateway_environment',  
  62. 'twocheckout_apiusername',  
  63. 'twocheckout_apipassword',  
  64. 'twocheckout_accountnumber',  
  65. 'twocheckout_secretword',  
  66. 'currency',  
  67. 'use_ssl',  
  68. 'tax_state',  
  69. 'tax_rate' 
  70. ); 
  71.  
  72. return $options; 
  73.  
  74. /** 
  75. * Set payment options for payment settings page. 
  76. *  
  77. * @since 1.8 
  78. */ 
  79. static function pmpro_payment_options($options) 
  80. {  
  81. //get stripe options 
  82. $twocheckout_options = PMProGateway_twocheckout::getGatewayOptions(); 
  83.  
  84. //merge with others. 
  85. $options = array_merge($twocheckout_options, $options); 
  86.  
  87. return $options; 
  88.  
  89. /** 
  90. * Display fields for this gateway's options. 
  91. *  
  92. * @since 1.8 
  93. */ 
  94. static function pmpro_payment_option_fields($values, $gateway) 
  95. ?> 
  96. <tr class="pmpro_settings_divider gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>> 
  97. <td colspan="2"> 
  98. <?php _e('2Checkout Settings', 'paid-memberships-pro' ); ?> 
  99. </td> 
  100. </tr> 
  101. <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>> 
  102. <th scope="row" valign="top"> 
  103. <label for="twocheckout_apiusername"><?php _e('API Username', 'paid-memberships-pro' );?>:</label> 
  104. </th> 
  105. <td> 
  106. <input type="text" id="twocheckout_apiusername" name="twocheckout_apiusername" size="60" value="<?php echo esc_attr($values['twocheckout_apiusername'])?>" /> 
  107. <br /><small><?php _e('Go to Account » User Management in 2Checkout and create a user with API Access and API Updating.');?></small> 
  108. </td> 
  109. </tr> 
  110. <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>> 
  111. <th scope="row" valign="top"> 
  112. <label for="twocheckout_apipassword"><?php _e('API Password', 'paid-memberships-pro' );?>:</label> 
  113. </th> 
  114. <td> 
  115. <input type="text" id="twocheckout_apipassword" name="twocheckout_apipassword" size="60" value="<?php echo esc_attr($values['twocheckout_apipassword'])?>" /> 
  116. <br /><small><?php _e('Password for the API user created.');?></small> 
  117. </td> 
  118. </tr>  
  119. <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>> 
  120. <th scope="row" valign="top"> 
  121. <label for="twocheckout_accountnumber"><?php _e('Account Number', 'paid-memberships-pro' );?>:</label> 
  122. </th> 
  123. <td> 
  124. <input type="text" name="twocheckout_accountnumber" size="60" value="<?php echo $values['twocheckout_accountnumber']?>" /> 
  125. <br /><small><?php _e('Click on the profile icon in 2Checkout to find your Account Number.');?></small> 
  126. </td> 
  127. </tr> 
  128. <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>> 
  129. <th scope="row" valign="top"> 
  130. <label for="twocheckout_secretword"><?php _e('Secret Word', 'paid-memberships-pro' );?>:</label> 
  131. </th> 
  132. <td> 
  133. <input type="text" name="twocheckout_secretword" size="60" value="<?php echo $values['twocheckout_secretword']?>" /> 
  134. <br /><small><?php _e('Go to Account » Site Management. Look under Checkout Options to find the Secret Word.');?></small> 
  135. </td> 
  136. </tr> 
  137. <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>> 
  138. <th scope="row" valign="top"> 
  139. <label><?php _e('TwoCheckout INS URL', 'paid-memberships-pro' );?>:</label> 
  140. </th> 
  141. <td> 
  142. <p><?php _e('To fully integrate with 2Checkout, be sure to use the following for your INS URL and Approved URL', 'paid-memberships-pro' );?> <pre><?php echo admin_url("admin-ajax.php") . "?action=twocheckout-ins";?></pre></p> 
  143.  
  144. </td> 
  145. </tr>  
  146. <?php 
  147.  
  148. /** 
  149. * Remove required billing fields 
  150. *  
  151. * @since 1.8 
  152. */ 
  153. static function pmpro_required_billing_fields($fields) 
  154. unset($fields['bfirstname']); 
  155. unset($fields['blastname']); 
  156. unset($fields['baddress1']); 
  157. unset($fields['bcity']); 
  158. unset($fields['bstate']); 
  159. unset($fields['bzipcode']); 
  160. unset($fields['bphone']); 
  161. unset($fields['bemail']); 
  162. unset($fields['bcountry']); 
  163. unset($fields['CardType']); 
  164. unset($fields['AccountNumber']); 
  165. unset($fields['ExpirationMonth']); 
  166. unset($fields['ExpirationYear']); 
  167. unset($fields['CVV']); 
  168.  
  169. return $fields; 
  170.  
  171. /** 
  172. * Swap in our submit buttons. 
  173. * @since 1.8 
  174. */ 
  175. static function pmpro_checkout_default_submit_button($show) 
  176. global $gateway, $pmpro_requirebilling; 
  177.  
  178. //show our submit buttons 
  179. ?>  
  180. <span id="pmpro_submit_span"> 
  181. <input type="hidden" name="submit-checkout" value="1" />  
  182. <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Check Out with 2Checkout', 'paid-memberships-pro' ); } else { _e('Submit and Confirm', 'paid-memberships-pro' );}?> »" />  
  183. </span> 
  184. <?php 
  185.  
  186. //don't show the default 
  187. return false; 
  188.  
  189. /** 
  190. * Instead of change membership levels, send users to 2Checkout to pay. 
  191. * @since 1.8 
  192. */ 
  193. static function pmpro_checkout_before_change_membership_level($user_id, $morder) 
  194. global $wpdb, $discount_code_id; 
  195.  
  196. //if no order, no need to pay 
  197. if(empty($morder)) 
  198. return; 
  199.  
  200. $morder->user_id = $user_id;  
  201. $morder->saveOrder(); 
  202.  
  203. //save discount code use 
  204. if(!empty($discount_code_id)) 
  205. $wpdb->query("INSERT INTO $wpdb->pmpro_discount_codes_uses (code_id, user_id, order_id, timestamp) VALUES('" . $discount_code_id . "', '" . $user_id . "', '" . $morder->id . "', now())");  
  206.  
  207. do_action("pmpro_before_send_to_twocheckout", $user_id, $morder); 
  208.  
  209. $morder->Gateway->sendToTwocheckout($morder); 
  210.  
  211. /** 
  212. * Process checkout. 
  213. *  
  214. */ 
  215. function process(&$order) 
  216. {  
  217. if(empty($order->code)) 
  218. $order->code = $order->getRandomCode();  
  219.  
  220. //clean up a couple values 
  221. $order->payment_type = "2CheckOut"; 
  222. $order->CardType = ""; 
  223. $order->cardtype = ""; 
  224.  
  225. //just save, the user will go to 2checkout to pay 
  226. $order->status = "review";  
  227. $order->saveOrder(); 
  228.  
  229. return true;  
  230.  
  231. function sendToTwocheckout(&$order) 
  232. {  
  233. global $pmpro_currency;  
  234.  
  235. $tco_args = array( 
  236. 'sid' => pmpro_getOption("twocheckout_accountnumber"),  
  237. 'mode' => '2CO', // will always be 2CO according to docs (@see https://www.2checkout.com/documentation/checkout/parameter-sets/pass-through-products/) 
  238. 'li_0_type' => 'product',  
  239. 'li_0_name' => substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127),  
  240. 'li_0_quantity' => 1,  
  241. 'li_0_tangible' => 'N',  
  242. 'li_0_product_id' => $order->code,  
  243. 'merchant_order_id' => $order->code,  
  244. 'currency_code' => $pmpro_currency,  
  245. 'pay_method' => 'CC',  
  246. 'purchase_step' => 'billing-information',  
  247. 'x_receipt_link_url' => admin_url("admin-ajax.php") . "?action=twocheckout-ins" //pmpro_url("confirmation", "?level=" . $order->membership_level->id) 
  248. ); 
  249.  
  250. //taxes on initial amount 
  251. $initial_payment = $order->InitialPayment; 
  252. $initial_payment_tax = $order->getTaxForPrice($initial_payment); 
  253. $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2); 
  254.  
  255. //taxes on the amount (NOT CURRENTLY USED) 
  256. $amount = $order->PaymentAmount; 
  257. $amount_tax = $order->getTaxForPrice($amount);  
  258. $amount = round((float)$amount + (float)$amount_tax, 2);  
  259.  
  260. // Recurring membership  
  261. if( pmpro_isLevelRecurring( $order->membership_level ) ) { 
  262. $tco_args['li_0_startup_fee'] = number_format($initial_payment - $amount, 2, ".", ""); //negative amount for lower initial payments 
  263. $recurring_payment = number_format($order->membership_level->billing_amount, 2, ".", ""); 
  264. $recurring_payment_tax = number_format($order->getTaxForPrice($recurring_payment), 2, ".", ""); 
  265. $recurring_payment = number_format(round((float)$recurring_payment + (float)$recurring_payment_tax, 2), 2, ".", ""); 
  266. $tco_args['li_0_price'] = number_format($recurring_payment, 2, ".", ""); 
  267.  
  268. $tco_args['li_0_recurrence'] = ( $order->BillingFrequency == 1 ) ? $order->BillingFrequency . ' ' . $order->BillingPeriod : $order->BillingFrequency . ' ' . $order->BillingPeriod; 
  269.  
  270. if( property_exists( $order, 'TotalBillingCycles' ) ) 
  271. $tco_args['li_0_duration'] = ($order->BillingFrequency * $order->TotalBillingCycles ) . ' ' . $order->BillingPeriod; 
  272. else 
  273. $tco_args['li_0_duration'] = 'Forever'; 
  274. // Non-recurring membership 
  275. else { 
  276. $tco_args['li_0_price'] = number_format($initial_payment, 2, ".", ""); 
  277.  
  278. // Demo mode? 
  279. if(empty($order->gateway_environment)) 
  280. $gateway_environment = pmpro_getOption("gateway_environment"); 
  281. else 
  282. $gateway_environment = $order->gateway_environment; 
  283. if("sandbox" === $gateway_environment || "beta-sandbox" === $gateway_environment) 
  284. Twocheckout::sandbox(true); 
  285. $tco_args['demo'] = 'Y'; 
  286. else 
  287. Twocheckout::sandbox(false); 
  288.  
  289. // Trial? 
  290. //li_#_startup_fee Any start up fees for the product or service. Can be negative to provide discounted first installment pricing, but cannot equal or surpass the product price. 
  291. if(!empty($order->TrialBillingPeriod)) { 
  292. $trial_amount = $order->TrialAmount; 
  293. $trial_tax = $order->getTaxForPrice($trial_amount); 
  294. $trial_amount = pmpro_formatPrice(round((float)$trial_amount + (float)$trial_tax, 2), false, false); 
  295. $tco_args['li_0_startup_fee'] = $trial_amount; // Negative trial amount 
  296. }  
  297.  
  298. $ptpStr = ''; 
  299. foreach( $tco_args as $key => $value ) { 
  300. reset( $tco_args ); // Used to verify whether or not we're on the first argument 
  301. $ptpStr .= ( $key == key($tco_args) ) ? '?' . $key . '=' . urlencode( $value ) : '&' . $key . '=' . urlencode( $value ); 
  302.  
  303. //anything modders might add 
  304. $additional_parameters = apply_filters( 'pmpro_twocheckout_return_url_parameters', array() );  
  305. if( ! empty( $additional_parameters ) ) 
  306. foreach( $additional_parameters as $key => $value )  
  307. $ptpStr .= "&" . urlencode($key) . "=" . urlencode($value); 
  308.  
  309. $ptpStr = apply_filters( 'pmpro_twocheckout_ptpstr', $ptpStr, $order ); 
  310.  
  311. ///useful for debugging 
  312. ///echo str_replace("&", "&<br />", $ptpStr); 
  313. ///exit; 
  314.  
  315. //figure out gateway environment and URL to use  
  316. if($gateway_environment == "live") 
  317. $host = "www.2checkout.com";  
  318. else 
  319. $host = "sandbox.2checkout.com";  
  320. $tco_url = 'https://' . $host . '/checkout/purchase' . $ptpStr; 
  321.  
  322. //redirect to 2checkout 
  323. wp_redirect( $tco_url ); 
  324. exit; 
  325.  
  326. function cancel(&$order) { 
  327. //no matter what happens below, we're going to cancel the order in our system 
  328. $order->updateStatus("cancelled"); 
  329.  
  330. //require a payment transaction id 
  331. if(empty($order->payment_transaction_id)) 
  332. return false; 
  333.  
  334. //build api params 
  335. $params = array(); 
  336. $params['sale_id'] = $order->payment_transaction_id; 
  337.  
  338. // Demo mode? 
  339. if(empty($order->gateway_environment)) 
  340. $gateway_environment = pmpro_getOption("gateway_environment"); 
  341. else 
  342. $gateway_environment = $order->gateway_environment; 
  343.  
  344. if("sandbox" === $gateway_environment || "beta-sandbox" === $gateway_environment) 
  345. Twocheckout::sandbox(true); 
  346. $params['demo'] = 'Y'; 
  347. else 
  348. Twocheckout::sandbox(false); 
  349.  
  350. $result = Twocheckout_Sale::stop( $params ); // Stop the recurring billing 
  351.  
  352. // Successfully cancelled 
  353. if (isset($result['response_code']) && $result['response_code'] === 'OK') { 
  354. $order->updateStatus("cancelled");  
  355. return true; 
  356. // Failed 
  357. else { 
  358. $order->status = "error"; 
  359. $order->errorcode = $result->getCode(); 
  360. $order->error = $result->getMessage(); 
  361.  
  362. return false; 
  363.  
  364. return $order;