invertase / stripe-firebase-extensions

Repository of Firebase Extensions built by Stripe.
https://firebase.google.com/products/extensions
Apache License 2.0
436 stars 164 forks source link

Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string. #368

Closed talalsiddiqui closed 1 year ago

talalsiddiqui commented 2 years ago

Bug report

Describe the bug

Function: ext-firestore-stripe-subscriptions-handleWebhookEvents Type: invoice.upcoming

I have noticed that on type [invoice. upcoming], document path is not a valid resource path error is coming. Please can anyone tell me is this from my side or it is genuine bug

jsteele-stripe commented 2 years ago

@talalsiddiqui invoice.upcoming events will trigger the insertInvoiceRecord function.

My assumption is that the customersCollectionPath value set in your instance configuration is not actually a valid Firebase document path. Please can you check and confirm.

abierbaum commented 2 years ago

@jsteele-stripe I am not the original poster of this bug, but I am seeing this exact issue coming up the last month or so after several months of no issues at all. In my case I know the customersCollectionPath values is definitely set to a value and subscription creation and processing is working correctly. I am seeing these errors though and would like to understand if there is something to worry about here.

talalsiddiqui commented 2 years ago

@jsteele-stripe All other invoice types such as paid, payment_succeeded, and payment_failed are working perfectly. The only issue is coming in [invoice. upcoming].

jsteele-stripe commented 2 years ago

@abierbaum @talalsiddiqui Are you able to provide some more detailed errors from your Firebase function logs?

SmartManDeveloper commented 2 years ago

@jsteele-stripe Hi, same issue here. Probably caused by null "payment_intent" for upcoming invoice. Detailed log - [Error]: Webhook handler for Stripe event [*] of type [invoice.upcoming] failed: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.

noelmansour commented 2 years ago

This is happening because the invoice.upcoming webhook event does not contain an id in the object. This results in an error on this line https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-payments/functions/src/index.ts#L608

I'm not sure if this is a Stripe API issue. I'd imagine the id should be returned in the webhook event. The other invoice.* include it.

Edit: I played around with this some more. It seems the invoice doesn't actually exist when this webhook event is triggered. It only exists after the invoice.created event is triggered. The id won't be available until after that.

The Stripe dashboard seems to simply maintain a single upcoming_invoice per subscription. Maybe it makes sense to store the upcoming invoices using a hardcoded firestore id of "upcoming"?

brooksdra commented 1 year ago

I am going through this stripe extension tutorial today and getting the same issue on the invoice.paid and invoice.payment_succeeded events. See Event Payload below.

The only missing id is the request.id? Am I missing something?

Event Payload with obscured ids...

{
  "id": "evt_1MKB...X9gS",
  "object": "event",
  "api_version": "2022-11-15",
  "created": 1672278487,
  "data": {
    "object": {
      "id": "in_1MKB....itf4",
      "object": "invoice",
      "account_country": "US",
      "account_name": "StripeSubDemo",
      "account_tax_ids": null,
      "amount_due": 0,
      "amount_paid": 0,
      "amount_remaining": 0,
      "application": null,
      "application_fee_amount": null,
      "attempt_count": 0,
      "attempted": true,
      "auto_advance": false,
      "automatic_tax": {
        "enabled": false,
        "status": null
      },
      "billing_reason": "subscription_create",
      "charge": null,
      "collection_method": "charge_automatically",
      "created": 1672278487,
      "currency": "usd",
      "custom_fields": null,
      "customer": "cus_N4Jq....rxdi",
      "customer_address": null,
      "customer_email": "eileen@eileen.com",
      "customer_name": null,
      "customer_phone": null,
      "customer_shipping": null,
      "customer_tax_exempt": "none",
      "customer_tax_ids": [
      ],
      "default_payment_method": null,
      "default_source": null,
      "default_tax_rates": [
      ],
      "description": null,
      "discount": null,
      "discounts": [
      ],
      "due_date": null,
      "ending_balance": 0,
      "footer": null,
      "from_invoice": null,
      "hosted_invoice_url": "https://invoice.stripe.com/i/acct_1MJmviLczxT5F8d6/test_YWNjd....UoQA?s=ap",
      "invoice_pdf": "https://pay.stripe.com/invoice/acct_1MJmviLczxT5F8d6/test_YWNjd....UoQA/pdf?s=ap",
      "last_finalization_error": null,
      "latest_revision": null,
      "lines": {
        "object": "list",
        "data": [
          {
            "id": "il_1MKB....xhqD",
            "object": "line_item",
            "amount": 0,
            "amount_excluding_tax": 0,
            "currency": "usd",
            "description": "Trial period for Premium Plan",
            "discount_amounts": [
            ],
            "discountable": true,
            "discounts": [
            ],
            "livemode": false,
            "metadata": {
            },
            "period": {
              "end": 1672364886,
              "start": 1672278486
            },
            "plan": {
              "id": "price_1MK9....cAUy",
              "object": "plan",
              "active": true,
              "aggregate_usage": null,
              "amount": 2000,
              "amount_decimal": "2000",
              "billing_scheme": "per_unit",
              "created": 1672270287,
              "currency": "usd",
              "interval": "month",
              "interval_count": 1,
              "livemode": false,
              "metadata": {
              },
              "nickname": null,
              "product": "prod_N4Hf....lWuN",
              "tiers_mode": null,
              "transform_usage": null,
              "trial_period_days": 1,
              "usage_type": "licensed"
            },
            "price": {
              "id": "price_1MK9...cAUy",
              "object": "price",
              "active": true,
              "billing_scheme": "per_unit",
              "created": 1672270287,
              "currency": "usd",
              "custom_unit_amount": null,
              "livemode": false,
              "lookup_key": null,
              "metadata": {
              },
              "nickname": null,
              "product": "prod_N4Hf....lWuN",
              "recurring": {
                "aggregate_usage": null,
                "interval": "month",
                "interval_count": 1,
                "trial_period_days": 1,
                "usage_type": "licensed"
              },
              "tax_behavior": "unspecified",
              "tiers_mode": null,
              "transform_quantity": null,
              "type": "recurring",
              "unit_amount": 2000,
              "unit_amount_decimal": "2000"
            },
            "proration": false,
            "proration_details": {
              "credited_items": null
            },
            "quantity": 1,
            "subscription": "sub_1MKBE....ivXw",
            "subscription_item": "si_N4Jr....fq99",
            "tax_amounts": [
            ],
            "tax_rates": [
            ],
            "type": "subscription",
            "unit_amount_excluding_tax": "0"
          }
        ],
        "has_more": false,
        "total_count": 1,
        "url": "/v1/invoices/in_1MKB....itf4/lines"
      },
      "livemode": false,
      "metadata": {
      },
      "next_payment_attempt": null,
      "number": "B8578FE2-0001",
      "on_behalf_of": null,
      "paid": true,
      "paid_out_of_band": false,
      "payment_intent": null,
      "payment_settings": {
        "default_mandate": null,
        "payment_method_options": null,
        "payment_method_types": null
      },
      "period_end": 1672278486,
      "period_start": 1672278486,
      "post_payment_credit_notes_amount": 0,
      "pre_payment_credit_notes_amount": 0,
      "quote": null,
      "receipt_number": null,
      "rendering_options": null,
      "starting_balance": 0,
      "statement_descriptor": null,
      "status": "paid",
      "status_transitions": {
        "finalized_at": 1672278487,
        "marked_uncollectible_at": null,
        "paid_at": 1672278486,
        "voided_at": null
      },
      "subscription": "sub_1MKB....ivXw",
      "subtotal": 0,
      "subtotal_excluding_tax": 0,
      "tax": null,
      "test_clock": null,
      "total": 0,
      "total_discount_amounts": [
      ],
      "total_excluding_tax": 0,
      "total_tax_amounts": [
      ],
      "transfer_data": null,
      "webhooks_delivered_at": 1672278487
    }
  },
  "livemode": false,
  "pending_webhooks": 1,
  "request": {
    "id": null,
    "idempotency_key": null
  },
  "type": "invoice.payment_succeeded"
}
brooksdra commented 1 year ago

Okay, with the help of noelmansour's comment:

This is happening because the invoice.upcoming webhook event does not contain an id in the object. This results in an error on this line https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-payments/functions/src/index.ts#L608

I'm not sure if this is a Stripe API issue. I'd imagine the id should be returned in the webhook event. The other invoice.* include it.

I figured out the root cause...

This is happening because the invoice.paid and invoice.payment_succeeded webhook events do not contain an payment_intent in the object. This results in an error on this line https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-payments/functions/src/index.ts#L626

I was able to correct the issue by removing the trial period on a product price.

From this, I now have two new questions. With a trial period, I only see the following webhook events, and the invoice-based events both fail:

invoice.paid.  -- Fail with error in my first post
checkout.session.completed
customer.subscription.created
invoice.payment_succeeded  -- Fail with error in my first post

Without the trial period, I see the following set of webhook events, and all event work properly:

payment_intent.created
payment_intent.succeeded
checkout.session.completed
customer.subscription.created
customer.subscription.updated
invoice.paid
invoice.payment_succeeded

1) Is the first scenario acceptable, or is this clearly a problem? 2) I'm dubious about the order of events (top to bottom) as the broken invoice.paid comes before customer.subscription. created.

vishishttiwari commented 1 year ago

Having the same issue with invoice.payment_succeeded, invoice.paid and invoice.upcoming when a trial period is there. The exact errors are:

❗️[Error]: Webhook handler for Stripe event [*] of type [invoice.payment_succeeded] failed: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.

❗️[Error]: Webhook handler for Stripe event [*] of type [invoice.paid] failed: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.

❗️[Error]: Webhook handler for Stripe event [*] of type [invoice.upcoming] failed: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.

I can also provide the event IDs if required. Thanks

jsteele-stripe commented 1 year ago

Should be fixed in #511.