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

No such transfer po_* #2003

Closed
patroqueeet opened this issue Nov 1, 2023 · 18 comments
Closed

No such transfer po_* #2003

patroqueeet opened this issue Nov 1, 2023 · 18 comments
Assignees
Labels

Comments

@patroqueeet
Copy link

Describe the bug

Every months first day, on web hook call I receive this exception:

ERROR 2023-11-01 02:21:38,929 log 2107788 140146881369984 Internal Server Error: /_stripe/webhook/***/
Traceback (most recent call last):
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/sentry_sdk/integrations/django/views.py", line 85, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/views.py", line 47, in post
    trigger = WebhookEventTrigger.from_request(
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/models/webhooks.py", line 268, in from_request
    raise e
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/models/webhooks.py", line 249, in from_request
    obj.process(save=False, api_key=api_key)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/models/webhooks.py", line 363, in process
    self.event = Event.process(self.json_body, api_key=api_key)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/models/core.py", line 1654, in process
    ret.invoke_webhook_handlers()
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/models/core.py", line 1666, in invoke_webhook_handlers
    webhooks.call_handlers(event=self)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/webhooks.py", line 98, in call_handlers
    handler_func(event=event)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/event_handlers.py", line 353, in other_object_webhook_handler
    _handle_crud_like_event(target_cls=target_cls, event=event)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/event_handlers.py", line 448, in _handle_crud_like_event
    data = target_cls(**kwargs).api_retrieve(
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/djstripe/models/base.py", line 202, in api_retrieve
    return self.stripe_class.retrieve(
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/api_resources/abstract/api_resource.py", line 12, in retrieve
    instance.refresh()
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/api_resources/abstract/api_resource.py", line 16, in refresh
    return self._request_and_refresh("get", self.instance_url())
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/api_resources/abstract/api_resource.py", line 90, in _request_and_refresh
    obj = StripeObject._request(
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/stripe_object.py", line 282, in _request
    response, api_key = requestor.request(method_, url_, params, headers)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/api_requestor.py", line 122, in request
    resp = self.interpret_response(rbody, rcode, rheaders)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/api_requestor.py", line 399, in interpret_response
    self.handle_error_response(rbody, rcode, resp.data, rheaders)
  File "/home/darg/darg/.ve/lib/python3.8/site-packages/stripe/api_requestor.py", line 159, in handle_error_response
    raise err
stripe.error.InvalidRequestError: Request req_Ah9ioeS1Odqn4Z: No such transfer: 'po_***'

Software versions

  • Dj-Stripe version: 2.8.2
  • Python version: 3.11
  • Django version: 4.2
  • Stripe API version: 2017
  • Database type and version: psql v11
@patroqueeet patroqueeet added the bug label Nov 1, 2023
@arnav13081994
Copy link
Contributor

@patroqueeet Is this a webhook event on your account or on a connected account (yours is a platform account)?

@arnav13081994 arnav13081994 self-assigned this Nov 3, 2023
@patroqueeet
Copy link
Author

patroqueeet commented Nov 3, 2023 via email

@arnav13081994
Copy link
Contributor

@patroqueeet What is your payout destination? And are you able to retrieve it using the stripe api? If so can you share the json?

@patroqueeet
Copy link
Author

patroqueeet commented Nov 6, 2023

not exactly sure what command I should run. but when checking in stripe I found it is looking for transfers with a po_*** id, but when I past this ID into stripe search field, I get a payout obj, not a transfer obj. does this help?

Screenshot 2023-11-06 at 14 03 08

@arnav13081994
Copy link
Contributor

@patroqueeet Please go to Django admin and hunt the Event related to this failed event and copy-paste the entire object. You can do so by running the following in django shell as well:

from django.forms import model_to_dict
from djstripe.models import Event

evt = Event.objects.get(id="<ID_OF_FAILED_EVENT>")
print(model_to_dict(evt))

@patroqueeet
Copy link
Author

@arnav13081994 that is not working, because the event is not saved to the local db because of the error described.

@arnav13081994
Copy link
Contributor

Please check in the webhook event triggers table for a failed event and then re-run the same command as mentioned below but for the WebhookEventTrigger object

@patroqueeet
Copy link
Author

patroqueeet commented Nov 13, 2023

like that:

{
"id": "evt_1O7T7kBBirzkVpobVI9LZcHQ",
"object": "event",
"api_version": "2017-01-27",
"created": 1698801696,
"data": {
"object": {
"id": "po_1O7SohBBirzkVpobNNDVrry3",
"object": "transfer",
"amount": 1,
"amount_reversed": 0,
"application_fee": null,
"arrival_date": 1698796800,
"automatic": true,
"balance_transaction": "txn_1O7SohBBirzkVpobgrc2rTus",
"bank_account": {
"id": "ba_1LX1SjBBirzkVpob7bckjG4y",
"object": "bank_account",
"account_holder_name": null,
"account_holder_type": null,
"account_type": null,
"bank_name": "...",
"country": "DE",
"currency": "eur",
"fingerprint": "2bbLdAFgfBVs1iY3",
"last4": "1234",
"routing_number": "DE...",
"status": "new"
},
"created": 1698800515,
"currency": "eur",
"date": 1698796800,
"description": "STRIPE PAYOUT",
"destination": "ba_1LX1SjBBirzkVpob7bckjG4y",
"failure_balance_transaction": null,
"failure_code": null,
"failure_message": null,
"livemode": true,
"metadata": {
},
"method": "standard",
"original_payout": null,
"recipient": null,
"reconciliation_status": "in_progress",
"reversals": {
"object": "list",
"data": [

],
"has_more": false,
"total_count": 0,
"url": "/v1/transfers/po_1O7SohBBirzkVpobNNDVrry3/reversals"
},
"reversed": false,
"reversed_by": null,
"source_transaction": null,
"source_type": "card",
"statement_descriptor": null,
"status": "in_transit",
"transfer_group": null,
"type": "bank_account"
}
},
"livemode": true,
"pending_webhooks": 2,
"request": null,
"type": "transfer.created"
}

@arnav13081994
Copy link
Contributor

@patroqueeet This is very interesting. I had no idea one could have a payout object id in a transfer object. Can you please run the following commands in the django shell and let me know if you get an error or a response. In case of a response, please share the JSON

import stripe
stripe.api_key="<YOUR_API_KEY>"

stripe.Payout.retrieve("po_1O7SohBBirzkVpobNNDVrry3")
stripe.Transfer.retrieve("po_1O7SohBBirzkVpobNNDVrry3")

@patroqueeet
Copy link
Author

patroqueeet commented Nov 15, 2023

In [212]: stripe.Payout.retrieve("po_1O7SohBBirzkVpobNNDVrry3")
Out[212]:
<Payout transfer id=po_1O7SohBBirzkVpobNNDVrry3 at 0x7fad94c17a40> JSON: {
  "amount": 1,
  "amount_reversed": 0,
  "application_fee": null,
  "arrival_date": 1698796800,
  "automatic": true,
  "balance_transaction": "txn_1O7SohBBirzkVpobgrc2rTus",
  "bank_account": {
    "account_holder_name": null,
    "account_holder_type": null,
    "account_type": null,
    "bank_name": "...",
    "country": "DE",
    "currency": "eur",
    "fingerprint": "...",
    "id": "ba_1LX1SjBBirzkVpob7bckjG4y",
    "last4": "...",
    "object": "bank_account",
    "routing_number": "...",
    "status": "new"
  },
  "created": 1698800515,
  "currency": "eur",
  "date": 1698796800,
  "description": "STRIPE PAYOUT",
  "destination": "ba_1LX1SjBBirzkVpob7bckjG4y",
  "failure_balance_transaction": null,
  "failure_code": null,
  "failure_message": null,
  "id": "po_1O7SohBBirzkVpobNNDVrry3",
  "livemode": true,
  "metadata": {},
  "method": "standard",
  "object": "transfer",
  "original_payout": null,
  "recipient": null,
  "reconciliation_status": "completed",
  "reversals": {
    "data": [],
    "has_more": false,
    "object": "list",
    "total_count": 0,
    "url": "/v1/transfers/po_1O7SohBBirzkVpobNNDVrry3/reversals"
  },
  "reversed": false,
  "reversed_by": null,
  "source_transaction": null,
  "source_type": "card",
  "statement_descriptor": null,
  "status": "paid",
  "transfer_group": null,
  "type": "bank_account"
}

and

In [213]: stripe.Transfer.retrieve("po_1O7SohBBirzkVpobNNDVrry3")
<Transfer transfer id=po_1O7SohBBirzkVpobNNDVrry3 at 0x7fada425a130> JSON: {
  "amount": 1,
  "amount_reversed": 0,
  "application_fee": null,
  "arrival_date": 1698796800,
  "automatic": true,
  "balance_transaction": "txn_1O7SohBBirzkVpobgrc2rTus",
  "bank_account": {
    "account_holder_name": null,
    "account_holder_type": null,
    "account_type": null,
    "bank_name": "...",
    "country": "DE",
    "currency": "eur",
    "fingerprint": "...",
    "id": "ba_1LX1SjBBirzkVpob7bckjG4y",
    "last4": "...",
    "object": "bank_account",
    "routing_number": "...",
    "status": "new"
  },
  "created": 1698800515,
  "currency": "eur",
  "date": 1698796800,
  "description": "STRIPE PAYOUT",
  "destination": "ba_1LX1SjBBirzkVpob7bckjG4y",
  "failure_balance_transaction": null,
  "failure_code": null,
  "failure_message": null,
  "id": "po_1O7SohBBirzkVpobNNDVrry3",
  "livemode": true,
  "metadata": {},
  "method": "standard",
  "object": "transfer",
  "original_payout": null,
  "recipient": null,
  "reconciliation_status": "completed",
  "reversals": {
    "data": [],
    "has_more": false,
    "object": "list",
    "total_count": 0,
    "url": "/v1/transfers/po_1O7SohBBirzkVpobNNDVrry3/reversals"
  },
  "reversed": false,
  "reversed_by": null,
  "source_transaction": null,
  "source_type": "card",
  "statement_descriptor": null,
  "status": "paid",
  "transfer_group": null,
  "type": "bank_account"
}

@arnav13081994
Copy link
Contributor

arnav13081994 commented Nov 15, 2023

not exactly sure what command I should run. but when checking in stripe I found it is looking for transfers with a po_*** id, but when I past this ID into stripe search field, I get a payout obj, not a transfer obj. does this help?

Screenshot 2023-11-06 at 14 03 08

@patroqueeet I do not understand how you got a response for stripe.Transfer.retrieve() when the screenshot shows that the object is not available. Or am I misunderstanding something?

Moreover looking at the JSON the fields are all from the Payout Object even when "object": "transfer" is mentioned in the JSON.

@patroqueeet
Copy link
Author

Indeed I see your point. Still, the symptoms are as they are. Anything I can do to narrow down the source of the symptoms?

@arnav13081994
Copy link
Contributor

arnav13081994 commented Nov 15, 2023

I see that you are using sentry. Can you tell me what all params are being passed to the api_retrieve call and what is self.stripe_class?

Also on this Stripe Account your api version is 2020-XXX.

@patroqueeet
Copy link
Author

Screenshot 2023-11-15 at 13 04 02

@arnav13081994
Copy link
Contributor

Thanks. @patroqueeet Can you run stripe.Transfer.retrieve with all the params you see above like stripe_account, expand, stripe_version, api_key and id as is done here?

@patroqueeet
Copy link
Author

patroqueeet commented Nov 16, 2023

learning: fails with version specified. succeeds with no version given. hence checked:

Screenshot 2023-11-16 at 09 10 58

what do you recommend from here? upgrade default to 2020 version?

And further checked. 2020 version is djstripe default (I did not override in settings). so means the webhook is not sending the default djstripe Stripe API version along? Do I read this like: stripe default setting is applied to web hook calls and conflicts with djstripe default setting? Just learned cannot upgrade djstripe default version to 2020. only latest is allowed. what now?

@arnav13081994
Copy link
Contributor

@patroqueeet Please check the api_version of the webhook endpoint that is receiving this event. It's visible in the admin. You can create a new webhook endpoint with the 2020 version

@patroqueeet
Copy link
Author

patroqueeet commented Nov 17, 2023

now I did after finding api version was empty.

In [70]: whep = WebhookEndpoint.objects.get(pk=2)

In [71]: whep.api_version = '2020-08-27'

In [72]: whep.save()

But also found that inside Stripe each WH has an api version assigned. this is set to default 2017* in my case. so now my local model is not aligned with stripe :/ . trying to adjust to 2020* api version in Stripe is not possible, I can only select default or lastest version - will find out what it does now on Dec, 1st...

THX for instantly creating a PR to prevent similar in the future and THX for the great support. was a tricky issue, I assume...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants