/app/controller/class-ms-controller-gateway.php

  1. <?php 
  2. /** 
  3. * This file defines the MS_Controller_Gateway class. 
  4. * 
  5. * @copyright Incsub (http://incsub.com/) 
  6. * 
  7. * @license http://opensource.org/licenses/GPL-2.0 GNU General Public License, version 2 (GPL-2.0) 
  8. * 
  9. * This program is free software; you can redistribute it and/or modify 
  10. * it under the terms of the GNU General Public License, version 2, as 
  11. * published by the Free Software Foundation. 
  12. * 
  13. * This program is distributed in the hope that it will be useful,  
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
  16. * GNU General Public License for more details. 
  17. * 
  18. * You should have received a copy of the GNU General Public License 
  19. * along with this program; if not, write to the Free Software 
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,  
  21. * MA 02110-1301 USA 
  22. * 
  23. */ 
  24.  
  25. /** 
  26. * Gateway controller. 
  27. * 
  28. * @since 1.0.0 
  29. * 
  30. * @package Membership2 
  31. * @subpackage Controller 
  32. */ 
  33. class MS_Controller_Gateway extends MS_Controller { 
  34.  
  35. /** 
  36. * AJAX action constants. 
  37. * 
  38. * @since 1.0.0 
  39. * 
  40. * @var string 
  41. */ 
  42. const AJAX_ACTION_TOGGLE_GATEWAY = 'toggle_gateway'; 
  43. const AJAX_ACTION_UPDATE_GATEWAY = 'update_gateway'; 
  44.  
  45. /** 
  46. * Allowed actions to execute in template_redirect hook. 
  47. * 
  48. * @since 1.0.0 
  49. * 
  50. * @var string 
  51. */ 
  52. private $allowed_actions = array( 'update_card', 'purchase_button' ); 
  53.  
  54. /** 
  55. * Prepare the gateway controller. 
  56. * 
  57. * @since 1.0.0 
  58. */ 
  59. public function __construct() { 
  60. parent::__construct(); 
  61.  
  62. $this->add_action( 'template_redirect', 'process_actions', 1 ); 
  63.  
  64. $this->add_action( 'ms_controller_gateway_settings_render_view', 'gateway_settings_edit' ); 
  65.  
  66. $this->add_action( 'ms_view_shortcode_invoice_purchase_button', 'purchase_button', 10, 2 ); 
  67. $this->add_action( 'ms_view_frontend_payment_purchase_button', 'purchase_button', 10, 2 ); 
  68.  
  69. $this->add_action( 'ms_controller_frontend_signup_gateway_form', 'gateway_form_mgr', 1 ); 
  70. $this->add_action( 'ms_controller_frontend_signup_process_purchase', 'process_purchase', 1 ); 
  71. $this->add_filter( 'ms_view_shortcode_membershipsignup_cancel_button', 'cancel_button', 10, 2 ); 
  72.  
  73. $this->add_action( 'ms_view_shortcode_account_card_info', 'card_info' ); 
  74.  
  75. $this->add_action( 'pre_get_posts', 'handle_payment_return', 1 ); 
  76.  
  77. $this->add_action( 'ms_controller_frontend_enqueue_scripts', 'enqueue_scripts' ); 
  78.  
  79. $this->add_ajax_action( self::AJAX_ACTION_TOGGLE_GATEWAY, 'toggle_ajax_action' ); 
  80. $this->add_ajax_action( self::AJAX_ACTION_UPDATE_GATEWAY, 'ajax_action_update_gateway' ); 
  81.  
  82. /** 
  83. * Handle URI actions for registration. 
  84. * 
  85. * Matches returned 'action' to method to execute. 
  86. * 
  87. * Related action hooks: 
  88. * - template_redirect 
  89. * 
  90. * @since 1.0.0 
  91. */ 
  92. public function process_actions() { 
  93. $action = $this->get_action(); 
  94.  
  95. /** 
  96. * If $action is set, then call relevant method. 
  97. * 
  98. * Methods: 
  99. * @see $allowed_actions property 
  100. * 
  101. */ 
  102. if ( ! empty( $action ) 
  103. && method_exists( $this, $action ) 
  104. && in_array( $action, $this->allowed_actions ) 
  105. ) { 
  106. $this->$action(); 
  107.  
  108. /** 
  109. * Handle Ajax toggle action. 
  110. * 
  111. * Related action hooks: 
  112. * - wp_ajax_toggle_gateway 
  113. * 
  114. * @since 1.0.0 
  115. */ 
  116. public function toggle_ajax_action() { 
  117. $msg = 0; 
  118.  
  119. $fields = array( 'gateway_id' ); 
  120. if ( $this->verify_nonce() 
  121. && self::validate_required( $fields ) 
  122. && $this->is_admin_user() 
  123. ) { 
  124. $msg = $this->gateway_list_do_action( 
  125. 'toggle_activation',  
  126. array( $_POST['gateway_id'] ) 
  127. ); 
  128.  
  129. wp_die( $msg ); 
  130.  
  131. /** 
  132. * Handle Ajax update gateway action. 
  133. * 
  134. * Related action hooks: 
  135. * - wp_ajax_update_gateway 
  136. * 
  137. * @since 1.0.0 
  138. */ 
  139. public function ajax_action_update_gateway() { 
  140. $msg = MS_Helper_Settings::SETTINGS_MSG_NOT_UPDATED; 
  141.  
  142. $fields = array( 'action', 'gateway_id', 'field', 'value' ); 
  143. if ( $this->verify_nonce() 
  144. && self::validate_required( $fields ) 
  145. && $this->is_admin_user() 
  146. ) { 
  147. lib2()->array->strip_slashes( $_POST, 'value' ); 
  148.  
  149. $msg = $this->gateway_list_do_action( 
  150. $_POST['action'],  
  151. array( $_POST['gateway_id'] ),  
  152. array( $_POST['field'] => $_POST['value'] ) 
  153. ); 
  154.  
  155. wp_die( $msg ); 
  156.  
  157. /** 
  158. * Show gateway settings page. 
  159. * 
  160. * 
  161. * Related action hooks: 
  162. * - ms_controller_gateway_settings_render_view 
  163. * 
  164. * @since 1.0.0 
  165. */ 
  166. public function gateway_settings_edit( $gateway_id ) { 
  167. if ( ! empty( $gateway_id ) 
  168. && MS_Model_Gateway::is_valid_gateway( $gateway_id ) 
  169. ) { 
  170. switch ( $gateway_id ) { 
  171. case MS_Gateway_Manual::ID: 
  172. $view = MS_Factory::create( 'MS_Gateway_Manual_View_Settings' ); 
  173. break; 
  174.  
  175. case MS_Gateway_Paypalsingle::ID: 
  176. $view = MS_Factory::create( 'MS_Gateway_Paypalsingle_View_Settings' ); 
  177. break; 
  178.  
  179. case MS_Gateway_Paypalstandard::ID: 
  180. $view = MS_Factory::create( 'MS_Gateway_Paypalstandard_View_Settings' ); 
  181. break; 
  182.  
  183. case MS_Gateway_Authorize::ID: 
  184. $view = MS_Factory::create( 'MS_Gateway_Authorize_View_Settings' ); 
  185. break; 
  186.  
  187. case MS_Gateway_Stripe::ID: 
  188. $view = MS_Factory::create( 'MS_Gateway_Stripe_View_Settings' ); 
  189. break; 
  190.  
  191. default: 
  192. // Empty form... 
  193. $view = MS_Factory::create( 'MS_View' ); 
  194. break; 
  195.  
  196. $data = array( 
  197. 'model' => MS_Model_Gateway::factory( $gateway_id ),  
  198. 'action' => 'edit',  
  199. ); 
  200.  
  201. $view->data = apply_filters( 
  202. 'ms_gateway_view_settings_edit_data',  
  203. $data 
  204. ); 
  205. $view = apply_filters( 
  206. 'ms_gateway_view_settings_edit',  
  207. $view,  
  208. $gateway_id 
  209. ); 
  210.  
  211. $view->render(); 
  212.  
  213. /** 
  214. * Handle Payment Gateway list actions. 
  215. * 
  216. * @since 1.0.0 
  217. * 
  218. * @param string $action The action to execute. 
  219. * @param int[] $gateways The gateways IDs to process. 
  220. * @param mixed[] $fields The data to process. 
  221. */ 
  222. public function gateway_list_do_action( $action, $gateways, $fields = null ) { 
  223. $msg = MS_Helper_Settings::SETTINGS_MSG_NOT_UPDATED; 
  224. if ( ! $this->is_admin_user() ) { 
  225. return $msg; 
  226.  
  227. foreach ( $gateways as $gateway_id ) { 
  228. $gateway = MS_Model_Gateway::factory( $gateway_id ); 
  229.  
  230. switch ( $action ) { 
  231. case 'toggle_activation': 
  232. $gateway->active = ! $gateway->active; 
  233. $gateway->save(); 
  234. $msg = MS_Helper_Settings::SETTINGS_MSG_UPDATED; 
  235.  
  236. /** 
  237. * Hook called after a gateway-status was toggled. 
  238. * 
  239. * @since 2.0.0 
  240. */ 
  241. do_action( 'ms_gateway_toggle_' . $gateway_id, $gateway ); 
  242. break; 
  243.  
  244. case 'edit': 
  245. case 'update_gateway': 
  246. foreach ( $fields as $field => $value ) { 
  247. $gateway->$field = trim( $value ); 
  248. $gateway->save(); 
  249.  
  250. /** 
  251. * $settings->is_global_payments_set is used to hide global 
  252. * payment settings in the membership setup payment step 
  253. */ 
  254. if ( $gateway->is_configured() ) { 
  255. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  256. $settings->is_global_payments_set = true; 
  257. $settings->save(); 
  258. $msg = MS_Helper_Settings::SETTINGS_MSG_UPDATED; 
  259. } else { 
  260. $msg = MS_Helper_Settings::SETTINGS_MSG_UNCONFIGURED; 
  261.  
  262. /** 
  263. * Hook called after a gateway-settings were modified. 
  264. * 
  265. * @since 2.0.0 
  266. */ 
  267. do_action( 'ms_gateway_changed_' . $gateway_id, $gateway ); 
  268. break; 
  269.  
  270. return apply_filters( 
  271. 'ms_controller_gateway_gateway_list_do_action',  
  272. $msg,  
  273. $action,  
  274. $gateways,  
  275. $fields,  
  276. $this 
  277. ); 
  278.  
  279. /** 
  280. * Show gateway purchase button. 
  281. * 
  282. * Related action hooks: 
  283. * - ms_view_frontend_payment_purchase_button 
  284. * - ms_view_shortcode_invoice_purchase_button 
  285. * 
  286. * @since 1.0.0 
  287. */ 
  288. public function purchase_button( $subscription, $invoice ) { 
  289. // Get only active gateways 
  290. $gateways = MS_Model_Gateway::get_gateways( true ); 
  291. $data = array(); 
  292.  
  293. $membership = $subscription->get_membership(); 
  294. $is_free = false; 
  295. if ( $membership->is_free() ) { $is_free = true; } 
  296. elseif ( 0 == $invoice->total ) { $is_free = true; } 
  297. elseif ( $invoice->uses_trial ) { $is_free = true; } 
  298.  
  299. // show gateway purchase button for every active gateway 
  300. foreach ( $gateways as $gateway ) { 
  301. $view = null; 
  302.  
  303. // Skip gateways that are not configured. 
  304. if ( ! $gateway->is_configured() ) { continue; } 
  305. if ( ! $membership->can_use_gateway( $gateway->id ) ) { continue; } 
  306.  
  307. $data['ms_relationship'] = $subscription; 
  308. $data['gateway'] = $gateway; 
  309. $data['step'] = MS_Controller_Frontend::STEP_PROCESS_PURCHASE; 
  310.  
  311. // Free membership, show only free gateway 
  312. if ( $is_free ) { 
  313. if ( MS_Gateway_Free::ID !== $gateway->id ) { 
  314. continue; 
  315. // Skip free gateway 
  316. elseif ( MS_Gateway_Free::ID === $gateway->id ) { 
  317. continue; 
  318.  
  319. $view_class = get_class( $gateway ) . '_View_Button'; 
  320. $view = MS_Factory::create( $view_class ); 
  321.  
  322. if ( MS_Gateway_Authorize::ID == $gateway->id ) { 
  323. /** 
  324. * set additional step for authorize.net (gateway specific form) 
  325. * @todo change to use popup, instead of another step (like stripe) 
  326. */ 
  327. $data['step'] = 'gateway_form'; 
  328.  
  329. if ( ! empty( $view ) ) { 
  330. $view = apply_filters( 
  331. 'ms_gateway_view_button',  
  332. $view,  
  333. $gateway->id 
  334. ); 
  335.  
  336. $view->data = apply_filters( 
  337. 'ms_gateway_view_button_data',  
  338. $data,  
  339. $gateway->id 
  340. ); 
  341.  
  342. $html = apply_filters( 
  343. 'ms_controller_gateway_purchase_button_'. $gateway->id,  
  344. $view->to_html(),  
  345. $subscription,  
  346. $this 
  347. ); 
  348.  
  349. echo '' . $html; 
  350.  
  351.  
  352. /** 
  353. * Show gateway purchase button. 
  354. * 
  355. * Related action hooks: 
  356. * - ms_view_shortcode_membershipsignup_cancel_button 
  357. * 
  358. * @since 1.0.0 
  359. */ 
  360. public function cancel_button( $button, $ms_relationship ) { 
  361. $view = null; 
  362. $data = array(); 
  363. $data['ms_relationship'] = $ms_relationship; 
  364. $new_button = null; 
  365.  
  366. switch ( $ms_relationship->gateway_id ) { 
  367. case MS_Gateway_Paypalstandard::ID: 
  368. $view = MS_Factory::create( 'MS_Gateway_Paypalstandard_View_Cancel' ); 
  369. $data['gateway'] = $ms_relationship->get_gateway(); 
  370. break; 
  371.  
  372. case MS_Gateway_Authorize::ID: 
  373. case MS_Gateway_Paypalsingle::ID: 
  374. case MS_Gateway_Stripe::ID: 
  375. case MS_Gateway_Free::ID: 
  376. case MS_Gateway_Manual::ID: 
  377. default: 
  378. break; 
  379. $view = apply_filters( 'ms_gateway_view_cancel_button', $view ); 
  380.  
  381. if ( ! empty( $view ) ) { 
  382. $view->data = apply_filters( 
  383. 'ms_gateway_view_cancel_button_data',  
  384. $data 
  385. ); 
  386. $new_button = $view->get_button(); 
  387.  
  388. if ( ! $new_button ) { 
  389. $new_button = $button; 
  390.  
  391. return apply_filters( 
  392. 'ms_controller_gateway_cancel_button',  
  393. $new_button,  
  394. $ms_relationship,  
  395. $this 
  396. ); 
  397.  
  398. /** 
  399. * Set hook to handle gateway extra form to commit payments. 
  400. * 
  401. * Related action hooks: 
  402. * - ms_controller_frontend_signup_gateway_form 
  403. * 
  404. * @since 1.0.0 
  405. */ 
  406. public function gateway_form_mgr() { 
  407. // Display gateway form 
  408. $this->add_filter( 'the_content', 'gateway_form', 10 ); 
  409.  
  410. // Enqueue styles and scripts used 
  411. $this->add_action( 'wp_enqueue_scripts', 'enqueue_scripts' ); 
  412.  
  413. /** 
  414. * Handles gateway extra form to commit payments. 
  415. * 
  416. * Related filter hooks: 
  417. * - the_content 
  418. * 
  419. * @since 1.0.0 
  420. * 
  421. * @param string $content The page content to filter. 
  422. * @return string The filtered content. 
  423. */ 
  424. public function gateway_form( $content ) { 
  425. $data = array(); 
  426.  
  427. $fields = array( 'gateway', 'ms_relationship_id' ); 
  428. if ( self::validate_required( $fields ) 
  429. && MS_Model_Gateway::is_valid_gateway( $_POST['gateway'] ) 
  430. ) { 
  431. $data['gateway'] = $_POST['gateway']; 
  432. $data['ms_relationship_id'] = $_POST['ms_relationship_id']; 
  433.  
  434. $ms_relationship = MS_Factory::load( 
  435. 'MS_Model_Relationship',  
  436. $_POST['ms_relationship_id'] 
  437. ); 
  438.  
  439. switch ( $_POST['gateway'] ) { 
  440. case MS_Gateway_Authorize::ID: 
  441. $member = $ms_relationship->get_member(); 
  442. $view = MS_Factory::create( 'MS_Gateway_Authorize_View_Form' ); 
  443. $gateway = MS_Model_Gateway::factory( MS_Gateway_Authorize::ID ); 
  444. $data['countries'] = $gateway->get_country_codes(); 
  445.  
  446. $data['action'] = $this->get_action(); 
  447.  
  448. if ( 'update_card' == $this->get_action() ) { 
  449. // Only new card option available on update card action. 
  450. $data['cim_profiles'] = array(); 
  451. } else { 
  452. // show existing credit card. 
  453. $data['cim_profiles'] = $gateway->get_cim_profile( $member ); 
  454.  
  455. lib2()->array->strip_slashes( $_POST, 'auth_error' ); 
  456.  
  457. $data['cim_payment_profile_id'] = $gateway->get_cim_payment_profile_id( $member ); 
  458. $data['auth_error'] = ! empty( $_POST['auth_error'] ) ? $_POST['auth_error'] : ''; 
  459. break; 
  460.  
  461. default: 
  462. break; 
  463.  
  464. $view = apply_filters( 'ms_gateway_view_form', $view ); 
  465. $view->data = apply_filters( 'ms_gateway_view_form_data', $data ); 
  466.  
  467. return apply_filters( 
  468. 'ms_controller_gateway_form',  
  469. $view->to_html(),  
  470. $this 
  471. ); 
  472.  
  473. /** 
  474. * Process purchase using gateway. 
  475. * 
  476. * Related Action Hooks: 
  477. * - ms_controller_frontend_signup_process_purchase 
  478. * 
  479. * @since 1.0.0 
  480. */ 
  481. public function process_purchase() { 
  482. $fields = array( 'gateway', 'ms_relationship_id' ); 
  483.  
  484. lib2()->array->equip_request( 'gateway', 'ms_relationship_id' ); 
  485.  
  486. $valid = true; 
  487. $nonce_name = $_REQUEST['gateway'] . '_' . $_REQUEST['ms_relationship_id']; 
  488.  
  489. if ( ! self::validate_required( $fields, 'any' ) ) { 
  490. $valid = false; 
  491. $err = 'GAT-01 (invalid fields)'; 
  492. } elseif ( ! MS_Model_Gateway::is_valid_gateway( $_REQUEST['gateway'] ) ) { 
  493. $valid = false; 
  494. $err = 'GAT-02 (invalid gateway)'; 
  495. } elseif ( ! $this->verify_nonce( $nonce_name, 'any' ) ) { 
  496. $valid = false; 
  497. $err = 'GAT-03 (invalid nonce)'; 
  498.  
  499. if ( $valid ) { 
  500. $subscription = MS_Factory::load( 
  501. 'MS_Model_Relationship',  
  502. $_REQUEST['ms_relationship_id'] 
  503. ); 
  504.  
  505. $gateway_id = $_REQUEST['gateway']; 
  506. $gateway = MS_Model_Gateway::factory( $gateway_id ); 
  507.  
  508. try { 
  509. $invoice = $gateway->process_purchase( $subscription ); 
  510.  
  511. // If invoice is successfully paid, redirect to welcome page. 
  512. if ( $invoice->is_paid() 
  513. || ( $invoice->uses_trial 
  514. && MS_Model_Invoice::STATUS_BILLED == $invoice->status 
  515. ) { 
  516. // Make sure to respect the single-membership rule 
  517. $this->validate_membership_states( $subscription ); 
  518.  
  519. // Redirect user to the Payment-Completed page. 
  520. if ( ! defined( 'IS_UNIT_TEST' ) ) { 
  521. MS_Model_Pages::redirect_to( 
  522. MS_Model_Pages::MS_PAGE_REG_COMPLETE,  
  523. array( 'ms_relationship_id' => $subscription->id ) 
  524. ); 
  525. } else { 
  526. // For manual gateway payments. 
  527. $this->add_action( 'the_content', 'purchase_info_content' ); 
  528. catch ( Exception $e ) { 
  529. MS_Helper_Debug::log( $e->getMessage() ); 
  530.  
  531. switch ( $gateway_id ) { 
  532. case MS_Gateway_Authorize::ID: 
  533. $_POST['auth_error'] = $e->getMessage(); 
  534. // call action to step back 
  535. do_action( 'ms_controller_frontend_signup_gateway_form' ); 
  536. break; 
  537.  
  538. case MS_Gateway_Stripe::ID: 
  539. $_POST['error'] = sprintf( 
  540. __( 'Error: %s', MS_TEXT_DOMAIN ),  
  541. $e->getMessage() 
  542. ); 
  543.  
  544. // Hack to send the error message back to the payment_table. 
  545. MS_Plugin::instance()->controller->controllers['frontend']->add_action( 
  546. 'the_content',  
  547. 'payment_table', 1 
  548. ); 
  549. break; 
  550.  
  551. default: 
  552. do_action( 'ms_controller_gateway_form_error', $e ); 
  553. $this->add_action( 'the_content', 'purchase_error_content' ); 
  554. break; 
  555. } else { 
  556. MS_Helper_Debug::log( 'Error Code ' . $err ); 
  557.  
  558. $this->add_action( 'the_content', 'purchase_error_content' ); 
  559.  
  560. // Hack to show signup page in case of errors 
  561. $ms_page = MS_Model_Pages::get_page( MS_Model_Pages::MS_PAGE_REGISTER ); 
  562.  
  563. if ( $ms_page ) { 
  564. // During unit-testing the $ms_page object might be empty. 
  565. global $wp_query; 
  566. $wp_query->query_vars['page_id'] = $ms_page->ID; 
  567. $wp_query->query_vars['post_type'] = 'page'; 
  568.  
  569. do_action( 
  570. 'ms_controller_gateway_process_purchase_after',  
  571. $this 
  572. ); 
  573.  
  574. /** 
  575. * Make sure that we respect the Single-Membership rule. 
  576. * This rule is active when the "Multiple-Memberships" Add-on is DISABLED. 
  577. * 
  578. * @since 1.0.4 
  579. * 
  580. * @param MS_Model_Relationship $new_relationship 
  581. */ 
  582. protected function validate_membership_states( $new_relationship ) { 
  583. if ( MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_MULTI_MEMBERSHIPS ) ) { 
  584. // Multiple memberships allowed. No need to check anything. 
  585. return; 
  586.  
  587. $cancel_these = array( 
  588. MS_Model_Relationship::STATUS_TRIAL,  
  589. MS_Model_Relationship::STATUS_ACTIVE,  
  590. MS_Model_Relationship::STATUS_PENDING,  
  591. ); 
  592.  
  593. $member = $new_relationship->get_member(); 
  594. foreach ( $member->subscriptions as $ms_relationship ) { 
  595. if ( $ms_relationship->id === $new_relationship->id ) { continue; } 
  596. if ( in_array( $ms_relationship->status, $cancel_these ) ) { 
  597. $ms_relationship->cancel_membership(); 
  598.  
  599. /** 
  600. * Show signup page with custom content. 
  601. * 
  602. * This is used by manual gateway (overridden) to show payment info. 
  603. * 
  604. * Related action hooks: 
  605. * 
  606. * @since 1.0.0 
  607. * 
  608. * @param string $content The page content to filter. 
  609. * @return string The filtered content. 
  610. */ 
  611. public function purchase_info_content( $content ) { 
  612. return apply_filters( 
  613. 'ms_controller_gateway_purchase_info_content',  
  614. $content,  
  615. $this 
  616. ); 
  617.  
  618. /** 
  619. * Show error message in the signup page. 
  620. * 
  621. * Related action hooks: 
  622. * 
  623. * @since 1.0.0 
  624. */ 
  625. public function purchase_error_content( $content ) { 
  626. return apply_filters( 
  627. 'ms_controller_gateway_purchase_error_content',  
  628. __( 'Sorry, your signup request has failed. Try again.', MS_TEXT_DOMAIN ),  
  629. $content,  
  630. $this 
  631. ); 
  632.  
  633. /** 
  634. * Handle payment gateway return IPNs. 
  635. * 
  636. * Used by Paypal gateways. 
  637. * A redirection rule is set up in the main MS_Plugin object 
  638. * (protected_content.php): 
  639. * /ms-payment-return/XYZ becomes index.php?paymentgateway=XYZ 
  640. * 
  641. * Related action hooks: 
  642. * - pre_get_posts 
  643. * 
  644. * @todo Review how this works when we use OAuth API's with gateways. 
  645. * 
  646. * @since 1.0.0 
  647. * 
  648. * @param WP_Query $wp_query The WordPress query object 
  649. */ 
  650. public function handle_payment_return( $wp_query ) { 
  651. // Do not check custom loops. 
  652. if ( ! $wp_query->is_main_query() ) { return; } 
  653.  
  654. if ( ! empty( $wp_query->query_vars['paymentgateway'] ) ) { 
  655. $gateway = $wp_query->query_vars['paymentgateway']; 
  656.  
  657. // Handle payment-responses from imported membership subscriptions. 
  658. if ( MS_Model_Import_Membership::did_import() ) { 
  659. if ( 'paypalsolo' == $gateway ) { $gateway = 'paypalsingle'; } 
  660. if ( 'paypalexpress' == $gateway ) { $gateway = 'paypalstandard'; } 
  661.  
  662. /** 
  663. * In 1.1.0 the underscore in payment gateway names was removed. 
  664. * To compensate for this we need to continue listen to these old 
  665. * gateway-names. 
  666. */ 
  667. switch ( $gateway ) { 
  668. case 'paypal_single': $gateway = 'paypalsingle'; break; 
  669. case 'paypal_standard': $gateway = 'paypalstandard'; break; 
  670.  
  671. do_action( 'lib2_debug_log', 'Incoming Payment Notification for "' . $gateway . '"' ); 
  672. do_action( 'lib2_debug_log', $_POST ); 
  673.  
  674. do_action( 
  675. 'ms_gateway_handle_payment_return_' . $gateway 
  676. ); 
  677.  
  678. /** 
  679. * Show gateway credit card information. 
  680. * 
  681. * If a card is used, show it in account's page. 
  682. * 
  683. * Related action hooks: 
  684. * - ms_view_shortcode_account_card_info 
  685. * 
  686. * @since 1.0.0 
  687. * 
  688. * @param mixed $data The data passed to hooked view. 
  689. */ 
  690. public function card_info( $data = null ) { 
  691. if ( ! empty( $data['gateway'] ) && is_array( $data['gateway'] ) ) { 
  692. $gateways = array(); 
  693.  
  694. foreach ( $data['gateway'] as $ms_relationship_id => $gateway ) { 
  695. // avoid duplicates 
  696. if ( ! in_array( $gateway->id, $gateways ) ) { 
  697. $gateways[] = $gateway->id; 
  698. } else { 
  699. continue; 
  700. $view = null; 
  701.  
  702. switch ( $gateway->id ) { 
  703. case MS_Gateway_Stripe::ID: 
  704. $member = MS_Model_Member::get_current_member(); 
  705. $data['stripe'] = $member->get_gateway_profile( 
  706. $gateway->id 
  707. ); 
  708.  
  709. if ( empty( $data['stripe']['card_exp'] ) ) { 
  710. continue 2; 
  711.  
  712. $view = MS_Factory::create( 'MS_Gateway_Stripe_View_Card' ); 
  713. $data['member'] = $member; 
  714. $data['publishable_key'] = $gateway->get_publishable_key(); 
  715. $data['ms_relationship_id'] = $ms_relationship_id; 
  716. $data['gateway'] = $gateway; 
  717. break; 
  718.  
  719. case MS_Gateway_Authorize::ID: 
  720. $member = MS_Model_Member::get_current_member(); 
  721. $data['authorize'] = $member->get_gateway_profile( 
  722. $gateway->id 
  723. ); 
  724.  
  725. if ( empty( $data['authorize']['card_exp'] ) ) { 
  726. continue 2; 
  727.  
  728. $view = MS_Factory::create( 'MS_Gateway_Authorize_View_Card' ); 
  729. $data['member'] = $member; 
  730. $data['ms_relationship_id'] = $ms_relationship_id; 
  731. $data['gateway'] = $gateway; 
  732. break; 
  733.  
  734. default: 
  735. break; 
  736.  
  737. if ( ! empty( $view ) ) { 
  738. $view = apply_filters( 
  739. 'ms_gateway_view_change_card',  
  740. $view,  
  741. $gateway->id 
  742. ); 
  743. $view->data = apply_filters( 
  744. 'ms_gateway_view_change_card_data',  
  745. $data,  
  746. $gateway->id 
  747. ); 
  748.  
  749. $html = $view->to_html(); 
  750. echo '' . $html; 
  751.  
  752. /** 
  753. * Handle update credit card information in gateway. 
  754. * 
  755. * Used to change credit card info in account's page. 
  756. * 
  757. * Related action hooks: 
  758. * - template_redirect 
  759. * 
  760. * @since 1.0.0 
  761. */ 
  762. public function update_card() { 
  763. if ( ! empty( $_POST['gateway'] ) ) { 
  764. $gateway = MS_Model_Gateway::factory( $_POST['gateway'] ); 
  765. $member = MS_Model_Member::get_current_member(); 
  766.  
  767. switch ( $gateway->id ) { 
  768. case MS_Gateway_Stripe::ID: 
  769. if ( ! empty( $_POST['stripeToken'] ) && $this->verify_nonce() ) { 
  770. lib2()->array->strip_slashes( $_POST, 'stripeToken' ); 
  771.  
  772. $gateway->add_card( $member, $_POST['stripeToken'] ); 
  773. if ( ! empty( $_POST['ms_relationship_id'] ) ) { 
  774. $ms_relationship = MS_Factory::load( 
  775. 'MS_Model_Relationship',  
  776. $_POST['ms_relationship_id'] 
  777. ); 
  778. MS_Model_Event::save_event( 
  779. MS_Model_Event::TYPE_UPDATED_INFO,  
  780. $ms_relationship 
  781. ); 
  782.  
  783. wp_safe_redirect( 
  784. esc_url_raw( add_query_arg( array( 'msg' => 1 ) ) ) 
  785. ); 
  786. exit; 
  787. break; 
  788.  
  789. case MS_Gateway_Authorize::ID: 
  790. if ( $this->verify_nonce() ) { 
  791. do_action( 
  792. 'ms_controller_frontend_signup_gateway_form',  
  793. $this 
  794. ); 
  795. } elseif ( ! empty( $_POST['ms_relationship_id'] ) 
  796. && $this->verify_nonce( $_POST['gateway'] .'_' . $_POST['ms_relationship_id'] ) 
  797. ) { 
  798. $gateway->update_cim_profile( $member ); 
  799. $gateway->save_card_info( $member ); 
  800. if ( ! empty( $_POST['ms_relationship_id'] ) ) { 
  801. $ms_relationship = MS_Factory::load( 
  802. 'MS_Model_Relationship',  
  803. $_POST['ms_relationship_id'] 
  804. ); 
  805. MS_Model_Event::save_event( 
  806. MS_Model_Event::TYPE_UPDATED_INFO,  
  807. $ms_relationship 
  808. ); 
  809.  
  810. wp_safe_redirect( 
  811. esc_url_raw( add_query_arg( array( 'msg' => 1 ) ) ) 
  812. ); 
  813. exit; 
  814. break; 
  815.  
  816. default: 
  817. break; 
  818.  
  819. do_action( 
  820. 'ms_controller_gateway_update_card',  
  821. $this 
  822. ); 
  823.  
  824. /** 
  825. * Adds CSS and javascript 
  826. * 
  827. * @since 1.0.0 
  828. */ 
  829. public function enqueue_scripts( $step = null ) { 
  830. if ( empty( $step ) && ! empty( $_POST['step'] ) ) { 
  831. $step = $_POST['step']; 
  832.  
  833. lib2()->array->equip_post( 'gateway' ); 
  834. $gateway_id = $_POST['gateway']; 
  835.  
  836. switch ( $step ) { 
  837. case MS_Controller_Frontend::STEP_GATEWAY_FORM: 
  838. if ( MS_Gateway_Authorize::ID == $gateway_id ) { 
  839. wp_enqueue_script( 'jquery-validate' ); 
  840.  
  841. $data = array( 
  842. 'ms_init' => array( 'gateway_authorize' ),  
  843. ); 
  844.  
  845. lib2()->ui->data( 'ms_data', $data ); 
  846. wp_enqueue_script( 'ms-public' ); 
  847. break; 
  848.  
.