Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/paid-member-subscriptions/includes/admin/class-admin-members.php
+++ b/paid-member-subscriptions/includes/admin/class-admin-members.php
@@ -840,6 +840,9 @@
case 'subscription_expired':
$message = __( 'Subscription expired.', 'paid-member-subscriptions' );
break;
+ case 'subscription_expired_automatically':
+ $message = __( 'Subscription expired (status check system).', 'paid-member-subscriptions' );
+ break;
case 'subscription_renewed_manually':
if( !empty( $log['data']['until'] ) )
--- a/paid-member-subscriptions/includes/admin/class-admin-subscriptions-list-table.php
+++ b/paid-member-subscriptions/includes/admin/class-admin-subscriptions-list-table.php
@@ -384,7 +384,9 @@
$search_where[] = $wpdb->prepare( 'subscriptions.id = %d', (int)$search_term );
$search_where[] = $wpdb->prepare( 'users.user_login LIKE %s', $search_like );
+ $search_where[] = $wpdb->prepare( 'users.user_email LIKE %s', $search_like );
$search_where[] = $wpdb->prepare( 'plans.post_title LIKE %s', $search_like );
+ $search_where[] = $wpdb->prepare( 'subscriptions.payment_profile_id LIKE %s', $search_like );
$query_where .= ' AND ( ' . implode( ' OR ', $search_where ) . ' )';
--- a/paid-member-subscriptions/includes/admin/views/view-page-addons.php
+++ b/paid-member-subscriptions/includes/admin/views/view-page-addons.php
@@ -177,6 +177,13 @@
'icon' => 'pms-add-on-tax-logo.png',
'doc_url' => 'https://www.cozmoslabs.com/docs/paid-member-subscriptions/add-ons/tax-eu-vat/?utm_source=pms-addons-pro&utm_medium=client-site&utm_campaign=pms-tax-eu-vat-addon',
),
+ array( 'slug' => 'pms-add-on-authorize-net/index.php',
+ 'type' => 'add-on',
+ 'name' => __( 'Authorize.Net', 'paid-member-subscriptions' ),
+ 'description' => __( 'Collect credit and debit card payments for your membership plans with Authorize.Net, including recurring subscriptions and renewals.', 'paid-member-subscriptions' ),
+ 'icon' => 'pms-add-on-authorize-net-logo.svg',
+ 'doc_url' => 'https://www.cozmoslabs.com/docs/paid-member-subscriptions/?utm_source=pms-addons-pro&utm_medium=client-site&utm_campaign=pms-authorize-net-addon',
+ ),
array( 'slug' => 'pms-add-on-mailchimp/index.php',
'type' => 'add-on',
'name' => __( 'Mailchimp', 'paid-member-subscriptions' ),
--- a/paid-member-subscriptions/includes/admin/views/view-page-basic-info.php
+++ b/paid-member-subscriptions/includes/admin/views/view-page-basic-info.php
@@ -399,6 +399,18 @@
</div>
<div>
+ <a href="https://www.cozmoslabs.com/docs/paid-member-subscriptions/?utm_source=pms-basic-info&utm_medium=client-site&utm_campaign=pms-authorize-net-addon" target="_blank">
+ <h4 class="pms-add-on-name"><?php esc_html_e( 'Authorize.Net', 'paid-member-subscriptions' ); ?></h4>
+ </a>
+
+ <a href="https://www.cozmoslabs.com/docs/paid-member-subscriptions/?utm_source=pms-basic-info&utm_medium=client-site&utm_campaign=pms-authorize-net-addon" target="_blank" class="pms-addon-image-container">
+ <img src="<?php echo esc_url( PMS_PLUGIN_DIR_URL ); ?>assets/images/add-on-authorize-net.png" alt="<?php esc_attr_e( 'Authorize.Net', 'paid-member-subscriptions' ); ?>" class="pms-addon-image" />
+ </a>
+
+ <p class="cozmoslabs-description"><?php esc_html_e( 'Collect credit and debit card payments for your membership plans with Authorize.Net, including recurring subscriptions and renewals.', 'paid-member-subscriptions' ); ?></p>
+ </div>
+
+ <div>
<a href="https://www.cozmoslabs.com/add-ons/pro-rate/?utm_source=pms-basic-info&utm_medium=client-site&utm_campaign=pms-pro-rate-addon" target="_blank">
<h4 class="pms-add-on-name"><?php esc_html_e( 'Pro Rate', 'paid-member-subscriptions' ); ?></h4>
</a>
--- a/paid-member-subscriptions/includes/admin/views/view-page-members-add-new-edit-subscription.php
+++ b/paid-member-subscriptions/includes/admin/views/view-page-members-add-new-edit-subscription.php
@@ -243,7 +243,7 @@
if( $member_subscription->is_auto_renewing() ){
- if( ( in_array( $member_subscription->payment_gateway, array( 'stripe_intents', 'stripe_connect', 'paypal_connect' ) ) || ( $member_subscription->payment_gateway == 'paypal_express' && !empty( $settings['gateways']['paypal']['reference_transactions'] ) ) ) )
+ if( ( in_array( $member_subscription->payment_gateway, array( 'stripe_intents', 'stripe_connect', 'paypal_connect', 'authorize_net' ) ) || ( $member_subscription->payment_gateway == 'paypal_express' && !empty( $settings['gateways']['paypal']['reference_transactions'] ) ) ) )
$hide_expiration_date = true;
elseif ( $plan->is_fixed_period_membership() && $plan->fixed_period_renewal_allowed() )
$hide_expiration_date = true;
--- a/paid-member-subscriptions/includes/admin/views/view-page-payments-add-new-edit.php
+++ b/paid-member-subscriptions/includes/admin/views/view-page-payments-add-new-edit.php
@@ -289,6 +289,18 @@
$transaction_url = 'https://dashboard.stripe.com/payments/' . $payment->transaction_id;
}
+ } else if( $payment->payment_gateway === 'authorize_net' ){
+
+ // "profile_<id>" is stored for zero-amount trial payments that only create a
+ // customer profile and have no gateway transaction record to link to.
+ if( strpos( $payment->transaction_id, 'profile_' ) !== 0 ){
+ if( $test_mode ){
+ $transaction_url = 'https://sandbox.authorize.net/ui/themes/sandbox/transaction/TransactionReceipt.aspx?transid=' . $payment->transaction_id;
+ } else {
+ $transaction_url = 'https://account.authorize.net/ui/themes/anet/Transaction/TransactionReceipt.aspx?transid=' . $payment->transaction_id;
+ }
+ }
+
}
}
--- a/paid-member-subscriptions/includes/class-ajax-checkout.php
+++ b/paid-member-subscriptions/includes/class-ajax-checkout.php
@@ -26,6 +26,7 @@
$this->supported_gateways = [
'stripe_connect',
'paypal_connect',
+ 'authorize_net',
];
// only load if the active gateways include one of the supported gateways
@@ -640,6 +641,10 @@
'subscription_plans',
'pms_default_recurring',
'discount_code',
+ 'pms_billing_first_name',
+ 'pms_billing_last_name',
+ 'pms_billing_email',
+ 'pms_billing_company',
'pms_billing_address',
'pms_billing_city',
'pms_billing_zip',
--- a/paid-member-subscriptions/includes/class-form-handler.php
+++ b/paid-member-subscriptions/includes/class-form-handler.php
@@ -491,6 +491,14 @@
}
+ // Validate if the payment gateway supports pay in installments for the selected subscription plan
+ if( $subscription_plan->has_installments() ) {
+
+ if( ! $payment_gateway->supports( 'billing_cycles' ) )
+ pms_errors()->add( 'form_general', __( 'Something went wrong. The selected payment gateway does not support paying in installments.', 'paid-member-subscriptions' ) );
+
+ }
+
// Validate fields for the payment gateway
if( method_exists( $payment_gateway , 'validate_fields' ) )
$payment_gateway->validate_fields();
@@ -794,6 +802,9 @@
if( ! in_array( $member_subscription->id, $member->get_subscription_ids() ) )
return;
+ if( $member_subscription->status !== 'active' || ! $member_subscription->is_auto_renewing() )
+ return;
+
// Remove subscription if confirm button was pressed
if( isset( $_POST['pms_confirm_cancel_subscription'] ) ) {
--- a/paid-member-subscriptions/includes/class-member-subscription.php
+++ b/paid-member-subscriptions/includes/class-member-subscription.php
@@ -346,12 +346,17 @@
if( !empty( $this->expiration_date ) && $this->expiration_date != '0000-00-00 00:00:00' && $expiration_date < time() ) {
- // Expire the subscription
- $this->update( array( 'status' => 'expired' ) );
+ // Auto-renewing guard does not apply to PayPal Standard / Express (24h adjustment + legacy expire behavior).
+ if( in_array( $this->payment_gateway, array( 'paypal_standard', 'paypal_express' ), true ) || ! $this->is_auto_renewing() ) {
- pms_add_member_subscription_log( $this->id, 'subscription_expired' );
+ // Expire the subscription
+ $this->update( array( 'status' => 'expired' ) );
- return $this->status;
+ pms_add_member_subscription_log( $this->id, 'subscription_expired_automatically' );
+
+ return $this->status;
+
+ }
}
}
--- a/paid-member-subscriptions/includes/class-plugin-scheduled-payments-scheduler.php
+++ b/paid-member-subscriptions/includes/class-plugin-scheduled-payments-scheduler.php
@@ -18,6 +18,8 @@
const TICK_HOOK = 'pms_recurring_payments_tick';
const JOB_HOOK = 'pms_process_member_subscription_renewal';
+ const ENSURE_TICK_CACHE_KEY = 'pms_recurring_payments_tick_ensure_checked';
+
/**
* @var self|null
*/
@@ -40,16 +42,17 @@
add_action( self::TICK_HOOK, array( $this, 'tick' ) );
add_action( self::JOB_HOOK, array( $this, 'run_subscription_job' ), 10, 1 );
- add_action( 'init', array( $this, 'maybe_sync_on_init' ), 20 );
+ add_action( 'init', array( $this, 'maybe_clear_legacy_cron_on_init' ), 20 );
+ add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'maybe_ensure_recurring_tick_scheduled' ) );
add_action( 'update_option_pms_misc_settings', array( $this, 'on_misc_settings_updated' ), 10, 2 );
}
/**
- * If Action Scheduler mode is on, clear stray legacy renewal cron and ensure the recurring action exists.
+ * When Action Scheduler mode is on, clear stray legacy WP-Cron renewal events.
*
* @return void
*/
- public function maybe_sync_on_init() {
+ public function maybe_clear_legacy_cron_on_init() {
if ( ! pms_is_scheduled_payments_action_scheduler_enabled() ) {
return;
@@ -58,8 +61,22 @@
if ( wp_next_scheduled( 'pms_cron_process_member_subscriptions_payments' ) ) {
wp_clear_scheduled_hook( 'pms_cron_process_member_subscriptions_payments' );
}
+ }
+
+ /**
+ * Ensure the hourly tick exists when Action Scheduler runs its daily ensure hook.
+ *
+ * @return void
+ */
+ public function maybe_ensure_recurring_tick_scheduled() {
+
+ if ( false !== wp_cache_get( self::ENSURE_TICK_CACHE_KEY, self::GROUP ) ) {
+ return;
+ }
$this->ensure_recurring_action_scheduled();
+
+ wp_cache_set( self::ENSURE_TICK_CACHE_KEY, true, self::GROUP, HOUR_IN_SECONDS );
}
/**
@@ -92,7 +109,7 @@
$interval = (int) apply_filters( 'pms_recurring_payments_tick_interval', HOUR_IN_SECONDS );
$interval = max( 60, $interval );
- as_schedule_recurring_action( time(), $interval, self::TICK_HOOK, array(), self::GROUP );
+ as_schedule_recurring_action( time(), $interval, self::TICK_HOOK, array(), self::GROUP, true );
}
/**
@@ -142,13 +159,13 @@
}
/**
- * Query due subscriptions and enqueue unique async renewal jobs.
+ * Query due subscriptions and enqueue async renewal jobs.
*
* @return void
*/
public function tick() {
- if ( ! pms_is_scheduled_payments_action_scheduler_enabled() || ! function_exists( 'as_enqueue_async_action' ) ) {
+ if ( ! pms_is_scheduled_payments_action_scheduler_enabled() || ! function_exists( 'as_enqueue_async_action' ) || ! function_exists( 'as_has_scheduled_action' ) ) {
return;
}
@@ -190,9 +207,15 @@
continue;
}
+ $job_args = array( (int) $subscription->id );
+
+ if ( as_has_scheduled_action( self::JOB_HOOK, $job_args, self::GROUP ) ) {
+ continue;
+ }
+
as_enqueue_async_action(
self::JOB_HOOK,
- array( (int) $subscription->id ),
+ $job_args,
self::GROUP,
false
);
--- a/paid-member-subscriptions/includes/features/discount-codes/index.php
+++ b/paid-member-subscriptions/includes/features/discount-codes/index.php
@@ -737,7 +737,7 @@
*/
function pms_in_dc_update_stripe_free_trial_discount_data( $subscription, $form_location ){
- if( !isset( $_POST['discount_code'] ) || empty( $subscription->subscription_plan_id ) || !in_array( $subscription->payment_gateway, [ 'stripe_connect', 'stripe_intents', 'paypal_connect' ] ) )
+ if( !isset( $_POST['discount_code'] ) || empty( $subscription->subscription_plan_id ) || !in_array( $subscription->payment_gateway, [ 'stripe_connect', 'stripe_intents', 'paypal_connect', 'authorize_net' ] ) )
return;
$code = sanitize_text_field( $_POST['discount_code'] );
--- a/paid-member-subscriptions/includes/functions-content-filtering.php
+++ b/paid-member-subscriptions/includes/functions-content-filtering.php
@@ -707,6 +707,9 @@
if( ! in_array( $member_subscription->id, $member->get_subscription_ids() ) )
return $content;
+ if( !$member_subscription->is_auto_renewing() )
+ return $content;
+
// Get subscription plan
$subscription_plan = pms_get_subscription_plan( (int)$member_subscription->subscription_plan_id );
--- a/paid-member-subscriptions/includes/functions-core.php
+++ b/paid-member-subscriptions/includes/functions-core.php
@@ -1177,6 +1177,7 @@
'stripe_intents',
'stripe_connect',
'paypal_connect',
+ 'authorize_net',
];
foreach( $gateways as $gateway ){
@@ -1643,8 +1644,8 @@
if( $current_date > strtotime( $black_friday['start_date'] ) && $current_date < strtotime( $black_friday['end_date'] ) )
return true;
-
- return false;
+
+ return apply_filters( 'pms_bf_promotion_is_active', false );
}
--- a/paid-member-subscriptions/includes/functions-member-subscriptions.php
+++ b/paid-member-subscriptions/includes/functions-member-subscriptions.php
@@ -293,6 +293,30 @@
/**
+ * Whether the member account should show the Cancel action for a subscription.
+ *
+ * @return bool
+ */
+function pms_member_subscription_should_show_cancel_action( $subscription, $subscription_plan ) {
+
+ if( empty( $subscription_plan ) || empty( $subscription_plan->id ) )
+ return false;
+
+ if( $subscription->status != 'active' || !$subscription->is_auto_renewing() )
+ return false;
+
+ if( $subscription_plan->duration == '0' && ( !$subscription_plan->is_fixed_period_membership() || $subscription_plan->fixed_expiration_date == '' ) )
+ return false;
+
+ if( $subscription_plan->price <= 0 )
+ return false;
+
+ return apply_filters( 'pms_member_subscription_should_show_cancel_action', true, $subscription, $subscription_plan );
+
+}
+
+
+/**
* Returns the metadata for a given member subscription
*
* @param int $member_subscription_id
--- a/paid-member-subscriptions/includes/functions-page.php
+++ b/paid-member-subscriptions/includes/functions-page.php
@@ -134,15 +134,21 @@
// get subscription array from the member object
$member_subscription = $member->get_subscription( (int)$plan_id );
+ if( empty( $member_subscription['id'] ) )
+ return false;
+
// get Member Subscription object
$subscription = pms_get_member_subscription( $member_subscription['id'] );
- // only active subscriptions can be canceled
- if( $subscription->status != 'active' )
+ if( ! $subscription )
+ return false;
+
+ $subscription_plan = pms_get_subscription_plan( $subscription->subscription_plan_id );
+
+ if( ! pms_member_subscription_should_show_cancel_action( $subscription, $subscription_plan ) )
return false;
- // return if subscription is recurring but HTTPS is not detected
- if( $subscription->is_auto_renewing() && !pms_is_https() )
+ if( ! pms_is_https() )
return false;
$url = wp_nonce_url( add_query_arg( array( 'pms-action' => 'cancel_subscription', 'subscription_id' => $subscription->id ), $account_page ), 'pms_member_nonce', 'pmstkn' );
--- a/paid-member-subscriptions/includes/functions-payment.php
+++ b/paid-member-subscriptions/includes/functions-payment.php
@@ -663,13 +663,14 @@
}
$subscription_data['billing_next_payment'] = $next_payment;
+ $subscription_data['expiration_date'] = '0000-00-00 00:00:00';
} else {
$subscription_data['billing_next_payment'] = null;
if ( isset( $subscription_plan->id, $subscription_plan->duration ) && $subscription_plan->duration == 0 && ! $subscription_plan->is_fixed_period_membership() ) {
- $subscription_data['expiration_date'] = '';
+ $subscription_data['expiration_date'] = '0000-00-00 00:00:00';
}
}
--- a/paid-member-subscriptions/includes/functions-plugin-scheduled-payments.php
+++ b/paid-member-subscriptions/includes/functions-plugin-scheduled-payments.php
@@ -249,7 +249,7 @@
$current_time = time();
$args = array(
'status' => array( 'active' ),
- 'payment_gateway' => array( 'stripe', 'stripe_intents', 'stripe_connect', 'paypal_connect' ),
+ 'payment_gateway' => array( 'stripe', 'stripe_intents', 'stripe_connect', 'paypal_connect', 'authorize_net' ),
'billing_next_payment_not_empty' => true,
);
--- a/paid-member-subscriptions/includes/functions-subscription-plan.php
+++ b/paid-member-subscriptions/includes/functions-subscription-plan.php
@@ -790,6 +790,10 @@
$subscription_plan_input_data_arr['recurring'] = $subscription_plan->recurring;
}
+ // Pay in installments (limit payment cycles) — used by front-end to require gateways with data-billing_cycles
+ if( $subscription_plan->has_installments() && pms_payment_gateways_support( pms_get_active_payment_gateways(), 'billing_cycles' ) ) {
+ $subscription_plan_input_data_arr['limit_payment_cycles'] = 'yes';
+ }
/**
* Filter extra input data attributes before concatenating them as a string
--- a/paid-member-subscriptions/includes/gateways/functions-payment-gateways.php
+++ b/paid-member-subscriptions/includes/gateways/functions-payment-gateways.php
@@ -39,7 +39,7 @@
'display_name_admin' => 'Stripe',
'class_name' => 'PMS_Payment_Gateway_Stripe_Connect',
'description' => __( 'Connect your existing Stripe Account or create a new one to start accepting payments.', 'paid-member-subscriptions' )
- )
+ ),
));
@@ -358,6 +358,9 @@
if( $gateway_obj->supports( 'recurring_payments' ) )
$gateway_supports_arr[$gateway_slug]['recurring'] = 1;
+ if( $gateway_obj->supports( 'billing_cycles' ) )
+ $gateway_supports_arr[$gateway_slug]['billing_cycles'] = 1;
+
}
}
--- a/paid-member-subscriptions/includes/gateways/paypal_connect/class-payment-gateway-paypal-connect.php
+++ b/paid-member-subscriptions/includes/gateways/paypal_connect/class-payment-gateway-paypal-connect.php
@@ -2060,6 +2060,38 @@
}
/**
+ * Whether PAYPAL-CERT-URL points at a PayPal notifications certificate (HTTPS, paypal.com only).
+ *
+ * @param string $cert_url Certificate URL from the webhook request.
+ * @return bool
+ */
+ private function is_allowed_paypal_webhook_cert_url( $cert_url ) {
+
+ if( empty( $cert_url ) )
+ return false;
+
+ $parts = wp_parse_url( $cert_url );
+
+ if( empty( $parts['scheme'] ) || 'https' !== strtolower( $parts['scheme'] ) )
+ return false;
+
+ if( empty( $parts['host'] ) || ! preg_match( '/(^|.)paypal.com$/i', $parts['host'] ) )
+ return false;
+
+ if( empty( $parts['path'] ) || strpos( $parts['path'], '/v1/notifications/certs/' ) !== 0 )
+ return false;
+
+ if( ! empty( $parts['user'] ) || ! empty( $parts['pass'] ) || ! empty( $parts['query'] ) || ! empty( $parts['fragment'] ) )
+ return false;
+
+ if( false === wp_http_validate_url( $cert_url ) )
+ return false;
+
+ return true;
+
+ }
+
+ /**
* Get cached certificate or download and cache it
*
* @param string $cert_url The certificate URL
@@ -2067,34 +2099,32 @@
*/
private function get_cached_cert( $cert_url ) {
- $cache_key = md5( $cert_url );
- $cache_dir = PMS_PLUGIN_DIR_PATH . '/includes/gateways/paypal_connect/cache/';
- $cache_file = $cache_dir . $cache_key;
-
- // Check if cached cert exists and is less than 24 hours old
- if( file_exists( $cache_file ) && ( time() - filemtime( $cache_file ) < ( 2 * DAY_IN_SECONDS ) ) ) {
- return file_get_contents( $cache_file );
- }
+ if( ! $this->is_allowed_paypal_webhook_cert_url( $cert_url ) )
+ return false;
+
+ $transient_key = 'pms_ppcp_webhook_cert_' . md5( $cert_url );
+ $cached_cert = get_transient( $transient_key );
+
+ if( false !== $cached_cert && is_string( $cached_cert ) && $cached_cert !== '' )
+ return $cached_cert;
- // Download certificate
- $response = wp_remote_get( $cert_url );
+ $response = wp_remote_get( $cert_url, array(
+ 'timeout' => 10,
+ 'reject_unsafe_urls' => true,
+ ) );
if( is_wp_error( $response ) )
return false;
+ if( 200 !== wp_remote_retrieve_response_code( $response ) )
+ return false;
+
$cert = wp_remote_retrieve_body( $response );
- if( empty( $cert ) )
+ if( empty( $cert ) || false === strpos( $cert, 'BEGIN CERTIFICATE' ) )
return false;
- // Create cache directory if it doesn't exist
- if( !file_exists( $cache_dir ) ) {
- if( !wp_mkdir_p( $cache_dir ) )
- return $cert; // Return cert without caching if directory creation fails
- }
-
- // Cache the certificate
- file_put_contents( $cache_file, $cert );
+ set_transient( $transient_key, $cert, 2 * DAY_IN_SECONDS );
return $cert;
--- a/paid-member-subscriptions/includes/gateways/paypal_standard/functions-paypal-standard.php
+++ b/paid-member-subscriptions/includes/gateways/paypal_standard/functions-paypal-standard.php
@@ -155,6 +155,93 @@
}
/**
+ * Whether any active recurring PayPal Standard or PayPal Express subscriptions exist.
+ *
+ * @return bool
+ */
+function pms_has_active_paypal_legacy_subscriptions() {
+
+ global $wpdb;
+
+ $subscription_id = $wpdb->get_var(
+ $wpdb->prepare(
+ "SELECT id FROM {$wpdb->prefix}pms_member_subscriptions
+ WHERE status = %s
+ AND payment_gateway IN ( 'paypal_standard', 'paypal_express' )
+ AND payment_profile_id IS NOT NULL
+ AND payment_profile_id != ''
+ LIMIT 1",
+ 'active'
+ )
+ );
+
+ return ! empty( $subscription_id );
+}
+
+/**
+ * PayPal legacy gateways need the merchant email for IPN verification.
+ *
+ * @return bool
+ */
+function pms_check_paypal_legacy_email_missing() {
+
+ if ( pms_get_paypal_email() !== false ) {
+ return false;
+ }
+
+ return pms_has_active_paypal_legacy_subscriptions();
+}
+
+/**
+ * @param array $issues Existing dashboard issues.
+ * @return array
+ */
+function pms_add_paypal_legacy_email_dashboard_issue( $issues ) {
+
+ if ( pms_check_paypal_legacy_email_missing() ) {
+ $issues['paypal_legacy_email_missing'] = true;
+ }
+
+ return $issues;
+}
+add_filter( 'pms_dashboard_issues', 'pms_add_paypal_legacy_email_dashboard_issue' );
+
+/**
+ * @param array|null $interpreted_issue Current interpretation.
+ * @param string $issue_key Issue key.
+ * @param array $issue_data Raw issue data.
+ * @return array|null
+ */
+function pms_interpret_paypal_legacy_email_dashboard_issue( $interpreted_issue, $issue_key, $issue_data ) {
+
+ if ( $issue_key !== 'paypal_legacy_email_missing' ) {
+ return $interpreted_issue;
+ }
+
+ $settings_url = admin_url( 'admin.php?page=pms-settings-page&tab=payments' );
+
+ return array(
+ 'severity' => 'critical',
+ 'title' => __( 'PayPal Email Address Missing', 'paid-member-subscriptions' ),
+ 'description' => sprintf(
+ __( 'You have active subscriptions using %1$s or %2$s, but the PayPal Email Address is not set. Add it in payment settings so Instant Payment Notifications (IPNs) from PayPal can be received and processed.', 'paid-member-subscriptions' ),
+ '<strong>' . esc_html__( 'PayPal Standard', 'paid-member-subscriptions' ) . '</strong>',
+ '<strong>' . esc_html__( 'PayPal Express', 'paid-member-subscriptions' ) . '</strong>'
+ ),
+ 'actions' => array(
+ array(
+ 'text' => __( 'Go to Payments Settings', 'paid-member-subscriptions' ),
+ 'url' => $settings_url,
+ 'type' => 'primary',
+ 'target' => '_self',
+ 'behavior' => 'url',
+ ),
+ ),
+ );
+}
+add_filter( 'pms_interpret_dashboard_issue', 'pms_interpret_paypal_legacy_email_dashboard_issue', 10, 3 );
+
+/**
* Add custom log messages for the PayPal Standard gateway
*
*/
--- a/paid-member-subscriptions/includes/gateways/stripe/admin/functions-admin-connect.php
+++ b/paid-member-subscriptions/includes/gateways/stripe/admin/functions-admin-connect.php
@@ -622,7 +622,13 @@
if( !isset( $_POST['pms_stripe_connect_webhook_secret'] ) )
return;
- if( !current_user_can( 'manage_options' ) )
+ if( ! is_admin() )
+ return;
+
+ if( ! current_user_can( 'manage_options' ) )
+ return;
+
+ if( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'pms_payments_settings-options' ) )
return;
$environment = pms_is_payment_test_mode() ? 'test' : 'live';
--- a/paid-member-subscriptions/includes/views/shortcodes/view-shortcode-account-subscription-details.php
+++ b/paid-member-subscriptions/includes/views/shortcodes/view-shortcode-account-subscription-details.php
@@ -138,10 +138,16 @@
<?php
$assets_src = esc_url( PMS_PLUGIN_DIR_PATH ) . 'assets/images/card-icons/';
- if( !empty( $payment_method_data['pms_payment_method_brand'] ) )
- echo file_get_contents( $assets_src . $payment_method_data['pms_payment_method_brand'] . '.svg' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- else if( !empty( $payment_method_data['pms_payment_method_type'] ) )
- echo file_get_contents( $assets_src . $payment_method_data['pms_payment_method_type'] . '.svg' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ if( !empty( $payment_method_data['pms_payment_method_brand'] ) ) {
+ $brand_svg = $assets_src . $payment_method_data['pms_payment_method_brand'] . '.svg';
+ if( file_exists( $brand_svg ) )
+ echo file_get_contents( $brand_svg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ } else if( !empty( $payment_method_data['pms_payment_method_type'] ) ) {
+ $type_svg = $assets_src . $payment_method_data['pms_payment_method_type'] . '.svg';
+ if( file_exists( $type_svg ) )
+ echo file_get_contents( $type_svg ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+
?>
</span>
<?php endif; ?>
@@ -249,13 +255,11 @@
}
- if( !pms_is_https() )
- $cancel_plan_button = apply_filters( 'pms_output_subscription_plan_action_cancel', '<span class="pms-account-subscription-action-link pms-account-subscription-action-link__cancel" title="'. __( 'This action is not available because your website doesn't have https enabled.', 'paid-member-subscriptions' ) .'">' . __( 'Cancel', 'paid-member-subscriptions' ) . '</span>', $subscription_plan, $subscription->to_array(), $member->user_id );
- elseif( $subscription->status == 'active' && (
- ( $subscription_plan->duration != '0' || ( $subscription_plan->is_fixed_period_membership() && $subscription_plan->fixed_expiration_date != '' ) )
- && ( $subscription_plan->price > 0 )
- ) ){
- $cancel_plan_button = apply_filters( 'pms_output_subscription_plan_action_cancel', '<a class="pms-account-subscription-action-link pms-account-subscription-action-link__cancel" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'pms-action' => 'cancel_subscription', 'subscription_id' => $subscription->id ), pms_get_current_page_url( true ) ), 'pms_member_nonce', 'pmstkn' ) ) . '" title="'. __( 'Cancels recurring payments for this subscription, letting it expire at the end of the current period.', 'paid-member-subscriptions' ) .'">' . __( 'Cancel', 'paid-member-subscriptions' ) . '</a>', $subscription_plan, $subscription->to_array(), $member->user_id );
+ if( pms_member_subscription_should_show_cancel_action( $subscription, $subscription_plan ) ) {
+ if( !pms_is_https() )
+ $cancel_plan_button = apply_filters( 'pms_output_subscription_plan_action_cancel', '<span class="pms-account-subscription-action-link pms-account-subscription-action-link__cancel" title="'. __( 'This action is not available because your website doesn't have https enabled.', 'paid-member-subscriptions' ) .'">' . __( 'Cancel', 'paid-member-subscriptions' ) . '</span>', $subscription_plan, $subscription->to_array(), $member->user_id );
+ else
+ $cancel_plan_button = apply_filters( 'pms_output_subscription_plan_action_cancel', '<a class="pms-account-subscription-action-link pms-account-subscription-action-link__cancel" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'pms-action' => 'cancel_subscription', 'subscription_id' => $subscription->id ), pms_get_current_page_url( true ) ), 'pms_member_nonce', 'pmstkn' ) ) . '" title="'. __( 'Cancels recurring payments for this subscription, letting it expire at the end of the current period.', 'paid-member-subscriptions' ) .'">' . __( 'Cancel', 'paid-member-subscriptions' ) . '</a>', $subscription_plan, $subscription->to_array(), $member->user_id );
}
}
--- a/paid-member-subscriptions/index.php
+++ b/paid-member-subscriptions/index.php
@@ -3,16 +3,16 @@
* Plugin Name: Paid Member Subscriptions
* Plugin URI: http://www.cozmoslabs.com/
* Description: Accept payments, create subscription plans and restrict content on your membership website.
- * Version: 3.0.4
+ * Version: 3.0.5
* Author: Cozmoslabs
* Author URI: http://www.cozmoslabs.com/
* Text Domain: paid-member-subscriptions
* Domain Path: /translations
* License: GPL2
* WC requires at least: 3.0.0
- * WC tested up to: 10.7
- * Elementor tested up to: 3.34
- * Elementor Pro tested up to: 3.34
+ * WC tested up to: 10.8
+ * Elementor tested up to: 4.1.1
+ * Elementor Pro tested up to: 4.1.1
*
* == Copyright ==
* Copyright 2015 Cozmoslabs (www.cozmoslabs.com)
@@ -39,7 +39,7 @@
public function __construct() {
- define( 'PMS_VERSION', '3.0.4' );
+ define( 'PMS_VERSION', '3.0.5' );
define( 'PMS_PLUGIN_DIR_PATH', plugin_dir_path( __FILE__ ) );
define( 'PMS_PLUGIN_DIR_URL', plugin_dir_url( __FILE__ ) );
define( 'PMS_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
--- a/paid-member-subscriptions/translations/paid-member-subscriptions.catalog.php
+++ b/paid-member-subscriptions/translations/paid-member-subscriptions.catalog.php
@@ -113,6 +113,7 @@
<?php __("Something went wrong. The selected payment gateway does not support free trials.", "paid-member-subscriptions"); ?>
<?php __("Something went wrong. The selected payment gateway does not support sign-up fees.", "paid-member-subscriptions"); ?>
<?php __("Something went wrong. The selected payment gateway does not support recurring payments.", "paid-member-subscriptions"); ?>
+<?php __("Something went wrong. The selected payment gateway does not support paying in installments.", "paid-member-subscriptions"); ?>
<?php __("The default currency you are using right now is not supported by PayPal. Contact the website administrator.", "paid-member-subscriptions"); ?>
<?php __("You are already a member.", "paid-member-subscriptions"); ?>
<?php __("Something went wrong. We could not cancel your subscription.", "paid-member-subscriptions"); ?>
@@ -974,6 +975,7 @@
<?php __("Subscription activated successfully.", "paid-member-subscriptions"); ?>
<?php __("Subscription activated until <strong>%s</strong>.", "paid-member-subscriptions"); ?>
<?php __("Subscription expired.", "paid-member-subscriptions"); ?>
+<?php __("Subscription expired (status check system).", "paid-member-subscriptions"); ?>
<?php __("Subscription renewed by user.", "paid-member-subscriptions"); ?>
<?php __("Subscription renewed until <strong>%s</strong>.", "paid-member-subscriptions"); ?>
<?php __("Subscription renewed automatically.", "paid-member-subscriptions"); ?>
@@ -1514,6 +1516,42 @@
<?php __("Please enter a price less than or equal to %s.", "paid-member-subscriptions"); ?>
<?php __("Please enter a price greater than or equal to %s.", "paid-member-subscriptions"); ?>
<?php __('Please enter a price between %1$s and %2$s.', 'paid-member-subscriptions' ); ?>
+<?php __("The selected gateway is not configured correctly: <strong>Authorize.Net API credentials are missing</strong>. Contact the system administrator.", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net API credentials not configured.", "paid-member-subscriptions"); ?>
+<?php __("Invalid payment ID or amount.", "paid-member-subscriptions"); ?>
+<?php __("Payment not found.", "paid-member-subscriptions"); ?>
+<?php __("No transaction ID found for this payment.", "paid-member-subscriptions"); ?>
+<?php __("Cannot refund: the original card details are not available for this subscription. Issue the refund directly from the Authorize.Net dashboard.", "paid-member-subscriptions"); ?>
+<?php __("Payment refunded successfully!", "paid-member-subscriptions"); ?>
+<?php __("Refund could not be processed.", "paid-member-subscriptions"); ?>
+<?php __("<strong>Authorize.Net:</strong> %s", "paid-member-subscriptions"); ?>
+<?php __("No response from Authorize.Net.", "paid-member-subscriptions"); ?>
+<?php __("No existing payment profile found. Please contact support.", "paid-member-subscriptions"); ?>
+<?php __("Something went wrong, please try again.", "paid-member-subscriptions"); ?>
+<?php __("Payment method updated successfully.", "paid-member-subscriptions"); ?>
+<?php __("Transaction held for review; completion will be processed when Authorize.Net sends a webhook.", "paid-member-subscriptions"); ?>
+<?php __("The card was declined.", "paid-member-subscriptions"); ?>
+<?php __("The payment gateway reported an error processing this transaction.", "paid-member-subscriptions"); ?>
+<?php __("The transaction is held for review by the payment processor.", "paid-member-subscriptions"); ?>
+<?php __("The payment could not be completed.", "paid-member-subscriptions"); ?>
+<?php __("Card payments are not available because the payment gateway is not configured. Please contact the site administrator.", "paid-member-subscriptions"); ?>
+<?php __("Card Number", "paid-member-subscriptions"); ?>
+<?php __("CVV", "paid-member-subscriptions"); ?>
+<?php __("Please enter a valid card number.", "paid-member-subscriptions"); ?>
+<?php __("Please enter a valid card expiration date.", "paid-member-subscriptions"); ?>
+<?php __("Please enter a valid card verification value.", "paid-member-subscriptions"); ?>
+<?php __("Accept.js library is not loaded. Please refresh the page and try again.", "paid-member-subscriptions"); ?>
+<?php __("An unexpected error occurred. Please try again.", "paid-member-subscriptions"); ?>
+<?php __("Collect credit and debit card payments for your membership plans with Authorize.Net, including recurring subscriptions and renewals.", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net transaction created successfully.", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net webhook received: %s", "paid-member-subscriptions"); ?>
+<?php __("Payment was refunded in the Authorize.Net Dashboard.", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net transaction is held for review; completion will be processed when the gateway sends a webhook.", "paid-member-subscriptions"); ?>
+<?php __("Subscription expired because the payment was refunded in the Authorize.Net Dashboard.", "paid-member-subscriptions"); ?>
+<?php __("Subscription activated after held transaction was approved in the Authorize.Net Dashboard.", "paid-member-subscriptions"); ?>
+<?php __("Subscription expired because the held transaction was declined in the Authorize.Net Dashboard.", "paid-member-subscriptions"); ?>
+<?php __("Payment could not be processed.", "paid-member-subscriptions"); ?>
+<?php __("The payment gateway is reporting the following error:", "paid-member-subscriptions"); ?>
<?php __("API Key successfully validated!", "paid-member-subscriptions"); ?>
<?php __("List ID successfully validated!", "paid-member-subscriptions"); ?>
<?php __("No users selected.", "paid-member-subscriptions"); ?>
@@ -1746,7 +1784,6 @@
<?php __("You are not allowed to do this.", "paid-member-subscriptions"); ?>
<?php __("Member invitation removed succesfully!", "paid-member-subscriptions"); ?>
<?php __("Member removed successfully!", "paid-member-subscriptions"); ?>
-<?php __("Something went wrong, please try again.", "paid-member-subscriptions"); ?>
<?php __("Invitation sent successfully!", "paid-member-subscriptions"); ?>
<?php __("Invalid subscription.", "paid-member-subscriptions"); ?>
<?php __("Invalid subscription type.", "paid-member-subscriptions"); ?>
@@ -1897,15 +1934,10 @@
<?php __("The selected gateway is not configured correctly: <strong>PayPal Address is missing</strong>. Contact the system administrator.", "paid-member-subscriptions"); ?>
<?php __("The selected gateway is not configured correctly: <strong>PayPal API credentials are missing</strong>. Contact the system administrator.", "paid-member-subscriptions"); ?>
<?php __("PayPal API credentials not configured.", "paid-member-subscriptions"); ?>
-<?php __("Invalid payment ID or amount.", "paid-member-subscriptions"); ?>
-<?php __("Payment not found.", "paid-member-subscriptions"); ?>
-<?php __("No transaction ID found for this payment.", "paid-member-subscriptions"); ?>
<?php __("PayPal API request failed: %s", "paid-member-subscriptions"); ?>
<?php __("PayPal API returned error code: %s", "paid-member-subscriptions"); ?>
<?php __("PayPal refund was not successful!", "paid-member-subscriptions"); ?>
-<?php __("Payment refunded successfully!", "paid-member-subscriptions"); ?>
<?php __("Credit Card Information", "paid-member-subscriptions"); ?>
-<?php __("Card Number", "paid-member-subscriptions"); ?>
<?php __("Card CVV", "paid-member-subscriptions"); ?>
<?php __("Please enter a Billing First Name.", "paid-member-subscriptions"); ?>
<?php __("Please enter a Billing Last Name.", "paid-member-subscriptions"); ?>
@@ -1914,9 +1946,6 @@
<?php __("Please enter a Billing State.", "paid-member-subscriptions"); ?>
<?php __("Please enter a Billing Country.", "paid-member-subscriptions"); ?>
<?php __("Please enter a Billing ZIP code.", "paid-member-subscriptions"); ?>
-<?php __("Please enter a valid card number.", "paid-member-subscriptions"); ?>
-<?php __("Please enter a valid card verification value.", "paid-member-subscriptions"); ?>
-<?php __("Please enter a valid card expiration date.", "paid-member-subscriptions"); ?>
<?php __("Payments using credit cards or customer accounts handled by PayPal (deprecated).", "paid-member-subscriptions"); ?>
<?php __("Payments using credit cards directly on your website through PayPal API. .", "paid-member-subscriptions"); ?>
<?php __("PayPal Recurring Initial Payment", "paid-member-subscriptions"); ?>
@@ -1934,7 +1963,6 @@
<?php __("Received Transaction ID from PayPal.", "paid-member-subscriptions"); ?>
<?php __("User did not accept the <strong>Billing Agreement</strong> on the <strong>PayPal Checkout</strong>.", "paid-member-subscriptions"); ?>
<?php __("Attempting to charge user based on the <strong>PayPal Checkout</strong>.", "paid-member-subscriptions"); ?>
-<?php __("The payment gateway is reporting the following error:", "paid-member-subscriptions"); ?>
<?php __("Payment Gateway Message", "paid-member-subscriptions"); ?>
<?php __("Error code:", "paid-member-subscriptions"); ?>
<?php __("Message:", "paid-member-subscriptions"); ?>
@@ -1967,7 +1995,6 @@
<?php __("3D Secure authentication has failed.", "paid-member-subscriptions"); ?>
<?php __("The user did not click on the confirmation link that was sent.", "paid-member-subscriptions"); ?>
<?php __("User returned to the website for authentication.", "paid-member-subscriptions"); ?>
-<?php __("Payment method updated successfully.", "paid-member-subscriptions"); ?>
<?php __("The selected gateway is not configured correctly: <strong>API credentials are missing</strong>. Contact the system administrator.", "paid-member-subscriptions"); ?>
<?php __('Your Stripe API settings are missing. In order to make payments you will need to add your API credentials %1$s here %2$s.', 'paid-member-subscriptions' ); ?>
<?php __("Payments using credit cards directly on your website through Stripe API.", "paid-member-subscriptions"); ?>
@@ -2160,6 +2187,7 @@
<?php __("Old Stripe implementation not available for new users.", "paid-member-subscriptions"); ?>
<?php __("Tax & EU VAT", "paid-member-subscriptions"); ?>
<?php __("Helps you collect tax or vat from your users depending on their location, with full control over tax rates and who to charge.", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net", "paid-member-subscriptions"); ?>
<?php __("Integrate Mailchimp to keep your membership audience up to date. Automatically add or update subscribers, enable Double Opt-In, and sync custom fields between Mailchimp and member profiles.", "paid-member-subscriptions"); ?>
<?php __("Sync your members with Brevo to manage contacts smoothly. Automate newsletter subscriptions, use Double Opt-In for compliance, and link custom fields between Brevo and your member data.", "paid-member-subscriptions"); ?>
<?php __("Recommended Plugins", "paid-member-subscriptions"); ?>
@@ -2612,6 +2640,9 @@
<?php __("Use the following URL for the IPN:", "paid-member-subscriptions"); ?>
<?php __("In order for <strong>PayPal payments to work correctly</strong>, you need to setup the IPN Url in your PayPal account. %s", "paid-member-subscriptions"); ?>
<?php __('Your <strong>PayPal Email Address</strong> is missing. In order to make payments you will need to add the Email Address of your PayPal account %1$s here %2$s.', 'paid-member-subscriptions' ); ?>
+<?php __("PayPal Email Address Missing", "paid-member-subscriptions"); ?>
+<?php __('You have active subscriptions using %1$s or %2$s, but the PayPal Email Address is not set. Add it in payment settings so Instant Payment Notifications (IPNs) from PayPal can be received and processed.', 'paid-member-subscriptions' ); ?>
+<?php __("PayPal Express", "paid-member-subscriptions"); ?>
<?php __("User sent to <strong>PayPal Checkout</strong> to continue the payment process.", "paid-member-subscriptions"); ?>
<?php __("Waiting to receive Instant Payment Notification (IPN) from <strong>PayPal</strong>.", "paid-member-subscriptions"); ?>
<?php __("Instant Payment Notification (IPN) received from PayPal.", "paid-member-subscriptions"); ?>
@@ -2632,7 +2663,6 @@
<?php __("Subscription expired because the payment was refunded in the Stripe Dashboard.", "paid-member-subscriptions"); ?>
<?php __("User attemped to setup a payment method for this subscription but failed. Reason: %s", "paid-member-subscriptions"); ?>
<?php __("Card - One Time", "paid-member-subscriptions"); ?>
-<?php __("Payment could not be processed.", "paid-member-subscriptions"); ?>
<?php __("Please %slog in%s and try again.", "paid-member-subscriptions"); ?>
<?php __("The card does not support this type of purchase.", "paid-member-subscriptions"); ?>
<?php __("The customer has exceeded the balance or credit limit available on their card.", "paid-member-subscriptions"); ?>
@@ -2749,6 +2779,29 @@
<?php __("Set the Expiration Date. A subsequent date change will only affect new users.", "paid-member-subscriptions"); ?>
<?php __("Allow plan to be renewed", "paid-member-subscriptions"); ?>
<?php __("Allow fixed period plan to be renewed each year.", "paid-member-subscriptions"); ?>
+<?php __("API Login ID", "paid-member-subscriptions"); ?>
+<?php __("Enter your API Login ID. You can find it in your Authorize.Net Merchant Interface under Account > Settings > Security Settings > API Credentials & Keys.", "paid-member-subscriptions"); ?>
+<?php __("Transaction Key", "paid-member-subscriptions"); ?>
+<?php __("Enter your Transaction Key. You can find it in your Authorize.Net Merchant Interface under Account > Settings > Security Settings > API Credentials & Keys.", "paid-member-subscriptions"); ?>
+<?php __("Signature Key", "paid-member-subscriptions"); ?>
+<?php __("<strong>Required for webhooks.</strong> Enter your Signature Key. Generate it in your Authorize.Net Merchant Interface under Account > Settings > Security Settings > API Credentials & Keys. Without it, incoming webhook requests cannot be verified and are rejected.", "paid-member-subscriptions"); ?>
+<?php __("Connection Status", "paid-member-subscriptions"); ?>
+<?php __("Not verified", "paid-member-subscriptions"); ?>
+<?php __("Save your settings to verify the connection and fetch the Public Client Key automatically.", "paid-member-subscriptions"); ?>
+<?php __("Connected", "paid-member-subscriptions"); ?>
+<?php __("Your account is connected in %s mode.", "paid-member-subscriptions"); ?>
+<?php __("Webhooks Status", "paid-member-subscriptions"); ?>
+<?php __("Webhooks are connected successfully. Last webhook received at: %s", "paid-member-subscriptions"); ?>
+<?php __("Unknown", "paid-member-subscriptions"); ?>
+<?php __("Webhooks were connected successfully, but the last webhook received was more than 14 days ago. You should verify that the webhook URL still exists in your Authorize.Net account.", "paid-member-subscriptions"); ?>
+<?php __("Waiting for data", "paid-member-subscriptions"); ?>
+<?php __("When the status changes to Connected, the website has started processing webhook data from Authorize.Net.", "paid-member-subscriptions"); ?>
+<?php __("Webhooks URL", "paid-member-subscriptions"); ?>
+<?php __("Copy this URL and configure it in your Authorize.Net Merchant Interface under Account > Settings > Webhooks. Select the following events: <strong>payment.authcapture.created</strong>, <strong>payment.refund.created</strong>, <strong>payment.fraud.approved</strong>, <strong>payment.fraud.declined</strong>, <strong>payment.fraud.held</strong>.", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net Customer Profile ID", "paid-member-subscriptions"); ?>
+<?php __("Authorize.Net Payment Profile ID", "paid-member-subscriptions"); ?>
+<?php __("The Authorize.Net Customer Profile ID must be numeric.", "paid-member-subscriptions"); ?>
+<?php __("The Authorize.Net Payment Profile ID must be numeric.", "paid-member-subscriptions"); ?>
<?php __("Select the subscription plan for which this content dripping set should apply.", "paid-member-subscriptions"); ?>
<?php __("Select content dripping set status.", "paid-member-subscriptions"); ?>
<?php __("Authentication", "paid-member-subscriptions"); ?>
@@ -3165,7 +3218,6 @@
<?php __("Download this sample discount codes files", "paid-member-subscriptions"); ?>
<?php __(" and modify it by adding your own discounts.", "paid-member-subscriptions"); ?>
<?php __(" PayPal", "paid-member-subscriptions"); ?>
-<?php __("Connection Status", "paid-member-subscriptions"); ?>
<?php __("Success", "paid-member-subscriptions"); ?>
<?php __("Your account is connected successfully in %s mode.", "paid-member-subscriptions"); ?>
<?php __("Connected Account", "paid-member-subscriptions"); ?>
@@ -3185,12 +3237,7 @@
<?php __("Vaulting", "paid-member-subscriptions"); ?>
<?php __("You are not able to offer the Vaulting functionality because its onboarding status is %s.", "paid-member-subscriptions"); ?>
<?php __(" Please reach out to %s for more information.", "paid-member-subscriptions"); ?>
-<?php __("Webhooks Status", "paid-member-subscriptions"); ?>
-<?php __("Connected", "paid-member-subscriptions"); ?>
-<?php __("Webhooks are connected successfully. Last webhook received at: %s", "paid-member-subscriptions"); ?>
-<?php __("Unknown", "paid-member-subscriptions"); ?>
<?php __("Webhooks were connected successfully, but the last webhook received was more than 14 days ago. You should verify that the webhook URL still exists in your PayPal Account.", "paid-member-subscriptions"); ?>
-<?php __("Waiting for data", "paid-member-subscriptions"); ?>
<?php __("When the status changes to Connected, the website has started processing webhook data from PayPal.", "paid-member-subscriptions"); ?>
<?php __("Disconnect", "paid-member-subscriptions"); ?>
<?php __("Disconnecting your account will stop all payments from being processed.", "paid-member-subscriptions"); ?>
@@ -3220,7 +3267,6 @@
<?php __("Please reload the page and connect your account again in order to receive payments.", "paid-member-subscriptions"); ?>
<?php __("Webhooks were connected successfully, but the last webhook received was more than 14 days ago. You should verify that the webhook URL still exists in your Stripe Account.", "paid-member-subscriptions"); ?>
<?php __("When the status changes to Connected, the website has started processing webhook data from Stripe.", "paid-member-subscriptions"); ?>
-<?php __("Webhooks URL", "paid-member-subscriptions"); ?>
<?php __("Copy this URL and configure it in your Stripe Account. After setting up the webhook endpoint, you can also copy the %sWebhook Signing Secret%s from Stripe and paste it in the field below for enhanced security. %sClick here%s to learn more about the Webhooks setup process. ", "paid-member-subscriptions"); ?>
<?php __("Webhook Signing Secret", "paid-member-subscriptions"); ?>
<?php __("whsec_...", "paid-member-subscriptions"); ?>