The pre-production release of the 2602.XX.YY versions of the SaaS are setup with a revised React-based subscription processor.

The My Profile | Subscription tab allows the user to…

  • Change the plan (upgrade, downgrade)
  • Update Card
  • Cancel Subscription

Update Card

The update card process appears to be calling the backend, however how Stripe stores payment data and how it is rendered has changed.

Resolution

Update \stripe\MySLP_Stripe_Payments::get_customer_card_details

If Payment Method (default payment method) is set it always returns that first, but that is not where the card payment info is set when the card is changed. It has the ‘default_source’ set for the customer, which should take precedence.

On a new customer the default_source is empty, thus \stripe\MySLP_Stripe_Payments::get_customer_card_details will fall back to the payment id.

Dev Notes

Call Stack

Update Card button on React interface pulls up the Stripe independent JavaScript modal to edit the card.

Upon submit of the Stripe JS modal form it posts back to the My Profile page forcing a render…

\MySLP::render_profile_page
  \MySLP_Customer_Profile::get_instance()->page_profile()
     \MySLP_Customer_Profile::initialize() // from get_instance call
     \MySLP_Customer_Profile::do_when_plugins_loaded
     \MySLP_Customer_Profile::update_card  // only runs for Stripe processor

     \stripe\MySLP_Stripe_Payments::change_card

\stripe\MySLP_Stripe_Payments::change_card

  • Requires $_REQUEST[‘stripToken’] to be set
  • Requires $_REQUEST[‘stripeEmail’] to match the current logged-in user email

It then calls the Stripe library to update the customer information:

$stripeCustomer = $stripeCustomer->update(
  $this->myslp->User->payment_customer_id,
  ['source' => $_REQUEST['stripeToken']]
);

\Customer_Profile_Subscription::get_subscription_data

This builds the JavaScript variables sent to React that impacts the displayed items. Those relevant to card details:

$user = $this->myslp->User;
$recurring_payments = $user->recurring_payments

Partial $recurring_payments data:

['customer_details']
  [ 'default_source' ] = 'card_1T1qAGBvHKfBw2LGldu03Qw1' // matches latest history log entry

['subscription_details']
  ['default_payment_method'] = 'pm_1Sw3IgBvHKfBw2LGqEHop4ts'

The code is currently set to build card details from…
1. $recurring_payments[‘customer_details’][‘sources’][‘data’][0] // this is empty in newer subscriptions
2.

My Profile | History

The history tab is showing the change card operation is working.

  • Payment Method Changed headers come from \MySLP_History::log_payment_changed
  • This is only called via the custom MySLP hook myslp_payment_changed.
  • The myslp_payment_changed hook is only fired from the end of \stripe\MySLP_Stripe_Payments::change_card when payment is successful.

Stripe test Cards

This is in the Cypress testing fixtures at SLP_SaaS/Testing/myslp-cypress/cypress/fixtures/stripe_test_cards.json

[
  {
    "id": "visa",
    "number": "4242424242424242",
    "cvc": "123",
    "expiration": "0130"
  },
  {
    "id": "mastercard",
    "number": "5555555555554444",
    "cvc": "456",
    "expiration": "0230"
  },
  {
    "id": "amex",
    "number": "378282246310005",
    "cvc": "1234",
    "expiration": "0330"
  },
  {
    "id": "discover",
    "number": "6011111111111117",
    "cvc": "789",
    "expiration": "0430"
  }
]

Related Commits

myslp-dashboard

  • Refactor the Update Card logic to us a common card information gathering method and message creation construct. Allows the React UX for My Profile | Subscriptions and the History logger to share logic and provide a consistent UX. 4d6d081 SaaS Update Script saas.update.script@storelocatorplus.com Feb 17, 2026 at 6:08 PM
  • No need to load the processor in update_card for Customer Profile (My Profile) unless a Stripe Token is in the $_REQUEST 07e8262 SaaS Update Script saas.update.script@storelocatorplus.com Feb 17, 2026 at 5:26 PM
  • Add notes about where card details are coming from. f97c591 SaaS Update Script saas.update.script@storelocatorplus.com Feb 17, 2026 at 11:34 AM
  • On update card, the default source takes precedence on the most current payment details. 36217d4 SaaS Update Script saas.update.script@storelocatorplus.com Feb 17, 2026 at 11:26 AM
  • PhpDoc and PSR-12 updates. da28cbf SaaS Update Script saas.update.script@storelocatorplus.com Feb 17, 2026 at 10:56 AM
  • Move update card logic to promote it to the higher level MySLP_Customer_Profile class and remove it from the fetching of subscription details. c4bf6bb SaaS Update Script saas.update.script@storelocatorplus.com Feb 17, 2026 at 10:17 AM

myslp-payments

Leave a Reply