Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webhook Parse failing with "invalid PriceId, expected id to start with "price_" or "plan_" #578

Closed
thomasmost opened this issue Jul 26, 2024 · 3 comments · Fixed by #580
Closed
Labels
bug Something isn't working released

Comments

@thomasmost
Copy link
Contributor

Describe the bug

My invoice.paid webhook event parse is failing with "invalid PriceId, expected id to start with "price_" or "plan_"

The price ID is "monthly8usd" — and this is from Stripe, mind you... so I think this must be a false presumption?

To Reproduce

Webhook

Event payload (scrubbed):

{
  "id": "evt_xxxm1gHdomXNXiDQq8TfykdS",
  "object": "event",
  "account": "acct_xxxow8HdomXNXiDQ",
  "api_version": "2024-06-20",
  "created": 1721753843,
  "data": {
    "object": {
      "id": "in_xxx1cHdomXNXiDQWDCXCEWg",
      "object": "invoice",
      "account_country": "US",
      "account_name": "Customer.com",
      "account_tax_ids": [
        "atxi_1NZedwHdomXNXiDQIo2Ow1Eg"
      ],
      "amount_due": 0,
      "amount_paid": 0,
      "amount_remaining": 0,
      "amount_shipping": 0,
      "application": null,
      "application_fee_amount": null,
      "attempt_count": 0,
      "attempted": true,
      "auto_advance": false,
      "automatic_tax": {
        "enabled": true,
        "liability": {
          "type": "self"
        },
        "status": "complete"
      },
      "automatically_finalizes_at": null,
      "billing_reason": "subscription_create",
      "charge": null,
      "collection_method": "charge_automatically",
      "created": 1721753840,
      "currency": "usd",
      "custom_fields": null,
      "customer": [""],
      "customer_address": {
        "city": "New York",
        "country": "US",
        "line1": "1 Murray Street",
        "line2": "",
        "postal_code": "10007",
        "state": "NY"
      },
      "customer_email": "customer@customer.com",
      "customer_name": "Customer Customer",
      "customer_phone": null,
      "customer_shipping": null,
      "customer_tax_exempt": "none",
      "default_payment_method": null,
      "default_source": null,
      "default_tax_rates": [
      ],
      "description": null,
      "discount": null,
      "discounts": [
      ],
      "due_date": null,
      "effective_at": 1721753840,
      "ending_balance": 0,
      "footer": null,
      "from_invoice": null,
      "hosted_invoice_url": "",
      "invoice_pdf": "",
      "issuer": {
        "type": "self"
      },
      "last_finalization_error": null,
      "latest_revision": null,
      "lines": {
        "object": "list",
        "data": [
          {
            "id": "il_1Pfm1cHdomXNXiDQJJo9yfOA",
            "object": "line_item",
            "amount": 0,
            "amount_excluding_tax": 0,
            "currency": "usd",
            "description": "Trial period for Twenty (per seats)",
            "discount_amounts": [
            ],
            "discountable": true,
            "discounts": [
            ],
            "invoice": "in_xxxm1cHdomXNXiDQWDCXCEWg",
            "livemode": true,
            "metadata": {
              "workspaceId": "1dc3bff7-ac38-4f7b-944a-ecd8740ccbae"
            },
            "period": {
              "end": 1722358639,
              "start": 1721753839
            },
            "plan": {
              "id": "monthly8usd",
              "object": "plan",
              "active": true,
              "aggregate_usage": null,
              "amount": 900,
              "amount_decimal": "900",
              "billing_scheme": "per_unit",
              "created": 1699860608,
              "currency": "usd",
              "interval": "month",
              "interval_count": 1,
              "livemode": true,
              "metadata": {
                "substack": "yes",
                "inactive": "yes"
              },
              "meter": null,
              "nickname": "Monthly",
              "product": "prod_xxxPg0pCf9PxLe",
              "tiers_mode": null,
              "transform_usage": null,
              "trial_period_days": null,
              "usage_type": "licensed"
            },
            "price": {
              "id": "monthly8usd",
              "object": "price",
              "active": true,
              "billing_scheme": "per_unit",
              "created": 1699860608,
              "currency": "usd",
              "custom_unit_amount": null,
              "livemode": true,
              "lookup_key": null,
              "metadata": {
                "substack": "yes",
                "inactive": "yes"
              },
              "nickname": "Monthly",
              "product": "prod_xxxPg0pCf9PxLe",
              "recurring": {
                "aggregate_usage": null,
                "interval": "month",
                "interval_count": 1,
                "meter": null,
                "trial_period_days": null,
                "usage_type": "licensed"
              },
              "tax_behavior": "exclusive",
              "tiers_mode": null,
              "transform_quantity": null,
              "type": "recurring",
              "unit_amount": 900,
              "unit_amount_decimal": "900"
            },
            "proration": false,
            "proration_details": {
              "credited_items": null
            },
            "quantity": 1,
            "subscription": "sub_xxxx1cHdomXNXiDQsa3Pz1gd",
            "subscription_item": "si_xxxhPtn1K9ivL9",
            "type": "subscription",
            "unit_amount_excluding_tax": "0"
          }
        ],
        "has_more": false,
        "total_count": 1,
        "url": "/v1/invoices/in_1Pfm1cHdomXNXiDQWDCXCEWg/lines"
      },
      "livemode": true,
      "metadata": {
      },
      "next_payment_attempt": null,
      "number": "15B18D14-0001",
      "on_behalf_of": null,
      "paid": true,
      "paid_out_of_band": false,
      "payment_intent": null,
      "payment_settings": {
        "default_mandate": null,
        "payment_method_options": {
          "acss_debit": null,
          "bancontact": null,
          "card": {
            "request_three_d_secure": "automatic"
          },
          "customer_balance": null,
          "konbini": null,
          "sepa_debit": null,
          "us_bank_account": null
        },
        "payment_method_types": null
      },
      "period_end": 1721753839,
      "period_start": 1721753839,
      "post_payment_credit_notes_amount": 0,
      "pre_payment_credit_notes_amount": 0,
      "quote": null,
      "receipt_number": null,
      "rendering": null,
      "shipping_cost": null,
      "shipping_details": null,
      "starting_balance": 0,
      "statement_descriptor": null,
      "status": "paid",
      "status_transitions": {
        "finalized_at": 1721753840,
        "marked_uncollectible_at": null,
        "paid_at": 1721753839,
        "voided_at": null
      },
      "subscription": "sub_xxxm1cHdomXNXiDQsa3Pz1gd",
      "subscription_details": {
        "metadata": {}
      },
      "subtotal": 0,
      "subtotal_excluding_tax": 0,
      "tax": 0,
      "test_clock": null,
      "total": 0,
      "total_discount_amounts": [
      ],
      "total_excluding_tax": 0,
      "total_tax_amounts": [
        {
          "amount": 0,
          "inclusive": false,
          "tax_rate": "txr_1Olak6HdomXNXiDQzkC5j57c",
          "taxability_reason": "not_collecting",
          "taxable_amount": 0
        }
      ],
      "transfer_data": null,
      "webhooks_delivered_at": 1721753840
    }
  },
  "livemode": true,
  "pending_webhooks": 1,
  "request": {
    "id": null,
    "idempotency_key": null
  },
  "type": "invoice.paid"
}

Expected behavior

It should parse a valid invoice.paid event

Code snippets

No response

OS

debian

Rust version

1.79.0

Library version

async-stripe 0.37.1

API version

2024-06-20

Additional context

No response

@thomasmost thomasmost added the bug Something isn't working label Jul 26, 2024
@augustoccesar
Copy link
Contributor

The PlanId is defined so that it can be any arbitrary string in here. The issue is that, since the "new way" is to use Price instead of Plan, they fill the price data with the plan to keep compatibility.

You can now model subscriptions more flexibly using the Prices API. It replaces the Plans API and is backwards compatible to simplify your migration.

This causes the code to try to parse the price.id that is the arbitrary string from the plan.id, as we can see from the example you sent:

"plan": {
  "id": "monthly8usd",
  "object": "plan",
  (...)
},
"price": {
  "id": "monthly8usd",
  "object": "price",
  (...)
}

I guess there might be the need to lift the restriction of the Price ID needing to be one of price_ or plan_, to instead be the same as the PlanId, any String 🤔

References:

@thomasmost
Copy link
Contributor Author

Got it! @augustoccesar thank you for the more thorough explanation/understanding than I possessed... I forked the repo earlier to fix this bug in our live service and I just opened a PR. Happy to make adjustments to get it up to merge-standard if you want to take a look!

#580

@arlyon arlyon closed this as completed in a16bc6e Aug 6, 2024
arlyon added a commit that referenced this issue Aug 6, 2024
fix: #578 by allowing arbitrary strings for PriceIds
arlyon pushed a commit that referenced this issue Aug 6, 2024
## [0.38.1](v0.38.0...v0.38.1) (2024-08-06)

### Bug Fixes

* [#578](#578) allow arbitrary strings for priceId ([a16bc6e](a16bc6e))
@arlyon
Copy link
Owner

arlyon commented Aug 6, 2024

🎉 This issue has been resolved in version 0.38.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@arlyon arlyon added the released label Aug 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants