enupal / stripe

Allows customers sign up for recurring and one-time payments with Stripe, perfect for orders, donations, subscriptions, and events. Create simple payment forms in seconds easily without coding. For Craft CMS
https://enupal.com/craft-plugins/stripe-payments/
Other
33 stars 19 forks source link

Get payment sources when no default #337

Closed iamkeir closed 1 year ago

iamkeir commented 1 year ago

We used to use stripeCustomer.default_source to display the "main" card saved on file for our customers. However, since switching to SCA and Stripe Checkout, none of the cards used during checkout are saved as "default" so this always returns null.

We noticed there is stripeCustomer.sources but it looks like an unexpanded Stripe list, so we can't get at this data/loop through to show cards saved.

Any idea how we can return the Stripe cards saved on file?

PHP version | 7.3.33
Database driver & version | MySQL 5.7.40
Craft edition & version | Craft Pro 3.7.63.1
Stripe Payments | 4.0.10
andrelopez commented 1 year ago

Hi @iamkeir could you please let me know how are you getting the stripeCustomer object? From the Stripe API it looks like there is a defaultSource -> https://stripe.com/docs/api/customers/retrieve

iamkeir commented 1 year ago

@andrelopez we get the customer via craft.enupalStripe.getStripeCustomer(currentUser.email). The problem, however, is that when you use Stripe checkout, the card gets saved in Stripe but not as a default source, thus a customer can have multiple cards on file but none are a default source, which makes this value null. It's a weird quirk of Stripe checkout (we chatted to them about it).

As Enupal Stripe Payments already seems to have the .sources value, it's just not expanded, we thought perhaps this contained all the cards on file.

andrelopez commented 1 year ago

@iamkeir So could you please confirm that this example is not working? https://docs.enupal.com/stripe-payments/templating/update-card-info.html#if-sca-is-enabled

{% set currentCard = 'No card' %}
{# Check first for default payment method #}
{% set paymentMethodId = stripeCustomer.invoice_settings.default_payment_method ?? null  %}

  {% if paymentMethodId %}

      {% set paymentMethod = craft.enupalStripe.getPaymentMethod(paymentMethodId) %}

      {% if paymentMethod.card is defined %}
          {% set currentCard = paymentMethod.card.brand ~ " ending in " ~ paymentMethod.card.last4 %}
      {% endif %}

  {% else %}

      {% set currentCard = stripeCustomer.default_source.brand ~ " ending in " ~ stripeCustomer.default_source.last4 %}

  {% endif %}

<h1>Current Card:<h2> <code> {{currentCard}}</code>

Please check if the {% set paymentMethodId = stripeCustomer.invoice_settings.default_payment_method ?? null %} approach works

iamkeir commented 1 year ago

If a customer has no default source in Stripe, both stripeCustomer.invoice_settings.default_payment_method and stripeCustomer.default_source are null.

If you try checking out with Stripe Checkout with a new customer/customer without any saved payment methods, you'll see that the card is saved against the customer but is not set to default. This means if someone has only ever used Stripe Checkout, they may never have a default source - only a list of sources, with most recently used one first.

Here's an abridged version of what I see:

object(Stripe\Customer)#1731 (29) {  
  ["default_source"]=>
  NULL
  ["invoice_settings"]=>
  object(Stripe\StripeObject)#1744 (4) {
    ["default_payment_method"]=>
    NULL    
  }  
  ["sources"]=>
  object(Stripe\Collection)#1749 (5) {
    ["object"]=>
    string(4) "list"
    ["data"]=>
    array(0) {
    }
    ["has_more"]=>
    bool(false)
    ["total_count"]=>
    int(0)
    ["url"]=>
    string(40) "/v1/customers/cus_XXXXXXXXXXXX/sources"
  }
}
andrelopez commented 1 year ago

Could you please confirm your Stripe Payments version?

iamkeir commented 1 year ago

Sure, it is v4.0.10.

andrelopez commented 1 year ago

Hi @iamkeir We just released Stripe Payments v4.1.0 (Craft3) and v5.1.0(Craft4) with support to expanded sources, please let me know if that works

iamkeir commented 1 year ago

@andrelopez that's amazing, thank you very much. It works - also, if you do have a default set, the first source is also the default so it works a charm with customer.sources.data[0].