/**
 * Cancel a member's payment profile
 *
 * @access      public
 * @since       2.1
 */
function rcp_cancel_member_payment_profile( $member_id = 0 ) {

	global $rcp_options;

	$success  = false;
	$member   = new RCP_Member( $member_id );

	if( ! rcp_can_member_cancel( $member_id ) ) {
		return $success;
	}

	if( rcp_is_stripe_subscriber( $member_id ) ) {

		if( ! class_exists( 'Stripe\Stripe' ) ) {
			require_once RCP_PLUGIN_DIR . 'includes/libraries/stripe/init.php';
		}

		if ( isset( $rcp_options['sandbox'] ) ) {
			$secret_key = trim( $rcp_options['stripe_test_secret'] );
		} else {
			$secret_key = trim( $rcp_options['stripe_live_secret'] );
		}

		\Stripe\Stripe::setApiKey( $secret_key );

		try {

			$cu = \Stripe\Customer::retrieve( $member->get_payment_profile_id() );
			$cu->cancelSubscription( array( 'at_period_end' => false ) );

			$success = true;

		} catch (\Stripe\Error\InvalidRequest $e) {

			// Invalid parameters were supplied to Stripe's API
			$body = $e->getJsonBody();
			$err  = $body['error'];

			$error = "<h4>" . __( 'An error occurred', 'rcp' ) . "</h4>";
			if( isset( $err['code'] ) ) {
				$error .= "<p>" . __( 'Error code:', 'rcp' ) . " " . $err['code'] ."</p>";
			}
			$error .= "<p>Status: " . $e->getHttpStatus() ."</p>";
			$error .= "<p>Message: " . $err['message'] . "</p>";

			wp_die( $error, __( 'Error', 'rcp' ), array( 'response' => 401 ) );

		} catch (\Stripe\Error\Authentication $e) {

			// Authentication with Stripe's API failed
			// (maybe you changed API keys recently)

			$body = $e->getJsonBody();
			$err  = $body['error'];

			$error = "<h4>" . __( 'An error occurred', 'rcp' ) . "</h4>";
			if( isset( $err['code'] ) ) {
				$error .= "<p>" . __( 'Error code:', 'rcp' ) . " " . $err['code'] ."</p>";
			}
			$error .= "<p>Status: " . $e->getHttpStatus() ."</p>";
			$error .= "<p>Message: " . $err['message'] . "</p>";

			wp_die( $error, __( 'Error', 'rcp' ), array( 'response' => 401 ) );

		} catch (\Stripe\Error\ApiConnection $e) {

			// Network communication with Stripe failed

			$body = $e->getJsonBody();
			$err  = $body['error'];

			$error = "<h4>" . __( 'An error occurred', 'rcp' ) . "</h4>";
			if( isset( $err['code'] ) ) {
				$error .= "<p>" . __( 'Error code:', 'rcp' ) . " " . $err['code'] ."</p>";
			}
			$error .= "<p>Status: " . $e->getHttpStatus() ."</p>";
			$error .= "<p>Message: " . $err['message'] . "</p>";

			wp_die( $error, __( 'Error', 'rcp' ), array( 'response' => 401 ) );

		} catch (\Stripe\Error\Base $e) {

			// Display a very generic error to the user

			$body = $e->getJsonBody();
			$err  = $body['error'];

			$error = "<h4>" . __( 'An error occurred', 'rcp' ) . "</h4>";
			if( isset( $err['code'] ) ) {
				$error .= "<p>" . __( 'Error code:', 'rcp' ) . " " . $err['code'] ."</p>";
			}
			$error .= "<p>Status: " . $e->getHttpStatus() ."</p>";
			$error .= "<p>Message: " . $err['message'] . "</p>";

			wp_die( $error, __( 'Error', 'rcp' ), array( 'response' => 401 ) );

		} catch (Exception $e) {

			// Something else happened, completely unrelated to Stripe

			$error = "<h4>" . __( 'An error occurred', 'rcp' ) . "</h4>";
			$error .= print_r( $e, true );

			wp_die( $error, __( 'Error', 'rcp' ), array( 'response' => 401 ) );

		}

	} elseif( rcp_is_paypal_subscriber( $member_id ) ) {

		if( rcp_has_paypal_api_access() && $member->get_payment_profile_id() ) {

			// Set PayPal API key credentials.
			$api_username  = isset( $rcp_options['sandbox'] ) ? 'test_paypal_api_username' : 'live_paypal_api_username';
			$api_password  = isset( $rcp_options['sandbox'] ) ? 'test_paypal_api_password' : 'live_paypal_api_password';
			$api_signature = isset( $rcp_options['sandbox'] ) ? 'test_paypal_api_signature' : 'live_paypal_api_signature';
			$api_endpoint  = isset( $rcp_options['sandbox'] ) ? 'https://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp';

			$args = array(
				'USER'      => $rcp_options[ $api_username ],
				'PWD'       => $rcp_options[ $api_password ],
				'SIGNATURE' => $rcp_options[ $api_signature ],
				'VERSION'   => '76.0',
				'METHOD'    => 'ManageRecurringPaymentsProfileStatus',
				'PROFILEID' => $member->get_payment_profile_id(),
				'ACTION'    => 'Cancel'
			);

			$error_msg = '';
			$request   = wp_remote_post( $api_endpoint, array( 'body' => $args, 'timeout' => 30 ) );

			if ( is_wp_error( $request ) ) {

				$success   = false;
				$error_msg = $request->get_error_message();

			} else {

				$body = wp_remote_retrieve_body( $request );
				if( is_string( $body ) ) {
					wp_parse_str( $body, $body );
				}

				if( empty( $request['response'] ) ) {
					$success = false;
				}

				if( empty( $request['response']['code'] ) || 200 !== (int) $request['response']['code'] ) {
					$success = false;
				}

				if( empty( $request['response']['message'] ) || 'OK' !== $request['response']['message'] ) {
					$success = false;
				}

				if( isset( $body['ACK'] ) && 'success' === strtolower( $body['ACK'] ) ) {
					$success = true;
				} else {
					$success = false;
					if( isset( $body['L_LONGMESSAGE0'] ) ) {
						$error_msg = $body['L_LONGMESSAGE0'];
					}
				}

			}

			if( ! $success ) {
				wp_die( sprintf( __( 'There was a problem cancelling the subscription, please contact customer support. Error: %s', 'rcp' ), $error_msg ), array( 'response' => 400 ) );
			}

		}

	}

	if( $success ) {
		$member->cancel();
	}

	return $success;
}
/**
 * Determines if a member can update the credit / debit card attached to their account
 *
 * @access      public
 * @since       2.1
 */
function rcp_member_can_update_billing_card($user_id = 0)
{
    if (empty($user_id)) {
        $user_id = get_current_user_id();
    }
    $ret = false;
    // Check if the member is a Stripe customer
    if (rcp_is_stripe_subscriber($user_id)) {
        $ret = true;
    } elseif (rcp_is_paypal_subscriber($user_id) && rcp_has_paypal_api_access()) {
        $ret = true;
    }
    return apply_filters('rcp_member_can_update_billing_card', $ret, $user_id);
}
/**
 * Process an update card form request
 *
 * @access      private
 * @since       2.1
 */
function rcp_stripe_update_billing_card($member_id = 0, $member_obj)
{
    if (empty($member_id)) {
        return;
    }
    if (!is_a($member_obj, 'RCP_Member')) {
        return;
    }
    if (!rcp_is_stripe_subscriber($member_id)) {
        return;
    }
    if (empty($_POST['stripeToken'])) {
        wp_die(__('Missing Stripe token', 'rcp'), __('Error', 'rcp'), array('response' => 400));
    }
    $customer_id = $member_obj->get_payment_profile_id();
    global $rcp_options;
    if (isset($rcp_options['sandbox'])) {
        $secret_key = trim($rcp_options['stripe_test_secret']);
    } else {
        $secret_key = trim($rcp_options['stripe_live_secret']);
    }
    if (!class_exists('Stripe\\Stripe')) {
        require_once RCP_PLUGIN_DIR . 'includes/libraries/stripe/init.php';
    }
    \Stripe\Stripe::setApiKey($secret_key);
    $customer = \Stripe\Customer::retrieve($customer_id);
    $customer->card = $_POST['stripeToken'];
    // obtained with stripe.js
    $customer->save();
    wp_redirect(add_query_arg('card', 'updated'));
    exit;
}
/**
 * Process an update card form request
 *
 * @access      private
 * @since       2.1
 */
function rcp_stripe_update_billing_card($member_id = 0, $member_obj)
{
    if (empty($member_id)) {
        return;
    }
    if (!is_a($member_obj, 'RCP_Member')) {
        return;
    }
    if (!rcp_is_stripe_subscriber($member_id)) {
        return;
    }
    if (empty($_POST['stripeToken'])) {
        wp_die(__('Missing Stripe token', 'rcp'), __('Error', 'rcp'), array('response' => 400));
    }
    $customer_id = $member_obj->get_payment_profile_id();
    global $rcp_options;
    if (isset($rcp_options['sandbox'])) {
        $secret_key = trim($rcp_options['stripe_test_secret']);
    } else {
        $secret_key = trim($rcp_options['stripe_live_secret']);
    }
    if (!class_exists('Stripe\\Stripe')) {
        require_once RCP_PLUGIN_DIR . 'includes/libraries/stripe/init.php';
    }
    \Stripe\Stripe::setApiKey($secret_key);
    try {
        $customer = \Stripe\Customer::retrieve($customer_id);
        $customer->card = $_POST['stripeToken'];
        // obtained with stripe.js
        $customer->save();
    } catch (\Stripe\Error\Card $e) {
        $body = $e->getJsonBody();
        $err = $body['error'];
        $error = '<h4>' . __('An error occurred', 'rcp') . '</h4>';
        if (isset($err['code'])) {
            $error .= '<p>' . sprintf(__('Error code: %s', 'rcp'), $err['code']) . '</p>';
        }
        $error .= "<p>Status: " . $e->getHttpStatus() . "</p>";
        $error .= "<p>Message: " . $err['message'] . "</p>";
        wp_die($error, __('Error', 'rcp'), array('response' => '401'));
        exit;
    } catch (\Stripe\Error\InvalidRequest $e) {
        // Invalid parameters were supplied to Stripe's API
        $body = $e->getJsonBody();
        $err = $body['error'];
        $error = '<h4>' . __('An error occurred', 'rcp') . '</h4>';
        if (isset($err['code'])) {
            $error .= '<p>' . sprintf(__('Error code: %s', 'rcp'), $err['code']) . '</p>';
        }
        $error .= "<p>Status: " . $e->getHttpStatus() . "</p>";
        $error .= "<p>Message: " . $err['message'] . "</p>";
        wp_die($error, __('Error', 'rcp'), array('response' => '401'));
    } catch (\Stripe\Error\Authentication $e) {
        // Authentication with Stripe's API failed
        // (maybe you changed API keys recently)
        $body = $e->getJsonBody();
        $err = $body['error'];
        $error = '<h4>' . __('An error occurred', 'rcp') . '</h4>';
        if (isset($err['code'])) {
            $error .= '<p>' . sprintf(__('Error code: %s', 'rcp'), $err['code']) . '</p>';
        }
        $error .= "<p>Status: " . $e->getHttpStatus() . "</p>";
        $error .= "<p>Message: " . $err['message'] . "</p>";
        wp_die($error, __('Error', 'rcp'), array('response' => '401'));
    } catch (\Stripe\Error\ApiConnection $e) {
        // Network communication with Stripe failed
        $body = $e->getJsonBody();
        $err = $body['error'];
        $error = '<h4>' . __('An error occurred', 'rcp') . '</h4>';
        if (isset($err['code'])) {
            $error .= '<p>' . sprintf(__('Error code: %s', 'rcp'), $err['code']) . '</p>';
        }
        $error .= "<p>Status: " . $e->getHttpStatus() . "</p>";
        $error .= "<p>Message: " . $err['message'] . "</p>";
        wp_die($error, __('Error', 'rcp'), array('response' => '401'));
    } catch (\Stripe\Error\Base $e) {
        // Display a very generic error to the user
        $body = $e->getJsonBody();
        $err = $body['error'];
        $error = '<h4>' . __('An error occurred', 'rcp') . '</h4>';
        if (isset($err['code'])) {
            $error .= '<p>' . sprintf(__('Error code: %s', 'rcp'), $err['code']) . '</p>';
        }
        $error .= "<p>Status: " . $e->getHttpStatus() . "</p>";
        $error .= "<p>Message: " . $err['message'] . "</p>";
        wp_die($error, __('Error', 'rcp'), array('response' => '401'));
    } catch (Exception $e) {
        // Something else happened, completely unrelated to Stripe
        $error = '<p>' . __('An unidentified error occurred.', 'rcp') . '</p>';
        $error .= print_r($e, true);
        wp_die($error, __('Error', 'rcp'), array('response' => '401'));
    }
    wp_redirect(add_query_arg('card', 'updated'));
    exit;
}
/**
 * Query Stripe API to get customer's card details
 *
 * @param $card       array
 * @param $member_id int
 * @param $member    object
 *
 * @since 2.5
 * @return array
 */
function rcp_stripe_get_card_details($cards, $member_id, $member)
{
    global $rcp_options;
    if (!rcp_is_stripe_subscriber($member_id)) {
        return $cards;
    }
    if (!class_exists('Stripe\\Stripe')) {
        require_once RCP_PLUGIN_DIR . 'includes/libraries/stripe/init.php';
    }
    if (rcp_is_sandbox()) {
        $secret_key = trim($rcp_options['stripe_test_secret']);
    } else {
        $secret_key = trim($rcp_options['stripe_live_secret']);
    }
    \Stripe\Stripe::setApiKey($secret_key);
    try {
        $customer = \Stripe\Customer::retrieve($member->get_payment_profile_id());
        $default = $customer->sources->retrieve($customer->default_source);
        $cards['stripe']['name'] = $default->name;
        $cards['stripe']['type'] = $default->brand;
        $cards['stripe']['zip'] = $default->address_zip;
        $cards['stripe']['exp_month'] = $default->exp_month;
        $cards['stripe']['exp_year'] = $default->exp_year;
        $cards['stripe']['last4'] = $default->last4;
    } catch (Exception $e) {
    }
    return $cards;
}