stripe icon indicating copy to clipboard operation
stripe copied to clipboard

Parsing fails due to "deleted" key not being present when implementing new library

Open whittle opened this issue 9 years ago • 7 comments

I’m writing an adapter library that uses stripe-core over http-conduit: https://github.com/whittle/stripe-http-conduit. It also leverages stripe-test as its test suite. I’m attempting to follow the example of stripe-http-streams as much as possible, but I’m getting a weird parse failure when I run the tests. Specifically, 77 of the test cases fail with the parse error key "deleted" not present. This struck me as particularly odd, as it seems to be originating from the call to Web.Stripe.Client.handleStream using the parser that is provided by StripeRequestF. The full output of the test run is available at http://lpaste.net/169059.

Do you have any insight on why this might be happening?

whittle avatar Jul 04 '16 23:07 whittle

Hey Jason, can you confirm the Stripe API version is being passed along in the HTTP header on the request.

Sent from my iPhone

On Jul 4, 2016, at 6:28 PM, Jason Whittle [email protected] wrote:

I’m writing an adapter library that uses stripe-core over http-conduit: https://github.com/whittle/stripe-http-conduit. It also leverages stripe-test as its test suite. I’m attempting to follow the example of stripe-http-streams as much as possible, but I’m getting a weird parse failure when I run the tests. Specifically, 80 of the test cases fail with the parse error key "deleted" not present. This struck me as particularly odd, as it seems to be originating from the call to Web.Stripe.Client.handleStream using the parser that is provided by StripeRequestF. The full output of the test run is available at http://lpaste.net/169059.

Do you have any insight on why this might be happening?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

dmjio avatar Jul 05 '16 01:07 dmjio

Logging the request objects before I send them, the header that I’m setting is Stripe-Version: 2014-10-07. I’m using the V20141007 constructor from Web.Stripe.Client. The API version set in the dashboard is “2016-06-15 (latest)”. Additionally, when I look at the logs in the Stripe dashboard, that also shows the version as “2014-10-07”.

By the way, thank you for making such an excellent set of libraries. Its design and implementation are a credit to the Haskell community.

whittle avatar Jul 05 '16 02:07 whittle

@whittle, thank you, very kinds word of you.

So the version in the request should be overriding the version in your dashboard (this is true for all endpoints except historical data retrieval). As to why deleted wouldn't parse, that remains a mystery, the JSON instances from this library haven't changed. Unsure why a new http-client would cause a parse failure.

Can you paste some of the json that's being returned in the tests, specifically the objects where a parse failure exists.

dmjio avatar Jul 07 '16 00:07 dmjio

As an example, here’s the result I get back from Stripe that causes an error in the test “Succesfully retrieves an Expanded Balance Transaction” (in response to a POST to /v1/customers/cus_8lFm4B1DHbhPc5):

Right (Object (fromList [("email",Null),("discount",Null),("livemode",Bool False),("default_card",String "card_18TjGZBfKr2Hg7NanRMY77CD"),("created",Number 1.467685587e9),("sources",Object (fromList [("has_more",Bool False),("data",Array [Object (fromList [("dynamic_last4",Null),("tokenization_method",Null),("country",String "US"),("fingerprint",String "dVh82fWtcOx2qDkS"),("address_zip_check",Null),("brand",String "Visa"),("address_city",Null),("address_state",Null),("funding",String "credit"),("customer",String "cus_8lFm4B1DHbhPc5"),("name",Null),("address_line1_check",Null),("cvc_check",String "pass"),("exp_month",Number 12.0),("address_zip",Null),("object",String "card"),("metadata",Object (fromList [])),("id",String "card_18TjGZBfKr2Hg7NanRMY77CD"),("exp_year",Number 2020.0),("address_line2",Null),("address_line1",Null),("last4",String "4242"),("address_country",Null)])]),("url",String "/v1/customers/cus_8lFm4B1DHbhPc5/sources"),("total_count",Number 1.0),("object",String "list")])),("currency",Null),("cards",Object (fromList [("has_more",Bool False),("data",Array [Object (fromList [("dynamic_last4",Null),("tokenization_method",Null),("country",String "US"),("fingerprint",String "dVh82fWtcOx2qDkS"),("address_zip_check",Null),("brand",String "Visa"),("address_city",Null),("address_state",Null),("funding",String "credit"),("customer",String "cus_8lFm4B1DHbhPc5"),("name",Null),("address_line1_check",Null),("cvc_check",String "pass"),("exp_month",Number 12.0),("address_zip",Null),("object",String "card"),("metadata",Object (fromList [])),("id",String "card_18TjGZBfKr2Hg7NanRMY77CD"),("exp_year",Number 2020.0),("address_line2",Null),("address_line1",Null),("last4",String "4242"),("address_country",Null)])]),("url",String "/v1/customers/cus_8lFm4B1DHbhPc5/cards"),("total_count",Number 1.0),("object",String "list")])),("shipping",Null),("object",String "customer"),("metadata",Object (fromList [])),("id",String "cus_8lFm4B1DHbhPc5"),("subscriptions",Object (fromList [("has_more",Bool False),("data",Array []),("url",String "/v1/customers/cus_8lFm4B1DHbhPc5/subscriptions"),("total_count",Number 0.0),("object",String "list")])),("account_balance",Number 0.0),("description",Null),("default_source",String "card_18TjGZBfKr2Hg7NanRMY77CD"),("delinquent",Bool False)]))

That’s the data structure after running the response body through Attoparsec using Data.Aeson.Parser.json as the parser.

whittle avatar Jul 07 '16 16:07 whittle

ah, which version of aeson are you using?

dmjio avatar Jul 07 '16 16:07 dmjio

stack exec ghc-pkg list | grep aeson

dmjio avatar Jul 07 '16 16:07 dmjio

⇒ stack exec ghc-pkg list | grep aeson aeson-0.11.2.0

whittle avatar Jul 07 '16 16:07 whittle