gateway class format.
*/
$this->gateways = apply_filters(
'charitable_payment_gateways',
array(
'stripe' => 'Charitable_Gateway_Stripe_AM',
'paypal' => 'Charitable_Gateway_Paypal',
'offline' => 'Charitable_Gateway_Offline',
)
);
$this->gateways['stripe'] = 'Charitable_Gateway_Stripe_AM';
}
/**
* Receives a request to enable or disable a payment gateway and validates it before passing it off.
*
* @since 1.0.0
*
* @return void
*/
public function handle_gateway_settings_request() {
if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'gateway' ) ) {
wp_die( __( 'Cheatin\' eh?!', 'charitable' ) );
}
$gateway = isset( $_REQUEST['gateway_id'] ) ? $_REQUEST['gateway_id'] : false;
/* Gateway must be set */
if ( false === $gateway ) {
wp_die( __( 'Missing gateway.', 'charitable' ) );
}
/* Validate gateway. */
if ( ! isset( $this->gateways[ $gateway ] ) ) {
wp_die( __( 'Invalid gateway.', 'charitable' ) );
}
switch ( $_REQUEST['charitable_action'] ) {
case 'disable_gateway':
$this->disable_gateway( $gateway );
break;
case 'enable_gateway':
$this->enable_gateway( $gateway );
$this->redirect_gateway_settings( $gateway );
break;
case 'make_default_gateway':
$this->set_default_gateway( $gateway );
break;
default:
/**
* Do something when a gateway settings request takes place.
*
* @since 1.0.0
*
* @param string $action The action taking place.
* @param string $gateway_id The gateway ID.
*/
do_action( 'charitable_gateway_settings_request', $_REQUEST['charitable_action'], $gateway );
}
}
/**
* Returns all available payment gateways.
*
* @since 1.0.0
*
* @return array
*/
public function get_available_gateways() {
if ( isset( $this->gateways['stripe'] ) ) {
$this->gateways['stripe'] = charitable()->is_stripe_connect_addon() ? 'Charitable_Gateway_Stripe_AM' : $this->gateways['stripe'];
}
return $this->gateways;
}
/**
* Returns the current active gateways.
*
* @since 1.0.0
*
* @return string[]
*/
public function get_active_gateways() {
$active_gateways = charitable_get_option( 'active_gateways', array() );
foreach ( $active_gateways as $gateway_id => $gateway_class ) {
if ( ! class_exists( $gateway_class ) ) {
unset( $active_gateways[ $gateway_id ] );
}
}
uksort( $active_gateways, array( $this, 'sort_by_default' ) );
// force the strip active gateway normally for stripe addon to point to the stripe built into core.
if ( isset( $active_gateways['stripe'] ) ) {
$active_gateways['stripe'] = 'Charitable_Gateway_Stripe_AM';
}
/**
* Filter the list of active gateways.
*
* @since 1.0.0
*
* @param array $gateways Active gateways.
*/
return apply_filters( 'charitable_active_gateways', $active_gateways );
}
/**
* Returns an array of the active gateways, in ID => name format.
*
* This is useful for select/radio input fields.
*
* @since 1.0.0
*
* @return string[]
*/
public function get_gateway_choices() {
$gateways = array();
foreach ( $this->get_active_gateways() as $id => $class ) {
$gateway = new $class;
$gateways[ $id ] = $gateway->get_label();
}
return $gateways;
}
/**
* Returns a text description of the active gateways.
*
* @since 1.3.0
*
* @return string[]
*/
public function get_active_gateways_names() {
$gateways = array();
foreach ( $this->get_active_gateways() as $id => $class ) {
$gateway = new $class;
$gateways[] = $gateway->get_name();
}
return $gateways;
}
/**
* Return the gateway class name for a given gateway.
*
* @since 1.0.0
*
* @param string $gateway Gateway ID.
* @return string|false
*/
public function get_gateway( $gateway ) {
return isset( $this->gateways[ $gateway ] ) ? $this->gateways[ $gateway ] : false;
}
/**
* Return the gateway object for a given gateway.
*
* @since 1.0.0
*
* @param string $gateway Gateway ID.
* @return Charitable_Gateway|null
*/
public function get_gateway_object( $gateway ) {
$class = $this->get_gateway( $gateway );
$object = $class ? new $class : null;
/**
* Filter the gateway object.
*
* @since 1.6.30
*
* @param Charitable_Gateway|null $object The gateway object.
*/
return apply_filters( 'charitable_gateway_object_' . $gateway, $object, $gateway );
}
/**
* Returns whether the passed gateway is active.
*
* @since 1.0.0
*
* @param string $gateway_id Gateway ID.
* @return boolean
*/
public function is_active_gateway( $gateway_id ) {
return array_key_exists( $gateway_id, $this->get_active_gateways() );
}
/**
* Checks whether the submitted gateway is valid.
*
* @since 1.4.3
*
* @param string $gateway Gateway ID.
* @return boolean
*/
public function is_valid_gateway( $gateway ) {
/**
* Validate a particular gatewya.
*
* @since 1.4.3
*
* @param boolean $valid Whether a gateway is valid.
* @param string $gateway The gateway ID.
*/
if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
error_log( 'is_valid_gateway' );
error_log( print_r( $gateway, true ) );
error_log( print_r( $this->gateways, true ) );
}
return apply_filters( 'charitable_is_valid_gateway', array_key_exists( $gateway, $this->gateways ), $gateway );
}
/**
* Returns the default gateway.
*
* @since 1.0.0
*
* @return string
*/
public function get_default_gateway() {
return charitable_get_option( 'default_gateway', '' );
}
/**
* Provide default gateway settings fields.
*
* @since 1.0.0
*
* @param array $settings Gateway settings.
* @param Charitable_Gateway $gateway The gateway's helper object.
* @return array
*/
public function register_gateway_settings( $settings, Charitable_Gateway $gateway ) {
add_filter( 'charitable_settings_fields_gateways_gateway_' . $gateway->get_gateway_id(), array( $gateway, 'default_gateway_settings' ), 5 );
add_filter( 'charitable_settings_fields_gateways_gateway_' . $gateway->get_gateway_id(), array( $gateway, 'gateway_settings' ), 15 );
/**
* Filter the settings to show for a particular gateway.
*
* @since 1.0.0
*
* @param array $settings Gateway settings.
*/
return apply_filters( 'charitable_settings_fields_gateways_gateway_' . $gateway->get_gateway_id(), $settings );
}
/**
* Returns true if test mode is enabled.
*
* @since 1.0.0
*
* @return boolean
*/
public function in_test_mode() {
$enabled = charitable_get_option( 'test_mode', false );
/**
* Return whether Charitable is in test mode.
*
* @since 1.0.0
*
* @param boolean $enabled Whether test mode is on.
*/
return apply_filters( 'charitable_in_test_mode', $enabled );
}
/**
* Checks whether all of the active gateways support a feature.
*
* If ANY gateway doesn't support the feature, this returns false.
*
* @since 1.4.0
*
* @param string $feature Feature to search for.
* @return boolean
*/
public function all_gateways_support( $feature ) {
foreach ( $this->get_active_gateways() as $gateway_id => $gateway_class ) {
$gateway_object = new $gateway_class;
if ( false === $gateway_object->supports( $feature ) ) {
return false;
}
}
return true;
}
/**
* Checks whether any of the active gateways support a feature.
*
* If any gateway supports the feature, this returns true. Otherwise false.
*
* @since 1.4.0
*
* @param string $feature Feature to check for.
* @return boolean
*/
public function any_gateway_supports( $feature ) {
foreach ( $this->get_active_gateways() as $gateway_id => $gateway_class ) {
$gateway_object = new $gateway_class;
if ( true === $gateway_object->supports( $feature ) ) {
return true;
}
}
return false;
}
/**
* Checks whether all of the active gateways support AJAX.
*
* If ANY gateway doesn't support AJAX, this returns false.
*
* @since 1.3.0
*
* @return boolean
*/
public function gateways_support_ajax() {
return $this->all_gateways_support( '1.3.0' );
}
/**
* Return an array of recommended gateways for the current site.
*
* Note that this will only return gateways that are not already
* available on the site. i.e. If you have Stripe installed, it
* will not suggest that.
*
* @since 1.5.0
*
* @return array
*/
public function get_recommended_gateways() {
$available = $this->get_available_gateways();
$gateways = array(
'payfast' => __( 'Payfast', 'charitable' ),
'paystack' => __( 'Paystack', 'charitable' ),
'stripe' => __( 'Stripe', 'charitable' ),
'authorize_net' => __( 'Authorize.Net', 'charitable' ),
'windcave' => __( 'Windcave', 'charitable' ),
'braintree' => __( 'Braintree', 'charitable' ),
'mollie' => __( 'Mollie', 'charitable' ),
'gocardless' => __( 'GoCardless', 'charitable' ),
'payrexx' => __( 'Payrexx', 'charitable' ),
);
/* If the user has already enabled one of these, leave them alone. :) */
foreach ( $gateways as $gateway_id => $gateway ) {
if ( array_key_exists( $gateway_id, $available ) ) {
return array();
}
}
$currency = charitable_get_default_currency();
$locale = get_locale();
if ( 'en_ZA' == $locale || 'ZAR' == $currency ) {
return charitable_array_subset( $gateways, array( 'payfast', 'paystack' ) );
}
if ( in_array( $currency, array( 'NGN', 'GHS' ) ) ) {
return charitable_array_subset( $gateways, array( 'paystack' ) );
}
if ( in_array( $locale, array( 'en_NZ', 'en_AU', 'en_GB' ) ) || in_array( $currency, array( 'NZD', 'AUD', 'GBP' ) ) ) {
return charitable_array_subset( $gateways, array( 'stripe', 'gocardless' ) );
}
if ( in_array( $locale, array( 'ms_MY', 'ja', 'zh_HK' ) ) || in_array( $currency, array( 'MYR', 'JPY', 'HKD' ) ) ) {
return charitable_array_subset( $gateways, array( 'stripe', 'windcave' ) );
}
if ( in_array( $locale, array( 'th' ) ) || in_array( $currency, array( 'BND', 'FJD', 'KWD', 'PGK', 'SBD', 'THB', 'TOP', 'VUV', 'WST' ) ) ) {
return charitable_array_subset( $gateways, array( 'windcave' ) );
}
if ( in_array( $currency, array( 'EUR' ) ) ) {
return charitable_array_subset( $gateways, array( 'stripe', 'mollie' ) );
}
if ( in_array( $currency, array( 'CHF', 'DKK' ) ) ) {
return charitable_array_subset( $gateways, array( 'stripe', 'payrexx' ) );
}
return charitable_array_subset( $gateways, array( 'stripe', 'braintree' ) );
}
/**
* Sets the default gateway.
*
* @since 1.0.0
*
* @param string $gateway Gateway ID.
* @return void
*/
protected function set_default_gateway( $gateway ) {
$settings = get_option( 'charitable_settings' );
$settings['default_gateway'] = $gateway;
update_option( 'charitable_settings', $settings );
charitable_get_admin_notices()->add_success( __( 'Default Gateway Updated', 'charitable' ) );
do_action( 'charitable_set_gateway_gateway', $gateway );
}
/**
* Enable a payment gateway.
*
* @since 1.0.0
*
* @param string $gateway Gateway ID.
* @return void
*/
protected function enable_gateway( $gateway ) {
$settings = get_option( 'charitable_settings' );
$active_gateways = isset( $settings['active_gateways'] ) ? $settings['active_gateways'] : array();
$active_gateways[ $gateway ] = $this->gateways[ $gateway ];
$settings['active_gateways'] = $active_gateways;
/* If this is the only gateway, make it the default gateway */
if ( 1 == count( $settings['active_gateways'] ) ) {
$settings['default_gateway'] = $gateway;
}
update_option( 'charitable_settings', $settings );
Charitable_Settings::get_instance()->add_update_message( __( 'Gateway enabled', 'charitable' ), 'success' );
/**
* Do something when a payment gateway is enabled.
*
* @since 1.0.0
*
* @param string $gateway The payment gateway.
*/
do_action( 'charitable_gateway_enable', $gateway );
}
/**
* Disable a payment gateway.
*
* @since 1.0.0
*
* @param string $gateway Gateway ID.
* @return void
*/
protected function disable_gateway( $gateway ) {
$settings = get_option( 'charitable_settings' );
if ( ! isset( $settings['active_gateways'][ $gateway ] ) ) {
return;
}
unset( $settings['active_gateways'][ $gateway ] );
/* Set a new default gateway */
if ( $gateway == $this->get_default_gateway() ) {
$settings['default_gateway'] = count( $settings['active_gateways'] ) ? key( $settings['active_gateways'] ) : '';
}
update_option( 'charitable_settings', $settings );
Charitable_Settings::get_instance()->add_update_message( __( 'Gateway disabled', 'charitable' ), 'success' );
/**
* Do something when a payment gateway is disabled.
*
* @since 1.0.0
*
* @param string $gateway The payment gateway.
*/
do_action( 'charitable_gateway_disable', $gateway );
}
/**
* Connects to Stripe by saving account information passed back to the plugin.
*
* @since 4.2.2
*
* @return void
*/
public function connect_gateways() {
// Current user cannot handle this request.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
// Do not need to handle this request, bail.
if (
! isset( $_GET['wpcharitable_gateway_connect_completion'] ) ||
'stripe_connect' !== $_GET['wpcharitable_gateway_connect_completion'] ||
! isset( $_GET['state'] )
) {
return;
}
// Unable to redirect, bail.
if ( headers_sent() ) {
return;
}
if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
$current_url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
} else {
$current_url = '';
}
$customer_site_url = remove_query_arg(
array(
'state',
'wpcharitable_gateway_connect_completion'
),
$current_url
);
$wpcharitable_credentials_url = add_query_arg(
array(
'live_mode' => (int) ! charitable_get_option( 'test_mode' ), // (int) ! $this->is_test_mode(),
'state' => sanitize_text_field( $_GET['state'] ),
'customer_site_url' => urlencode( $customer_site_url ),
),
'https://wpcharitable.com/stripe-connect/?wpcharitable_gateway_connect_credentials=stripe_connect' // todo: filter market site url
);
$response = wp_remote_get( esc_url_raw( $wpcharitable_credentials_url ) ); // add add_filter('https_ssl_verify', '__return_false'); here if testing local
if (
is_wp_error( $response ) ||
200 !== wp_remote_retrieve_response_code( $response )
) {
$stripe_account_settings_url = add_query_arg(
array(
'tab' => 'gateways',
'page' => 'charitable-settings',
'group' => 'gateways_stripe',
),
admin_url( 'admin.php' )
);
$message = wpautop(
sprintf(
/* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
__(
'There was an error getting your Stripe credentials. Please %1$stry again%2$s. If you continue to have this problem, please contact support.',
'stripe'
),
'',
''
)
);
wp_die( $message );
}
$body = wp_remote_retrieve_body( $response );
/** @var string $body */
$body = json_decode( $body, true );
/** @var array> $body */
$account_data = $body['data'];
$this->save_account_information( $account_data );
// update the option to track that we are using stripe connect.
update_option( 'charitable_using_stripe_connect', time() );
/**
* Allow further processing after connecting a Stripe account.
*
* @since 3.6.0
*
* @param array $data Stripe response data.
*/
do_action( 'wpcharitable_stripe_account_connected', $account_data );
// If you configure Stripe and the offline gateway is the default gateway, after you have connected successfully with Stripe, it should automatically be set as the default gateway.
if ( false === $this->get_default_gateway() || 'offline' === $this->get_default_gateway() ) {
$this->set_default_gateway( 'stripe' );
}
wp_redirect( esc_url_raw( $customer_site_url ) );
exit;
}
/**
* Saves the account information sent back from Stripe, alongside other, to identify the connected account.
*
* @since 4.4.2
*
* @param array $data Stripe oAuth account data.
* @return void
*/
private function save_account_information( $data, $gateway_id = 'stripe' ) {
$prefix = $this->in_test_mode()
? 'test'
: 'live';
$settings = get_option( 'charitable_settings' );
$settings['gateways_' . $gateway_id ]['live_secret_key'] = '';
$settings['gateways_' . $gateway_id ]['live_public_key'] = '';
$settings['gateways_' . $gateway_id ]['test_secret_key'] = '';
$settings['gateways_' . $gateway_id ]['test_public_key'] = '';
$settings['gateways_' . $gateway_id ][ $prefix . '_secret_key' ] = isset( $data['secret_key'] ) ? sanitize_text_field( $data['secret_key'] ) : false;
$settings['gateways_' . $gateway_id ][ $prefix . '_public_key' ] = isset( $data['publishable_key'] ) ? sanitize_text_field( $data['publishable_key'] ) : false;
if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
error_log( 'save_account_information' );
error_log( print_r( $settings, true ) );
}
update_option( 'charitable_settings', $settings );
charitable_get_admin_notices()->add_success( __( 'Stripe Information Updated', 'charitable' ) );
do_action( 'charitable_save_account_information_gateway_' . $gateway_id, $settings, $data, $gateway_id );
}
/**
* Disconnects from Stripe by removing associated account information.
*
* This does not deauthorize the application within the Stripe account.
*
* @since 4.2.2
*
* @return void
*/
public function disconnect_gateways() {
// Do not need to handle this request, bail.
if (
! ( isset( $_GET['page'] ) && 'charitable-settings' === $_GET['page'] ) ||
! isset( $_GET['wpcharitable-stripe-disconnect'] )
) {
return;
}
// Current user cannot handle this request.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( ! isset( $_GET['_wpnonce'] ) ) {
return;
}
// Invalid nonce, bail.
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'wpcharitable-stripe-connect-disconnect' ) ) {
return;
}
$settings = get_option( 'charitable_settings' );
unset( $settings['gateways_stripe'][ 'live_secret_key' ] );
unset( $settings['gateways_stripe'][ 'live_public_key' ] );
unset( $settings['gateways_stripe'][ 'test_secret_key' ] );
unset( $settings['gateways_stripe'][ 'test_public_key' ] );
update_option( 'charitable_settings', $settings );
// update the option to track that we are using stripe connect.
delete_option( 'charitable_using_stripe_connect' );
charitable_get_admin_notices()->add_success( __( 'Stripe Connected Removed', 'charitable' ) );
do_action( 'charitable_remove_connection_gateway_stripe', $settings );
$redirect_url = add_query_arg(
array(
'tab' => 'gateways',
'page' => 'charitable-settings',
'group' => 'gateways_stripe',
),
admin_url( 'admin.php' )
);
wp_safe_redirect( $redirect_url );
exit;
}
/**
* Redirects to the gateway settings page once a gateway has been activated.
*
* @since 1.7.0
*
* @param string $gateway Gateway ID.
* @return void
*/
public function redirect_gateway_settings( $gateway ) {
$settings_url = add_query_arg( array(
'group' => 'gateways_' . $gateway,
), admin_url( 'admin.php?page=charitable-settings&tab=gateways' ) );
wp_safe_redirect( $settings_url );
exit;
}
/**
* Sort the active gateways, placing the default gateway first.
*
* @since 1.4.0
*
* @param string $a Gateway to compare.
* @param string $b Gateway to compare against.
* @return int
*/
protected function sort_by_default( $a, $b ) {
$default = $this->get_default_gateway();
if ( $a == $default ) {
return -1;
}
if ( $b == $default ) {
return 1;
}
return 0;
}
/**
* Ensure there is a settings option when landing on settings pages, even if init blank. Mostly applicable to new installs.
*
* @since 1.4.0
*
*/
public function check_settings() {
if ( isset( $_GET['page'] ) && 'charitable-settings' !== $_GET['page'] ) {
return;
}
$settings = get_option( 'charitable_settings' );
// attach this to CHARITABLE_DEBUG constant.
if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG && defined( 'CHARITABLE_DEBUG_SETTINGS' ) && CHARITABLE_DEBUG_SETTINGS ) {
error_log( 'checking_settings');
error_log( print_r( $settings, true ) );
}
if ( false === $settings ||( is_array( $settings ) && empty( $settings ) ) ) {
$settings_blank_slate = array( 'default_gateway' => 'stripe' ); // settings are brand new and include setting the default gateway
update_option( 'charitable_settings', $settings_blank_slate );
}
}
/**
* Display the test and live fields that represent the manual keys for Stripe that users might be already using prior to 1.7.0.
*
* @since 1.7.0
*
*/
public function show_stripe_manual_keys_ajax() {
if ( ! isset( $_POST ) || 'charitable-show-stripe-keys' !== $_POST['action'] ) {
return;
}
$settings = get_option( 'charitable_settings' );
if ( false === $settings ) {
return;
}
$gateway_id = 'stripe';
$live_secret_key = $settings['gateways_' . $gateway_id ][ 'live_secret_key' ];
$live_public_key = $settings['gateways_' . $gateway_id ][ 'live_public_key' ];
$test_secret_key = $settings['gateways_' . $gateway_id ][ 'test_secret_key' ];
$test_public_key = $settings['gateways_' . $gateway_id ][ 'test_public_key' ];
$html = '| Live Settings |
|
|---|
| Live Secret Key |
|
|---|
| Live Publishable Key |
|
|---|
| Test Settings |
|
|---|
| Test Secret Key |
|
|---|
| Test Publishable Key |
|
';
wp_send_json_success( $html );
}
}
endif;