Skip to content

Incorrect objects parsing in API v4 #89

@mpetrik-phrase

Description

@mpetrik-phrase

Description of the Bug

Our integration tests check Invoices content. After migration to v4 is started failing on the id field.

Our assumption is, that the parser does not work correctly with object hierarchies, specifically JsonUtil.getString. It uses RegExp parsing which may get a wrong field if a field of the same name exists somewhere in the parsed object too. It looks the implementation just finds the first occurrence of the key in the string provided (which is quite risky, I would say - it would require unique key names across the whole object - not sure it can be guaranteed - amount, total, discount, ... - not possible with multiple line-items, ...).

I would dare to mark this issue as a significant blocker - if the JSON parsing can't be trusted, we cannot rely on the API values anymore.

Steps to reproduce

A minimal sample:

@Test
  void testInvoiceParsing() {
    var json = """
    {
      "date" : 1517490266,
      "amount_paid" : 1000,
      "write_off_amount" : 0,
      "adjustment_credit_notes" : [ ],
      "applied_credits" : [ ],
      "billing_address" : {
        "last_name" : "Mathew",
        "validation_status" : "not_validated",
        "first_name" : "John",
        "object" : "billing_address"
      },
      "line_items" : [ {
        "tax_amount" : 0,
        "is_taxed" : false,
        "amount" : 1000,
        "quantity" : 1,
        "discount_amount" : 0,
        "description" : "basic USD",
        "date_to" : 1519909466,
        "unit_amount" : 1000,
        "entity_id" : "basic-USD",
        "subscription_id" : "__test__8asyKSOcTI3k1c",
        "entity_type" : "plan_item_price",
        "pricing_model" : "per_unit",
        "item_level_discount_amount" : 0,
        "tax_exempt_reason" : "tax_not_configured",
        "id" : "li___test__8asyKSOcTI6v1e",
        "customer_id" : "__test__8asyKSOcTHxf1V",
        "date_from" : 1517490266,
        "object" : "line_item"
      } ],
      "issued_credit_notes" : [ {
        "cn_status" : "refunded",
        "cn_reason_code" : "subscription_change",
        "cn_date" : 1517490267,
        "cn_total" : 1000,
        "cn_create_reason_code" : "Subscription Change",
        "cn_id" : "__demo_cn__2"
      } ],
      "resource_version" : 1517490268022,
      "currency_code" : "USD",
      "amount_to_collect" : 0,
      "subscription_id" : "__test__8asyKSOcTI3k1c",
      "first_invoice" : true,
      "new_sales_amount" : 1000,
      "total" : 1000,
      "linked_orders" : [ ],
      "updated_at" : 1517490268,
      "credits_applied" : 0,
      "term_finalized" : true,
      "amount_due" : 0,
      "id" : "expected_id",
      "dunning_attempts" : [ ],
      "linked_payments" : [ {
        "txn_id" : "txn___test__8asyKSOcTIAy1f",
        "applied_at" : 1517490266,
        "txn_date" : 1517490266,
        "applied_amount" : 1000,
        "txn_amount" : 1000,
        "txn_status" : "success"
      } ],
      "base_currency_code" : "USD",
      "exchange_rate" : 1,
      "net_term_days" : 0,
      "recurring" : false,
      "is_gifted" : false,
      "due_date" : 1517490266,
      "tax" : 0,
      "has_advance_charges" : false,
      "paid_at" : 1517490266,
      "deleted" : false,
      "amount_adjusted" : 0,
      "sub_total" : 1000,
      "price_type" : "tax_exclusive",
      "round_off_amount" : 0,
      "customer_id" : "__test__8asyKSOcTHxf1V",
      "object" : "invoice",
      "status" : "paid"
    }""";

    var invoice = Invoice.fromJson(json);
    assertThat(invoice.getId()).isEqualTo("expected_id");
  }

The result is:

Expected :"expected_id"
Actual   :"li___test__8asyKSOcTI6v1e"

Expected Behavior

The JSON objects are parsed correctly - the API works with financial data - any mistake may have significant impacts.

Code Snippets (if applicable)

Operating System

Any

Language version

Java 25

Library version

4.3.0

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Waiting_on_requestorIssues/PR where we have responded and are currently waiting on the requestor to respond back

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions