PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260917
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260917
260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 All 189 releases
← All changes | src/includes/classes/utils-users.inc.php +138 -91 260805260917 View file →
@@ -189,8 +189,9 @@
189 189 // Do not guess term values in fallback vars (risk of incorrect EOT decisions).
190 190 if (!empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['ipn_signup_vars_fallback'])) {
191 191 $userdata = get_userdata((int)$user_id);
192 192 $ipn_signup_vars = array(
193 + 's2member_ipn_signup_vars_fallback' => '1', //260829.1709 Mark generated fallback vars explicitly so gateway-aware EOT logic can distinguish missing local signup metadata from malformed stored signup data.
193 194 'subscr_cid' => !empty($_subscr_cid) ? $_subscr_cid : '',
194 195 'subscr_id' => $_subscr_id,
195 196 'custom' => esc_html($_SERVER["HTTP_HOST"]),
196 197 'period1' => '',
@@ -438,9 +439,9 @@
438 439 * - `debug` A string of details that explain to a developer what was returned. For debugging only.
439 440 */
440 441 public static function get_user_eot($user_id = 0, $check_gateway = TRUE, $favor = 'fixed')
441 442 {
442 - if(!($user_id = (integer)$user_id)) // Empty user ID in this call?
443 + if(!($user_id = (int)$user_id)) // Empty user ID in this call?
443 444 $user_id = get_current_user_id(); // Assume current user.
444 445
445 446 if(!$favor || !in_array($favor, array('fixed', 'next'), TRUE))
446 447 $favor = 'fixed'; // Default behavior.
@@ -445,10 +446,10 @@
445 446 if(!$favor || !in_array($favor, array('fixed', 'next'), TRUE))
446 447 $favor = 'fixed'; // Default behavior.
447 448
448 449 $now = time(); // Current timestamp.
449 - $grace_time = (integer)$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_grace_time'];
450 - $grace_time = (integer)apply_filters('ws_plugin__s2member_eot_grace_time', $grace_time);
450 + $grace_time = (int)$GLOBALS['WS_PLUGIN__']['s2member']['o']['eot_grace_time'];
451 + $grace_time = (int)apply_filters('ws_plugin__s2member_eot_grace_time', $grace_time);
451 452 $demotion_role = c_ws_plugin__s2member_option_forces::force_demotion_role('subscriber');
452 453 $empty_response = array('type' => '', 'time' => 0, 'tense' => '', 'debug' => '');
453 454
454 455 if(!$user_id || !($user = new WP_User($user_id)) || !$user->ID)
@@ -457,10 +458,10 @@
457 458 $ipn_signup_vars = self::get_user_ipn_signup_vars($user->ID);
458 459 $subscr_gateway = (string)get_user_option('s2member_subscr_gateway', $user->ID);
459 460 $subscr_id = (string)get_user_option('s2member_subscr_id', $user->ID);
460 461 $subscr_cid = (string)get_user_option('s2member_subscr_cid', $user->ID);
461 - $last_auto_eot_time = (integer)get_user_option('s2member_last_auto_eot_time', $user->ID);
462 - $auto_eot_time = (integer)get_user_option('s2member_auto_eot_time', $user->ID);
462 + $last_auto_eot_time = (int)get_user_option('s2member_last_auto_eot_time', $user->ID);
463 + $auto_eot_time = (int)get_user_option('s2member_auto_eot_time', $user->ID);
463 464
464 465 if($auto_eot_time) // They have a hard-coded EOT time at present?
465 466 return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
466 467 'debug' => 'This is a fixed EOT time recorded by s2Member. It can be altered in the WordPress Dashboard for this user.');
@@ -465,127 +466,173 @@
465 466 return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
466 467 'debug' => 'This is a fixed EOT time recorded by s2Member. It can be altered in the WordPress Dashboard for this user.');
467 468
468 469 if(!$subscr_gateway && !$subscr_id && !$subscr_cid && $last_auto_eot_time // EOTd?
469 - && (!user_can($user->ID, 'access_s2member_level1') || c_ws_plugin__s2member_user_access::user_access_role($user) === $demotion_role)
470 + //260916.1840 A preserved unrelated role may sort before the destination role, so inspect all assigned roles instead of only s2Member's historical first-role result.
471 + && (!user_can($user->ID, 'access_s2member_level1') || in_array($demotion_role, (array)$user->roles, TRUE))
470 472 && !c_ws_plugin__s2member_user_access::user_access_ccaps($user) // And no CCAPs either?
471 473 ) return array('type' => 'fixed', 'time' => $last_auto_eot_time, 'tense' => $last_auto_eot_time <= $now ? 'past' : 'future',
472 - 'debug' => 'This is an archived/fixed EOT time recorded by s2Member; i.e., the date this customer\'s access expired.');
474 + 'debug' => 'This is an archived/fixed EOT time recorded by s2Member; i.e., the date this customer\'s membership EOT was processed.');
473 475
474 476 if(!$subscr_gateway || !$subscr_id || !is_array($ipn_signup_vars) || !$ipn_signup_vars)
475 477 return array_merge($empty_response, array('debug' => 'This user has no subscription; i.e., missing `subscr_id`, `subscr_gateway` or `ipn_signup_vars`.'));
476 478
477 - if(empty($ipn_signup_vars['txn_type']) || $ipn_signup_vars['txn_type'] !== 'subscr_signup')
479 + $ipn_signup_vars_fallback = !empty($ipn_signup_vars['s2member_ipn_signup_vars_fallback']);
480 + //260829.1709 A PayPal fallback still has a bound local subscription ID, so allow the configured PayPal APIs to recover authoritative timing before rejecting it for missing legacy signup metadata.
481 + $can_recover_paypal_fallback = ($check_gateway && $subscr_gateway === 'paypal' && $ipn_signup_vars_fallback);
482 +
483 + if((empty($ipn_signup_vars['txn_type']) || $ipn_signup_vars['txn_type'] !== 'subscr_signup') && !$can_recover_paypal_fallback)
478 484 return array_merge($empty_response, array('debug' => 'This user has no subscription; i.e., `txn_type` != `subscr_signup`.'));
479 485
480 - $auto_eot_time // Update this now; i.e., build a new EOT time based on IPN signup vars.
481 - = c_ws_plugin__s2member_utils_time::auto_eot_time($user->ID, $ipn_signup_vars['period1'], $ipn_signup_vars['period3']);
486 + //260829.1709 Never turn deliberately blank fallback billing terms into an estimated EOT of "now"; PayPal API recovery below must succeed or the existing empty/fallback behavior remains.
487 + $auto_eot_time = ($ipn_signup_vars_fallback && empty($ipn_signup_vars['period3']))
488 + ? 0
489 + : c_ws_plugin__s2member_utils_time::auto_eot_time($user->ID, $ipn_signup_vars['period1'], $ipn_signup_vars['period3']);
482 490
491 + //260828.0710 !!! TO-DO: Track a gateway-independent `s2member_access_through_time`, meaning the end of the latest confirmed entitlement period, before EOT grace.
492 + // 1. On signup/received payment, save the provider's then-current next billing/period-end time as access-through. Failed payments never advance it. 2. Cancellation/EOT should use this value when available, even if already past.
493 + // 3. For older users without it, estimate conservatively from provider billing schedule + signup vars/last successful payment when reliable; otherwise keep the existing estimated EOT fallback.
483 494 if($check_gateway) switch($subscr_gateway) // A bit different for each payment gateway.
484 495 {
485 496 case 'paypal': // PayPal (legacy Pro NVP/Payflow + PayPal Checkout REST).
486 497
487 - //260213 PayPal Checkout subscriptions: use REST Subscriptions API for reconciliation (NVP GetRecurringPaymentsProfileDetails returns 11592).
488 - if(!empty($ipn_signup_vars['s2member_paypal_proxy_use']) && $ipn_signup_vars['s2member_paypal_proxy_use'] === 'paypal_checkout')
498 + $ppco_creds = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_creds();
499 + $can_try_ppco = (!empty($ppco_creds['client_id']) && !empty($ppco_creds['secret']));
500 + $can_try_standard = (!empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_username'])
501 + && !empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_password'])
502 + && !empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_signature']));
503 + $can_try_payflow = (c_ws_plugin__s2member_utils_conds::pro_is_installed()
504 + && class_exists('c_ws_plugin__s2member_pro_paypal_utilities')
505 + && !empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_payflow_api_username']));
506 +
507 + //260819.0543 Prefer positive product provenance, then fall through to other configured PayPal APIs when lookup fails.
508 + // Classic Recurring Payments and REST Subscriptions can both use I-* IDs; Payflow profile IDs use RP/RT prefixes.
509 + $ppco_hint = ((!empty($ipn_signup_vars['s2member_paypal_proxy_use']) && $ipn_signup_vars['s2member_paypal_proxy_use'] === 'paypal_checkout')
510 + || (!empty($ipn_signup_vars['invoice']) && strpos((string)$ipn_signup_vars['invoice'], 's2mpf-') === 0));
511 + $payflow_hint = (bool)preg_match('/^R[PT]/i', $subscr_id);
512 + if($ppco_hint)
513 + $paypal_routes = array('ppco', 'standard', 'payflow');
514 + else if($payflow_hint)
515 + $paypal_routes = array('payflow', 'standard', 'ppco');
516 + else
517 + $paypal_routes = array('standard', 'ppco', 'payflow');
518 +
519 + foreach($paypal_routes as $_paypal_route)
489 520 {
490 - $ppco_enabled = !empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_checkout_enable']) && (string)$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_checkout_enable'] !== '0';
521 + switch($_paypal_route)
522 + {
523 + case 'ppco':
524 + if(!$can_try_ppco)
525 + break;
491 526
492 - $ppco_creds = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_creds();
527 + $subscription = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_subscription_details($subscr_id);
528 + if(!$subscription || !empty($subscription['__error']))
529 + break; // Try another configured PayPal API family.
493 530
494 - if(!$ppco_enabled || empty($ppco_creds['client_id']) || empty($ppco_creds['secret']))
495 - return array_merge($empty_response, array(
496 - 'debug' => 'PayPal Checkout subscription reconciliation skipped (disabled or missing REST API credentials).',
497 - ));
531 + $status = !empty($subscription['status']) ? strtoupper((string)$subscription['status']) : '';
532 + $next = !empty($subscription['billing_info']['next_billing_time']) ? (string)$subscription['billing_info']['next_billing_time'] : '';
498 533
499 - $subscription_r = c_ws_plugin__s2member_paypal_utilities::paypal_checkout_api_request('GET', '/v1/billing/subscriptions/'.rawurlencode($subscr_id));
534 + if($status && $status !== 'ACTIVE')
535 + {
536 + if($auto_eot_time)
537 + return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
538 + 'debug' => 'This is the estimated EOT time. PayPal Checkout says this subscription is no longer active, and thus, access should be terminated at this time.');
500 539
501 - $subscription_code = !empty($subscription_r['code']) ? (int)$subscription_r['code'] : 0;
502 - $subscription_body = !empty($subscription_r['body']) ? (string)$subscription_r['body'] : '';
540 + return array_merge($empty_response, array('debug' => 'PayPal Checkout says this subscription is no longer active, but local signup billing terms are unavailable; refusing to guess an EOT.'));
541 + }
503 542
504 - $subscription = array();
505 - if($subscription_body)
506 - $subscription = json_decode($subscription_body, true);
543 + if($next && ($time = strtotime($next)) > $now)
544 + return array('type' => 'next', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
545 + 'debug' => 'PayPal Checkout says this is the next payment time.');
507 546
508 - if(!is_array($subscription))
509 - $subscription = array();
547 + return array_merge($empty_response, array(
548 + 'debug' => 'PayPal Checkout says this subscription is active; no next billing time was returned.',
549 + ));
510 550
511 - if(!($subscription_code >= 200 && $subscription_code <= 299 && !empty($subscription['id'])))
512 - return array_merge($empty_response, array(
513 - 'debug' => 'PayPal Checkout subscription reconciliation failed (REST subscription lookup unsuccessful); skipping legacy PayPal status checks.',
514 - ));
551 + case 'payflow':
552 + if(!$can_try_payflow)
553 + break;
515 554
516 - $status = !empty($subscription['status']) ? strtoupper((string)$subscription['status']) : '';
517 - $next = !empty($subscription['billing_info']['next_billing_time']) ? (string)$subscription['billing_info']['next_billing_time'] : '';
555 + if(!($api_response = c_ws_plugin__s2member_pro_paypal_utilities::payflow_get_profile($subscr_id)) || !empty($api_response['__error']))
556 + break; // Try another configured PayPal API family.
518 557
519 - if($status && $status !== 'ACTIVE')
520 - return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
521 - 'debug' => 'This is the estimated EOT time. PayPal Checkout says this subscription is no longer active, and thus, access should be terminated at this time.');
558 + if(preg_match('/^(?:Pending|PendingProfile)$/i', $api_response['STATUS']))
559 + return array_merge($empty_response, array('debug' => 'No fixed EOT, and the PayPal Pro API says the subscription for this user is currently pending changes. Unable to determine at this moment. Please try again in 15 minutes.'));
522 560
523 - if($next && ($time = strtotime($next)) > $now)
524 - return array('type' => 'next', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
525 - 'debug' => 'PayPal Checkout says this is the next payment time.');
561 + if(!preg_match('/^(?:Active|ActiveProfile)$/i', $api_response['STATUS']))
562 + {
563 + if($auto_eot_time)
564 + return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
565 + 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription is no longer active, and thus, access should be terminated at this time.');
526 566
527 - return array_merge($empty_response, array(
528 - 'debug' => 'PayPal Checkout says this subscription is active; no next billing time was returned.',
529 - ));
530 - }
567 + return array_merge($empty_response, array('debug' => 'The PayPal Pro API says this subscription is no longer active, but local signup billing terms are unavailable; refusing to guess an EOT.'));
568 + }
531 569
532 - if(!c_ws_plugin__s2member_utils_conds::pro_is_installed()
533 - || !class_exists('c_ws_plugin__s2member_pro_paypal_utilities')
534 - || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_username']
535 - || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_password']
536 - || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_signature']
537 - ) return array_merge($empty_response, array('debug' => 'PayPal Pro API credentials missing in your s2Member configuration.'));
570 + if($api_response['TERM'] > 0 && $api_response['PAYMENTSLEFT'] <= 0)
571 + {
572 + if($auto_eot_time)
573 + return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
574 + 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription has reached its last payment, and thus, access should be terminated at this time.');
538 575
539 - if($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_payflow_api_username'])
540 - {
541 - if(!($api_response = c_ws_plugin__s2member_pro_paypal_utilities::payflow_get_profile($subscr_id)) || !empty($api_response['__error']))
542 - return array_merge($empty_response, array('debug' => 'No fixed EOT, and the PayPal Pro API says there is no subscription for this user.'));
576 + return array_merge($empty_response, array('debug' => 'The PayPal Pro API says this subscription has reached its last payment, but local signup billing terms are unavailable; refusing to guess an EOT.'));
577 + }
543 578
544 - if(preg_match('/^(?:Pending|PendingProfile)$/i', $api_response['STATUS']))
545 - return array_merge($empty_response, array('debug' => 'No fixed EOT, and the PayPal Pro API says the subscription for this user is currently pending changes. Unable to determine at this moment. Please try again in 15 minutes.'));
579 + if($api_response['TERM'] <= 0 || $api_response['PAYMENTSLEFT'] > 0)
580 + if($api_response['NEXTPAYMENT'] && strlen($api_response['NEXTPAYMENT']) === 8) // MMDDYYYY format is not `strtotime()` compatible.
581 + if(($time = strtotime(substr($api_response['NEXTPAYMENT'], -4).'-'.substr($api_response['NEXTPAYMENT'], 0, 2).'-'.substr($api_response['NEXTPAYMENT'], 2, 2))) > $now)
582 + return array('type' => 'next', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
583 + 'debug' => 'The PayPal Pro API says this is the next payment time.');
546 584
547 - if(!preg_match('/^(?:Active|ActiveProfile)$/i', $api_response['STATUS']))
548 - return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
549 - 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription is no longer active, and thus, access should be terminated at this time.');
585 + return array_merge($empty_response, array('debug' => 'No fixed EOT, and there are no more payments needed from this user.'));
550 586
551 - if($api_response['TERM'] > 0 && $api_response['PAYMENTSLEFT'] <= 0)
552 - return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
553 - 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription has reached its last payment, and thus, access should be terminated at this time.');
587 + case 'standard':
588 + if(!$can_try_standard)
589 + break;
554 590
555 - if($api_response['TERM'] <= 0 || $api_response['PAYMENTSLEFT'] > 0)
556 - if($api_response['NEXTPAYMENT'] && strlen($api_response['NEXTPAYMENT']) === 8) // MMDDYYYY format is not `strtotime()` compatible.
557 - if(($time = strtotime(substr($api_response['NEXTPAYMENT'], -4).'-'.substr($api_response['NEXTPAYMENT'], 0, 2).'-'.substr($api_response['NEXTPAYMENT'], 2, 2))) > $now)
558 - return array('type' => 'next', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
559 - 'debug' => 'The PayPal Pro API says this is the next payment time.');
560 - }
561 - else // Use PayPal Pro API (old flavor).
562 - {
563 - $api_args = array(
564 - 'METHOD' => 'GetRecurringPaymentsProfileDetails',
565 - 'PROFILEID' => $subscr_id,
566 - );
567 - if(!($api_response = c_ws_plugin__s2member_paypal_utilities::paypal_api_response($api_args)) || !empty($api_response['__error']))
568 - return array_merge($empty_response, array('debug' => 'No fixed EOT, and the PayPal Pro API says there is no subscription for this user.'));
591 + $api_args = array(
592 + 'METHOD' => 'GetRecurringPaymentsProfileDetails',
593 + 'PROFILEID' => $subscr_id,
594 + );
595 + if(!($api_response = c_ws_plugin__s2member_paypal_utilities::paypal_api_response($api_args)) || !empty($api_response['__error']))
596 + break; // 11592 and other profile-family misses may resolve through REST.
569 597
570 - if(preg_match('/^(?:Pending|PendingProfile)$/i', $api_response['STATUS']))
571 - return array_merge($empty_response, array('debug' => 'No fixed EOT, and the PayPal Pro API says the subscription for this user is currently pending changes. Unable to determine at this moment. Please try again in 15 minutes.'));
598 + if(preg_match('/^(?:Pending|PendingProfile)$/i', $api_response['STATUS']))
599 + return array_merge($empty_response, array('debug' => 'No fixed EOT, and the PayPal Pro API says the subscription for this user is currently pending changes. Unable to determine at this moment. Please try again in 15 minutes.'));
572 600
573 - if(!preg_match('/^(?:Active|ActiveProfile)$/i', $api_response['STATUS']))
574 - return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
575 - 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription is no longer active, and thus, access should be terminated at this time.');
601 + if(!preg_match('/^(?:Active|ActiveProfile)$/i', $api_response['STATUS']))
602 + {
603 + if($auto_eot_time)
604 + return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
605 + 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription is no longer active, and thus, access should be terminated at this time.');
576 606
577 - if($api_response['TOTALBILLINGCYCLES'] > 0 && $api_response['NUMCYCLESREMAINING'] <= 0)
578 - return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
579 - 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription has reached its last payment, and thus, access should be terminated at this time.');
607 + return array_merge($empty_response, array('debug' => 'The PayPal Pro API says this subscription is no longer active, but local signup billing terms are unavailable; refusing to guess an EOT.'));
608 + }
580 609
581 - if($api_response['TOTALBILLINGCYCLES'] <= 0 || $api_response['NUMCYCLESREMAINING'] > 0)
582 - if($api_response['NEXTBILLINGDATE'] && ($time = strtotime($api_response['NEXTBILLINGDATE'])) > $now)
583 - return array('type' => 'next', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
584 - 'debug' => 'The PayPal Pro API says this is the next payment time.');
585 - }
586 - return array_merge($empty_response, array('debug' => 'No fixed EOT, and there are no more payments needed from this user.'));
610 + if($api_response['TOTALBILLINGCYCLES'] > 0 && $api_response['NUMCYCLESREMAINING'] <= 0)
611 + {
612 + if($auto_eot_time)
613 + return array('type' => 'fixed', 'time' => $auto_eot_time, 'tense' => $auto_eot_time <= $now ? 'past' : 'future',
614 + 'debug' => 'This is the estimated EOT time. The PayPal Pro API says this subscription has reached its last payment, and thus, access should be terminated at this time.');
587 615
616 + return array_merge($empty_response, array('debug' => 'The PayPal Pro API says this subscription has reached its last payment, but local signup billing terms are unavailable; refusing to guess an EOT.'));
617 + }
618 +
619 + if($api_response['TOTALBILLINGCYCLES'] <= 0 || $api_response['NUMCYCLESREMAINING'] > 0)
620 + if($api_response['NEXTBILLINGDATE'] && ($time = strtotime($api_response['NEXTBILLINGDATE'])) > $now)
621 + return array('type' => 'next', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
622 + 'debug' => 'The PayPal Pro API says this is the next payment time.');
623 +
624 + return array_merge($empty_response, array('debug' => 'No fixed EOT, and there are no more payments needed from this user.'));
625 + }
626 + }
627 +
628 + if(!$can_try_ppco && !$can_try_standard && !$can_try_payflow)
629 + return array_merge($empty_response, array('debug' => 'PayPal subscription API credentials missing in your s2Member configuration.'));
630 +
631 + return array_merge($empty_response, array(
632 + 'debug' => 'No fixed EOT, and no configured PayPal API could resolve this subscription. Older recurring profiles may still require legacy PayPal API credentials.',
633 + ));
634 +
588 635 break; // Break switch.
589 636
590 637 case 'authnet': // Authorize.Net (EOT only; w/ limited functionality).
591 638
@@ -624,9 +671,9 @@
624 671
625 672 if(!is_object($stripe_subscription = c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription($subscr_cid, $subscr_id)) || empty($stripe_subscription->id))
626 673 return array_merge($empty_response, array('debug' => 'No fixed EOT, and the Stripe API says there is no subscription for this user.'));
627 674
628 - if((integer)$stripe_subscription->ended_at > 0) // Done?
675 + if((int)$stripe_subscription->ended_at > 0) // Done?
629 676 {
630 677 $time = $stripe_subscription->ended_at + $grace_time;
631 678 return array('type' => 'fixed', 'time' => $time, 'tense' => $time <= $now ? 'past' : 'future',
632 679 'debug' => 'The Stripe API says this subscription reached an expiration on this date + grace time.');
@@ -639,9 +686,9 @@
639 686 }
640 687 if(isset($stripe_subscription->plan->metadata->recurring, $stripe_subscription->plan->metadata->recurring_times)
641 688 && !$stripe_subscription->plan->metadata->recurring) // Non-recurring subscription?
642 689 {
643 - $time = (integer)$stripe_subscription->start;
690 + $time = (int)$stripe_subscription->start;
644 691 $time += $stripe_subscription->plan->trial_period_days * DAY_IN_SECONDS;
645 692
646 693 switch($stripe_subscription->plan->interval)
647 694 {
@@ -688,9 +735,9 @@
688 735 }
689 736 if(isset($stripe_subscription->plan->metadata->recurring, $stripe_subscription->plan->metadata->recurring_times)
690 737 && $stripe_subscription->plan->metadata->recurring && $stripe_subscription->plan->metadata->recurring_times > 0)
691 738 {
692 - $time = (integer)$stripe_subscription->start;
739 + $time = (int)$stripe_subscription->start;
693 740 $time += $stripe_subscription->plan->trial_period_days * DAY_IN_SECONDS;
694 741
695 742 switch($stripe_subscription->plan->interval)
696 743 {