Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WooCommerce Subscriptions support #42

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 200 additions & 84 deletions components/integration/integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,18 @@ public function __construct() {
$this->api_key = $this->get_option( 'api_key' );
$this->api_secret = $this->get_option( 'api_secret' );
$this->subscription = $this->get_option( 'subscription' );
if( class_exists( 'WC_Subscriptions' ) ) {
$statuses = wcs_get_subscription_statuses();
foreach( $statuses as $status => $status_label ) {
$this->{"subscription_wc_subscriptions_$status"} = $this->get_option( "subscription_wc_subscriptions_$status" );
}
}

// Enabled and when it should take place
$this->enabled = $this->get_option( 'enabled' );
$this->event = $this->get_option( 'event' );
$this->send_purchases = $this->get_option( 'send_purchases' );
$this->enabled_wc_subscriptions = $this->get_option( 'enabled_wc_subscriptions' );

// Opt-in field
$this->display_opt_in = $this->get_option( 'display_opt_in' );
Expand All @@ -48,13 +55,15 @@ public function __construct() {
add_action( 'save_post_product', array( $this, 'save_product' ) );
}

if ( 'yes' === $this->enabled && 'yes' === $this->display_opt_in ) {
if ( ('yes' === $this->enabled || 'yes' === $this->enabled_wc_subscriptions) && 'yes' === $this->display_opt_in ) {
add_filter( 'woocommerce_checkout_fields', array( $this, 'add_opt_in_checkbox' ) );
}

if ( 'yes' === $this->enabled ) {
if ( 'yes' === $this->enabled || 'yes' === $this->enabled_wc_subscriptions ) {
add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'save_opt_in_checkbox' ) );
}

if ( 'yes' === $this->enabled ) {
add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'order_status' ), 99999, 1 );
add_action( 'woocommerce_order_status_changed', array( $this, 'order_status' ), 99999, 3 );

Expand All @@ -63,6 +72,10 @@ public function __construct() {
}
}

if ( 'yes' === $this->enabled_wc_subscriptions ) {
add_action( 'woocommerce_subscription_status_updated', array( $this, 'subscription_status' ), 99999, 3 );
}

}

/**
Expand Down Expand Up @@ -118,101 +131,135 @@ public function init_form_fields() {
),
),

'display_opt_in' => array(
'title' => __( 'Display Opt-In Checkbox' ),
'label' => __( 'Display an Opt-In checkbox on checkout' ),
'type' => 'checkbox',
'default' => 'no',
'description' => __( 'If enabled, customers will only be subscribed if the "Opt-In" checkbox presented on checkout is checked.' ),
'desc_tip' => false,
'subscription' => array(
'title' => __( 'Subscription' ),
'type' => 'subscription',
'default' => '',
'description' => __( 'Customers will be added to the selected item' ),
),
);

'opt_in_label' => array(
'title' => __( 'Opt-In Checkbox Label' ),
'type' => 'text',
'default' => __( 'I want to subscribe to the newsletter' ),
'description' => __( 'Optional (only used if the above field is checked): Customize the label next to the opt-in checkbox.' ),
'desc_tip' => false,
),
if( class_exists( 'WC_Subscriptions' ) ) {

'opt_in_status' => array(
'title' => __( 'Opt-In Checkbox<br />Default Status' ),
'type' => 'select',
'default' => 'checked',
'description' => __( 'The default state of the opt-in checkbox' ),
'desc_tip' => false,
'options' => array(
'checked' => __( 'Checked' ),
'unchecked' => __( 'Unchecked' ),
$statuses = wcs_get_subscription_statuses();

$this->form_fields = array_merge( $this->form_fields,
array(
"enabled_wc_subscriptions" => array(
'title' => __( 'Enable/Disable for WooCommerce Subscriptions' ),
'type' => 'checkbox',
'label' => __( 'Enable ConvertKit integration for WooCommerce Subscriptions' ),
'default' => 'no',
),
)
);

foreach( $statuses as $status => $status_label ) {
$this->form_fields = array_merge( $this->form_fields,
array(
"subscription_wc_subscriptions_$status" => array(
'title' => __( 'Subscription for ' . $status_label ),
'type' => 'subscription',
'default' => '',
'description' => __( 'Customers will be added to the selected item when the subscription becomes ' . $status_label ),
),
)
);
}

}

$this->form_fields = array_merge( $this->form_fields,
array(
'display_opt_in' => array(
'title' => __( 'Display Opt-In Checkbox' ),
'label' => __( 'Display an Opt-In checkbox on checkout' ),
'type' => 'checkbox',
'default' => 'no',
'description' => __( 'If enabled, customers will only be subscribed if the "Opt-In" checkbox presented on checkout is checked.' ),
'desc_tip' => false,
),
),

'opt_in_location' => array(
'title' => __( 'Opt-In Checkbox<br />Display Location' ),
'type' => 'select',
'default' => 'billing',
'description' => __( 'Where to display the opt-in checkbox on the checkout page (under Billing Info or Order Info).' ),
'desc_tip' => false,
'options' => array(
'billing' => __( 'Billing' ),
'order' => __( 'Order' ),
'opt_in_label' => array(
'title' => __( 'Opt-In Checkbox Label' ),
'type' => 'text',
'default' => __( 'I want to subscribe to the newsletter' ),
'description' => __( 'Optional (only used if the above field is checked): Customize the label next to the opt-in checkbox.' ),
'desc_tip' => false,
),
),

'api_key' => array(
'title' => __( 'API Key' ),
'type' => 'text',
'default' => '',
// translators: this is a url to the ConvertKit site.
'description' => sprintf( __( 'If you already have an account, <a href="%1$s" target="_blank">click here to retrieve your API Key</a>.<br />If you don\'t have a ConvertKit account, you can <a href="%2$s" target="_blank">sign up for one here</a>.' ), esc_attr( esc_html( 'https://app.convertkit.com/account/edit' ) ), esc_attr( esc_url( 'http://convertkit.com/pricing/' ) ) ),
'desc_tip' => false,
),
'opt_in_status' => array(
'title' => __( 'Opt-In Checkbox<br />Default Status' ),
'type' => 'select',
'default' => 'checked',
'description' => __( 'The default state of the opt-in checkbox' ),
'desc_tip' => false,
'options' => array(
'checked' => __( 'Checked' ),
'unchecked' => __( 'Unchecked' ),
),
),

'api_secret' => array(
'title' => __( 'API Secret' ),
'type' => 'text',
'default' => '',
// translators: this is a url to the ConvertKit site.
'description' => sprintf( __( 'If you already have an account, <a href="%1$s" target="_blank">click here to retrieve your API Secret</a>.<br />If you don\'t have a ConvertKit account, you can <a href="%2$s" target="_blank">sign up for one here</a>.' ), esc_attr( esc_html( 'https://app.convertkit.com/account/edit' ) ), esc_attr( esc_url( 'http://convertkit.com/pricing/' ) ) ),
'desc_tip' => false,
),
'opt_in_location' => array(
'title' => __( 'Opt-In Checkbox<br />Display Location' ),
'type' => 'select',
'default' => 'billing',
'description' => __( 'Where to display the opt-in checkbox on the checkout page (under Billing Info or Order Info).' ),
'desc_tip' => false,
'options' => array(
'billing' => __( 'Billing' ),
'order' => __( 'Order' ),
),
),

'subscription' => array(
'title' => __( 'Subscription' ),
'type' => 'subscription',
'default' => '',
'description' => __( 'Customers will be added to the selected item' ),
),
'api_key' => array(
'title' => __( 'API Key' ),
'type' => 'text',
'default' => '',
// translators: this is a url to the ConvertKit site.
'description' => sprintf( __( 'If you already have an account, <a href="%1$s" target="_blank">click here to retrieve your API Key</a>.<br />If you don\'t have a ConvertKit account, you can <a href="%2$s" target="_blank">sign up for one here</a>.' ), esc_attr( esc_html( 'https://app.convertkit.com/account/edit' ) ), esc_attr( esc_url( 'http://convertkit.com/pricing/' ) ) ),
'desc_tip' => false,
),

'name_format' => array(
'title' => __( 'Name Format' ),
'type' => 'select',
'default' => 'first',
'description' => __( 'How should the customer name be sent to ConvertKit?' ),
'desc_tip' => false,
'options' => array(
'first' => __( 'Billing First Name' ),
'last' => __( 'Billing Last Name' ),
'both' => __( 'Billing First Name + Billing Last Name' ),
'api_secret' => array(
'title' => __( 'API Secret' ),
'type' => 'text',
'default' => '',
// translators: this is a url to the ConvertKit site.
'description' => sprintf( __( 'If you already have an account, <a href="%1$s" target="_blank">click here to retrieve your API Secret</a>.<br />If you don\'t have a ConvertKit account, you can <a href="%2$s" target="_blank">sign up for one here</a>.' ), esc_attr( esc_html( 'https://app.convertkit.com/account/edit' ) ), esc_attr( esc_url( 'http://convertkit.com/pricing/' ) ) ),
'desc_tip' => false,
),
),

'send_purchases' => array(
'title' => __( 'Purchases' ),
'label' => __( 'Send purchase data to ConvertKit.' ),
'type' => 'checkbox',
'default' => 'no',
'description' => __( '' ),
'desc_tip' => false,
),
'name_format' => array(
'title' => __( 'Name Format' ),
'type' => 'select',
'default' => 'first',
'description' => __( 'How should the customer name be sent to ConvertKit?' ),
'desc_tip' => false,
'options' => array(
'first' => __( 'Billing First Name' ),
'last' => __( 'Billing Last Name' ),
'both' => __( 'Billing First Name + Billing Last Name' ),
),
),

'debug' => array(
'title' => __( 'Debug' ),
'type' => 'checkbox',
'label' => __('Write data to a log file'),
'description' => 'You can view the log file by going to WooCommerce > Status, click the Logs tab, then selecting convertkit.',
'default' => 'no',
),
'send_purchases' => array(
'title' => __( 'Purchases' ),
'label' => __( 'Send purchase data to ConvertKit.' ),
'type' => 'checkbox',
'default' => 'no',
'description' => __( '' ),
'desc_tip' => false,
),

'debug' => array(
'title' => __( 'Debug' ),
'type' => 'checkbox',
'label' => __('Write data to a log file'),
'description' => 'You can view the log file by going to WooCommerce > Status, click the Logs tab, then selecting convertkit.',
'default' => 'no',
),
)
);

ob_start();
Expand Down Expand Up @@ -485,6 +532,75 @@ public function send_payment( $order_id ){
}
}

/**
* @param $subscription
* @param string $status_new
* @param string $status_old
*/
public function subscription_status( $wc_subscription, $status_new, $status_old ) {
$api_key_correct = ! empty( $this->api_key );
$status_correct = isset( $this->{"subscription_wc_subscriptions_wc-$status_new"} );
$opt_in_correct = 'yes' === get_post_meta( $wc_subscription->get_parent()->get_id(), 'ckwc_opt_in', 'no' );
if ( $api_key_correct && $status_correct && $opt_in_correct ) {
if ( version_compare( WC()->version, '3.0.0', '>=' ) ) {
$email = $wc_subscription->get_billing_email();
$first_name = $wc_subscription->get_billing_first_name();
$last_name = $wc_subscription->get_billing_last_name();

} else {
$email = $wc_subscription->billing_email;
$first_name = $wc_subscription->billing_first_name;
$last_name = $wc_subscription->billing_last_name;
}

switch ( $this->name_format ) {
case 'first':
$name = $first_name;
break;
case 'last':
$name = $last_name;
break;
default:
$name = sprintf("%s %s", $first_name, $last_name);
break;

}
$subscriptions = array( $this->{"subscription_wc_subscriptions_wc-$status_new"} );

$subscriptions = array_filter( array_unique( $subscriptions ) );
foreach ( $subscriptions as $subscription ) {
$subscription_parts = explode( ':', $subscription );
$subscription_type = $subscription_parts[0];
$subscription_id = $subscription_parts[1];
$subscription_function = "ckwc_convertkit_api_add_subscriber_to_{$subscription_type}";

if ( function_exists( $subscription_function ) ) {
$response = call_user_func( $subscription_function, $subscription_id, $email, $name );

$debug = $this->get_option( 'debug' );
if ( 'yes' === $debug ) {
$this->debug_log( 'API call: ' . $subscription_type . "\nResponse: \n" . print_r( $response, true ) );
}
}
}

$subscription = $this->{"subscription_wc_subscriptions_wc-$status_old"};
$subscription_parts = explode( ':', $subscription );
$subscription_type = $subscription_parts[0];
$subscription_id = $subscription_parts[1];
$subscription_function = "ckwc_convertkit_api_remove_subscriber_from_{$subscription_type}";

if ( function_exists( $subscription_function ) ) {
$response = call_user_func( $subscription_function, $subscription_id, $email, $name );

$debug = $this->get_option( 'debug' );
if ( 'yes' === $debug ) {
$this->debug_log( 'API call: ' . $subscription_type . "\nResponse: \n" . print_r( $response, true ) );
}
}
}// End if().
}

/**
* Write API request results to a debug log
* @param $message
Expand Down
25 changes: 24 additions & 1 deletion functions/convertkit.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ function ckwc_convertkit_api_request( $path, $query_args = array(), $request_bod
'timeout' => 5,
), $request_args);

if ( ! isset( $query_args['api_key'] ) ) {
if ( ! isset( $query_args['api_key'] ) && strpos( $path, 'unsubscribe' ) === false ) {
$query_args['api_key'] = ckwc_instance()->api_key;
}

if ( ! isset( $query_args['api_secret'] ) && strpos( $path, 'unsubscribe' ) !== false ) {
$query_args['api_secret'] = ckwc_instance()->api_secret;
}

$request_url = add_query_arg( $query_args, $request_url );
$response = wp_remote_request( $request_url, $request_args );

Expand Down Expand Up @@ -154,3 +158,22 @@ function ckwc_convertkit_api_add_subscriber_to_tag( $tag, $email, $name, $api_ke
'method' => 'POST',
));
}

/**
* @param string $tag
* @param string $email
* @param string $name
* @param string|null $api_secret
*
* @return array|mixed|object|WP_Error
*/
function ckwc_convertkit_api_remove_subscriber_from_tag( $tag, $email, $name, $api_secret = null ) {
$query_args = is_null( $api_secret ) ? array() : array(
'api_secret' => $api_secret,
);
return ckwc_convertkit_api_request(sprintf( 'tags/%d/unsubscribe', $tag ), $query_args, array(
'email' => $email,
), array(
'method' => 'POST',
));
}
2 changes: 1 addition & 1 deletion woocommerce-convertkit.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
}

if ( ! defined( 'CKWC_TITLE' ) ) {
define( 'CKWC_TITLE', 'Gravity Forms ConvertKit Add-On' );
define( 'CKWC_TITLE', 'ConvertKit for WooCommerce' );
}

if ( ! defined( 'CKWC_SHORT_TITLE' ) ) {
Expand Down