/** * This will hide subscription levels on the registration form page * if their price is lower than the price of member's current * subscription level. */ function jp_hide_lower_cost_levels($levels) { if (!rcp_is_registration_page() || !is_user_logged_in()) { return $levels; } $existing_sub = rcp_get_subscription_id(wp_get_current_user()->ID); if (empty($existing_sub)) { return $levels; } foreach ($levels as $key => $level) { if (rcp_get_subscription_price($level->id) < rcp_get_subscription_price($existing_sub)) { unset($levels[$key]); } } return $levels; }
/** * Register a new user * * @access public * @since 1.0 */ function rcp_process_registration() { if ( isset( $_POST["rcp_register_nonce"] ) && wp_verify_nonce( $_POST['rcp_register_nonce'], 'rcp-register-nonce' ) ) { global $rcp_options, $user_ID; $subscription_id = isset( $_POST['rcp_level'] ) ? absint( $_POST['rcp_level'] ) : false; $discount = isset( $_POST['rcp_discount'] ) ? sanitize_text_field( $_POST['rcp_discount'] ) : ''; $discount_valid = false; $price = number_format( (float) rcp_get_subscription_price( $subscription_id ), 2 ); $price = str_replace( ',', '', $price ); $base_price = $price; // Used for discount calculations later $expiration = rcp_get_subscription_length( $subscription_id ); $subscription = rcp_get_subscription_details( $subscription_id ); // get the selected payment method/gateway if( ! isset( $_POST['rcp_gateway'] ) ) { $gateway = 'paypal'; } else { $gateway = sanitize_text_field( $_POST['rcp_gateway'] ); } /*********************** * validate the form ***********************/ do_action( 'rcp_before_form_errors', $_POST ); $is_ajax = isset( $_POST['rcp_ajax'] ); $user_data = rcp_validate_user_data(); if( ! $subscription_id ) { // no subscription level was chosen rcp_errors()->add( 'no_level', __( 'Please choose a subscription level', 'rcp' ), 'register' ); } if( $subscription_id ) { if( $price == 0 && $expiration->duration > 0 && rcp_has_used_trial( $user_data['id'] ) ) { // this ensures that users only sign up for a free trial once rcp_errors()->add( 'free_trial_used', __( 'You may only sign up for a free trial once', 'rcp' ), 'register' ); } } if( ! empty( $discount ) ) { if( rcp_validate_discount( $discount, $subscription_id ) ) { $discount_valid = true; } else { // the entered discount code is incorrect rcp_errors()->add( 'invalid_discount', __( 'The discount you entered is invalid', 'rcp' ), 'register' ); } if( $discount_valid && $price > 0 ) { if( ! $user_data['need_new'] && rcp_user_has_used_discount( $user_data['id'] , $discount ) && apply_filters( 'rcp_discounts_once_per_user', true ) ) { $discount_valid = false; rcp_errors()->add( 'discount_already_used', __( 'You can only use the discount code once', 'rcp' ), 'register' ); } if( $discount_valid ) { $discounts = new RCP_Discounts(); $discount_obj = $discounts->get_by( 'code', $discount ); if( is_object( $discount_obj ) ) { // calculate the after-discount price $price = $discounts->calc_discounted_price( $base_price, $discount_obj->amount, $discount_obj->unit ); } } } } if( $price == 0 && isset( $_POST['rcp_auto_renew'] ) ) { // since free subscriptions do not go through PayPal, they cannot be auto renewed rcp_errors()->add( 'invalid_auto_renew', __( 'Free subscriptions cannot be automatically renewed', 'rcp' ), 'register' ); } // Validate extra fields in gateways with the 2.1+ gateway API if( ! has_action( 'rcp_gateway_' . $gateway ) && $price > 0 ) { $gateways = new RCP_Payment_Gateways; $gateway_var = $gateways->get_gateway( $gateway ); $gateway_obj = new $gateway_var['class']; $gateway_obj->validate_fields(); } do_action( 'rcp_form_errors', $_POST ); // retrieve all error messages, if any $errors = rcp_errors()->get_error_messages(); if ( ! empty( $errors ) && $is_ajax ) { wp_send_json_error( array( 'success' => false, 'errors' => rcp_get_error_messages_html( 'register' ), 'nonce' => wp_create_nonce( 'rcp-register-nonce' ) ) ); } elseif( $is_ajax ) { wp_send_json_success( array( 'success' => true ) ); } // only create the user if there are no errors if( ! empty( $errors ) ) { return; } // deterime the expiration date of the user's subscription if( $expiration->duration > 0 ) { $member_expires = rcp_calc_member_expiration( $expiration ); } else { $member_expires = 'none'; } if( $user_data['need_new'] ) { $user_data['id'] = wp_insert_user( array( 'user_login' => $user_data['login'], 'user_pass' => $user_data['password'], 'user_email' => $user_data['email'], 'first_name' => $user_data['first_name'], 'last_name' => $user_data['last_name'], 'user_registered' => date( 'Y-m-d H:i:s' ) ) ); } if( $user_data['id'] ) { if( ! rcp_is_active( $user_data['id'] ) ) { rcp_set_status( $user_data['id'], 'pending' ); } // setup a unique key for this subscription $subscription_key = rcp_generate_subscription_key(); update_user_meta( $user_data['id'], 'rcp_subscription_key', $subscription_key ); update_user_meta( $user_data['id'], 'rcp_subscription_level', $subscription_id ); rcp_set_expiration_date( $user_data['id'], $member_expires ); // Set the user's role $role = ! empty( $subscription->role ) ? $subscription->role : 'subscriber'; $user = new WP_User( $user_data['id'] ); $user->add_role( apply_filters( 'rcp_default_user_level', $role, $subscription_id ) ); do_action( 'rcp_form_processing', $_POST, $user_data['id'], $price ); // process a paid subscription if( $price > '0' ) { if( ! empty( $discount ) ) { // record the usage of this discount code $discounts->add_to_user( $user_data['id'], $discount ); // incrase the usage count for the code $discounts->increase_uses( $discount_obj->id ); // if the discount is 100%, log the user in and redirect to success page if( $price == '0' ) { rcp_set_status( $user_data['id'], 'active' ); rcp_email_subscription_status( $user_data['id'], 'active' ); rcp_login_user_in( $user_data['id'], $user_data['login'] ); wp_redirect( rcp_get_return_url( $user_data['id'] ) ); exit; } } // Determine auto renew behavior if( '3' == rcp_get_auto_renew_behavior() && isset( $_POST['rcp_auto_renew'] ) ) { $auto_renew = true; } elseif( '1' == rcp_get_auto_renew_behavior() ) { $auto_renew = true; } else { $auto_renew = false; } // Remove trialing status, if it exists delete_user_meta( $user_data['id'], 'rcp_is_trialing' ); // log the new user in rcp_login_user_in( $user_data['id'], $user_data['login'] ); $redirect = rcp_get_return_url( $user_data['id'] ); $subscription_data = array( 'price' => $price, 'discount' => $base_price - $price, 'discount_code' => $discount, 'fee' => ! empty( $subscription->fee ) ? number_format( $subscription->fee, 2 ) : 0, 'length' => $expiration->duration, 'length_unit' => strtolower( $expiration->duration_unit ), 'subscription_id' => $subscription->id, 'subscription_name' => $subscription->name, 'key' => $subscription_key, 'user_id' => $user_data['id'], 'user_name' => $user_data['login'], 'user_email' => $user_data['email'], 'currency' => $rcp_options['currency'], 'auto_renew' => $auto_renew, 'return_url' => $redirect, 'new_user' => $user_data['need_new'], 'post_data' => $_POST ); // send all of the subscription data off for processing by the gateway rcp_send_to_gateway( $gateway, apply_filters( 'rcp_subscription_data', $subscription_data ) ); // process a free or trial subscription } else { // This is a free user registration or trial // if the subscription is a free trial, we need to record it in the user meta if( $member_expires != 'none' ) { // this is so that users can only sign up for one trial update_user_meta( $user_data['id'], 'rcp_has_trialed', 'yes' ); update_user_meta( $user_data['id'], 'rcp_is_trialing', 'yes' ); // activate the user's trial subscription rcp_set_status( $user_data['id'], 'active' ); rcp_email_subscription_status( $user_data['id'], 'trial' ); } else { // set the user's status to free rcp_set_status( $user_data['id'], 'free' ); rcp_email_subscription_status( $user_data['id'], 'free' ); } // date for trial / paid users, "none" for free users rcp_set_expiration_date( $user_data['id'], $member_expires ); if( $user_data['need_new'] ) { if( ! isset( $rcp_options['disable_new_user_notices'] ) ) { // send an email to the admin alerting them of the registration wp_new_user_notification( $user_data['id']) ; } // log the new user in rcp_login_user_in( $user_data['id'], $user_data['login'] ); } // send the newly created user to the redirect page after logging them in wp_redirect( rcp_get_return_url( $user_data['id'] ) ); exit; } // end price check } // end if new user id } // end nonce check }
/** * Determines if the member can access current content * * @access public * @since 2.1 */ public function can_access($post_id = 0) { $subscription_levels = rcp_get_content_subscription_levels($post_id); $access_level = get_post_meta($post_id, 'rcp_access_level', true); $sub_id = $this->get_subscription_id(); // Assume the user can until proven false $ret = true; if (rcp_is_paid_content($post_id) && $this->is_expired()) { $ret = false; } if (!empty($subscription_levels)) { if (is_string($subscription_levels)) { switch ($subscription_levels) { case 'any': $ret = !empty($sub_id) && !$this->is_expired(); break; case 'any-paid': $ret = $this->is_active(); break; } } else { if (in_array($sub_id, $subscription_levels)) { $needs_paid = false; foreach ($subscription_levels as $level) { $price = rcp_get_subscription_price($level); if (!empty($price) && $price > 0) { $needs_paid = true; } } if ($needs_paid) { $ret = $this->is_active(); } else { $ret = true; } } else { $ret = false; } } } if (!rcp_user_has_access($this->ID, $access_level) && $access_level > 0) { $ret = false; } if (user_can($this->ID, 'manage_options')) { $ret = true; } return apply_filters('rcp_member_can_access', $ret, $this->ID, $post_id, $this); }
/** * Get the registration recurring total * * @param bool $discounts | Include discounts? * @param bool $fees | Include fees? * * @since 2.5 * @return mixed|void */ public function get_recurring_total($discounts = true, $fees = true) { $total = rcp_get_subscription_price($this->subscription); if ($discounts) { $total -= $this->get_total_discounts($total, true); } if ($fees) { $total += $this->get_total_fees($total, true); } if (0 > $total) { $total = 0; } return apply_filters('rcp_registration_get_recurring_total', floatval($total), $this); }
/** * Process PayPal IPN * * @since 2.1 */ public function process_webhooks() { if (!isset($_GET['listener']) || strtoupper($_GET['listener']) != 'IPN') { return; } global $rcp_options; nocache_headers(); if (!class_exists('IpnListener')) { // instantiate the IpnListener class include RCP_PLUGIN_DIR . 'includes/gateways/paypal/paypal-ipnlistener.php'; } $listener = new IpnListener(); $verified = false; if ($this->test_mode) { $listener->use_sandbox = true; } /* if( isset( $rcp_options['ssl'] ) ) { $listener->use_ssl = true; } else { $listener->use_ssl = false; } */ //To post using the fsockopen() function rather than cURL, use: if (isset($rcp_options['disable_curl'])) { $listener->use_curl = false; } try { $listener->requirePostMethod(); $verified = $listener->processIpn(); } catch (Exception $e) { status_header(402); //die( 'IPN exception: ' . $e->getMessage() ); } /* The processIpn() method returned true if the IPN was "VERIFIED" and false if it was "INVALID". */ if ($verified || isset($_POST['verification_override']) || ($this->test_mode || isset($rcp_options['disable_ipn_verify']))) { status_header(200); $user_id = 0; $posted = apply_filters('rcp_ipn_post', $_POST); // allow $_POST to be modified if (!empty($posted['custom']) && is_numeric($posted['custom'])) { $user_id = absint($posted['custom']); } else { if (!empty($posted['subscr_id'])) { $user_id = rcp_get_member_id_from_profile_id($posted['subscr_id']); } else { if (!empty($posted['payer_email'])) { $user = get_user_by('email', $posted['payer_email']); $user_id = $user ? $user->ID : false; } } } $member = new RCP_Member($user_id); if (!$member || !$member->get_subscription_id()) { die('no member found'); } if (!rcp_get_subscription_details($member->get_subscription_id())) { die('no subscription level found'); } $subscription_name = $posted['item_name']; $subscription_key = $posted['item_number']; $amount = number_format((double) $posted['mc_gross'], 2); $amount2 = number_format((double) $posted['mc_amount3'], 2); $payment_status = $posted['payment_status']; $currency_code = $posted['mc_currency']; $subscription_price = number_format((double) rcp_get_subscription_price($member->get_subscription_id()), 2); // setup the payment info in an array for storage $payment_data = array('date' => date('Y-m-d g:i:s', strtotime($posted['payment_date'], current_time('timestamp'))), 'subscription' => $posted['item_name'], 'payment_type' => $posted['txn_type'], 'subscription_key' => $subscription_key, 'amount' => $amount, 'user_id' => $user_id, 'transaction_id' => $posted['txn_id']); do_action('rcp_valid_ipn', $payment_data, $user_id, $posted); if ($posted['txn_type'] == 'web_accept' || $posted['txn_type'] == 'subscr_payment') { // only check for an existing payment if this is a payment IPD request if (rcp_check_for_existing_payment($posted['txn_type'], $posted['payment_date'], $subscription_key)) { $log_data = array('post_title' => __('Duplicate Payment', 'rcp'), 'post_content' => __('A duplicate payment was detected. The new payment was still recorded, so you may want to check into both payments.', 'rcp'), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); die('duplicate IPN detected'); } if (strtolower($currency_code) != strtolower($rcp_options['currency'])) { // the currency code is invalid $log_data = array('post_title' => __('Invalid Currency Code', 'rcp'), 'post_content' => sprintf(__('The currency code in an IPN request did not match the site currency code. Payment data: %s', 'rcp'), json_encode($payment_data)), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); die('invalid currency code'); } } if (isset($rcp_options['email_ipn_reports'])) { wp_mail(get_bloginfo('admin_email'), __('IPN report', 'rcp'), $listener->getTextReport()); } /* now process the kind of subscription/payment */ $rcp_payments = new RCP_Payments(); // Subscriptions switch ($posted['txn_type']) { case "subscr_signup": // when a new user signs up // store the recurring payment ID update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); $member->set_payment_profile_id($posted['subscr_id']); do_action('rcp_ipn_subscr_signup', $user_id); die('successful subscr_signup'); break; case "subscr_payment": // when a user makes a recurring payment update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); $member->set_payment_profile_id($posted['subscr_id']); $member->renew(true); // record this payment in the database $rcp_payments->insert($payment_data); do_action('rcp_ipn_subscr_payment', $user_id); die('successful subscr_payment'); break; case "subscr_cancel": // user is marked as cancelled but retains access until end of term $member->set_status('cancelled'); // set the use to no longer be recurring delete_user_meta($user_id, 'rcp_paypal_subscriber'); do_action('rcp_ipn_subscr_cancel', $user_id); die('successful subscr_cancel'); break; case "subscr_failed": do_action('rcp_ipn_subscr_failed'); die('successful subscr_failed'); break; case "subscr_eot": // user's subscription has reached the end of its term if ('cancelled' !== $member->get_status($user_id)) { $member->set_status('expired'); } do_action('rcp_ipn_subscr_eot', $user_id); die('successful subscr_eot'); break; case "web_accept": switch (strtolower($payment_status)) { case 'completed': // set this user to active $member->renew(); $rcp_payments->insert($payment_data); break; case 'denied': case 'expired': case 'failed': case 'voided': $member->set_status('cancelled'); break; } die('successful web_accept'); break; case "cart": case "express_checkout": default: break; } } else { if (isset($rcp_options['email_ipn_reports'])) { // an invalid IPN attempt was made. Send an email to the admin account to investigate wp_mail(get_bloginfo('admin_email'), __('Invalid IPN', 'rcp'), $listener->getTextReport()); } status_header(400); die('invalid IPN'); } }
function rcp_show_subscription_level($level_id = 0, $user_id = 0) { if (empty($user_id)) { $user_id = get_current_user_id(); } $ret = true; $user_level = rcp_get_subscription_id($user_id); $sub_length = rcp_get_subscription_length($level_id); $sub_price = rcp_get_subscription_price($level_id); // Don't show free trial if user has already used it. Don't show if sub is free and user is already free if (is_user_logged_in() && $sub_price == '0' && $sub_length->duration > 0 && rcp_has_used_trial($user_id) || is_user_logged_in() && $sub_price == '0' && $user_level == $level_id) { $ret = false; } return apply_filters('rcp_show_subscription_level', $ret, $level_id, $user_id); }
function rcp_member_levels_page() { global $rcp_options, $rcp_db_name, $wpdb; $page = admin_url('/admin.php?page=rcp-member-levels'); ?> <div class="wrap"> <?php if (isset($_GET['edit_subscription'])) { include 'edit-subscription.php'; } else { ?> <h2><?php _e('Subscription Levels', 'rcp'); ?> </h2> <table class="wp-list-table widefat fixed posts rcp-subscriptions"> <thead> <tr> <th scope="col" class="rcp-sub-name-col column-primary"><?php _e('Name', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-desc-col"><?php _e('Description', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-level-col"><?php _e('Access Level', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-duration-col"><?php _e('Duration', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-price-col"><?php _e('Price', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-subs-col"><?php _e('Subscribers', 'rcp'); ?> </th> <?php do_action('rcp_levels_page_table_header'); ?> <th scope="col" class="rcp-sub-order-col"><?php _e('Order', 'rcp'); ?> </th> </tr> </thead> <tbody id="the-list"> <?php $levels = rcp_get_subscription_levels('all'); ?> <?php if ($levels) { $i = 1; foreach ($levels as $key => $level) { ?> <tr id="recordsArray_<?php echo $level->id; ?> " class="rcp-subscription rcp_row <?php if (rcp_is_odd($i)) { echo 'alternate'; } ?> "> <td class="rcp-sub-name-col column-primary has-row-actions" data-colname="<?php _e('Name', 'rcp'); ?> "> <strong><a href="<?php echo esc_url(add_query_arg('edit_subscription', $level->id, $page)); ?> "><?php echo stripslashes($level->name); ?> </a></strong> <?php if (current_user_can('rcp_manage_levels')) { ?> <div class="row-actions"> <span class="rcp-sub-id-col" data-colname="<?php _e('ID:', 'rcp'); ?> "> <?php echo __('ID:', 'rcp') . ' ' . $level->id; ?> | </span> <a href="<?php echo esc_url(add_query_arg('edit_subscription', $level->id, $page)); ?> "><?php _e('Edit', 'rcp'); ?> </a> | <?php if ($level->status != 'inactive') { ?> <a href="<?php echo esc_url(add_query_arg('deactivate_subscription', $level->id, $page)); ?> "><?php _e('Deactivate', 'rcp'); ?> </a> | <?php } else { ?> <a href="<?php echo esc_url(add_query_arg('activate_subscription', $level->id, $page)); ?> "><?php _e('Activate', 'rcp'); ?> </a> | <?php } ?> <a href="<?php echo esc_url(add_query_arg('delete_subscription', $level->id, $page)); ?> " class="rcp_delete_subscription"><?php _e('Delete', 'rcp'); ?> </a> </div> <?php } ?> <button type="button" class="toggle-row"><span class="screen-reader-text"><?php _e('Show more details', 'rcp'); ?> </span></button> </td> <td class="rcp-sub-desc-col" data-colname="<?php _e('Description', 'rcp'); ?> "><?php echo stripslashes($level->description); ?> </td> <td class="rcp-sub-level-col" data-colname="<?php _e('Access Level', 'rcp'); ?> "><?php echo $level->level != '' ? $level->level : __('none', 'rcp'); ?> </td> <td class="rcp-sub-duration-col" data-colname="<?php _e('Duration', 'rcp'); ?> "> <?php if ($level->duration > 0) { echo $level->duration . ' ' . rcp_filter_duration_unit($level->duration_unit, $level->duration); } else { echo __('unlimited', 'rcp'); } ?> </td> <td class="rcp-sub-price-col" data-colname="<?php _e('Price', 'rcp'); ?> "> <?php $price = rcp_get_subscription_price($level->id); if (!$price) { echo __('Free', 'rcp'); } else { echo rcp_currency_filter($price); } ?> </td> <td class="rcp-sub-subs-col" data-colname="<?php _e('Subscribers', 'rcp'); ?> "> <?php if ($price || $level->duration > 0) { echo rcp_get_subscription_member_count($level->id, 'active'); } else { echo rcp_get_subscription_member_count($level->id, 'free'); } ?> </td> <?php do_action('rcp_levels_page_table_column', $level->id); ?> <td class="rcp-sub-order-col"><a href="#" class="dragHandle"></a></td> </tr> <?php $i++; } } else { ?> <tr><td colspan="9"><?php _e('No subscription levels added yet.', 'rcp'); ?> </td></tr> <?php } ?> </tbody> <tfoot> <tr> <th scope="col" class="rcp-sub-name-col column-primary"><?php _e('Name', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-desc-col"><?php _e('Description', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-level-col"><?php _e('Access Level', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-duration-col"><?php _e('Duration', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-price-col"><?php _e('Price', 'rcp'); ?> </th> <th scope="col" class="rcp-sub-subs-col"><?php _e('Subscribers', 'rcp'); ?> </th> <?php do_action('rcp_levels_page_table_footer'); ?> <th scope="col" class="rcp-sub-order-col"><?php _e('Order', 'rcp'); ?> </th> </tr> </tfoot> </table> <?php do_action('rcp_levels_below_table'); ?> <?php if (current_user_can('rcp_manage_levels')) { ?> <h3><?php _e('Add New Level', 'rcp'); ?> </h3> <form id="rcp-member-levels" action="" method="post"> <table class="form-table"> <tbody> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-name"><?php _e('Name', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-name" name="name" value="" style="width: 300px;"/> <p class="description"><?php _e('The name of the membership level.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-description"><?php _e('Description', 'rcp'); ?> </label> </th> <td> <textarea id="rcp-description" name="description" style="width: 300px;"></textarea> <p class="description"><?php _e('Membership level description. This is shown on the registration form.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-level"><?php _e('Access Level', 'rcp'); ?> </label> </th> <td> <select id="rcp-level" name="level"> <?php $access_levels = rcp_get_access_levels(); foreach ($access_levels as $access) { echo '<option value="' . $access . '">' . $access . '</option>'; } ?> </select> <p class="description"> <?php _e('Level of access this subscription gives. Leave None for default or you are unsure what this is.', 'rcp'); ?> <span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e('<strong>Access Level</strong>: refers to a tiered system where a member\'s ability to view content is determined by the access level assigned to their account. A member with an access level of 5 can view content assigned to access levels of 5 and lower, whereas a member with an access level of 4 can only view content assigned to levels of 4 and lower.', 'rcp'); ?> "></span> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-duration"><?php _e('Duration', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-duration" style="width: 40px;" name="duration" value="0"/> <select name="duration_unit" id="rcp-duration-unit"> <option value="day"><?php _e('Day(s)', 'rcp'); ?> </option> <option value="month"><?php _e('Month(s)', 'rcp'); ?> </option> <option value="year"><?php _e('Year(s)', 'rcp'); ?> </option> </select> <p class="description"> <?php _e('Length of time for this membership level. Enter 0 for unlimited.', 'rcp'); ?> <span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e('<strong>Example</strong>: setting this to 1 month would make memberships last 1 month, after which they will renew automatically or be marked as expired.', 'rcp'); ?> "></span> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-price"><?php _e('Price', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-price" name="price" value="0" pattern="^(\d+\.\d{2})|(\d+)$" style="width: 40px;"/> <select name="rcp-price-select" id="rcp-price-select"> <option value="normal"><?php echo rcp_get_currency(); ?> </option> <option value="free"><?php _e('Free', 'rcp'); ?> </option> </select> <p class="description"> <?php _e('The price of this membership level. Enter 0 for free.', 'rcp'); ?> <span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e('This price refers to the amount paid per duration period. For example, if duration period is set to 1 month, this would be the amount charged each month.', 'rcp'); ?> "></span> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-fee"><?php _e('Signup Fee', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-fee" name="fee" value="0" style="width: 40px;"/> <p class="description"><?php _e('Optional signup fee to charge subscribers for the first billing cycle. Enter a negative number to give a discount on the first payment.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-status"><?php _e('Status', 'rcp'); ?> </label> </th> <td> <select name="status" id="rcp-status"> <option value="active"><?php _e('Active', 'rcp'); ?> </option> <option value="inactive"><?php _e('Inactive', 'rcp'); ?> </option> </select> <p class="description"><?php _e('Members may only sign up for active subscription levels.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-role"><?php _e('User Role', 'rcp'); ?> </label> </th> <td> <select name="role" id="rcp-role"> <?php wp_dropdown_roles('subscriber'); ?> </select> <p class="description"><?php _e('The user role given to the member after signing up.', 'rcp'); ?> </p> </td> </tr> <?php do_action('rcp_add_subscription_form'); ?> </tbody> </table> <p class="submit"> <input type="hidden" name="rcp-action" value="add-level"/> <input type="submit" value="<?php _e('Add Membership Level', 'rcp'); ?> " class="button-primary"/> </p> <?php wp_nonce_field('rcp_add_level_nonce', 'rcp_add_level_nonce'); ?> </form> <?php } ?> <?php } ?> </div><!--end wrap--> <?php }
function rcp_member_levels_page() { global $rcp_options, $rcp_db_name, $wpdb; $page = admin_url('/admin.php?page=rcp-member-levels'); ?> <div class="wrap"> <?php if (isset($_GET['edit_subscription'])) { include 'edit-subscription.php'; } else { ?> <h2><?php _e('Subscription Levels', 'rcp'); ?> </h2> <table class="wp-list-table widefat fixed posts rcp-subscriptions"> <thead> <tr> <th class="rcp-sub-order-col"><?php _e('Order', 'rcp'); ?> </th> <th class="rcp-sub-id-col"><?php _e('ID', 'rcp'); ?> </th> <th class="rcp-sub-name-col"><?php _e('Name', 'rcp'); ?> </th> <th class="rcp-sub-desc-col"><?php _e('Description', 'rcp'); ?> </th> <th class="rcp-sub-level-col"><?php _e('Access Level', 'rcp'); ?> </th> <th class="rcp-sub-duration-col"><?php _e('Duration', 'rcp'); ?> </th> <th class="rcp-sub-price-col"><?php _e('Price', 'rcp'); ?> </th> <th class="rcp-sub-subs-col"><?php _e('Subscribers', 'rcp'); ?> </th> <?php do_action('rcp_levels_page_table_header'); ?> <?php if (current_user_can('rcp_manage_levels')) { ?> <th class="rcp-sub-actions-col"><?php _e('Actions', 'rcp'); ?> </th> <?php } ?> </tr> </thead> <tfoot> <tr> <th class="rcp-sub-order-col"><?php _e('Order', 'rcp'); ?> </th> <th class="rcp-sub-id-col"><?php _e('ID', 'rcp'); ?> </th> <th class="rcp-sub-name-col"><?php _e('Name', 'rcp'); ?> </th> <th class="rcp-sub-desc-col" style="width: 300px;"><?php _e('Description', 'rcp'); ?> </th> <th class="rcp-sub-level-col"><?php _e('Access Level', 'rcp'); ?> </th> <th class="rcp-sub-duration-col"><?php _e('Duration', 'rcp'); ?> </th> <th class="rcp-sub-price-col"><?php _e('Price', 'rcp'); ?> </th> <th class="rcp-sub-subs-col"><?php _e('Subscribers', 'rcp'); ?> </th> <?php do_action('rcp_levels_page_table_footer'); ?> <?php if (current_user_can('rcp_manage_levels')) { ?> <th class="rcp-sub-actions-col"><?php _e('Actions', 'rcp'); ?> </th> <?php } ?> </tr> </tfoot> <tbody> <?php $levels = rcp_get_subscription_levels('all'); ?> <?php if ($levels) { $i = 1; foreach ($levels as $key => $level) { ?> <tr id="recordsArray_<?php echo $level->id; ?> " class="rcp-subscription rcp_row <?php if (rcp_is_odd($i)) { echo 'alternate'; } ?> "> <td class="rcp-sub-order-col"><a href="#" class="dragHandle"></a></td> <td class="rcp-sub-id-col"><?php echo $level->id; ?> </td> <td class="rcp-sub-name-col"><?php echo stripslashes($level->name); ?> </td> <td class="rcp-sub-desc-col"><?php echo stripslashes($level->description); ?> </td> <td class="rcp-sub-level-col"><?php echo $level->level != '' ? $level->level : __('none', 'rcp'); ?> </td> <td class="rcp-sub-duration-col"> <?php if ($level->duration > 0) { echo $level->duration . ' ' . rcp_filter_duration_unit($level->duration_unit, $level->duration); } else { echo __('unlimited', 'rcp'); } ?> </td> <td class="rcp-sub-price-col"> <?php $price = rcp_get_subscription_price($level->id); if (!$price) { echo __('Free', 'rcp'); } else { echo rcp_currency_filter($price); } ?> </td> <td class="rcp-sub-subs-col"> <?php if ($price || $level->duration > 0) { echo rcp_count_members($level->id, 'active'); } else { echo rcp_count_members($level->id, 'free'); } ?> </td> <?php do_action('rcp_levels_page_table_column', $level->id); ?> <?php if (current_user_can('rcp_manage_levels')) { ?> <td class="rcp-sub-actions-col"> <a href="<?php echo esc_url(add_query_arg('edit_subscription', $level->id, $page)); ?> "><?php _e('Edit', 'rcp'); ?> </a> | <?php if ($level->status != 'inactive') { ?> <a href="<?php echo esc_url(add_query_arg('deactivate_subscription', $level->id, $page)); ?> "><?php _e('Deactivate', 'rcp'); ?> </a> | <?php } else { ?> <a href="<?php echo esc_url(add_query_arg('activate_subscription', $level->id, $page)); ?> "><?php _e('Activate', 'rcp'); ?> </a> | <?php } ?> <a href="<?php echo esc_url(add_query_arg('delete_subscription', $level->id, $page)); ?> " class="rcp_delete_subscription"><?php _e('Delete', 'rcp'); ?> </a> </td> <?php } ?> </tr> <?php $i++; } } else { ?> <tr><td colspan="9"><?php _e('No subscription levels added yet.', 'rcp'); ?> </td> <?php } ?> </table> <?php do_action('rcp_levels_below_table'); ?> <?php if (current_user_can('rcp_manage_levels')) { ?> <h3><?php _e('Add New Level', 'rcp'); ?> </h3> <form id="rcp-member-levels" action="" method="post"> <table class="form-table"> <tbody> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-name"><?php _e('Name', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-name" name="name" value="" style="width: 300px;"/> <p class="description"><?php _e('The name of the membership level.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-description"><?php _e('Description', 'rcp'); ?> </label> </th> <td> <textarea id="rcp-description" name="description" style="width: 300px;"></textarea> <p class="description"><?php _e('Membership level description. This is shown on the registration form.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-level"><?php _e('Access Level', 'rcp'); ?> </label> </th> <td> <select id="rcp-level" name="level"> <?php $access_levels = rcp_get_access_levels(); foreach ($access_levels as $access) { echo '<option value="' . $access . '">' . $access . '</option>'; } ?> </select> <p class="description"><?php _e('Level of access this subscription gives. Leave None for default or you are unsure what this is.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-duration"><?php _e('Duration', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-duration" style="width: 40px;" name="duration" value=""/> <select name="duration_unit" id="rcp-duration-unit"> <option value="day"><?php _e('Day(s)', 'rcp'); ?> </option> <option value="month"><?php _e('Month(s)', 'rcp'); ?> </option> <option value="year"><?php _e('Year(s)', 'rcp'); ?> </option> </select> <p class="description"><?php _e('Length of time for this membership level. Enter 0 for unlimited.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-price"><?php _e('Price', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-price" name="price" value="" style="width: 40px;"/> <select name="rcp-price-select" id="rcp-price-select"> <option value="normal"><?php echo isset($rcp_options['currency']) ? $rcp_options['currency'] : 'USD'; ?> </option> <option value="free"><?php _e('Free', 'rcp'); ?> </option> </select> <p class="description"><?php _e('The price of this membership level. Enter 0 for free.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-fee"><?php _e('Signup Fee', 'rcp'); ?> </label> </th> <td> <input type="text" id="rcp-fee" name="fee" value="" style="width: 40px;"/> <p class="description"><?php _e('Optional signup fee to charge subscribers for the first billing cycle. Enter a negative number to give a discount on the first payment. This only applies to recurring subscriptions.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-status"><?php _e('Status', 'rcp'); ?> </label> </th> <td> <select name="status" id="rcp-status"> <option value="active"><?php _e('Active', 'rcp'); ?> </option> <option value="inactive"><?php _e('Inactive', 'rcp'); ?> </option> </select> <p class="description"><?php _e('Members may only sign up for active subscription levels.', 'rcp'); ?> </p> </td> </tr> <tr class="form-field"> <th scope="row" valign="top"> <label for="rcp-role"><?php _e('User Role', 'rcp'); ?> </label> </th> <td> <select name="role" id="rcp-role"> <?php wp_dropdown_roles('subscriber'); ?> </select> <p class="description"><?php _e('The user role given to the member after signing up.', 'rcp'); ?> </p> </td> </tr> <?php do_action('rcp_add_subscription_form'); ?> </tbody> </table> <p class="submit"> <input type="hidden" name="rcp-action" value="add-level"/> <input type="submit" value="<?php _e('Add Membership Level', 'rcp'); ?> " class="button-primary"/> </p> </form> <?php } ?> <?php } ?> </div><!--end wrap--> <?php }
function rcp_save_meta_data($post_id) { // verify nonce if (!isset($_POST['rcp_meta_box']) || !wp_verify_nonce($_POST['rcp_meta_box'], basename(__FILE__))) { return; } // check autosave if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // check permissions if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) { return; } } elseif (!current_user_can('edit_post', $post_id)) { return; } $is_paid = false; $restrict_by = sanitize_text_field($_POST['rcp_restrict_by']); switch ($restrict_by) { case 'unrestricted': delete_post_meta($post_id, 'rcp_access_level'); delete_post_meta($post_id, 'rcp_subscription_level'); delete_post_meta($post_id, 'rcp_user_level'); break; case 'subscription-level': $level_set = sanitize_text_field($_POST['rcp_subscription_level_any_set']); switch ($level_set) { case 'any': update_post_meta($post_id, 'rcp_subscription_level', 'any'); break; case 'any-paid': $is_paid = true; update_post_meta($post_id, 'rcp_subscription_level', 'any-paid'); break; case 'specific': $levels = array_map('absint', $_POST['rcp_subscription_level']); foreach ($levels as $level) { $price = rcp_get_subscription_price($level); if (!empty($price)) { $is_paid = true; break; } } update_post_meta($post_id, 'rcp_subscription_level', $levels); break; } // Remove unneeded fields delete_post_meta($post_id, 'rcp_access_level'); break; case 'access-level': update_post_meta($post_id, 'rcp_access_level', absint($_POST['rcp_access_level'])); $levels = rcp_get_subscription_levels(); foreach ($levels as $level) { if (!empty($level->price)) { $is_paid = true; break; } } // Remove unneeded fields delete_post_meta($post_id, 'rcp_subscription_level'); break; case 'registered-users': // Remove unneeded fields delete_post_meta($post_id, 'rcp_access_level'); // Remove unneeded fields delete_post_meta($post_id, 'rcp_subscription_level'); $levels = rcp_get_subscription_levels(); foreach ($levels as $level) { if (!empty($level->price)) { $is_paid = true; break; } } break; } $show_excerpt = isset($_POST['rcp_show_excerpt']); $hide_in_feed = isset($_POST['rcp_hide_from_feed']); $user_role = sanitize_text_field($_POST['rcp_user_level']); update_post_meta($post_id, 'rcp_show_excerpt', $show_excerpt); update_post_meta($post_id, 'rcp_hide_from_feed', $hide_in_feed); if ('unrestricted' !== $_POST['rcp_restrict_by']) { update_post_meta($post_id, 'rcp_user_level', $user_role); } update_post_meta($post_id, '_is_paid', $is_paid); }
function rcp_check_ipn() { global $rcp_options; if (!class_exists('IpnListener')) { // instantiate the IpnListener class include RCP_PLUGIN_DIR . 'includes/gateways/paypal/ipnlistener.php'; } $listener = new IpnListener(); if (isset($rcp_options['sandbox'])) { $listener->use_sandbox = true; } if (isset($rcp_options['ssl'])) { $listener->use_ssl = true; } else { $listener->use_ssl = false; } //To post using the fsockopen() function rather than cURL, use: if (isset($rcp_options['disable_curl'])) { $listener->use_curl = false; } try { $listener->requirePostMethod(); $verified = $listener->processIpn(); } catch (Exception $e) { //exit(0); } /* The processIpn() method returned true if the IPN was "VERIFIED" and false if it was "INVALID". */ if ($verified || isset($_POST['verification_override']) || (isset($rcp_options['sandbox']) || isset($rcp_options['disable_ipn_verify']))) { $posted = apply_filters('rcp_ipn_post', $_POST); // allow $_POST to be modified $user_id = $posted['custom']; $subscription_name = $posted['item_name']; $subscription_key = $posted['item_number']; $amount = number_format((double) $posted['mc_gross'], 2); $amount2 = number_format((double) $posted['mc_amount3'], 2); $payment_status = $posted['payment_status']; $currency_code = $posted['mc_currency']; $subscription_id = rcp_get_subscription_id($user_id); $subscription_price = number_format((double) rcp_get_subscription_price(rcp_get_subscription_id($user_id)), 2); $user_data = get_userdata($user_id); if (!$user_data || !$subscription_id) { return; } if (!rcp_get_subscription_details($subscription_id)) { return; } // setup the payment info in an array for storage $payment_data = array('date' => date('Y-m-d g:i:s', strtotime($posted['payment_date'])), 'subscription' => $posted['item_name'], 'payment_type' => $posted['txn_type'], 'subscription_key' => $subscription_key, 'amount' => $amount, 'user_id' => $user_id, 'transaction_id' => $posted['txn_id']); do_action('rcp_valid_ipn', $payment_data, $user_id, $posted); if ($posted['txn_type'] == 'web_accept' || $posted['txn_type'] == 'subscr_payment') { // only check for an existing payment if this is a payment IPD request if (rcp_check_for_existing_payment($posted['txn_type'], $posted['payment_date'], $subscription_key)) { $log_data = array('post_title' => __('Duplicate Payment', 'rcp'), 'post_content' => __('A duplicate payment was detected. The new payment was still recorded, so you may want to check into both payments.', 'rcp'), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); return; // this IPN request has already been processed } /* do some quick checks to make sure all necessary data validates */ if ($amount < $subscription_price && $amount2 < $subscription_price) { /* // the subscription price doesn't match, so lets check to see if it matches with a discount code if( ! rcp_check_paypal_return_price_after_discount( $subscription_price, $amount, $amount2, $user_id ) ) { $log_data = array( 'post_title' => __( 'Price Mismatch', 'rcp' ), 'post_content' => sprintf( __( 'The price in an IPN request did not match the subscription price. Payment data: %s', 'rcp' ), json_encode( $payment_data ) ), 'post_parent' => 0, 'log_type' => 'gateway_error' ); $log_meta = array( 'user_subscription' => $posted['item_name'], 'user_id' => $user_id ); $log_entry = WP_Logging::insert_log( $log_data, $log_meta ); //return; } */ } if (strtolower($currency_code) != strtolower($rcp_options['currency'])) { // the currency code is invalid $log_data = array('post_title' => __('Invalid Currency Code', 'rcp'), 'post_content' => sprintf(__('The currency code in an IPN request did not match the site currency code. Payment data: %s', 'rcp'), json_encode($payment_data)), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); return; } } if (isset($rcp_options['email_ipn_reports'])) { wp_mail(get_bloginfo('admin_email'), __('IPN report', 'rcp'), $listener->getTextReport()); } if (rcp_get_subscription_key($user_id) != $subscription_key) { // the subscription key is invalid $log_data = array('post_title' => __('Subscription Key Mismatch', 'rcp'), 'post_content' => sprintf(__('The subscription key in an IPN request did not match the subscription key recorded for the user. Payment data: %s', 'rcp'), json_encode($payment_data)), 'post_parent' => 0, 'log_type' => 'gateway_error'); $log_meta = array('user_subscription' => $posted['item_name'], 'user_id' => $user_id); $log_entry = WP_Logging::insert_log($log_data, $log_meta); return; } /* now process the kind of subscription/payment */ $rcp_payments = new RCP_Payments(); // Subscriptions switch ($posted['txn_type']) { case "subscr_signup": // when a new user signs up // store the recurring payment ID update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); // set the user's status to active rcp_set_status($user_id, 'active'); if (!isset($rcp_options['disable_new_user_notices'])) { wp_new_user_notification($user_id); } // send welcome email rcp_email_subscription_status($user_id, 'active'); update_user_meta($user_id, 'rcp_recurring', 'yes'); do_action('rcp_ipn_subscr_signup', $user_id); break; case "subscr_payment": // when a user makes a recurring payment // record this payment in the database $rcp_payments->insert($payment_data); $subscription = rcp_get_subscription_details(rcp_get_subscription_id($user_id)); // update the user's expiration to correspond with the new payment $member_new_expiration = date('Y-m-d H:i:s', strtotime('+' . $subscription->duration . ' ' . $subscription->duration_unit . ' 23:59:59')); rcp_set_expiration_date($user_id, $member_new_expiration); update_user_meta($user_id, 'rcp_paypal_subscriber', $posted['payer_id']); // make sure the user's status is active rcp_set_status($user_id, 'active'); update_user_meta($user_id, 'rcp_recurring', 'yes'); delete_user_meta($user_id, '_rcp_expired_email_sent'); do_action('rcp_ipn_subscr_payment', $user_id); break; case "subscr_cancel": // user is marked as cancelled but retains access until end of term rcp_set_status($user_id, 'cancelled'); // set the use to no longer be recurring delete_user_meta($user_id, 'rcp_recurring'); delete_user_meta($user_id, 'rcp_paypal_subscriber'); // send sub cancelled email rcp_email_subscription_status($user_id, 'cancelled'); do_action('rcp_ipn_subscr_cancel', $user_id); break; case "subscr_failed": do_action('rcp_ipn_subscr_failed'); break; case "subscr_eot": // user's subscription has reach the end of its term // set the use to no longer be recurring delete_user_meta($user_id, 'rcp_recurring'); if ('cancelled' !== rcp_get_status($user_id)) { rcp_set_status($user_id, 'expired'); // send expired email rcp_email_subscription_status($user_id, 'expired'); } do_action('rcp_ipn_subscr_eot', $user_id); break; case "cart": return; // get out of here // get out of here case "express_checkout": return; // get out of here // get out of here case "web_accept": switch (strtolower($payment_status)) { case 'completed': if (isset($_POST['verification_override'])) { // this is a method for providing a new expiration if it doesn't exist $subscription = rcp_get_subscription_details_by_name($payment_data['subscription']); // update the user's expiration to correspond with the new payment $member_new_expiration = date('Y-m-d H:i:s', strtotime('+' . $subscription->duration . ' ' . $subscription->duration_unit . ' 23:59:59')); rcp_set_expiration_date($user_id, $member_new_expiration); } // set this user to active rcp_set_status($user_id, 'active'); $rcp_payments->insert($payment_data); rcp_email_subscription_status($user_id, 'active'); if (!isset($rcp_options['disable_new_user_notices'])) { // send welcome email here wp_new_user_notification($user_id); } delete_user_meta($user_id, '_rcp_expired_email_sent'); break; case 'denied': case 'expired': case 'failed': case 'voided': rcp_set_status($user_id, 'cancelled'); // send cancelled email here break; } break; default: break; } } else { if (isset($rcp_options['email_ipn_reports'])) { // an invalid IPN attempt was made. Send an email to the admin account to investigate wp_mail(get_bloginfo('admin_email'), __('Invalid IPN', 'rcp'), $listener->getTextReport()); } } }
</th> </tr> <tr> <td><?php echo rcp_get_subscription_name(rcp_get_registration()->get_subscription()); ?> </td> <td><?php echo rcp_get_subscription_price(rcp_get_registration()->get_subscription()) > 0 ? rcp_currency_filter(number_format(rcp_get_subscription_price(rcp_get_registration()->get_subscription()), rcp_currency_decimal_filter())) : __('free', 'rcp'); ?> </td> </tr> <?php if (rcp_get_subscription_price(rcp_get_registration()->get_subscription())) { ?> <?php if (rcp_get_registration()->get_fees() || rcp_get_registration()->get_discounts()) { ?> <tr> <th colspan="2"><?php _e('Discounts and Fees', 'rcp'); ?> </th> </tr> <?php // Discounts ?> <?php