From 498c5fe9b52733f1723a1f5014b354c0b52a3d3b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 12:53:00 +0000 Subject: [PATCH 01/15] feat(types): add OTHER enum value to AuthRuleType --- .stats.yml | 4 +-- .../kotlin/com/lithic/api/models/AuthRule.kt | 12 +++++++ .../api/models/AuthRuleV2CreateParams.kt | 36 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 47c7d7549..9326df23d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 216 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-38a020a15ab14f79c7fea3290822406cf80a9d43d46ab3295632a9723f5e42cd.yml -openapi_spec_hash: 5a7357a17c5119bc91d8f5e42297fac3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-9a4064ca9be1efe3e33d922cae77a5d186b6a0119ef1d3601b5ded1447feb7f7.yml +openapi_spec_hash: bff457821129b2eb4fc5150e23efa197 config_hash: 27fa50e251754c8982e3dc615ef6da41 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt index e3ae59125..b0bcd85b9 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt @@ -210,6 +210,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or ACH_PAYMENT_UPDATE event * stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -662,6 +664,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or ACH_PAYMENT_UPDATE * event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -3254,6 +3258,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or ACH_PAYMENT_UPDATE event * stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -3280,6 +3286,8 @@ private constructor( @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmField val OTHER = of("OTHER") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -3290,6 +3298,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, } /** @@ -3307,6 +3316,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -3327,6 +3337,7 @@ private constructor( MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE + OTHER -> Value.OTHER else -> Value._UNKNOWN } @@ -3346,6 +3357,7 @@ private constructor( MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE + OTHER -> Known.OTHER else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt index c0a400f36..f36432fcd 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt @@ -521,6 +521,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected @@ -798,6 +800,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type + * are read-only; `OTHER` cannot be used when creating a rule. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -1717,6 +1721,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. */ class AuthRuleType @JsonCreator @@ -1744,6 +1750,8 @@ private constructor( @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmField val OTHER = of("OTHER") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1754,6 +1762,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, } /** @@ -1772,6 +1781,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -1793,6 +1803,7 @@ private constructor( MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE + OTHER -> Value.OTHER else -> Value._UNKNOWN } @@ -1812,6 +1823,7 @@ private constructor( MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE + OTHER -> Known.OTHER else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -1972,6 +1984,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected @@ -2245,6 +2259,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type + * are read-only; `OTHER` cannot be used when creating a rule. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -3108,6 +3124,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. */ class AuthRuleType @JsonCreator @@ -3135,6 +3153,8 @@ private constructor( @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmField val OTHER = of("OTHER") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -3145,6 +3165,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, } /** @@ -3163,6 +3184,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -3184,6 +3206,7 @@ private constructor( MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE + OTHER -> Value.OTHER else -> Value._UNKNOWN } @@ -3203,6 +3226,7 @@ private constructor( MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE + OTHER -> Known.OTHER else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -3376,6 +3400,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected @@ -3704,6 +3730,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type + * are read-only; `OTHER` cannot be used when creating a rule. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -4663,6 +4691,8 @@ private constructor( * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, ACH_DEBIT_RECEIPT, CARD_TRANSACTION_UPDATE, or * ACH_PAYMENT_UPDATE event stream. + * - `OTHER`: A rule whose type is not exposed through this API. Rules of this type are + * read-only; `OTHER` cannot be used when creating a rule. */ class AuthRuleType @JsonCreator @@ -4690,6 +4720,8 @@ private constructor( @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmField val OTHER = of("OTHER") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -4700,6 +4732,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, } /** @@ -4718,6 +4751,7 @@ private constructor( MERCHANT_LOCK, CONDITIONAL_ACTION, TYPESCRIPT_CODE, + OTHER, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -4739,6 +4773,7 @@ private constructor( MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE + OTHER -> Value.OTHER else -> Value._UNKNOWN } @@ -4758,6 +4793,7 @@ private constructor( MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE + OTHER -> Known.OTHER else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } From 71a8dc7df0db29dc489ba45c3c677e3d1dbeafa1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 16:13:03 +0000 Subject: [PATCH 02/15] feat(api): add EXTERNAL_STABLECOIN category/events to payments and account activity models --- .stats.yml | 4 +-- .../api/models/AccountActivityListParams.kt | 6 ++++ .../api/models/AccountActivityListResponse.kt | 6 ++++ ...ountActivityRetrieveTransactionResponse.kt | 6 ++++ .../com/lithic/api/models/ExternalPayment.kt | 36 +++++++++++++++++++ .../api/models/ExternalPaymentCreateParams.kt | 6 ++++ .../api/models/ExternalPaymentListParams.kt | 6 ++++ .../com/lithic/api/models/FinancialEvent.kt | 30 ++++++++++++++++ .../kotlin/com/lithic/api/models/Payment.kt | 6 ++++ .../lithic/api/models/StatementLineItems.kt | 36 +++++++++++++++++++ 10 files changed, 140 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9326df23d..36e76ee0a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 216 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-9a4064ca9be1efe3e33d922cae77a5d186b6a0119ef1d3601b5ded1447feb7f7.yml -openapi_spec_hash: bff457821129b2eb4fc5150e23efa197 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-61d6a4ff8361065995b3a743d6034b7deb3d307e3f3d0c9ef24010dd1b71d692.yml +openapi_spec_hash: 736b5c82d6b4a14788140fe05e0fbc30 config_hash: 27fa50e251754c8982e3dc615ef6da41 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt index 0dec1db34..3a1db69cc 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt @@ -414,6 +414,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmField val EXTERNAL_WIRE = of("EXTERNAL_WIRE") @@ -453,6 +455,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -489,6 +492,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -529,6 +533,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Value.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Value.MANAGEMENT_ADJUSTMENT @@ -567,6 +572,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Known.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Known.MANAGEMENT_ADJUSTMENT diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt index e5bff9e4c..972c5c9d8 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt @@ -1136,6 +1136,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmField val EXTERNAL_WIRE = of("EXTERNAL_WIRE") @@ -1175,6 +1177,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1213,6 +1216,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1253,6 +1257,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Value.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Value.MANAGEMENT_ADJUSTMENT @@ -1291,6 +1296,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Known.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Known.MANAGEMENT_ADJUSTMENT diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt index 7630a2e1e..52fa21012 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt @@ -1158,6 +1158,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmField val EXTERNAL_WIRE = of("EXTERNAL_WIRE") @@ -1197,6 +1199,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1235,6 +1238,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1275,6 +1279,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Value.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Value.MANAGEMENT_ADJUSTMENT @@ -1313,6 +1318,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Known.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Known.MANAGEMENT_ADJUSTMENT diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPayment.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPayment.kt index 7643d0349..f0a8f0132 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPayment.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPayment.kt @@ -866,6 +866,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmStatic fun of(value: String) = ExternalPaymentCategory(JsonField.of(value)) @@ -878,6 +880,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, } @@ -898,6 +901,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, /** * An enum member indicating that [ExternalPaymentCategory] was instantiated with an @@ -920,6 +924,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER else -> Value._UNKNOWN } @@ -940,6 +945,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER else -> throw LithicInvalidDataException("Unknown ExternalPaymentCategory: $value") } @@ -1792,6 +1798,16 @@ private constructor( @JvmField val EXTERNAL_RTP_RELEASED = of("EXTERNAL_RTP_RELEASED") + @JvmField val EXTERNAL_STABLECOIN_INITIATED = of("EXTERNAL_STABLECOIN_INITIATED") + + @JvmField val EXTERNAL_STABLECOIN_CANCELED = of("EXTERNAL_STABLECOIN_CANCELED") + + @JvmField val EXTERNAL_STABLECOIN_SETTLED = of("EXTERNAL_STABLECOIN_SETTLED") + + @JvmField val EXTERNAL_STABLECOIN_REVERSED = of("EXTERNAL_STABLECOIN_REVERSED") + + @JvmField val EXTERNAL_STABLECOIN_RELEASED = of("EXTERNAL_STABLECOIN_RELEASED") + @JvmStatic fun of(value: String) = ExternalPaymentEventType(JsonField.of(value)) } @@ -1827,6 +1843,11 @@ private constructor( EXTERNAL_RTP_SETTLED, EXTERNAL_RTP_REVERSED, EXTERNAL_RTP_RELEASED, + EXTERNAL_STABLECOIN_INITIATED, + EXTERNAL_STABLECOIN_CANCELED, + EXTERNAL_STABLECOIN_SETTLED, + EXTERNAL_STABLECOIN_REVERSED, + EXTERNAL_STABLECOIN_RELEASED, } /** @@ -1871,6 +1892,11 @@ private constructor( EXTERNAL_RTP_SETTLED, EXTERNAL_RTP_REVERSED, EXTERNAL_RTP_RELEASED, + EXTERNAL_STABLECOIN_INITIATED, + EXTERNAL_STABLECOIN_CANCELED, + EXTERNAL_STABLECOIN_SETTLED, + EXTERNAL_STABLECOIN_REVERSED, + EXTERNAL_STABLECOIN_RELEASED, /** * An enum member indicating that [ExternalPaymentEventType] was instantiated with * an unknown value. @@ -1917,6 +1943,11 @@ private constructor( EXTERNAL_RTP_SETTLED -> Value.EXTERNAL_RTP_SETTLED EXTERNAL_RTP_REVERSED -> Value.EXTERNAL_RTP_REVERSED EXTERNAL_RTP_RELEASED -> Value.EXTERNAL_RTP_RELEASED + EXTERNAL_STABLECOIN_INITIATED -> Value.EXTERNAL_STABLECOIN_INITIATED + EXTERNAL_STABLECOIN_CANCELED -> Value.EXTERNAL_STABLECOIN_CANCELED + EXTERNAL_STABLECOIN_SETTLED -> Value.EXTERNAL_STABLECOIN_SETTLED + EXTERNAL_STABLECOIN_REVERSED -> Value.EXTERNAL_STABLECOIN_REVERSED + EXTERNAL_STABLECOIN_RELEASED -> Value.EXTERNAL_STABLECOIN_RELEASED else -> Value._UNKNOWN } @@ -1961,6 +1992,11 @@ private constructor( EXTERNAL_RTP_SETTLED -> Known.EXTERNAL_RTP_SETTLED EXTERNAL_RTP_REVERSED -> Known.EXTERNAL_RTP_REVERSED EXTERNAL_RTP_RELEASED -> Known.EXTERNAL_RTP_RELEASED + EXTERNAL_STABLECOIN_INITIATED -> Known.EXTERNAL_STABLECOIN_INITIATED + EXTERNAL_STABLECOIN_CANCELED -> Known.EXTERNAL_STABLECOIN_CANCELED + EXTERNAL_STABLECOIN_SETTLED -> Known.EXTERNAL_STABLECOIN_SETTLED + EXTERNAL_STABLECOIN_REVERSED -> Known.EXTERNAL_STABLECOIN_REVERSED + EXTERNAL_STABLECOIN_RELEASED -> Known.EXTERNAL_STABLECOIN_RELEASED else -> throw LithicInvalidDataException("Unknown ExternalPaymentEventType: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentCreateParams.kt index 201de3314..9eef74f3a 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentCreateParams.kt @@ -1006,6 +1006,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmStatic fun of(value: String) = ExternalPaymentCategory(JsonField.of(value)) @@ -1018,6 +1020,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, } @@ -1038,6 +1041,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, /** * An enum member indicating that [ExternalPaymentCategory] was instantiated with an @@ -1060,6 +1064,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER else -> Value._UNKNOWN } @@ -1080,6 +1085,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER else -> throw LithicInvalidDataException("Unknown ExternalPaymentCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentListParams.kt index c4a356486..1969781a5 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ExternalPaymentListParams.kt @@ -386,6 +386,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmStatic fun of(value: String) = ExternalPaymentCategory(JsonField.of(value)) @@ -398,6 +400,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, } @@ -418,6 +421,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, /** * An enum member indicating that [ExternalPaymentCategory] was instantiated with an @@ -440,6 +444,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER else -> Value._UNKNOWN } @@ -460,6 +465,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER else -> throw LithicInvalidDataException("Unknown ExternalPaymentCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt index d7f28b871..b08c57268 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt @@ -555,6 +555,16 @@ private constructor( @JvmField val EXTERNAL_RTP_SETTLED = of("EXTERNAL_RTP_SETTLED") + @JvmField val EXTERNAL_STABLECOIN_CANCELED = of("EXTERNAL_STABLECOIN_CANCELED") + + @JvmField val EXTERNAL_STABLECOIN_INITIATED = of("EXTERNAL_STABLECOIN_INITIATED") + + @JvmField val EXTERNAL_STABLECOIN_RELEASED = of("EXTERNAL_STABLECOIN_RELEASED") + + @JvmField val EXTERNAL_STABLECOIN_REVERSED = of("EXTERNAL_STABLECOIN_REVERSED") + + @JvmField val EXTERNAL_STABLECOIN_SETTLED = of("EXTERNAL_STABLECOIN_SETTLED") + @JvmField val EXTERNAL_TRANSFER_CANCELED = of("EXTERNAL_TRANSFER_CANCELED") @JvmField val EXTERNAL_TRANSFER_INITIATED = of("EXTERNAL_TRANSFER_INITIATED") @@ -699,6 +709,11 @@ private constructor( EXTERNAL_RTP_RELEASED, EXTERNAL_RTP_REVERSED, EXTERNAL_RTP_SETTLED, + EXTERNAL_STABLECOIN_CANCELED, + EXTERNAL_STABLECOIN_INITIATED, + EXTERNAL_STABLECOIN_RELEASED, + EXTERNAL_STABLECOIN_REVERSED, + EXTERNAL_STABLECOIN_SETTLED, EXTERNAL_TRANSFER_CANCELED, EXTERNAL_TRANSFER_INITIATED, EXTERNAL_TRANSFER_RELEASED, @@ -807,6 +822,11 @@ private constructor( EXTERNAL_RTP_RELEASED, EXTERNAL_RTP_REVERSED, EXTERNAL_RTP_SETTLED, + EXTERNAL_STABLECOIN_CANCELED, + EXTERNAL_STABLECOIN_INITIATED, + EXTERNAL_STABLECOIN_RELEASED, + EXTERNAL_STABLECOIN_REVERSED, + EXTERNAL_STABLECOIN_SETTLED, EXTERNAL_TRANSFER_CANCELED, EXTERNAL_TRANSFER_INITIATED, EXTERNAL_TRANSFER_RELEASED, @@ -919,6 +939,11 @@ private constructor( EXTERNAL_RTP_RELEASED -> Value.EXTERNAL_RTP_RELEASED EXTERNAL_RTP_REVERSED -> Value.EXTERNAL_RTP_REVERSED EXTERNAL_RTP_SETTLED -> Value.EXTERNAL_RTP_SETTLED + EXTERNAL_STABLECOIN_CANCELED -> Value.EXTERNAL_STABLECOIN_CANCELED + EXTERNAL_STABLECOIN_INITIATED -> Value.EXTERNAL_STABLECOIN_INITIATED + EXTERNAL_STABLECOIN_RELEASED -> Value.EXTERNAL_STABLECOIN_RELEASED + EXTERNAL_STABLECOIN_REVERSED -> Value.EXTERNAL_STABLECOIN_REVERSED + EXTERNAL_STABLECOIN_SETTLED -> Value.EXTERNAL_STABLECOIN_SETTLED EXTERNAL_TRANSFER_CANCELED -> Value.EXTERNAL_TRANSFER_CANCELED EXTERNAL_TRANSFER_INITIATED -> Value.EXTERNAL_TRANSFER_INITIATED EXTERNAL_TRANSFER_RELEASED -> Value.EXTERNAL_TRANSFER_RELEASED @@ -1029,6 +1054,11 @@ private constructor( EXTERNAL_RTP_RELEASED -> Known.EXTERNAL_RTP_RELEASED EXTERNAL_RTP_REVERSED -> Known.EXTERNAL_RTP_REVERSED EXTERNAL_RTP_SETTLED -> Known.EXTERNAL_RTP_SETTLED + EXTERNAL_STABLECOIN_CANCELED -> Known.EXTERNAL_STABLECOIN_CANCELED + EXTERNAL_STABLECOIN_INITIATED -> Known.EXTERNAL_STABLECOIN_INITIATED + EXTERNAL_STABLECOIN_RELEASED -> Known.EXTERNAL_STABLECOIN_RELEASED + EXTERNAL_STABLECOIN_REVERSED -> Known.EXTERNAL_STABLECOIN_REVERSED + EXTERNAL_STABLECOIN_SETTLED -> Known.EXTERNAL_STABLECOIN_SETTLED EXTERNAL_TRANSFER_CANCELED -> Known.EXTERNAL_TRANSFER_CANCELED EXTERNAL_TRANSFER_INITIATED -> Known.EXTERNAL_TRANSFER_INITIATED EXTERNAL_TRANSFER_RELEASED -> Known.EXTERNAL_TRANSFER_RELEASED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt index 9290be4aa..585984833 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt @@ -1213,6 +1213,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmField val EXTERNAL_WIRE = of("EXTERNAL_WIRE") @@ -1252,6 +1254,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1288,6 +1291,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1328,6 +1332,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Value.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Value.MANAGEMENT_ADJUSTMENT @@ -1366,6 +1371,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Known.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Known.MANAGEMENT_ADJUSTMENT diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt index 7fc41b0d8..e23f281a6 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt @@ -979,6 +979,8 @@ private constructor( @JvmField val EXTERNAL_RTP = of("EXTERNAL_RTP") + @JvmField val EXTERNAL_STABLECOIN = of("EXTERNAL_STABLECOIN") + @JvmField val EXTERNAL_TRANSFER = of("EXTERNAL_TRANSFER") @JvmField val EXTERNAL_WIRE = of("EXTERNAL_WIRE") @@ -1018,6 +1020,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1056,6 +1059,7 @@ private constructor( EXTERNAL_CHECK, EXTERNAL_FEDNOW, EXTERNAL_RTP, + EXTERNAL_STABLECOIN, EXTERNAL_TRANSFER, EXTERNAL_WIRE, MANAGEMENT_ADJUSTMENT, @@ -1096,6 +1100,7 @@ private constructor( EXTERNAL_CHECK -> Value.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Value.EXTERNAL_FEDNOW EXTERNAL_RTP -> Value.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Value.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Value.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Value.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Value.MANAGEMENT_ADJUSTMENT @@ -1134,6 +1139,7 @@ private constructor( EXTERNAL_CHECK -> Known.EXTERNAL_CHECK EXTERNAL_FEDNOW -> Known.EXTERNAL_FEDNOW EXTERNAL_RTP -> Known.EXTERNAL_RTP + EXTERNAL_STABLECOIN -> Known.EXTERNAL_STABLECOIN EXTERNAL_TRANSFER -> Known.EXTERNAL_TRANSFER EXTERNAL_WIRE -> Known.EXTERNAL_WIRE MANAGEMENT_ADJUSTMENT -> Known.MANAGEMENT_ADJUSTMENT @@ -1333,6 +1339,16 @@ private constructor( @JvmField val EXTERNAL_RTP_SETTLED = of("EXTERNAL_RTP_SETTLED") + @JvmField val EXTERNAL_STABLECOIN_CANCELED = of("EXTERNAL_STABLECOIN_CANCELED") + + @JvmField val EXTERNAL_STABLECOIN_INITIATED = of("EXTERNAL_STABLECOIN_INITIATED") + + @JvmField val EXTERNAL_STABLECOIN_RELEASED = of("EXTERNAL_STABLECOIN_RELEASED") + + @JvmField val EXTERNAL_STABLECOIN_REVERSED = of("EXTERNAL_STABLECOIN_REVERSED") + + @JvmField val EXTERNAL_STABLECOIN_SETTLED = of("EXTERNAL_STABLECOIN_SETTLED") + @JvmField val EXTERNAL_TRANSFER_CANCELED = of("EXTERNAL_TRANSFER_CANCELED") @JvmField val EXTERNAL_TRANSFER_INITIATED = of("EXTERNAL_TRANSFER_INITIATED") @@ -1477,6 +1493,11 @@ private constructor( EXTERNAL_RTP_RELEASED, EXTERNAL_RTP_REVERSED, EXTERNAL_RTP_SETTLED, + EXTERNAL_STABLECOIN_CANCELED, + EXTERNAL_STABLECOIN_INITIATED, + EXTERNAL_STABLECOIN_RELEASED, + EXTERNAL_STABLECOIN_REVERSED, + EXTERNAL_STABLECOIN_SETTLED, EXTERNAL_TRANSFER_CANCELED, EXTERNAL_TRANSFER_INITIATED, EXTERNAL_TRANSFER_RELEASED, @@ -1587,6 +1608,11 @@ private constructor( EXTERNAL_RTP_RELEASED, EXTERNAL_RTP_REVERSED, EXTERNAL_RTP_SETTLED, + EXTERNAL_STABLECOIN_CANCELED, + EXTERNAL_STABLECOIN_INITIATED, + EXTERNAL_STABLECOIN_RELEASED, + EXTERNAL_STABLECOIN_REVERSED, + EXTERNAL_STABLECOIN_SETTLED, EXTERNAL_TRANSFER_CANCELED, EXTERNAL_TRANSFER_INITIATED, EXTERNAL_TRANSFER_RELEASED, @@ -1699,6 +1725,11 @@ private constructor( EXTERNAL_RTP_RELEASED -> Value.EXTERNAL_RTP_RELEASED EXTERNAL_RTP_REVERSED -> Value.EXTERNAL_RTP_REVERSED EXTERNAL_RTP_SETTLED -> Value.EXTERNAL_RTP_SETTLED + EXTERNAL_STABLECOIN_CANCELED -> Value.EXTERNAL_STABLECOIN_CANCELED + EXTERNAL_STABLECOIN_INITIATED -> Value.EXTERNAL_STABLECOIN_INITIATED + EXTERNAL_STABLECOIN_RELEASED -> Value.EXTERNAL_STABLECOIN_RELEASED + EXTERNAL_STABLECOIN_REVERSED -> Value.EXTERNAL_STABLECOIN_REVERSED + EXTERNAL_STABLECOIN_SETTLED -> Value.EXTERNAL_STABLECOIN_SETTLED EXTERNAL_TRANSFER_CANCELED -> Value.EXTERNAL_TRANSFER_CANCELED EXTERNAL_TRANSFER_INITIATED -> Value.EXTERNAL_TRANSFER_INITIATED EXTERNAL_TRANSFER_RELEASED -> Value.EXTERNAL_TRANSFER_RELEASED @@ -1809,6 +1840,11 @@ private constructor( EXTERNAL_RTP_RELEASED -> Known.EXTERNAL_RTP_RELEASED EXTERNAL_RTP_REVERSED -> Known.EXTERNAL_RTP_REVERSED EXTERNAL_RTP_SETTLED -> Known.EXTERNAL_RTP_SETTLED + EXTERNAL_STABLECOIN_CANCELED -> Known.EXTERNAL_STABLECOIN_CANCELED + EXTERNAL_STABLECOIN_INITIATED -> Known.EXTERNAL_STABLECOIN_INITIATED + EXTERNAL_STABLECOIN_RELEASED -> Known.EXTERNAL_STABLECOIN_RELEASED + EXTERNAL_STABLECOIN_REVERSED -> Known.EXTERNAL_STABLECOIN_REVERSED + EXTERNAL_STABLECOIN_SETTLED -> Known.EXTERNAL_STABLECOIN_SETTLED EXTERNAL_TRANSFER_CANCELED -> Known.EXTERNAL_TRANSFER_CANCELED EXTERNAL_TRANSFER_INITIATED -> Known.EXTERNAL_TRANSFER_INITIATED EXTERNAL_TRANSFER_RELEASED -> Known.EXTERNAL_TRANSFER_RELEASED From 585fdd50392d686c01877f07189ed696345267c8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:52:40 +0000 Subject: [PATCH 03/15] feat: TRE-14429: Document the stablecoin payments endpoint --- .stats.yml | 8 +- .../lithic/api/models/PaymentCreateParams.kt | 9 +- .../models/PaymentCreateStablecoinParams.kt | 1199 +++++++++++++++ .../models/PaymentCreateStablecoinResponse.kt | 1320 +++++++++++++++++ .../lithic/api/models/PaymentListParams.kt | 8 +- .../api/services/async/PaymentServiceAsync.kt | 54 +- .../services/async/PaymentServiceAsyncImpl.kt | 40 + .../api/services/blocking/PaymentService.kt | 54 +- .../services/blocking/PaymentServiceImpl.kt | 37 + .../PaymentCreateStablecoinParamsTest.kt | 79 + .../PaymentCreateStablecoinResponseTest.kt | 296 ++++ .../services/async/PaymentServiceAsyncTest.kt | 31 + .../services/blocking/PaymentServiceTest.kt | 30 + 13 files changed, 3157 insertions(+), 8 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponse.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponseTest.kt diff --git a/.stats.yml b/.stats.yml index 36e76ee0a..3bbc47373 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 216 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-61d6a4ff8361065995b3a743d6034b7deb3d307e3f3d0c9ef24010dd1b71d692.yml -openapi_spec_hash: 736b5c82d6b4a14788140fe05e0fbc30 -config_hash: 27fa50e251754c8982e3dc615ef6da41 +configured_endpoints: 217 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-70147140a7b2043acf622024eb3bde9b04264f8e9a695d4c79b5ee4db1534518.yml +openapi_spec_hash: 7a181cb1cfaaa201143bd9d04a841a2e +config_hash: e95c2dda5d175f9316457e0a84e35dce diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateParams.kt index 823df27a3..caf00b1b3 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateParams.kt @@ -21,7 +21,14 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Initiates a payment between a financial account and an external bank account. */ +/** + * Initiates an ACH payment between a financial account and an external bank account. + * + * This endpoint originates on the ACH rail only. To send a stablecoin payout, use the + * [Create stablecoin payment](https://docs.lithic.com/reference/createstablecoinpayment) endpoint. + * Payments on every rail are read back through + * [List payments](https://docs.lithic.com/reference/searchpayments). + */ class PaymentCreateParams private constructor( private val body: CreatePaymentRequest, diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinParams.kt new file mode 100644 index 000000000..6fcdc91d7 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinParams.kt @@ -0,0 +1,1199 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.Params +import com.lithic.api.core.checkRequired +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Initiates a stablecoin payout from a financial account to a registered blockchain recipient. + * + * The recipient must have been registered with + * [Create blockchain recipient](https://docs.lithic.com/reference/createblockchainrecipient) and + * have completed address screening — only a recipient in the `ENABLED` verification state can + * receive a payout. The destination address and chain come from the recipient, so they are not + * supplied here. + * + * Only payouts are initiated through this endpoint. Stablecoin pay-ins are credited from on-chain + * deposits to a financial account's deposit address and are not created through the API. Funds are + * placed on hold when the payout is initiated, and a payout that fails on chain reverses that hold. + * A payout cannot be cancelled once it has been submitted on chain. + * + * This endpoint is only available to stablecoin-enabled programs. Contact your customer success + * manager to learn more. + */ +class PaymentCreateStablecoinParams +private constructor( + private val body: CreateStablecoinPaymentRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** + * Payout amount in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amount(): Long = body.amount() + + /** + * Token of the blockchain recipient to send the payout to. The recipient must be in the + * `ENABLED` verification state + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun blockchainRecipientToken(): String = body.blockchainRecipientToken() + + /** + * Token of the financial account the payout is funded from + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun financialAccountToken(): String = body.financialAccountToken() + + /** + * Direction of the payment. Stablecoin supports payouts only + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = body.type() + + /** + * Customer-provided token that will serve as an idempotency token. This token will become the + * transaction token + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun token(): Optional = body.token() + + /** + * Optional hold to settle when this payout is initiated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun hold(): Optional = body.hold() + + /** + * Memo recorded on the payout. Defaults to `Stablecoin payout on ` when omitted + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = body.memo() + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _amount(): JsonField = body._amount() + + /** + * Returns the raw JSON value of [blockchainRecipientToken]. + * + * Unlike [blockchainRecipientToken], this method doesn't throw if the JSON field has an + * unexpected type. + */ + fun _blockchainRecipientToken(): JsonField = body._blockchainRecipientToken() + + /** + * Returns the raw JSON value of [financialAccountToken]. + * + * Unlike [financialAccountToken], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _financialAccountToken(): JsonField = body._financialAccountToken() + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _type(): JsonField = body._type() + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _token(): JsonField = body._token() + + /** + * Returns the raw JSON value of [hold]. + * + * Unlike [hold], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _hold(): JsonField = body._hold() + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _memo(): JsonField = body._memo() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [PaymentCreateStablecoinParams]. + * + * The following fields are required: + * ```java + * .amount() + * .blockchainRecipientToken() + * .financialAccountToken() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [PaymentCreateStablecoinParams]. */ + class Builder internal constructor() { + + private var body: CreateStablecoinPaymentRequest.Builder = + CreateStablecoinPaymentRequest.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(paymentCreateStablecoinParams: PaymentCreateStablecoinParams) = apply { + body = paymentCreateStablecoinParams.body.toBuilder() + additionalHeaders = paymentCreateStablecoinParams.additionalHeaders.toBuilder() + additionalQueryParams = paymentCreateStablecoinParams.additionalQueryParams.toBuilder() + } + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [amount] + * - [blockchainRecipientToken] + * - [financialAccountToken] + * - [type] + * - [token] + * - etc. + */ + fun body(body: CreateStablecoinPaymentRequest) = apply { this.body = body.toBuilder() } + + /** Payout amount in cents */ + fun amount(amount: Long) = apply { body.amount(amount) } + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { body.amount(amount) } + + /** + * Token of the blockchain recipient to send the payout to. The recipient must be in the + * `ENABLED` verification state + */ + fun blockchainRecipientToken(blockchainRecipientToken: String) = apply { + body.blockchainRecipientToken(blockchainRecipientToken) + } + + /** + * Sets [Builder.blockchainRecipientToken] to an arbitrary JSON value. + * + * You should usually call [Builder.blockchainRecipientToken] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun blockchainRecipientToken(blockchainRecipientToken: JsonField) = apply { + body.blockchainRecipientToken(blockchainRecipientToken) + } + + /** Token of the financial account the payout is funded from */ + fun financialAccountToken(financialAccountToken: String) = apply { + body.financialAccountToken(financialAccountToken) + } + + /** + * Sets [Builder.financialAccountToken] to an arbitrary JSON value. + * + * You should usually call [Builder.financialAccountToken] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun financialAccountToken(financialAccountToken: JsonField) = apply { + body.financialAccountToken(financialAccountToken) + } + + /** Direction of the payment. Stablecoin supports payouts only */ + fun type(type: Type) = apply { body.type(type) } + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { body.type(type) } + + /** + * Customer-provided token that will serve as an idempotency token. This token will become + * the transaction token + */ + fun token(token: String) = apply { body.token(token) } + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { body.token(token) } + + /** Optional hold to settle when this payout is initiated */ + fun hold(hold: Hold) = apply { body.hold(hold) } + + /** + * Sets [Builder.hold] to an arbitrary JSON value. + * + * You should usually call [Builder.hold] with a well-typed [Hold] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun hold(hold: JsonField) = apply { body.hold(hold) } + + /** Memo recorded on the payout. Defaults to `Stablecoin payout on ` when omitted */ + fun memo(memo: String) = apply { body.memo(memo) } + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun memo(memo: JsonField) = apply { body.memo(memo) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PaymentCreateStablecoinParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .amount() + * .blockchainRecipientToken() + * .financialAccountToken() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PaymentCreateStablecoinParams = + PaymentCreateStablecoinParams( + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): CreateStablecoinPaymentRequest = body + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + class CreateStablecoinPaymentRequest + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val blockchainRecipientToken: JsonField, + private val financialAccountToken: JsonField, + private val type: JsonField, + private val token: JsonField, + private val hold: JsonField, + private val memo: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("blockchain_recipient_token") + @ExcludeMissing + blockchainRecipientToken: JsonField = JsonMissing.of(), + @JsonProperty("financial_account_token") + @ExcludeMissing + financialAccountToken: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("hold") @ExcludeMissing hold: JsonField = JsonMissing.of(), + @JsonProperty("memo") @ExcludeMissing memo: JsonField = JsonMissing.of(), + ) : this( + amount, + blockchainRecipientToken, + financialAccountToken, + type, + token, + hold, + memo, + mutableMapOf(), + ) + + /** + * Payout amount in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amount(): Long = amount.getRequired("amount") + + /** + * Token of the blockchain recipient to send the payout to. The recipient must be in the + * `ENABLED` verification state + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun blockchainRecipientToken(): String = + blockchainRecipientToken.getRequired("blockchain_recipient_token") + + /** + * Token of the financial account the payout is funded from + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun financialAccountToken(): String = + financialAccountToken.getRequired("financial_account_token") + + /** + * Direction of the payment. Stablecoin supports payouts only + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * Customer-provided token that will serve as an idempotency token. This token will become + * the transaction token + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun token(): Optional = token.getOptional("token") + + /** + * Optional hold to settle when this payout is initiated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun hold(): Optional = hold.getOptional("hold") + + /** + * Memo recorded on the payout. Defaults to `Stablecoin payout on ` when omitted + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = memo.getOptional("memo") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [blockchainRecipientToken]. + * + * Unlike [blockchainRecipientToken], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("blockchain_recipient_token") + @ExcludeMissing + fun _blockchainRecipientToken(): JsonField = blockchainRecipientToken + + /** + * Returns the raw JSON value of [financialAccountToken]. + * + * Unlike [financialAccountToken], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("financial_account_token") + @ExcludeMissing + fun _financialAccountToken(): JsonField = financialAccountToken + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [hold]. + * + * Unlike [hold], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("hold") @ExcludeMissing fun _hold(): JsonField = hold + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("memo") @ExcludeMissing fun _memo(): JsonField = memo + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [CreateStablecoinPaymentRequest]. + * + * The following fields are required: + * ```java + * .amount() + * .blockchainRecipientToken() + * .financialAccountToken() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CreateStablecoinPaymentRequest]. */ + class Builder internal constructor() { + + private var amount: JsonField? = null + private var blockchainRecipientToken: JsonField? = null + private var financialAccountToken: JsonField? = null + private var type: JsonField? = null + private var token: JsonField = JsonMissing.of() + private var hold: JsonField = JsonMissing.of() + private var memo: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(createStablecoinPaymentRequest: CreateStablecoinPaymentRequest) = + apply { + amount = createStablecoinPaymentRequest.amount + blockchainRecipientToken = + createStablecoinPaymentRequest.blockchainRecipientToken + financialAccountToken = createStablecoinPaymentRequest.financialAccountToken + type = createStablecoinPaymentRequest.type + token = createStablecoinPaymentRequest.token + hold = createStablecoinPaymentRequest.hold + memo = createStablecoinPaymentRequest.memo + additionalProperties = + createStablecoinPaymentRequest.additionalProperties.toMutableMap() + } + + /** Payout amount in cents */ + fun amount(amount: Long) = amount(JsonField.of(amount)) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** + * Token of the blockchain recipient to send the payout to. The recipient must be in the + * `ENABLED` verification state + */ + fun blockchainRecipientToken(blockchainRecipientToken: String) = + blockchainRecipientToken(JsonField.of(blockchainRecipientToken)) + + /** + * Sets [Builder.blockchainRecipientToken] to an arbitrary JSON value. + * + * You should usually call [Builder.blockchainRecipientToken] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun blockchainRecipientToken(blockchainRecipientToken: JsonField) = apply { + this.blockchainRecipientToken = blockchainRecipientToken + } + + /** Token of the financial account the payout is funded from */ + fun financialAccountToken(financialAccountToken: String) = + financialAccountToken(JsonField.of(financialAccountToken)) + + /** + * Sets [Builder.financialAccountToken] to an arbitrary JSON value. + * + * You should usually call [Builder.financialAccountToken] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun financialAccountToken(financialAccountToken: JsonField) = apply { + this.financialAccountToken = financialAccountToken + } + + /** Direction of the payment. Stablecoin supports payouts only */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** + * Customer-provided token that will serve as an idempotency token. This token will + * become the transaction token + */ + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + /** Optional hold to settle when this payout is initiated */ + fun hold(hold: Hold) = hold(JsonField.of(hold)) + + /** + * Sets [Builder.hold] to an arbitrary JSON value. + * + * You should usually call [Builder.hold] with a well-typed [Hold] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun hold(hold: JsonField) = apply { this.hold = hold } + + /** + * Memo recorded on the payout. Defaults to `Stablecoin payout on ` when omitted + */ + fun memo(memo: String) = memo(JsonField.of(memo)) + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun memo(memo: JsonField) = apply { this.memo = memo } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CreateStablecoinPaymentRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .amount() + * .blockchainRecipientToken() + * .financialAccountToken() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CreateStablecoinPaymentRequest = + CreateStablecoinPaymentRequest( + checkRequired("amount", amount), + checkRequired("blockchainRecipientToken", blockchainRecipientToken), + checkRequired("financialAccountToken", financialAccountToken), + checkRequired("type", type), + token, + hold, + memo, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): CreateStablecoinPaymentRequest = apply { + if (validated) { + return@apply + } + + amount() + blockchainRecipientToken() + financialAccountToken() + type().validate() + token() + hold().ifPresent { it.validate() } + memo() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + + (if (blockchainRecipientToken.asKnown().isPresent) 1 else 0) + + (if (financialAccountToken.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (token.asKnown().isPresent) 1 else 0) + + (hold.asKnown().getOrNull()?.validity() ?: 0) + + (if (memo.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CreateStablecoinPaymentRequest && + amount == other.amount && + blockchainRecipientToken == other.blockchainRecipientToken && + financialAccountToken == other.financialAccountToken && + type == other.type && + token == other.token && + hold == other.hold && + memo == other.memo && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + blockchainRecipientToken, + financialAccountToken, + type, + token, + hold, + memo, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CreateStablecoinPaymentRequest{amount=$amount, blockchainRecipientToken=$blockchainRecipientToken, financialAccountToken=$financialAccountToken, type=$type, token=$token, hold=$hold, memo=$memo, additionalProperties=$additionalProperties}" + } + + /** Direction of the payment. Stablecoin supports payouts only */ + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PAYMENT = of("PAYMENT") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + PAYMENT + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PAYMENT, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PAYMENT -> Value.PAYMENT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PAYMENT -> Known.PAYMENT + else -> throw LithicInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Optional hold to settle when this payout is initiated */ + class Hold + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val token: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of() + ) : this(token, mutableMapOf()) + + /** + * Token of the hold to settle when this payout is initiated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun token(): String = token.getRequired("token") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Hold]. + * + * The following fields are required: + * ```java + * .token() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Hold]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(hold: Hold) = apply { + token = hold.token + additionalProperties = hold.additionalProperties.toMutableMap() + } + + /** Token of the hold to settle when this payout is initiated */ + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Hold]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Hold = + Hold(checkRequired("token", token), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Hold = apply { + if (validated) { + return@apply + } + + token() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Hold && + token == other.token && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(token, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Hold{token=$token, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PaymentCreateStablecoinParams && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PaymentCreateStablecoinParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponse.kt new file mode 100644 index 000000000..b9730eb14 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponse.kt @@ -0,0 +1,1320 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.time.LocalDate +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Payment transaction */ +class PaymentCreateStablecoinResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val token: JsonField, + private val category: JsonField, + private val created: JsonField, + private val descriptor: JsonField, + private val direction: JsonField, + private val events: JsonField>, + private val family: JsonField, + private val financialAccountToken: JsonField, + private val method: JsonField, + private val methodAttributes: JsonField, + private val pendingAmount: JsonField, + private val relatedAccountTokens: JsonField, + private val result: JsonField, + private val settledAmount: JsonField, + private val source: JsonField, + private val status: JsonField, + private val updated: JsonField, + private val blockchainRecipientToken: JsonField, + private val currency: JsonField, + private val expectedReleaseDate: JsonField, + private val externalBankAccountToken: JsonField, + private val tags: JsonField, + private val type: JsonField, + private val userDefinedId: JsonField, + private val balance: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("category") + @ExcludeMissing + category: JsonField = JsonMissing.of(), + @JsonProperty("created") + @ExcludeMissing + created: JsonField = JsonMissing.of(), + @JsonProperty("descriptor") + @ExcludeMissing + descriptor: JsonField = JsonMissing.of(), + @JsonProperty("direction") + @ExcludeMissing + direction: JsonField = JsonMissing.of(), + @JsonProperty("events") + @ExcludeMissing + events: JsonField> = JsonMissing.of(), + @JsonProperty("family") + @ExcludeMissing + family: JsonField = JsonMissing.of(), + @JsonProperty("financial_account_token") + @ExcludeMissing + financialAccountToken: JsonField = JsonMissing.of(), + @JsonProperty("method") + @ExcludeMissing + method: JsonField = JsonMissing.of(), + @JsonProperty("method_attributes") + @ExcludeMissing + methodAttributes: JsonField = JsonMissing.of(), + @JsonProperty("pending_amount") + @ExcludeMissing + pendingAmount: JsonField = JsonMissing.of(), + @JsonProperty("related_account_tokens") + @ExcludeMissing + relatedAccountTokens: JsonField = JsonMissing.of(), + @JsonProperty("result") + @ExcludeMissing + result: JsonField = JsonMissing.of(), + @JsonProperty("settled_amount") + @ExcludeMissing + settledAmount: JsonField = JsonMissing.of(), + @JsonProperty("source") + @ExcludeMissing + source: JsonField = JsonMissing.of(), + @JsonProperty("status") + @ExcludeMissing + status: JsonField = JsonMissing.of(), + @JsonProperty("updated") + @ExcludeMissing + updated: JsonField = JsonMissing.of(), + @JsonProperty("blockchain_recipient_token") + @ExcludeMissing + blockchainRecipientToken: JsonField = JsonMissing.of(), + @JsonProperty("currency") @ExcludeMissing currency: JsonField = JsonMissing.of(), + @JsonProperty("expected_release_date") + @ExcludeMissing + expectedReleaseDate: JsonField = JsonMissing.of(), + @JsonProperty("external_bank_account_token") + @ExcludeMissing + externalBankAccountToken: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("user_defined_id") + @ExcludeMissing + userDefinedId: JsonField = JsonMissing.of(), + @JsonProperty("balance") @ExcludeMissing balance: JsonField = JsonMissing.of(), + ) : this( + token, + category, + created, + descriptor, + direction, + events, + family, + financialAccountToken, + method, + methodAttributes, + pendingAmount, + relatedAccountTokens, + result, + settledAmount, + source, + status, + updated, + blockchainRecipientToken, + currency, + expectedReleaseDate, + externalBankAccountToken, + tags, + type, + userDefinedId, + balance, + mutableMapOf(), + ) + + fun toPayment(): Payment = + Payment.builder() + .token(token) + .category(category) + .created(created) + .descriptor(descriptor) + .direction(direction) + .events(events) + .family(family) + .financialAccountToken(financialAccountToken) + .method(method) + .methodAttributes(methodAttributes) + .pendingAmount(pendingAmount) + .relatedAccountTokens(relatedAccountTokens) + .result(result) + .settledAmount(settledAmount) + .source(source) + .status(status) + .updated(updated) + .blockchainRecipientToken(blockchainRecipientToken) + .currency(currency) + .expectedReleaseDate(expectedReleaseDate) + .externalBankAccountToken(externalBankAccountToken) + .tags(tags) + .type(type) + .userDefinedId(userDefinedId) + .build() + + /** + * Unique identifier for the transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun token(): String = token.getRequired("token") + + /** + * Transaction category + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun category(): Payment.TransactionCategory = category.getRequired("category") + + /** + * ISO 8601 timestamp of when the transaction was created + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun created(): OffsetDateTime = created.getRequired("created") + + /** + * Transaction descriptor + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun descriptor(): String = descriptor.getRequired("descriptor") + + /** + * Transfer direction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun direction(): Payment.Direction = direction.getRequired("direction") + + /** + * List of transaction events + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun events(): List = events.getRequired("events") + + /** + * PAYMENT - Payment Transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun family(): Payment.Family = family.getRequired("family") + + /** + * Financial account token + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun financialAccountToken(): String = + financialAccountToken.getRequired("financial_account_token") + + /** + * Transfer method + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun method(): Payment.Method = method.getRequired("method") + + /** + * Method-specific attributes + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun methodAttributes(): Payment.MethodAttributes = + methodAttributes.getRequired("method_attributes") + + /** + * Pending amount in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun pendingAmount(): Long = pendingAmount.getRequired("pending_amount") + + /** + * Account tokens related to a payment transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun relatedAccountTokens(): Optional = + relatedAccountTokens.getOptional("related_account_tokens") + + /** + * Transaction result + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun result(): Payment.TransactionResult = result.getRequired("result") + + /** + * Settled amount in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun settledAmount(): Long = settledAmount.getRequired("settled_amount") + + /** + * Transaction source + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun source(): Payment.Source = source.getRequired("source") + + /** + * The status of the transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun status(): Payment.TransactionStatus = status.getRequired("status") + + /** + * ISO 8601 timestamp of when the transaction was last updated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun updated(): OffsetDateTime = updated.getRequired("updated") + + /** + * Token of the blockchain recipient the payout is sent to + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun blockchainRecipientToken(): Optional = + blockchainRecipientToken.getOptional("blockchain_recipient_token") + + /** + * Currency of the transaction in ISO 4217 format + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun currency(): Optional = currency.getOptional("currency") + + /** + * Expected release date for the transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun expectedReleaseDate(): Optional = + expectedReleaseDate.getOptional("expected_release_date") + + /** + * External bank account token + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun externalBankAccountToken(): Optional = + externalBankAccountToken.getOptional("external_bank_account_token") + + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata with a + * resource for your own purposes. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun tags(): Optional = tags.getOptional("tags") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") + + /** + * User-defined identifier + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun userDefinedId(): Optional = userDefinedId.getOptional("user_defined_id") + + /** + * Balance + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun balance(): Optional = balance.getOptional("balance") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [category]. + * + * Unlike [category], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("category") + @ExcludeMissing + fun _category(): JsonField = category + + /** + * Returns the raw JSON value of [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [descriptor]. + * + * Unlike [descriptor], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("descriptor") @ExcludeMissing fun _descriptor(): JsonField = descriptor + + /** + * Returns the raw JSON value of [direction]. + * + * Unlike [direction], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("direction") + @ExcludeMissing + fun _direction(): JsonField = direction + + /** + * Returns the raw JSON value of [events]. + * + * Unlike [events], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("events") + @ExcludeMissing + fun _events(): JsonField> = events + + /** + * Returns the raw JSON value of [family]. + * + * Unlike [family], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("family") @ExcludeMissing fun _family(): JsonField = family + + /** + * Returns the raw JSON value of [financialAccountToken]. + * + * Unlike [financialAccountToken], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("financial_account_token") + @ExcludeMissing + fun _financialAccountToken(): JsonField = financialAccountToken + + /** + * Returns the raw JSON value of [method]. + * + * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method + + /** + * Returns the raw JSON value of [methodAttributes]. + * + * Unlike [methodAttributes], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("method_attributes") + @ExcludeMissing + fun _methodAttributes(): JsonField = methodAttributes + + /** + * Returns the raw JSON value of [pendingAmount]. + * + * Unlike [pendingAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pending_amount") + @ExcludeMissing + fun _pendingAmount(): JsonField = pendingAmount + + /** + * Returns the raw JSON value of [relatedAccountTokens]. + * + * Unlike [relatedAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("related_account_tokens") + @ExcludeMissing + fun _relatedAccountTokens(): JsonField = relatedAccountTokens + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") + @ExcludeMissing + fun _result(): JsonField = result + + /** + * Returns the raw JSON value of [settledAmount]. + * + * Unlike [settledAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("settled_amount") + @ExcludeMissing + fun _settledAmount(): JsonField = settledAmount + + /** + * Returns the raw JSON value of [source]. + * + * Unlike [source], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("source") @ExcludeMissing fun _source(): JsonField = source + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") + @ExcludeMissing + fun _status(): JsonField = status + + /** + * Returns the raw JSON value of [updated]. + * + * Unlike [updated], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated") @ExcludeMissing fun _updated(): JsonField = updated + + /** + * Returns the raw JSON value of [blockchainRecipientToken]. + * + * Unlike [blockchainRecipientToken], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("blockchain_recipient_token") + @ExcludeMissing + fun _blockchainRecipientToken(): JsonField = blockchainRecipientToken + + /** + * Returns the raw JSON value of [currency]. + * + * Unlike [currency], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("currency") @ExcludeMissing fun _currency(): JsonField = currency + + /** + * Returns the raw JSON value of [expectedReleaseDate]. + * + * Unlike [expectedReleaseDate], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("expected_release_date") + @ExcludeMissing + fun _expectedReleaseDate(): JsonField = expectedReleaseDate + + /** + * Returns the raw JSON value of [externalBankAccountToken]. + * + * Unlike [externalBankAccountToken], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("external_bank_account_token") + @ExcludeMissing + fun _externalBankAccountToken(): JsonField = externalBankAccountToken + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField = tags + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [userDefinedId]. + * + * Unlike [userDefinedId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("user_defined_id") + @ExcludeMissing + fun _userDefinedId(): JsonField = userDefinedId + + /** + * Returns the raw JSON value of [balance]. + * + * Unlike [balance], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("balance") @ExcludeMissing fun _balance(): JsonField = balance + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [PaymentCreateStablecoinResponse]. + * + * The following fields are required: + * ```java + * .token() + * .category() + * .created() + * .descriptor() + * .direction() + * .events() + * .family() + * .financialAccountToken() + * .method() + * .methodAttributes() + * .pendingAmount() + * .relatedAccountTokens() + * .result() + * .settledAmount() + * .source() + * .status() + * .updated() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [PaymentCreateStablecoinResponse]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var category: JsonField? = null + private var created: JsonField? = null + private var descriptor: JsonField? = null + private var direction: JsonField? = null + private var events: JsonField>? = null + private var family: JsonField? = null + private var financialAccountToken: JsonField? = null + private var method: JsonField? = null + private var methodAttributes: JsonField? = null + private var pendingAmount: JsonField? = null + private var relatedAccountTokens: JsonField? = null + private var result: JsonField? = null + private var settledAmount: JsonField? = null + private var source: JsonField? = null + private var status: JsonField? = null + private var updated: JsonField? = null + private var blockchainRecipientToken: JsonField = JsonMissing.of() + private var currency: JsonField = JsonMissing.of() + private var expectedReleaseDate: JsonField = JsonMissing.of() + private var externalBankAccountToken: JsonField = JsonMissing.of() + private var tags: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var userDefinedId: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(paymentCreateStablecoinResponse: PaymentCreateStablecoinResponse) = + apply { + token = paymentCreateStablecoinResponse.token + category = paymentCreateStablecoinResponse.category + created = paymentCreateStablecoinResponse.created + descriptor = paymentCreateStablecoinResponse.descriptor + direction = paymentCreateStablecoinResponse.direction + events = paymentCreateStablecoinResponse.events.map { it.toMutableList() } + family = paymentCreateStablecoinResponse.family + financialAccountToken = paymentCreateStablecoinResponse.financialAccountToken + method = paymentCreateStablecoinResponse.method + methodAttributes = paymentCreateStablecoinResponse.methodAttributes + pendingAmount = paymentCreateStablecoinResponse.pendingAmount + relatedAccountTokens = paymentCreateStablecoinResponse.relatedAccountTokens + result = paymentCreateStablecoinResponse.result + settledAmount = paymentCreateStablecoinResponse.settledAmount + source = paymentCreateStablecoinResponse.source + status = paymentCreateStablecoinResponse.status + updated = paymentCreateStablecoinResponse.updated + blockchainRecipientToken = paymentCreateStablecoinResponse.blockchainRecipientToken + currency = paymentCreateStablecoinResponse.currency + expectedReleaseDate = paymentCreateStablecoinResponse.expectedReleaseDate + externalBankAccountToken = paymentCreateStablecoinResponse.externalBankAccountToken + tags = paymentCreateStablecoinResponse.tags + type = paymentCreateStablecoinResponse.type + userDefinedId = paymentCreateStablecoinResponse.userDefinedId + balance = paymentCreateStablecoinResponse.balance + additionalProperties = + paymentCreateStablecoinResponse.additionalProperties.toMutableMap() + } + + /** Unique identifier for the transaction */ + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + /** Transaction category */ + fun category(category: Payment.TransactionCategory) = category(JsonField.of(category)) + + /** + * Sets [Builder.category] to an arbitrary JSON value. + * + * You should usually call [Builder.category] with a well-typed + * [Payment.TransactionCategory] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun category(category: JsonField) = apply { + this.category = category + } + + /** ISO 8601 timestamp of when the transaction was created */ + fun created(created: OffsetDateTime) = created(JsonField.of(created)) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + /** Transaction descriptor */ + fun descriptor(descriptor: String) = descriptor(JsonField.of(descriptor)) + + /** + * Sets [Builder.descriptor] to an arbitrary JSON value. + * + * You should usually call [Builder.descriptor] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun descriptor(descriptor: JsonField) = apply { this.descriptor = descriptor } + + /** Transfer direction */ + fun direction(direction: Payment.Direction) = direction(JsonField.of(direction)) + + /** + * Sets [Builder.direction] to an arbitrary JSON value. + * + * You should usually call [Builder.direction] with a well-typed [Payment.Direction] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun direction(direction: JsonField) = apply { + this.direction = direction + } + + /** List of transaction events */ + fun events(events: List) = events(JsonField.of(events)) + + /** + * Sets [Builder.events] to an arbitrary JSON value. + * + * You should usually call [Builder.events] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun events(events: JsonField>) = apply { + this.events = events.map { it.toMutableList() } + } + + /** + * Adds a single [Payment.PaymentEvent] to [events]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addEvent(event: Payment.PaymentEvent) = apply { + events = + (events ?: JsonField.of(mutableListOf())).also { + checkKnown("events", it).add(event) + } + } + + /** PAYMENT - Payment Transaction */ + fun family(family: Payment.Family) = family(JsonField.of(family)) + + /** + * Sets [Builder.family] to an arbitrary JSON value. + * + * You should usually call [Builder.family] with a well-typed [Payment.Family] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun family(family: JsonField) = apply { this.family = family } + + /** Financial account token */ + fun financialAccountToken(financialAccountToken: String) = + financialAccountToken(JsonField.of(financialAccountToken)) + + /** + * Sets [Builder.financialAccountToken] to an arbitrary JSON value. + * + * You should usually call [Builder.financialAccountToken] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun financialAccountToken(financialAccountToken: JsonField) = apply { + this.financialAccountToken = financialAccountToken + } + + /** Transfer method */ + fun method(method: Payment.Method) = method(JsonField.of(method)) + + /** + * Sets [Builder.method] to an arbitrary JSON value. + * + * You should usually call [Builder.method] with a well-typed [Payment.Method] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun method(method: JsonField) = apply { this.method = method } + + /** Method-specific attributes */ + fun methodAttributes(methodAttributes: Payment.MethodAttributes) = + methodAttributes(JsonField.of(methodAttributes)) + + /** + * Sets [Builder.methodAttributes] to an arbitrary JSON value. + * + * You should usually call [Builder.methodAttributes] with a well-typed + * [Payment.MethodAttributes] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun methodAttributes(methodAttributes: JsonField) = apply { + this.methodAttributes = methodAttributes + } + + /** Alias for calling [methodAttributes] with `Payment.MethodAttributes.ofAch(ach)`. */ + fun methodAttributes(ach: Payment.MethodAttributes.AchMethodAttributes) = + methodAttributes(Payment.MethodAttributes.ofAch(ach)) + + /** Alias for calling [methodAttributes] with `Payment.MethodAttributes.ofWire(wire)`. */ + fun methodAttributes(wire: Payment.MethodAttributes.WireMethodAttributes) = + methodAttributes(Payment.MethodAttributes.ofWire(wire)) + + /** + * Alias for calling [methodAttributes] with + * `Payment.MethodAttributes.ofStablecoin(stablecoin)`. + */ + fun methodAttributes(stablecoin: Payment.MethodAttributes.StablecoinMethodAttributes) = + methodAttributes(Payment.MethodAttributes.ofStablecoin(stablecoin)) + + /** Pending amount in cents */ + fun pendingAmount(pendingAmount: Long) = pendingAmount(JsonField.of(pendingAmount)) + + /** + * Sets [Builder.pendingAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.pendingAmount] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun pendingAmount(pendingAmount: JsonField) = apply { + this.pendingAmount = pendingAmount + } + + /** Account tokens related to a payment transaction */ + fun relatedAccountTokens(relatedAccountTokens: Payment.RelatedAccountTokens?) = + relatedAccountTokens(JsonField.ofNullable(relatedAccountTokens)) + + /** + * Alias for calling [Builder.relatedAccountTokens] with + * `relatedAccountTokens.orElse(null)`. + */ + fun relatedAccountTokens(relatedAccountTokens: Optional) = + relatedAccountTokens(relatedAccountTokens.getOrNull()) + + /** + * Sets [Builder.relatedAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.relatedAccountTokens] with a well-typed + * [Payment.RelatedAccountTokens] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun relatedAccountTokens(relatedAccountTokens: JsonField) = + apply { + this.relatedAccountTokens = relatedAccountTokens + } + + /** Transaction result */ + fun result(result: Payment.TransactionResult) = result(JsonField.of(result)) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed [Payment.TransactionResult] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun result(result: JsonField) = apply { this.result = result } + + /** Settled amount in cents */ + fun settledAmount(settledAmount: Long) = settledAmount(JsonField.of(settledAmount)) + + /** + * Sets [Builder.settledAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.settledAmount] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun settledAmount(settledAmount: JsonField) = apply { + this.settledAmount = settledAmount + } + + /** Transaction source */ + fun source(source: Payment.Source) = source(JsonField.of(source)) + + /** + * Sets [Builder.source] to an arbitrary JSON value. + * + * You should usually call [Builder.source] with a well-typed [Payment.Source] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun source(source: JsonField) = apply { this.source = source } + + /** The status of the transaction */ + fun status(status: Payment.TransactionStatus) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Payment.TransactionStatus] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** ISO 8601 timestamp of when the transaction was last updated */ + fun updated(updated: OffsetDateTime) = updated(JsonField.of(updated)) + + /** + * Sets [Builder.updated] to an arbitrary JSON value. + * + * You should usually call [Builder.updated] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun updated(updated: JsonField) = apply { this.updated = updated } + + /** Token of the blockchain recipient the payout is sent to */ + fun blockchainRecipientToken(blockchainRecipientToken: String?) = + blockchainRecipientToken(JsonField.ofNullable(blockchainRecipientToken)) + + /** + * Alias for calling [Builder.blockchainRecipientToken] with + * `blockchainRecipientToken.orElse(null)`. + */ + fun blockchainRecipientToken(blockchainRecipientToken: Optional) = + blockchainRecipientToken(blockchainRecipientToken.getOrNull()) + + /** + * Sets [Builder.blockchainRecipientToken] to an arbitrary JSON value. + * + * You should usually call [Builder.blockchainRecipientToken] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun blockchainRecipientToken(blockchainRecipientToken: JsonField) = apply { + this.blockchainRecipientToken = blockchainRecipientToken + } + + /** Currency of the transaction in ISO 4217 format */ + fun currency(currency: String) = currency(JsonField.of(currency)) + + /** + * Sets [Builder.currency] to an arbitrary JSON value. + * + * You should usually call [Builder.currency] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun currency(currency: JsonField) = apply { this.currency = currency } + + /** Expected release date for the transaction */ + fun expectedReleaseDate(expectedReleaseDate: LocalDate?) = + expectedReleaseDate(JsonField.ofNullable(expectedReleaseDate)) + + /** + * Alias for calling [Builder.expectedReleaseDate] with `expectedReleaseDate.orElse(null)`. + */ + fun expectedReleaseDate(expectedReleaseDate: Optional) = + expectedReleaseDate(expectedReleaseDate.getOrNull()) + + /** + * Sets [Builder.expectedReleaseDate] to an arbitrary JSON value. + * + * You should usually call [Builder.expectedReleaseDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun expectedReleaseDate(expectedReleaseDate: JsonField) = apply { + this.expectedReleaseDate = expectedReleaseDate + } + + /** External bank account token */ + fun externalBankAccountToken(externalBankAccountToken: String?) = + externalBankAccountToken(JsonField.ofNullable(externalBankAccountToken)) + + /** + * Alias for calling [Builder.externalBankAccountToken] with + * `externalBankAccountToken.orElse(null)`. + */ + fun externalBankAccountToken(externalBankAccountToken: Optional) = + externalBankAccountToken(externalBankAccountToken.getOrNull()) + + /** + * Sets [Builder.externalBankAccountToken] to an arbitrary JSON value. + * + * You should usually call [Builder.externalBankAccountToken] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun externalBankAccountToken(externalBankAccountToken: JsonField) = apply { + this.externalBankAccountToken = externalBankAccountToken + } + + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata + * with a resource for your own purposes. + */ + fun tags(tags: Payment.Tags) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed [Payment.Tags] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tags(tags: JsonField) = apply { this.tags = tags } + + fun type(type: Payment.TransferType) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Payment.TransferType] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** User-defined identifier */ + fun userDefinedId(userDefinedId: String?) = + userDefinedId(JsonField.ofNullable(userDefinedId)) + + /** Alias for calling [Builder.userDefinedId] with `userDefinedId.orElse(null)`. */ + fun userDefinedId(userDefinedId: Optional) = + userDefinedId(userDefinedId.getOrNull()) + + /** + * Sets [Builder.userDefinedId] to an arbitrary JSON value. + * + * You should usually call [Builder.userDefinedId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun userDefinedId(userDefinedId: JsonField) = apply { + this.userDefinedId = userDefinedId + } + + /** Balance */ + fun balance(balance: Balance) = balance(JsonField.of(balance)) + + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Balance] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [PaymentCreateStablecoinResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * .category() + * .created() + * .descriptor() + * .direction() + * .events() + * .family() + * .financialAccountToken() + * .method() + * .methodAttributes() + * .pendingAmount() + * .relatedAccountTokens() + * .result() + * .settledAmount() + * .source() + * .status() + * .updated() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PaymentCreateStablecoinResponse = + PaymentCreateStablecoinResponse( + checkRequired("token", token), + checkRequired("category", category), + checkRequired("created", created), + checkRequired("descriptor", descriptor), + checkRequired("direction", direction), + checkRequired("events", events).map { it.toImmutable() }, + checkRequired("family", family), + checkRequired("financialAccountToken", financialAccountToken), + checkRequired("method", method), + checkRequired("methodAttributes", methodAttributes), + checkRequired("pendingAmount", pendingAmount), + checkRequired("relatedAccountTokens", relatedAccountTokens), + checkRequired("result", result), + checkRequired("settledAmount", settledAmount), + checkRequired("source", source), + checkRequired("status", status), + checkRequired("updated", updated), + blockchainRecipientToken, + currency, + expectedReleaseDate, + externalBankAccountToken, + tags, + type, + userDefinedId, + balance, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): PaymentCreateStablecoinResponse = apply { + if (validated) { + return@apply + } + + token() + category().validate() + created() + descriptor() + direction().validate() + events().forEach { it.validate() } + family().validate() + financialAccountToken() + method().validate() + methodAttributes().validate() + pendingAmount() + relatedAccountTokens().ifPresent { it.validate() } + result().validate() + settledAmount() + source().validate() + status().validate() + updated() + blockchainRecipientToken() + currency() + expectedReleaseDate() + externalBankAccountToken() + tags().ifPresent { it.validate() } + type().ifPresent { it.validate() } + userDefinedId() + balance().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (token.asKnown().isPresent) 1 else 0) + + (category.asKnown().getOrNull()?.validity() ?: 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (if (descriptor.asKnown().isPresent) 1 else 0) + + (direction.asKnown().getOrNull()?.validity() ?: 0) + + (events.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (family.asKnown().getOrNull()?.validity() ?: 0) + + (if (financialAccountToken.asKnown().isPresent) 1 else 0) + + (method.asKnown().getOrNull()?.validity() ?: 0) + + (methodAttributes.asKnown().getOrNull()?.validity() ?: 0) + + (if (pendingAmount.asKnown().isPresent) 1 else 0) + + (relatedAccountTokens.asKnown().getOrNull()?.validity() ?: 0) + + (result.asKnown().getOrNull()?.validity() ?: 0) + + (if (settledAmount.asKnown().isPresent) 1 else 0) + + (source.asKnown().getOrNull()?.validity() ?: 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + (if (updated.asKnown().isPresent) 1 else 0) + + (if (blockchainRecipientToken.asKnown().isPresent) 1 else 0) + + (if (currency.asKnown().isPresent) 1 else 0) + + (if (expectedReleaseDate.asKnown().isPresent) 1 else 0) + + (if (externalBankAccountToken.asKnown().isPresent) 1 else 0) + + (tags.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (userDefinedId.asKnown().isPresent) 1 else 0) + + (balance.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PaymentCreateStablecoinResponse && + token == other.token && + category == other.category && + created == other.created && + descriptor == other.descriptor && + direction == other.direction && + events == other.events && + family == other.family && + financialAccountToken == other.financialAccountToken && + method == other.method && + methodAttributes == other.methodAttributes && + pendingAmount == other.pendingAmount && + relatedAccountTokens == other.relatedAccountTokens && + result == other.result && + settledAmount == other.settledAmount && + source == other.source && + status == other.status && + updated == other.updated && + blockchainRecipientToken == other.blockchainRecipientToken && + currency == other.currency && + expectedReleaseDate == other.expectedReleaseDate && + externalBankAccountToken == other.externalBankAccountToken && + tags == other.tags && + type == other.type && + userDefinedId == other.userDefinedId && + balance == other.balance && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + token, + category, + created, + descriptor, + direction, + events, + family, + financialAccountToken, + method, + methodAttributes, + pendingAmount, + relatedAccountTokens, + result, + settledAmount, + source, + status, + updated, + blockchainRecipientToken, + currency, + expectedReleaseDate, + externalBankAccountToken, + tags, + type, + userDefinedId, + balance, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "PaymentCreateStablecoinResponse{token=$token, category=$category, created=$created, descriptor=$descriptor, direction=$direction, events=$events, family=$family, financialAccountToken=$financialAccountToken, method=$method, methodAttributes=$methodAttributes, pendingAmount=$pendingAmount, relatedAccountTokens=$relatedAccountTokens, result=$result, settledAmount=$settledAmount, source=$source, status=$status, updated=$updated, blockchainRecipientToken=$blockchainRecipientToken, currency=$currency, expectedReleaseDate=$expectedReleaseDate, externalBankAccountToken=$externalBankAccountToken, tags=$tags, type=$type, userDefinedId=$userDefinedId, balance=$balance, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentListParams.kt index 46abda514..c70f2e30e 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentListParams.kt @@ -371,12 +371,15 @@ private constructor( @JvmField val ACH = of("ACH") + @JvmField val STABLECOIN = of("STABLECOIN") + @JvmStatic fun of(value: String) = Category(JsonField.of(value)) } /** An enum containing [Category]'s known values. */ enum class Known { - ACH + ACH, + STABLECOIN, } /** @@ -390,6 +393,7 @@ private constructor( */ enum class Value { ACH, + STABLECOIN, /** An enum member indicating that [Category] was instantiated with an unknown value. */ _UNKNOWN, } @@ -404,6 +408,7 @@ private constructor( fun value(): Value = when (this) { ACH -> Value.ACH + STABLECOIN -> Value.STABLECOIN else -> Value._UNKNOWN } @@ -419,6 +424,7 @@ private constructor( fun known(): Known = when (this) { ACH -> Known.ACH + STABLECOIN -> Known.STABLECOIN else -> throw LithicInvalidDataException("Unknown Category: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsync.kt index 2e0dd10da..8dc99dabc 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsync.kt @@ -8,6 +8,8 @@ import com.lithic.api.core.http.HttpResponseFor import com.lithic.api.models.Payment import com.lithic.api.models.PaymentCreateParams import com.lithic.api.models.PaymentCreateResponse +import com.lithic.api.models.PaymentCreateStablecoinParams +import com.lithic.api.models.PaymentCreateStablecoinResponse import com.lithic.api.models.PaymentListPageAsync import com.lithic.api.models.PaymentListParams import com.lithic.api.models.PaymentRetrieveParams @@ -39,7 +41,14 @@ interface PaymentServiceAsync { */ fun withOptions(modifier: Consumer): PaymentServiceAsync - /** Initiates a payment between a financial account and an external bank account. */ + /** + * Initiates an ACH payment between a financial account and an external bank account. + * + * This endpoint originates on the ACH rail only. To send a stablecoin payout, use the + * [Create stablecoin payment](https://docs.lithic.com/reference/createstablecoinpayment) + * endpoint. Payments on every rail are read back through + * [List payments](https://docs.lithic.com/reference/searchpayments). + */ fun create(params: PaymentCreateParams): CompletableFuture = create(params, RequestOptions.none()) @@ -99,6 +108,34 @@ interface PaymentServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(PaymentListParams.none(), requestOptions) + /** + * Initiates a stablecoin payout from a financial account to a registered blockchain recipient. + * + * The recipient must have been registered with + * [Create blockchain recipient](https://docs.lithic.com/reference/createblockchainrecipient) + * and have completed address screening — only a recipient in the `ENABLED` verification state + * can receive a payout. The destination address and chain come from the recipient, so they are + * not supplied here. + * + * Only payouts are initiated through this endpoint. Stablecoin pay-ins are credited from + * on-chain deposits to a financial account's deposit address and are not created through the + * API. Funds are placed on hold when the payout is initiated, and a payout that fails on chain + * reverses that hold. A payout cannot be cancelled once it has been submitted on chain. + * + * This endpoint is only available to stablecoin-enabled programs. Contact your customer success + * manager to learn more. + */ + fun createStablecoin( + params: PaymentCreateStablecoinParams + ): CompletableFuture = + createStablecoin(params, RequestOptions.none()) + + /** @see createStablecoin */ + fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + /** Retry an origination which has been returned. */ fun retry(paymentToken: String): CompletableFuture = retry(paymentToken, PaymentRetryParams.none()) @@ -326,6 +363,21 @@ interface PaymentServiceAsync { ): CompletableFuture> = list(PaymentListParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /v1/payments/stablecoin`, but is otherwise the same + * as [PaymentServiceAsync.createStablecoin]. + */ + fun createStablecoin( + params: PaymentCreateStablecoinParams + ): CompletableFuture> = + createStablecoin(params, RequestOptions.none()) + + /** @see createStablecoin */ + fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + /** * Returns a raw HTTP response for `post /v1/payments/{payment_token}/retry`, but is * otherwise the same as [PaymentServiceAsync.retry]. diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt index 5ccec83c1..992d731c1 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt @@ -19,6 +19,8 @@ import com.lithic.api.core.prepareAsync import com.lithic.api.models.Payment import com.lithic.api.models.PaymentCreateParams import com.lithic.api.models.PaymentCreateResponse +import com.lithic.api.models.PaymentCreateStablecoinParams +import com.lithic.api.models.PaymentCreateStablecoinResponse import com.lithic.api.models.PaymentListPageAsync import com.lithic.api.models.PaymentListPageResponse import com.lithic.api.models.PaymentListParams @@ -71,6 +73,13 @@ class PaymentServiceAsyncImpl internal constructor(private val clientOptions: Cl // get /v1/payments withRawResponse().list(params, requestOptions).thenApply { it.parse() } + override fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /v1/payments/stablecoin + withRawResponse().createStablecoin(params, requestOptions).thenApply { it.parse() } + override fun retry( params: PaymentRetryParams, requestOptions: RequestOptions, @@ -228,6 +237,37 @@ class PaymentServiceAsyncImpl internal constructor(private val clientOptions: Cl } } + private val createStablecoinHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "payments", "stablecoin") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createStablecoinHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + private val retryHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentService.kt index f9120c5e5..f9961d83e 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentService.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentService.kt @@ -9,6 +9,8 @@ import com.lithic.api.core.http.HttpResponseFor import com.lithic.api.models.Payment import com.lithic.api.models.PaymentCreateParams import com.lithic.api.models.PaymentCreateResponse +import com.lithic.api.models.PaymentCreateStablecoinParams +import com.lithic.api.models.PaymentCreateStablecoinResponse import com.lithic.api.models.PaymentListPage import com.lithic.api.models.PaymentListParams import com.lithic.api.models.PaymentRetrieveParams @@ -39,7 +41,14 @@ interface PaymentService { */ fun withOptions(modifier: Consumer): PaymentService - /** Initiates a payment between a financial account and an external bank account. */ + /** + * Initiates an ACH payment between a financial account and an external bank account. + * + * This endpoint originates on the ACH rail only. To send a stablecoin payout, use the + * [Create stablecoin payment](https://docs.lithic.com/reference/createstablecoinpayment) + * endpoint. Payments on every rail are read back through + * [List payments](https://docs.lithic.com/reference/searchpayments). + */ fun create(params: PaymentCreateParams): PaymentCreateResponse = create(params, RequestOptions.none()) @@ -96,6 +105,32 @@ interface PaymentService { fun list(requestOptions: RequestOptions): PaymentListPage = list(PaymentListParams.none(), requestOptions) + /** + * Initiates a stablecoin payout from a financial account to a registered blockchain recipient. + * + * The recipient must have been registered with + * [Create blockchain recipient](https://docs.lithic.com/reference/createblockchainrecipient) + * and have completed address screening — only a recipient in the `ENABLED` verification state + * can receive a payout. The destination address and chain come from the recipient, so they are + * not supplied here. + * + * Only payouts are initiated through this endpoint. Stablecoin pay-ins are credited from + * on-chain deposits to a financial account's deposit address and are not created through the + * API. Funds are placed on hold when the payout is initiated, and a payout that fails on chain + * reverses that hold. A payout cannot be cancelled once it has been submitted on chain. + * + * This endpoint is only available to stablecoin-enabled programs. Contact your customer success + * manager to learn more. + */ + fun createStablecoin(params: PaymentCreateStablecoinParams): PaymentCreateStablecoinResponse = + createStablecoin(params, RequestOptions.none()) + + /** @see createStablecoin */ + fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): PaymentCreateStablecoinResponse + /** Retry an origination which has been returned. */ fun retry(paymentToken: String): PaymentRetryResponse = retry(paymentToken, PaymentRetryParams.none()) @@ -309,6 +344,23 @@ interface PaymentService { fun list(requestOptions: RequestOptions): HttpResponseFor = list(PaymentListParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /v1/payments/stablecoin`, but is otherwise the same + * as [PaymentService.createStablecoin]. + */ + @MustBeClosed + fun createStablecoin( + params: PaymentCreateStablecoinParams + ): HttpResponseFor = + createStablecoin(params, RequestOptions.none()) + + /** @see createStablecoin */ + @MustBeClosed + fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + /** * Returns a raw HTTP response for `post /v1/payments/{payment_token}/retry`, but is * otherwise the same as [PaymentService.retry]. diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt index 7ab67081a..318f47886 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt @@ -19,6 +19,8 @@ import com.lithic.api.core.prepare import com.lithic.api.models.Payment import com.lithic.api.models.PaymentCreateParams import com.lithic.api.models.PaymentCreateResponse +import com.lithic.api.models.PaymentCreateStablecoinParams +import com.lithic.api.models.PaymentCreateStablecoinResponse import com.lithic.api.models.PaymentListPage import com.lithic.api.models.PaymentListPageResponse import com.lithic.api.models.PaymentListParams @@ -64,6 +66,13 @@ class PaymentServiceImpl internal constructor(private val clientOptions: ClientO // get /v1/payments withRawResponse().list(params, requestOptions).parse() + override fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions, + ): PaymentCreateStablecoinResponse = + // post /v1/payments/stablecoin + withRawResponse().createStablecoin(params, requestOptions).parse() + override fun retry( params: PaymentRetryParams, requestOptions: RequestOptions, @@ -208,6 +217,34 @@ class PaymentServiceImpl internal constructor(private val clientOptions: ClientO } } + private val createStablecoinHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createStablecoin( + params: PaymentCreateStablecoinParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "payments", "stablecoin") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createStablecoinHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + private val retryHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinParamsTest.kt new file mode 100644 index 000000000..a9a26d3f1 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinParamsTest.kt @@ -0,0 +1,79 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PaymentCreateStablecoinParamsTest { + + @Test + fun create() { + PaymentCreateStablecoinParams.builder() + .amount(1588L) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .type(PaymentCreateStablecoinParams.Type.PAYMENT) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .hold( + PaymentCreateStablecoinParams.Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .memo("Vendor payout") + .build() + } + + @Test + fun body() { + val params = + PaymentCreateStablecoinParams.builder() + .amount(1588L) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .type(PaymentCreateStablecoinParams.Type.PAYMENT) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .hold( + PaymentCreateStablecoinParams.Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .memo("Vendor payout") + .build() + + val body = params._body() + + assertThat(body.amount()).isEqualTo(1588L) + assertThat(body.blockchainRecipientToken()) + .isEqualTo("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + assertThat(body.financialAccountToken()).isEqualTo("35b0c466-a3e3-519a-9549-ead6a6a2277d") + assertThat(body.type()).isEqualTo(PaymentCreateStablecoinParams.Type.PAYMENT) + assertThat(body.token()).contains("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(body.hold()) + .contains( + PaymentCreateStablecoinParams.Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + assertThat(body.memo()).contains("Vendor payout") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + PaymentCreateStablecoinParams.builder() + .amount(1588L) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .type(PaymentCreateStablecoinParams.Type.PAYMENT) + .build() + + val body = params._body() + + assertThat(body.amount()).isEqualTo(1588L) + assertThat(body.blockchainRecipientToken()) + .isEqualTo("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + assertThat(body.financialAccountToken()).isEqualTo("35b0c466-a3e3-519a-9549-ead6a6a2277d") + assertThat(body.type()).isEqualTo(PaymentCreateStablecoinParams.Type.PAYMENT) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponseTest.kt new file mode 100644 index 000000000..c65c85a60 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentCreateStablecoinResponseTest.kt @@ -0,0 +1,296 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.JsonValue +import com.lithic.api.core.jsonMapper +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PaymentCreateStablecoinResponseTest { + + @Test + fun create() { + val paymentCreateStablecoinResponse = + PaymentCreateStablecoinResponse.builder() + .token("bd4efddb-771b-49e3-9af9-49b077ab5eb8") + .category(Payment.TransactionCategory.ACH) + .created(OffsetDateTime.parse("2025-10-27T20:12:22Z")) + .descriptor("ach_origination_credit") + .direction(Payment.Direction.CREDIT) + .addEvent( + Payment.PaymentEvent.builder() + .token("327dccc3-fe42-54d2-962c-7f8135805464") + .amount(-1588L) + .created(OffsetDateTime.parse("2025-10-27T20:12:22Z")) + .result(Payment.PaymentEvent.Result.APPROVED) + .type(Payment.PaymentEvent.PaymentEventType.ACH_ORIGINATION_INITIATED) + .addDetailedResult(Payment.PaymentEvent.DetailedResult.APPROVED) + .externalId("external_id") + .build() + ) + .addEvent( + Payment.PaymentEvent.builder() + .token("f9165477-7cfc-53c6-98f1-84e9ec856a60") + .amount(-1588L) + .created(OffsetDateTime.parse("2025-10-27T20:12:25Z")) + .result(Payment.PaymentEvent.Result.APPROVED) + .type(Payment.PaymentEvent.PaymentEventType.ACH_ORIGINATION_REVIEWED) + .addDetailedResult(Payment.PaymentEvent.DetailedResult.APPROVED) + .externalId("external_id") + .build() + ) + .family(Payment.Family.PAYMENT) + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .method(Payment.Method.ACH_NEXT_DAY) + .methodAttributes( + Payment.MethodAttributes.AchMethodAttributes.builder() + .secCode(Payment.MethodAttributes.AchMethodAttributes.SecCode.CCD) + .achHoldPeriod(1L) + .addenda(null) + .companyId("1111111111") + .overrideCompanyName("override_company_name") + .receiptRoutingNumber(null) + .recipientName(null) + .retries(0L) + .returnReasonCode(null) + .addTraceNumber("string") + .build() + ) + .pendingAmount(-1588L) + .relatedAccountTokens( + Payment.RelatedAccountTokens.builder() + .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .businessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .result(Payment.TransactionResult.APPROVED) + .settledAmount(0L) + .source(Payment.Source.LITHIC) + .status(Payment.TransactionStatus.PENDING) + .updated(OffsetDateTime.parse("2025-10-27T20:12:25Z")) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .currency("USD") + .expectedReleaseDate(null) + .externalBankAccountToken("feb4fee1-2414-4c38-a5f6-9deac293c8f4") + .tags( + Payment.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) + .type(Payment.TransferType.ORIGINATION_CREDIT) + .userDefinedId(null) + .balance( + Balance.builder() + .availableAmount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .financialAccountToken("3fa85f64-5717-4562-b3fc-2c963f66afa6") + .financialAccountType(Balance.FinancialAccountType.CARD) + .lastTransactionEventToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .lastTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .totalAmount(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + ) + .build() + + assertThat(paymentCreateStablecoinResponse.token()) + .isEqualTo("bd4efddb-771b-49e3-9af9-49b077ab5eb8") + assertThat(paymentCreateStablecoinResponse.category()) + .isEqualTo(Payment.TransactionCategory.ACH) + assertThat(paymentCreateStablecoinResponse.created()) + .isEqualTo(OffsetDateTime.parse("2025-10-27T20:12:22Z")) + assertThat(paymentCreateStablecoinResponse.descriptor()).isEqualTo("ach_origination_credit") + assertThat(paymentCreateStablecoinResponse.direction()).isEqualTo(Payment.Direction.CREDIT) + assertThat(paymentCreateStablecoinResponse.events()) + .containsExactly( + Payment.PaymentEvent.builder() + .token("327dccc3-fe42-54d2-962c-7f8135805464") + .amount(-1588L) + .created(OffsetDateTime.parse("2025-10-27T20:12:22Z")) + .result(Payment.PaymentEvent.Result.APPROVED) + .type(Payment.PaymentEvent.PaymentEventType.ACH_ORIGINATION_INITIATED) + .addDetailedResult(Payment.PaymentEvent.DetailedResult.APPROVED) + .externalId("external_id") + .build(), + Payment.PaymentEvent.builder() + .token("f9165477-7cfc-53c6-98f1-84e9ec856a60") + .amount(-1588L) + .created(OffsetDateTime.parse("2025-10-27T20:12:25Z")) + .result(Payment.PaymentEvent.Result.APPROVED) + .type(Payment.PaymentEvent.PaymentEventType.ACH_ORIGINATION_REVIEWED) + .addDetailedResult(Payment.PaymentEvent.DetailedResult.APPROVED) + .externalId("external_id") + .build(), + ) + assertThat(paymentCreateStablecoinResponse.family()).isEqualTo(Payment.Family.PAYMENT) + assertThat(paymentCreateStablecoinResponse.financialAccountToken()) + .isEqualTo("35b0c466-a3e3-519a-9549-ead6a6a2277d") + assertThat(paymentCreateStablecoinResponse.method()).isEqualTo(Payment.Method.ACH_NEXT_DAY) + assertThat(paymentCreateStablecoinResponse.methodAttributes()) + .isEqualTo( + Payment.MethodAttributes.ofAch( + Payment.MethodAttributes.AchMethodAttributes.builder() + .secCode(Payment.MethodAttributes.AchMethodAttributes.SecCode.CCD) + .achHoldPeriod(1L) + .addenda(null) + .companyId("1111111111") + .overrideCompanyName("override_company_name") + .receiptRoutingNumber(null) + .recipientName(null) + .retries(0L) + .returnReasonCode(null) + .addTraceNumber("string") + .build() + ) + ) + assertThat(paymentCreateStablecoinResponse.pendingAmount()).isEqualTo(-1588L) + assertThat(paymentCreateStablecoinResponse.relatedAccountTokens()) + .contains( + Payment.RelatedAccountTokens.builder() + .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .businessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + assertThat(paymentCreateStablecoinResponse.result()) + .isEqualTo(Payment.TransactionResult.APPROVED) + assertThat(paymentCreateStablecoinResponse.settledAmount()).isEqualTo(0L) + assertThat(paymentCreateStablecoinResponse.source()).isEqualTo(Payment.Source.LITHIC) + assertThat(paymentCreateStablecoinResponse.status()) + .isEqualTo(Payment.TransactionStatus.PENDING) + assertThat(paymentCreateStablecoinResponse.updated()) + .isEqualTo(OffsetDateTime.parse("2025-10-27T20:12:25Z")) + assertThat(paymentCreateStablecoinResponse.blockchainRecipientToken()) + .contains("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + assertThat(paymentCreateStablecoinResponse.currency()).contains("USD") + assertThat(paymentCreateStablecoinResponse.expectedReleaseDate()).isEmpty + assertThat(paymentCreateStablecoinResponse.externalBankAccountToken()) + .contains("feb4fee1-2414-4c38-a5f6-9deac293c8f4") + assertThat(paymentCreateStablecoinResponse.tags()) + .contains( + Payment.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) + assertThat(paymentCreateStablecoinResponse.type()) + .contains(Payment.TransferType.ORIGINATION_CREDIT) + assertThat(paymentCreateStablecoinResponse.userDefinedId()).isEmpty + assertThat(paymentCreateStablecoinResponse.balance()) + .contains( + Balance.builder() + .availableAmount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .financialAccountToken("3fa85f64-5717-4562-b3fc-2c963f66afa6") + .financialAccountType(Balance.FinancialAccountType.CARD) + .lastTransactionEventToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .lastTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .totalAmount(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val paymentCreateStablecoinResponse = + PaymentCreateStablecoinResponse.builder() + .token("bd4efddb-771b-49e3-9af9-49b077ab5eb8") + .category(Payment.TransactionCategory.ACH) + .created(OffsetDateTime.parse("2025-10-27T20:12:22Z")) + .descriptor("ach_origination_credit") + .direction(Payment.Direction.CREDIT) + .addEvent( + Payment.PaymentEvent.builder() + .token("327dccc3-fe42-54d2-962c-7f8135805464") + .amount(-1588L) + .created(OffsetDateTime.parse("2025-10-27T20:12:22Z")) + .result(Payment.PaymentEvent.Result.APPROVED) + .type(Payment.PaymentEvent.PaymentEventType.ACH_ORIGINATION_INITIATED) + .addDetailedResult(Payment.PaymentEvent.DetailedResult.APPROVED) + .externalId("external_id") + .build() + ) + .addEvent( + Payment.PaymentEvent.builder() + .token("f9165477-7cfc-53c6-98f1-84e9ec856a60") + .amount(-1588L) + .created(OffsetDateTime.parse("2025-10-27T20:12:25Z")) + .result(Payment.PaymentEvent.Result.APPROVED) + .type(Payment.PaymentEvent.PaymentEventType.ACH_ORIGINATION_REVIEWED) + .addDetailedResult(Payment.PaymentEvent.DetailedResult.APPROVED) + .externalId("external_id") + .build() + ) + .family(Payment.Family.PAYMENT) + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .method(Payment.Method.ACH_NEXT_DAY) + .methodAttributes( + Payment.MethodAttributes.AchMethodAttributes.builder() + .secCode(Payment.MethodAttributes.AchMethodAttributes.SecCode.CCD) + .achHoldPeriod(1L) + .addenda(null) + .companyId("1111111111") + .overrideCompanyName("override_company_name") + .receiptRoutingNumber(null) + .recipientName(null) + .retries(0L) + .returnReasonCode(null) + .addTraceNumber("string") + .build() + ) + .pendingAmount(-1588L) + .relatedAccountTokens( + Payment.RelatedAccountTokens.builder() + .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .businessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .result(Payment.TransactionResult.APPROVED) + .settledAmount(0L) + .source(Payment.Source.LITHIC) + .status(Payment.TransactionStatus.PENDING) + .updated(OffsetDateTime.parse("2025-10-27T20:12:25Z")) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .currency("USD") + .expectedReleaseDate(null) + .externalBankAccountToken("feb4fee1-2414-4c38-a5f6-9deac293c8f4") + .tags( + Payment.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) + .type(Payment.TransferType.ORIGINATION_CREDIT) + .userDefinedId(null) + .balance( + Balance.builder() + .availableAmount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .financialAccountToken("3fa85f64-5717-4562-b3fc-2c963f66afa6") + .financialAccountType(Balance.FinancialAccountType.CARD) + .lastTransactionEventToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .lastTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .totalAmount(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + ) + .build() + + val roundtrippedPaymentCreateStablecoinResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(paymentCreateStablecoinResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedPaymentCreateStablecoinResponse) + .isEqualTo(paymentCreateStablecoinResponse) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt index 45c7d5e53..db58bab23 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt @@ -5,6 +5,7 @@ package com.lithic.api.services.async import com.lithic.api.TestServerExtension import com.lithic.api.client.okhttp.LithicOkHttpClientAsync import com.lithic.api.models.PaymentCreateParams +import com.lithic.api.models.PaymentCreateStablecoinParams import com.lithic.api.models.PaymentReturnParams import com.lithic.api.models.PaymentSimulateActionParams import com.lithic.api.models.PaymentSimulateReceiptParams @@ -87,6 +88,36 @@ internal class PaymentServiceAsyncTest { page.response().validate() } + @Test + fun createStablecoin() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val paymentServiceAsync = client.payments() + + val responseFuture = + paymentServiceAsync.createStablecoin( + PaymentCreateStablecoinParams.builder() + .amount(1588L) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .type(PaymentCreateStablecoinParams.Type.PAYMENT) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .hold( + PaymentCreateStablecoinParams.Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .memo("Vendor payout") + .build() + ) + + val response = responseFuture.get() + response.validate() + } + @Test fun retry() { val client = diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt index 06ff46221..94df014ab 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt @@ -5,6 +5,7 @@ package com.lithic.api.services.blocking import com.lithic.api.TestServerExtension import com.lithic.api.client.okhttp.LithicOkHttpClient import com.lithic.api.models.PaymentCreateParams +import com.lithic.api.models.PaymentCreateStablecoinParams import com.lithic.api.models.PaymentReturnParams import com.lithic.api.models.PaymentSimulateActionParams import com.lithic.api.models.PaymentSimulateReceiptParams @@ -84,6 +85,35 @@ internal class PaymentServiceTest { page.response().validate() } + @Test + fun createStablecoin() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val paymentService = client.payments() + + val response = + paymentService.createStablecoin( + PaymentCreateStablecoinParams.builder() + .amount(1588L) + .blockchainRecipientToken("1e3fdb71-4b52-4a30-a7a9-52c85e26a1d9") + .financialAccountToken("35b0c466-a3e3-519a-9549-ead6a6a2277d") + .type(PaymentCreateStablecoinParams.Type.PAYMENT) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .hold( + PaymentCreateStablecoinParams.Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .memo("Vendor payout") + .build() + ) + + response.validate() + } + @Test fun retry() { val client = From 97fabed2eefe8fe7c76fa4c45a66ed8495a28f9d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 17:04:28 +0000 Subject: [PATCH 04/15] feat: TRE-14349: add installment plan management operation event types --- .stats.yml | 4 ++-- .../kotlin/com/lithic/api/models/FinancialEvent.kt | 12 ++++++++++++ .../api/models/ManagementOperationCreateParams.kt | 12 ++++++++++++ .../api/models/ManagementOperationTransaction.kt | 12 ++++++++++++ .../com/lithic/api/models/StatementLineItems.kt | 12 ++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3bbc47373..d5cfb7940 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 217 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-70147140a7b2043acf622024eb3bde9b04264f8e9a695d4c79b5ee4db1534518.yml -openapi_spec_hash: 7a181cb1cfaaa201143bd9d04a841a2e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-17e70cd484ec2fc2aca1243462ac8849153dbbe9b9245959ff51681b14f74024.yml +openapi_spec_hash: cc75e169c1c5ddc9ed619de07ee94d70 config_hash: e95c2dda5d175f9316457e0a84e35dce diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt index b08c57268..4b94db71d 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt @@ -589,6 +589,10 @@ private constructor( @JvmField val FINANCIAL_CREDIT_AUTHORIZATION = of("FINANCIAL_CREDIT_AUTHORIZATION") + @JvmField val INSTALLMENT_FEE = of("INSTALLMENT_FEE") + + @JvmField val INSTALLMENT_FEE_REVERSAL = of("INSTALLMENT_FEE_REVERSAL") + @JvmField val INTEREST = of("INTEREST") @JvmField val INTEREST_REVERSAL = of("INTEREST_REVERSAL") @@ -726,6 +730,8 @@ private constructor( EXTERNAL_WIRE_SETTLED, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, INTEREST, INTEREST_REVERSAL, INTERNAL_ADJUSTMENT, @@ -839,6 +845,8 @@ private constructor( EXTERNAL_WIRE_SETTLED, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, INTEREST, INTEREST_REVERSAL, INTERNAL_ADJUSTMENT, @@ -956,6 +964,8 @@ private constructor( EXTERNAL_WIRE_SETTLED -> Value.EXTERNAL_WIRE_SETTLED FINANCIAL_AUTHORIZATION -> Value.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Value.FINANCIAL_CREDIT_AUTHORIZATION + INSTALLMENT_FEE -> Value.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Value.INSTALLMENT_FEE_REVERSAL INTEREST -> Value.INTEREST INTEREST_REVERSAL -> Value.INTEREST_REVERSAL INTERNAL_ADJUSTMENT -> Value.INTERNAL_ADJUSTMENT @@ -1071,6 +1081,8 @@ private constructor( EXTERNAL_WIRE_SETTLED -> Known.EXTERNAL_WIRE_SETTLED FINANCIAL_AUTHORIZATION -> Known.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Known.FINANCIAL_CREDIT_AUTHORIZATION + INSTALLMENT_FEE -> Known.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Known.INSTALLMENT_FEE_REVERSAL INTEREST -> Known.INTEREST INTEREST_REVERSAL -> Known.INTEREST_REVERSAL INTERNAL_ADJUSTMENT -> Known.INTERNAL_ADJUSTMENT diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt index f84492a1d..ba4e95fb7 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt @@ -1449,6 +1449,10 @@ private constructor( @JvmField val INTEREST_REVERSAL = of("INTEREST_REVERSAL") + @JvmField val INSTALLMENT_FEE = of("INSTALLMENT_FEE") + + @JvmField val INSTALLMENT_FEE_REVERSAL = of("INSTALLMENT_FEE_REVERSAL") + @JvmField val LATE_PAYMENT = of("LATE_PAYMENT") @JvmField val LATE_PAYMENT_REVERSAL = of("LATE_PAYMENT_REVERSAL") @@ -1497,6 +1501,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL, INTEREST, INTEREST_REVERSAL, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, LATE_PAYMENT, LATE_PAYMENT_REVERSAL, BILLING_ERROR, @@ -1536,6 +1542,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL, INTEREST, INTEREST_REVERSAL, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, LATE_PAYMENT, LATE_PAYMENT_REVERSAL, BILLING_ERROR, @@ -1577,6 +1585,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL -> Value.CURRENCY_CONVERSION_REVERSAL INTEREST -> Value.INTEREST INTEREST_REVERSAL -> Value.INTEREST_REVERSAL + INSTALLMENT_FEE -> Value.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Value.INSTALLMENT_FEE_REVERSAL LATE_PAYMENT -> Value.LATE_PAYMENT LATE_PAYMENT_REVERSAL -> Value.LATE_PAYMENT_REVERSAL BILLING_ERROR -> Value.BILLING_ERROR @@ -1616,6 +1626,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL -> Known.CURRENCY_CONVERSION_REVERSAL INTEREST -> Known.INTEREST INTEREST_REVERSAL -> Known.INTEREST_REVERSAL + INSTALLMENT_FEE -> Known.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Known.INSTALLMENT_FEE_REVERSAL LATE_PAYMENT -> Known.LATE_PAYMENT LATE_PAYMENT_REVERSAL -> Known.LATE_PAYMENT_REVERSAL BILLING_ERROR -> Known.BILLING_ERROR diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt index 744006b8a..aa9c2c882 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt @@ -2013,6 +2013,10 @@ private constructor( @JvmField val INTEREST_REVERSAL = of("INTEREST_REVERSAL") + @JvmField val INSTALLMENT_FEE = of("INSTALLMENT_FEE") + + @JvmField val INSTALLMENT_FEE_REVERSAL = of("INSTALLMENT_FEE_REVERSAL") + @JvmField val LATE_PAYMENT = of("LATE_PAYMENT") @JvmField val LATE_PAYMENT_REVERSAL = of("LATE_PAYMENT_REVERSAL") @@ -2061,6 +2065,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL, INTEREST, INTEREST_REVERSAL, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, LATE_PAYMENT, LATE_PAYMENT_REVERSAL, BILLING_ERROR, @@ -2100,6 +2106,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL, INTEREST, INTEREST_REVERSAL, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, LATE_PAYMENT, LATE_PAYMENT_REVERSAL, BILLING_ERROR, @@ -2141,6 +2149,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL -> Value.CURRENCY_CONVERSION_REVERSAL INTEREST -> Value.INTEREST INTEREST_REVERSAL -> Value.INTEREST_REVERSAL + INSTALLMENT_FEE -> Value.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Value.INSTALLMENT_FEE_REVERSAL LATE_PAYMENT -> Value.LATE_PAYMENT LATE_PAYMENT_REVERSAL -> Value.LATE_PAYMENT_REVERSAL BILLING_ERROR -> Value.BILLING_ERROR @@ -2180,6 +2190,8 @@ private constructor( CURRENCY_CONVERSION_REVERSAL -> Known.CURRENCY_CONVERSION_REVERSAL INTEREST -> Known.INTEREST INTEREST_REVERSAL -> Known.INTEREST_REVERSAL + INSTALLMENT_FEE -> Known.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Known.INSTALLMENT_FEE_REVERSAL LATE_PAYMENT -> Known.LATE_PAYMENT LATE_PAYMENT_REVERSAL -> Known.LATE_PAYMENT_REVERSAL BILLING_ERROR -> Known.BILLING_ERROR diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt index e23f281a6..08d72aa9d 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt @@ -1373,6 +1373,10 @@ private constructor( @JvmField val FINANCIAL_CREDIT_AUTHORIZATION = of("FINANCIAL_CREDIT_AUTHORIZATION") + @JvmField val INSTALLMENT_FEE = of("INSTALLMENT_FEE") + + @JvmField val INSTALLMENT_FEE_REVERSAL = of("INSTALLMENT_FEE_REVERSAL") + @JvmField val INTEREST = of("INTEREST") @JvmField val INTEREST_REVERSAL = of("INTEREST_REVERSAL") @@ -1510,6 +1514,8 @@ private constructor( EXTERNAL_WIRE_SETTLED, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, INTEREST, INTEREST_REVERSAL, INTERNAL_ADJUSTMENT, @@ -1625,6 +1631,8 @@ private constructor( EXTERNAL_WIRE_SETTLED, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, + INSTALLMENT_FEE, + INSTALLMENT_FEE_REVERSAL, INTEREST, INTEREST_REVERSAL, INTERNAL_ADJUSTMENT, @@ -1742,6 +1750,8 @@ private constructor( EXTERNAL_WIRE_SETTLED -> Value.EXTERNAL_WIRE_SETTLED FINANCIAL_AUTHORIZATION -> Value.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Value.FINANCIAL_CREDIT_AUTHORIZATION + INSTALLMENT_FEE -> Value.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Value.INSTALLMENT_FEE_REVERSAL INTEREST -> Value.INTEREST INTEREST_REVERSAL -> Value.INTEREST_REVERSAL INTERNAL_ADJUSTMENT -> Value.INTERNAL_ADJUSTMENT @@ -1857,6 +1867,8 @@ private constructor( EXTERNAL_WIRE_SETTLED -> Known.EXTERNAL_WIRE_SETTLED FINANCIAL_AUTHORIZATION -> Known.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Known.FINANCIAL_CREDIT_AUTHORIZATION + INSTALLMENT_FEE -> Known.INSTALLMENT_FEE + INSTALLMENT_FEE_REVERSAL -> Known.INSTALLMENT_FEE_REVERSAL INTEREST -> Known.INTEREST INTEREST_REVERSAL -> Known.INTEREST_REVERSAL INTERNAL_ADJUSTMENT -> Known.INTERNAL_ADJUSTMENT From 5cdc715990d26e494c33d6dfd5bd6581ce21b6c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 17:56:52 +0000 Subject: [PATCH 05/15] feat: Add missing blockchain/stablecoin endpoints to the spec --- .stats.yml | 8 +- .../BlockchainRecipientRetrieveParams.kt | 211 ++++++++++++++++++ .../async/BlockchainRecipientServiceAsync.kt | 97 ++++++++ .../BlockchainRecipientServiceAsyncImpl.kt | 43 ++++ .../blocking/BlockchainRecipientService.kt | 98 ++++++++ .../BlockchainRecipientServiceImpl.kt | 40 ++++ .../BlockchainRecipientRetrieveParamsTest.kt | 28 +++ .../BlockchainRecipientServiceAsyncTest.kt | 16 ++ .../BlockchainRecipientServiceTest.kt | 15 ++ 9 files changed, 552 insertions(+), 4 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParams.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParamsTest.kt diff --git a/.stats.yml b/.stats.yml index d5cfb7940..a8ba03900 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 217 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-17e70cd484ec2fc2aca1243462ac8849153dbbe9b9245959ff51681b14f74024.yml -openapi_spec_hash: cc75e169c1c5ddc9ed619de07ee94d70 -config_hash: e95c2dda5d175f9316457e0a84e35dce +configured_endpoints: 218 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-c4c2ee9eddaa18ab29ef2d881e7c373d214d167b3eb7a74559f862ce36e95f74.yml +openapi_spec_hash: 3b1897cb075e1f19e2ce33e95781656a +config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParams.kt new file mode 100644 index 000000000..cd0557c62 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParams.kt @@ -0,0 +1,211 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.Params +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Get a blockchain recipient by token + * + * Use this to poll the `verification_state` after registering an address: a recipient cannot + * receive a payout until screening completes and moves it out of `PENDING` + */ +class BlockchainRecipientRetrieveParams +private constructor( + private val blockchainRecipientToken: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun blockchainRecipientToken(): Optional = Optional.ofNullable(blockchainRecipientToken) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): BlockchainRecipientRetrieveParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of + * [BlockchainRecipientRetrieveParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [BlockchainRecipientRetrieveParams]. */ + class Builder internal constructor() { + + private var blockchainRecipientToken: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(blockchainRecipientRetrieveParams: BlockchainRecipientRetrieveParams) = + apply { + blockchainRecipientToken = + blockchainRecipientRetrieveParams.blockchainRecipientToken + additionalHeaders = blockchainRecipientRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = + blockchainRecipientRetrieveParams.additionalQueryParams.toBuilder() + } + + fun blockchainRecipientToken(blockchainRecipientToken: String?) = apply { + this.blockchainRecipientToken = blockchainRecipientToken + } + + /** + * Alias for calling [Builder.blockchainRecipientToken] with + * `blockchainRecipientToken.orElse(null)`. + */ + fun blockchainRecipientToken(blockchainRecipientToken: Optional) = + blockchainRecipientToken(blockchainRecipientToken.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [BlockchainRecipientRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): BlockchainRecipientRetrieveParams = + BlockchainRecipientRetrieveParams( + blockchainRecipientToken, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> blockchainRecipientToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BlockchainRecipientRetrieveParams && + blockchainRecipientToken == other.blockchainRecipientToken && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(blockchainRecipientToken, additionalHeaders, additionalQueryParams) + + override fun toString() = + "BlockchainRecipientRetrieveParams{blockchainRecipientToken=$blockchainRecipientToken, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsync.kt index 271e8b61c..a7add57ce 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsync.kt @@ -7,6 +7,7 @@ import com.lithic.api.core.RequestOptions import com.lithic.api.core.http.HttpResponseFor import com.lithic.api.models.BlockchainRecipient import com.lithic.api.models.BlockchainRecipientCreateParams +import com.lithic.api.models.BlockchainRecipientRetrieveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer @@ -41,6 +42,51 @@ interface BlockchainRecipientServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** + * Get a blockchain recipient by token + * + * Use this to poll the `verification_state` after registering an address: a recipient cannot + * receive a payout until screening completes and moves it out of `PENDING` + */ + fun retrieve(blockchainRecipientToken: String): CompletableFuture = + retrieve(blockchainRecipientToken, BlockchainRecipientRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve( + params.toBuilder().blockchainRecipientToken(blockchainRecipientToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + ): CompletableFuture = + retrieve(blockchainRecipientToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see retrieve */ + fun retrieve( + params: BlockchainRecipientRetrieveParams + ): CompletableFuture = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + requestOptions: RequestOptions, + ): CompletableFuture = + retrieve(blockchainRecipientToken, BlockchainRecipientRetrieveParams.none(), requestOptions) + /** * A view of [BlockchainRecipientServiceAsync] that provides access to raw HTTP responses for * each method. @@ -70,5 +116,56 @@ interface BlockchainRecipientServiceAsync { params: BlockchainRecipientCreateParams, requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get + * /v1/blockchain_recipients/{blockchain_recipient_token}`, but is otherwise the same as + * [BlockchainRecipientServiceAsync.retrieve]. + */ + fun retrieve( + blockchainRecipientToken: String + ): CompletableFuture> = + retrieve(blockchainRecipientToken, BlockchainRecipientRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve( + params.toBuilder().blockchainRecipientToken(blockchainRecipientToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + ): CompletableFuture> = + retrieve(blockchainRecipientToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see retrieve */ + fun retrieve( + params: BlockchainRecipientRetrieveParams + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + retrieve( + blockchainRecipientToken, + BlockchainRecipientRetrieveParams.none(), + requestOptions, + ) } } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncImpl.kt index 6c47d1e09..83efe93e1 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.lithic.api.services.async import com.lithic.api.core.ClientOptions import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired import com.lithic.api.core.handlers.errorBodyHandler import com.lithic.api.core.handlers.errorHandler import com.lithic.api.core.handlers.jsonHandler @@ -17,8 +18,10 @@ import com.lithic.api.core.http.parseable import com.lithic.api.core.prepareAsync import com.lithic.api.models.BlockchainRecipient import com.lithic.api.models.BlockchainRecipientCreateParams +import com.lithic.api.models.BlockchainRecipientRetrieveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull class BlockchainRecipientServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : BlockchainRecipientServiceAsync { @@ -44,6 +47,13 @@ internal constructor(private val clientOptions: ClientOptions) : BlockchainRecip // post /v1/blockchain_recipients withRawResponse().create(params, requestOptions).thenApply { it.parse() } + override fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /v1/blockchain_recipients/{blockchain_recipient_token} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : BlockchainRecipientServiceAsync.WithRawResponse { @@ -87,5 +97,38 @@ internal constructor(private val clientOptions: ClientOptions) : BlockchainRecip } } } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("blockchainRecipientToken", params.blockchainRecipientToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "blockchain_recipients", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } } } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientService.kt index 67020b171..e3dbcec86 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientService.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientService.kt @@ -8,6 +8,7 @@ import com.lithic.api.core.RequestOptions import com.lithic.api.core.http.HttpResponseFor import com.lithic.api.models.BlockchainRecipient import com.lithic.api.models.BlockchainRecipientCreateParams +import com.lithic.api.models.BlockchainRecipientRetrieveParams import java.util.function.Consumer interface BlockchainRecipientService { @@ -41,6 +42,49 @@ interface BlockchainRecipientService { requestOptions: RequestOptions = RequestOptions.none(), ): BlockchainRecipient + /** + * Get a blockchain recipient by token + * + * Use this to poll the `verification_state` after registering an address: a recipient cannot + * receive a payout until screening completes and moves it out of `PENDING` + */ + fun retrieve(blockchainRecipientToken: String): BlockchainRecipient = + retrieve(blockchainRecipientToken, BlockchainRecipientRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): BlockchainRecipient = + retrieve( + params.toBuilder().blockchainRecipientToken(blockchainRecipientToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + ): BlockchainRecipient = retrieve(blockchainRecipientToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): BlockchainRecipient + + /** @see retrieve */ + fun retrieve(params: BlockchainRecipientRetrieveParams): BlockchainRecipient = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + blockchainRecipientToken: String, + requestOptions: RequestOptions, + ): BlockchainRecipient = + retrieve(blockchainRecipientToken, BlockchainRecipientRetrieveParams.none(), requestOptions) + /** * A view of [BlockchainRecipientService] that provides access to raw HTTP responses for each * method. @@ -70,5 +114,59 @@ interface BlockchainRecipientService { params: BlockchainRecipientCreateParams, requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get + * /v1/blockchain_recipients/{blockchain_recipient_token}`, but is otherwise the same as + * [BlockchainRecipientService.retrieve]. + */ + @MustBeClosed + fun retrieve(blockchainRecipientToken: String): HttpResponseFor = + retrieve(blockchainRecipientToken, BlockchainRecipientRetrieveParams.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve( + params.toBuilder().blockchainRecipientToken(blockchainRecipientToken).build(), + requestOptions, + ) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + blockchainRecipientToken: String, + params: BlockchainRecipientRetrieveParams = BlockchainRecipientRetrieveParams.none(), + ): HttpResponseFor = + retrieve(blockchainRecipientToken, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: BlockchainRecipientRetrieveParams + ): HttpResponseFor = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + blockchainRecipientToken: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + retrieve( + blockchainRecipientToken, + BlockchainRecipientRetrieveParams.none(), + requestOptions, + ) } } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceImpl.kt index 946e5a2dc..f49167ffd 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceImpl.kt @@ -4,6 +4,7 @@ package com.lithic.api.services.blocking import com.lithic.api.core.ClientOptions import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired import com.lithic.api.core.handlers.errorBodyHandler import com.lithic.api.core.handlers.errorHandler import com.lithic.api.core.handlers.jsonHandler @@ -17,7 +18,9 @@ import com.lithic.api.core.http.parseable import com.lithic.api.core.prepare import com.lithic.api.models.BlockchainRecipient import com.lithic.api.models.BlockchainRecipientCreateParams +import com.lithic.api.models.BlockchainRecipientRetrieveParams import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull class BlockchainRecipientServiceImpl internal constructor(private val clientOptions: ClientOptions) : BlockchainRecipientService { @@ -40,6 +43,13 @@ internal constructor(private val clientOptions: ClientOptions) : BlockchainRecip // post /v1/blockchain_recipients withRawResponse().create(params, requestOptions).parse() + override fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions, + ): BlockchainRecipient = + // get /v1/blockchain_recipients/{blockchain_recipient_token} + withRawResponse().retrieve(params, requestOptions).parse() + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : BlockchainRecipientService.WithRawResponse { @@ -80,5 +90,35 @@ internal constructor(private val clientOptions: ClientOptions) : BlockchainRecip } } } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: BlockchainRecipientRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("blockchainRecipientToken", params.blockchainRecipientToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "blockchain_recipients", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } } } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParamsTest.kt new file mode 100644 index 000000000..02821c5d8 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/BlockchainRecipientRetrieveParamsTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class BlockchainRecipientRetrieveParamsTest { + + @Test + fun create() { + BlockchainRecipientRetrieveParams.builder() + .blockchainRecipientToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + } + + @Test + fun pathParams() { + val params = + BlockchainRecipientRetrieveParams.builder() + .blockchainRecipientToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncTest.kt index 1e1b7077f..529e783ab 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/BlockchainRecipientServiceAsyncTest.kt @@ -37,4 +37,20 @@ internal class BlockchainRecipientServiceAsyncTest { val blockchainRecipient = blockchainRecipientFuture.get() blockchainRecipient.validate() } + + @Test + fun retrieve() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val blockchainRecipientServiceAsync = client.blockchainRecipients() + + val blockchainRecipientFuture = + blockchainRecipientServiceAsync.retrieve("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + val blockchainRecipient = blockchainRecipientFuture.get() + blockchainRecipient.validate() + } } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceTest.kt index 9db896ff1..fdc8dab44 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/BlockchainRecipientServiceTest.kt @@ -36,4 +36,19 @@ internal class BlockchainRecipientServiceTest { blockchainRecipient.validate() } + + @Test + fun retrieve() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val blockchainRecipientService = client.blockchainRecipients() + + val blockchainRecipient = + blockchainRecipientService.retrieve("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + blockchainRecipient.validate() + } } From 8ab17b8600e670de5baedfb831bf3aa327c3163a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 11 Sep 2026 15:28:45 +0000 Subject: [PATCH 06/15] feat(api): add card.pin_updated webhook event --- .stats.yml | 4 +- .../api/models/CardPinUpdatedWebhookEvent.kt | 749 ++++++++++++++++++ .../kotlin/com/lithic/api/models/Event.kt | 12 + .../com/lithic/api/models/EventListParams.kt | 8 + .../lithic/api/models/EventSubscription.kt | 8 + .../models/EventSubscriptionCreateParams.kt | 8 + ...tSubscriptionSendSimulatedExampleParams.kt | 6 + .../models/EventSubscriptionUpdateParams.kt | 8 + .../lithic/api/models/ParsedWebhookEvent.kt | 28 + .../models/CardPinUpdatedWebhookEventTest.kt | 51 ++ .../api/models/ParsedWebhookEventTest.kt | 171 ++++ 11 files changed, 1051 insertions(+), 2 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEvent.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEventTest.kt diff --git a/.stats.yml b/.stats.yml index a8ba03900..848bba662 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-c4c2ee9eddaa18ab29ef2d881e7c373d214d167b3eb7a74559f862ce36e95f74.yml -openapi_spec_hash: 3b1897cb075e1f19e2ce33e95781656a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-6acbf033ded2c03ed5d5c64b6bea9f3250323bf7879a11e9c545aa30e65b3cca.yml +openapi_spec_hash: c6007083223ccff12c5c15bc9e531b41 config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEvent.kt new file mode 100644 index 000000000..d672179d4 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEvent.kt @@ -0,0 +1,749 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkRequired +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +class CardPinUpdatedWebhookEvent +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val cardToken: JsonField, + private val eventType: JsonField, + private val pinStatus: JsonField, + private val statusReason: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("card_token") @ExcludeMissing cardToken: JsonField = JsonMissing.of(), + @JsonProperty("event_type") + @ExcludeMissing + eventType: JsonField = JsonMissing.of(), + @JsonProperty("pin_status") + @ExcludeMissing + pinStatus: JsonField = JsonMissing.of(), + @JsonProperty("status_reason") + @ExcludeMissing + statusReason: JsonField = JsonMissing.of(), + ) : this(cardToken, eventType, pinStatus, statusReason, mutableMapOf()) + + /** + * The token of the card whose PIN or PIN status was updated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun cardToken(): String = cardToken.getRequired("card_token") + + /** + * The type of event that occurred. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun eventType(): EventType = eventType.getRequired("event_type") + + /** + * The card's PIN status after the update + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun pinStatus(): PinStatus = pinStatus.getRequired("pin_status") + + /** + * The reason for the PIN update: + * * `PIN_SET` - The PIN was set for the first time; `pin_status` is `OK` + * * `PIN_CHANGED` - The PIN was changed, including when changing a blocked PIN; `pin_status` is + * `OK` + * * `PIN_UNBLOCKED` - The PIN was unblocked without changing it; `pin_status` is `OK` + * * `EXCESSIVE_PIN_ATTEMPTS` - The PIN was blocked due to excessive incorrect PIN attempts; + * `pin_status` is `BLOCKED` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun statusReason(): StatusReason = statusReason.getRequired("status_reason") + + /** + * Returns the raw JSON value of [cardToken]. + * + * Unlike [cardToken], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("card_token") @ExcludeMissing fun _cardToken(): JsonField = cardToken + + /** + * Returns the raw JSON value of [eventType]. + * + * Unlike [eventType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("event_type") @ExcludeMissing fun _eventType(): JsonField = eventType + + /** + * Returns the raw JSON value of [pinStatus]. + * + * Unlike [pinStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pin_status") @ExcludeMissing fun _pinStatus(): JsonField = pinStatus + + /** + * Returns the raw JSON value of [statusReason]. + * + * Unlike [statusReason], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status_reason") + @ExcludeMissing + fun _statusReason(): JsonField = statusReason + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [CardPinUpdatedWebhookEvent]. + * + * The following fields are required: + * ```java + * .cardToken() + * .eventType() + * .pinStatus() + * .statusReason() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CardPinUpdatedWebhookEvent]. */ + class Builder internal constructor() { + + private var cardToken: JsonField? = null + private var eventType: JsonField? = null + private var pinStatus: JsonField? = null + private var statusReason: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(cardPinUpdatedWebhookEvent: CardPinUpdatedWebhookEvent) = apply { + cardToken = cardPinUpdatedWebhookEvent.cardToken + eventType = cardPinUpdatedWebhookEvent.eventType + pinStatus = cardPinUpdatedWebhookEvent.pinStatus + statusReason = cardPinUpdatedWebhookEvent.statusReason + additionalProperties = cardPinUpdatedWebhookEvent.additionalProperties.toMutableMap() + } + + /** The token of the card whose PIN or PIN status was updated */ + fun cardToken(cardToken: String) = cardToken(JsonField.of(cardToken)) + + /** + * Sets [Builder.cardToken] to an arbitrary JSON value. + * + * You should usually call [Builder.cardToken] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun cardToken(cardToken: JsonField) = apply { this.cardToken = cardToken } + + /** The type of event that occurred. */ + fun eventType(eventType: EventType) = eventType(JsonField.of(eventType)) + + /** + * Sets [Builder.eventType] to an arbitrary JSON value. + * + * You should usually call [Builder.eventType] with a well-typed [EventType] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun eventType(eventType: JsonField) = apply { this.eventType = eventType } + + /** The card's PIN status after the update */ + fun pinStatus(pinStatus: PinStatus) = pinStatus(JsonField.of(pinStatus)) + + /** + * Sets [Builder.pinStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.pinStatus] with a well-typed [PinStatus] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun pinStatus(pinStatus: JsonField) = apply { this.pinStatus = pinStatus } + + /** + * The reason for the PIN update: + * * `PIN_SET` - The PIN was set for the first time; `pin_status` is `OK` + * * `PIN_CHANGED` - The PIN was changed, including when changing a blocked PIN; + * `pin_status` is `OK` + * * `PIN_UNBLOCKED` - The PIN was unblocked without changing it; `pin_status` is `OK` + * * `EXCESSIVE_PIN_ATTEMPTS` - The PIN was blocked due to excessive incorrect PIN attempts; + * `pin_status` is `BLOCKED` + */ + fun statusReason(statusReason: StatusReason) = statusReason(JsonField.of(statusReason)) + + /** + * Sets [Builder.statusReason] to an arbitrary JSON value. + * + * You should usually call [Builder.statusReason] with a well-typed [StatusReason] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun statusReason(statusReason: JsonField) = apply { + this.statusReason = statusReason + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [CardPinUpdatedWebhookEvent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .cardToken() + * .eventType() + * .pinStatus() + * .statusReason() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CardPinUpdatedWebhookEvent = + CardPinUpdatedWebhookEvent( + checkRequired("cardToken", cardToken), + checkRequired("eventType", eventType), + checkRequired("pinStatus", pinStatus), + checkRequired("statusReason", statusReason), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): CardPinUpdatedWebhookEvent = apply { + if (validated) { + return@apply + } + + cardToken() + eventType().validate() + pinStatus().validate() + statusReason().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (cardToken.asKnown().isPresent) 1 else 0) + + (eventType.asKnown().getOrNull()?.validity() ?: 0) + + (pinStatus.asKnown().getOrNull()?.validity() ?: 0) + + (statusReason.asKnown().getOrNull()?.validity() ?: 0) + + /** The type of event that occurred. */ + class EventType @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + + @JvmStatic fun of(value: String) = EventType(JsonField.of(value)) + } + + /** An enum containing [EventType]'s known values. */ + enum class Known { + CARD_PIN_UPDATED + } + + /** + * An enum containing [EventType]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [EventType] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + CARD_PIN_UPDATED, + /** + * An enum member indicating that [EventType] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED + else -> throw LithicInvalidDataException("Unknown EventType: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): EventType = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is EventType && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The card's PIN status after the update */ + class PinStatus @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val OK = of("OK") + + @JvmField val BLOCKED = of("BLOCKED") + + @JvmStatic fun of(value: String) = PinStatus(JsonField.of(value)) + } + + /** An enum containing [PinStatus]'s known values. */ + enum class Known { + OK, + BLOCKED, + } + + /** + * An enum containing [PinStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [PinStatus] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + OK, + BLOCKED, + /** + * An enum member indicating that [PinStatus] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + OK -> Value.OK + BLOCKED -> Value.BLOCKED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + OK -> Known.OK + BLOCKED -> Known.BLOCKED + else -> throw LithicInvalidDataException("Unknown PinStatus: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): PinStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PinStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * The reason for the PIN update: + * * `PIN_SET` - The PIN was set for the first time; `pin_status` is `OK` + * * `PIN_CHANGED` - The PIN was changed, including when changing a blocked PIN; `pin_status` is + * `OK` + * * `PIN_UNBLOCKED` - The PIN was unblocked without changing it; `pin_status` is `OK` + * * `EXCESSIVE_PIN_ATTEMPTS` - The PIN was blocked due to excessive incorrect PIN attempts; + * `pin_status` is `BLOCKED` + */ + class StatusReason @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PIN_SET = of("PIN_SET") + + @JvmField val PIN_CHANGED = of("PIN_CHANGED") + + @JvmField val PIN_UNBLOCKED = of("PIN_UNBLOCKED") + + @JvmField val EXCESSIVE_PIN_ATTEMPTS = of("EXCESSIVE_PIN_ATTEMPTS") + + @JvmStatic fun of(value: String) = StatusReason(JsonField.of(value)) + } + + /** An enum containing [StatusReason]'s known values. */ + enum class Known { + PIN_SET, + PIN_CHANGED, + PIN_UNBLOCKED, + EXCESSIVE_PIN_ATTEMPTS, + } + + /** + * An enum containing [StatusReason]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [StatusReason] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PIN_SET, + PIN_CHANGED, + PIN_UNBLOCKED, + EXCESSIVE_PIN_ATTEMPTS, + /** + * An enum member indicating that [StatusReason] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PIN_SET -> Value.PIN_SET + PIN_CHANGED -> Value.PIN_CHANGED + PIN_UNBLOCKED -> Value.PIN_UNBLOCKED + EXCESSIVE_PIN_ATTEMPTS -> Value.EXCESSIVE_PIN_ATTEMPTS + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PIN_SET -> Known.PIN_SET + PIN_CHANGED -> Known.PIN_CHANGED + PIN_UNBLOCKED -> Known.PIN_UNBLOCKED + EXCESSIVE_PIN_ATTEMPTS -> Known.EXCESSIVE_PIN_ATTEMPTS + else -> throw LithicInvalidDataException("Unknown StatusReason: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): StatusReason = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StatusReason && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CardPinUpdatedWebhookEvent && + cardToken == other.cardToken && + eventType == other.eventType && + pinStatus == other.pinStatus && + statusReason == other.statusReason && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(cardToken, eventType, pinStatus, statusReason, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CardPinUpdatedWebhookEvent{cardToken=$cardToken, eventType=$eventType, pinStatus=$pinStatus, statusReason=$statusReason, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt index fb5a6891b..9c2f276b1 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt @@ -85,6 +85,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due to + * excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -304,6 +306,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due + * to excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -522,6 +526,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due to + * excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -656,6 +662,8 @@ private constructor( @JvmField val CARD_CREATED = of("card.created") + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + @JvmField val CARD_REISSUED = of("card.reissued") @JvmField val CARD_RENEWED = of("card.renewed") @@ -779,6 +787,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -852,6 +861,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -930,6 +940,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Value.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Value.CARD_CONVERTED CARD_CREATED -> Value.CARD_CREATED + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED @@ -1011,6 +1022,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Known.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Known.CARD_CONVERTED CARD_CREATED -> Known.CARD_CREATED + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt index 3b0ffb8cf..527d9d30e 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt @@ -343,6 +343,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due to + * excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -477,6 +479,8 @@ private constructor( @JvmField val CARD_CREATED = of("card.created") + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + @JvmField val CARD_REISSUED = of("card.reissued") @JvmField val CARD_RENEWED = of("card.renewed") @@ -600,6 +604,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -673,6 +678,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -751,6 +757,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Value.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Value.CARD_CONVERTED CARD_CREATED -> Value.CARD_CREATED + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED @@ -832,6 +839,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Known.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Known.CARD_CONVERTED CARD_CREATED -> Known.CARD_CREATED + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt index 1ac9217f3..39d0b0c10 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt @@ -353,6 +353,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due to + * excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -487,6 +489,8 @@ private constructor( @JvmField val CARD_CREATED = of("card.created") + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + @JvmField val CARD_REISSUED = of("card.reissued") @JvmField val CARD_RENEWED = of("card.renewed") @@ -610,6 +614,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -683,6 +688,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -761,6 +767,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Value.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Value.CARD_CONVERTED CARD_CREATED -> Value.CARD_CREATED + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED @@ -842,6 +849,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Known.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Known.CARD_CONVERTED CARD_CREATED -> Known.CARD_CREATED + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt index 120a4e9c0..729baa419 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt @@ -676,6 +676,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due to + * excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -810,6 +812,8 @@ private constructor( @JvmField val CARD_CREATED = of("card.created") + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + @JvmField val CARD_REISSUED = of("card.reissued") @JvmField val CARD_RENEWED = of("card.renewed") @@ -933,6 +937,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -1006,6 +1011,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -1084,6 +1090,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Value.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Value.CARD_CONVERTED CARD_CREATED -> Value.CARD_CREATED + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED @@ -1165,6 +1172,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Known.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Known.CARD_CONVERTED CARD_CREATED -> Known.CARD_CREATED + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt index 0bee59c6c..094ce1721 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt @@ -471,6 +471,8 @@ private constructor( @JvmField val CARD_CREATED = of("card.created") + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + @JvmField val CARD_REISSUED = of("card.reissued") @JvmField val CARD_RENEWED = of("card.renewed") @@ -594,6 +596,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -667,6 +670,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -745,6 +749,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Value.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Value.CARD_CONVERTED CARD_CREATED -> Value.CARD_CREATED + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED @@ -826,6 +831,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Known.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Known.CARD_CONVERTED CARD_CREATED -> Known.CARD_CREATED + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt index 91de84e1c..a75dc9eb5 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt @@ -699,6 +699,8 @@ private constructor( * - card_transaction.updated: Occurs when a card transaction happens. * - card.converted: Occurs when a card is converted from virtual to physical cards. * - card.created: Occurs when a new card is created. + * - card.pin_updated: Occurs when a card's PIN is set, changed, unblocked, or blocked due to + * excessive incorrect PIN attempts. * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. @@ -833,6 +835,8 @@ private constructor( @JvmField val CARD_CREATED = of("card.created") + @JvmField val CARD_PIN_UPDATED = of("card.pin_updated") + @JvmField val CARD_REISSUED = of("card.reissued") @JvmField val CARD_RENEWED = of("card.renewed") @@ -956,6 +960,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -1029,6 +1034,7 @@ private constructor( CARD_TRANSACTION_UPDATED, CARD_CONVERTED, CARD_CREATED, + CARD_PIN_UPDATED, CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, @@ -1107,6 +1113,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Value.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Value.CARD_CONVERTED CARD_CREATED -> Value.CARD_CREATED + CARD_PIN_UPDATED -> Value.CARD_PIN_UPDATED CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED @@ -1188,6 +1195,7 @@ private constructor( CARD_TRANSACTION_UPDATED -> Known.CARD_TRANSACTION_UPDATED CARD_CONVERTED -> Known.CARD_CONVERTED CARD_CREATED -> Known.CARD_CREATED + CARD_PIN_UPDATED -> Known.CARD_PIN_UPDATED CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ParsedWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ParsedWebhookEvent.kt index 3bdbe366e..6521b09ce 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ParsedWebhookEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ParsedWebhookEvent.kt @@ -55,6 +55,7 @@ private constructor( private val bookTransferTransactionUpdated: BookTransferTransactionUpdatedWebhookEvent? = null, private val cardCreated: CardCreatedWebhookEvent? = null, private val cardConverted: CardConvertedWebhookEvent? = null, + private val cardPinUpdated: CardPinUpdatedWebhookEvent? = null, private val cardRenewed: CardRenewedWebhookEvent? = null, private val cardReissued: CardReissuedWebhookEvent? = null, private val cardShipped: CardShippedWebhookEvent? = null, @@ -173,6 +174,8 @@ private constructor( fun cardConverted(): Optional = Optional.ofNullable(cardConverted) + fun cardPinUpdated(): Optional = Optional.ofNullable(cardPinUpdated) + fun cardRenewed(): Optional = Optional.ofNullable(cardRenewed) fun cardReissued(): Optional = Optional.ofNullable(cardReissued) @@ -372,6 +375,8 @@ private constructor( fun isCardConverted(): Boolean = cardConverted != null + fun isCardPinUpdated(): Boolean = cardPinUpdated != null + fun isCardRenewed(): Boolean = cardRenewed != null fun isCardReissued(): Boolean = cardReissued != null @@ -525,6 +530,8 @@ private constructor( fun asCardConverted(): CardConvertedWebhookEvent = cardConverted.getOrThrow("cardConverted") + fun asCardPinUpdated(): CardPinUpdatedWebhookEvent = cardPinUpdated.getOrThrow("cardPinUpdated") + fun asCardRenewed(): CardRenewedWebhookEvent = cardRenewed.getOrThrow("cardRenewed") fun asCardReissued(): CardReissuedWebhookEvent = cardReissued.getOrThrow("cardReissued") @@ -757,6 +764,7 @@ private constructor( visitor.visitBookTransferTransactionUpdated(bookTransferTransactionUpdated) cardCreated != null -> visitor.visitCardCreated(cardCreated) cardConverted != null -> visitor.visitCardConverted(cardConverted) + cardPinUpdated != null -> visitor.visitCardPinUpdated(cardPinUpdated) cardRenewed != null -> visitor.visitCardRenewed(cardRenewed) cardReissued != null -> visitor.visitCardReissued(cardReissued) cardShipped != null -> visitor.visitCardShipped(cardShipped) @@ -954,6 +962,10 @@ private constructor( cardConverted.validate() } + override fun visitCardPinUpdated(cardPinUpdated: CardPinUpdatedWebhookEvent) { + cardPinUpdated.validate() + } + override fun visitCardRenewed(cardRenewed: CardRenewedWebhookEvent) { cardRenewed.validate() } @@ -1322,6 +1334,9 @@ private constructor( override fun visitCardConverted(cardConverted: CardConvertedWebhookEvent) = cardConverted.validity() + override fun visitCardPinUpdated(cardPinUpdated: CardPinUpdatedWebhookEvent) = + cardPinUpdated.validity() + override fun visitCardRenewed(cardRenewed: CardRenewedWebhookEvent) = cardRenewed.validity() @@ -1549,6 +1564,7 @@ private constructor( bookTransferTransactionUpdated == other.bookTransferTransactionUpdated && cardCreated == other.cardCreated && cardConverted == other.cardConverted && + cardPinUpdated == other.cardPinUpdated && cardRenewed == other.cardRenewed && cardReissued == other.cardReissued && cardShipped == other.cardShipped && @@ -1624,6 +1640,7 @@ private constructor( bookTransferTransactionUpdated, cardCreated, cardConverted, + cardPinUpdated, cardRenewed, cardReissued, cardShipped, @@ -1703,6 +1720,7 @@ private constructor( "ParsedWebhookEvent{bookTransferTransactionUpdated=$bookTransferTransactionUpdated}" cardCreated != null -> "ParsedWebhookEvent{cardCreated=$cardCreated}" cardConverted != null -> "ParsedWebhookEvent{cardConverted=$cardConverted}" + cardPinUpdated != null -> "ParsedWebhookEvent{cardPinUpdated=$cardPinUpdated}" cardRenewed != null -> "ParsedWebhookEvent{cardRenewed=$cardRenewed}" cardReissued != null -> "ParsedWebhookEvent{cardReissued=$cardReissued}" cardShipped != null -> "ParsedWebhookEvent{cardShipped=$cardShipped}" @@ -1875,6 +1893,10 @@ private constructor( fun ofCardConverted(cardConverted: CardConvertedWebhookEvent) = ParsedWebhookEvent(cardConverted = cardConverted) + @JvmStatic + fun ofCardPinUpdated(cardPinUpdated: CardPinUpdatedWebhookEvent) = + ParsedWebhookEvent(cardPinUpdated = cardPinUpdated) + @JvmStatic fun ofCardRenewed(cardRenewed: CardRenewedWebhookEvent) = ParsedWebhookEvent(cardRenewed = cardRenewed) @@ -2215,6 +2237,8 @@ private constructor( fun visitCardConverted(cardConverted: CardConvertedWebhookEvent): T + fun visitCardPinUpdated(cardPinUpdated: CardPinUpdatedWebhookEvent): T + fun visitCardRenewed(cardRenewed: CardRenewedWebhookEvent): T fun visitCardReissued(cardReissued: CardReissuedWebhookEvent): T @@ -2514,6 +2538,9 @@ private constructor( tryDeserialize(node, jacksonTypeRef())?.let { ParsedWebhookEvent(cardConverted = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + ParsedWebhookEvent(cardPinUpdated = it, _json = json) + }, tryDeserialize(node, jacksonTypeRef())?.let { ParsedWebhookEvent(cardRenewed = it, _json = json) }, @@ -2849,6 +2876,7 @@ private constructor( generator.writeObject(value.bookTransferTransactionUpdated) value.cardCreated != null -> generator.writeObject(value.cardCreated) value.cardConverted != null -> generator.writeObject(value.cardConverted) + value.cardPinUpdated != null -> generator.writeObject(value.cardPinUpdated) value.cardRenewed != null -> generator.writeObject(value.cardRenewed) value.cardReissued != null -> generator.writeObject(value.cardReissued) value.cardShipped != null -> generator.writeObject(value.cardShipped) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEventTest.kt new file mode 100644 index 000000000..347796677 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardPinUpdatedWebhookEventTest.kt @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class CardPinUpdatedWebhookEventTest { + + @Test + fun create() { + val cardPinUpdatedWebhookEvent = + CardPinUpdatedWebhookEvent.builder() + .cardToken("4df9a19c-9e1e-40d1-b27a-05e01152ee07") + .eventType(CardPinUpdatedWebhookEvent.EventType.CARD_PIN_UPDATED) + .pinStatus(CardPinUpdatedWebhookEvent.PinStatus.OK) + .statusReason(CardPinUpdatedWebhookEvent.StatusReason.PIN_SET) + .build() + + assertThat(cardPinUpdatedWebhookEvent.cardToken()) + .isEqualTo("4df9a19c-9e1e-40d1-b27a-05e01152ee07") + assertThat(cardPinUpdatedWebhookEvent.eventType()) + .isEqualTo(CardPinUpdatedWebhookEvent.EventType.CARD_PIN_UPDATED) + assertThat(cardPinUpdatedWebhookEvent.pinStatus()) + .isEqualTo(CardPinUpdatedWebhookEvent.PinStatus.OK) + assertThat(cardPinUpdatedWebhookEvent.statusReason()) + .isEqualTo(CardPinUpdatedWebhookEvent.StatusReason.PIN_SET) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val cardPinUpdatedWebhookEvent = + CardPinUpdatedWebhookEvent.builder() + .cardToken("4df9a19c-9e1e-40d1-b27a-05e01152ee07") + .eventType(CardPinUpdatedWebhookEvent.EventType.CARD_PIN_UPDATED) + .pinStatus(CardPinUpdatedWebhookEvent.PinStatus.OK) + .statusReason(CardPinUpdatedWebhookEvent.StatusReason.PIN_SET) + .build() + + val roundtrippedCardPinUpdatedWebhookEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(cardPinUpdatedWebhookEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedCardPinUpdatedWebhookEvent).isEqualTo(cardPinUpdatedWebhookEvent) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt index bd431f06e..227d2a165 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt @@ -52,6 +52,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -232,6 +233,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -431,6 +433,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -566,6 +569,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -682,6 +686,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -817,6 +822,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -1153,6 +1159,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -1704,6 +1711,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2064,6 +2072,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2222,6 +2231,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2388,6 +2398,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2550,6 +2561,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2746,6 +2758,7 @@ internal class ParsedWebhookEventTest { .contains(bookTransferTransactionUpdated) assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2894,6 +2907,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).contains(cardCreated) assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -2995,6 +3009,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).contains(cardConverted) + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -3070,6 +3085,111 @@ internal class ParsedWebhookEventTest { assertThat(roundtrippedParsedWebhookEvent).isEqualTo(parsedWebhookEvent) } + @Test + fun ofCardPinUpdated() { + val cardPinUpdated = + CardPinUpdatedWebhookEvent.builder() + .cardToken("4df9a19c-9e1e-40d1-b27a-05e01152ee07") + .eventType(CardPinUpdatedWebhookEvent.EventType.CARD_PIN_UPDATED) + .pinStatus(CardPinUpdatedWebhookEvent.PinStatus.OK) + .statusReason(CardPinUpdatedWebhookEvent.StatusReason.PIN_SET) + .build() + + val parsedWebhookEvent = ParsedWebhookEvent.ofCardPinUpdated(cardPinUpdated) + + assertThat(parsedWebhookEvent.accountHolderCreated()).isEmpty + assertThat(parsedWebhookEvent.kybPayload()).isEmpty + assertThat(parsedWebhookEvent.kycPayload()).isEmpty + assertThat(parsedWebhookEvent.legacyPayload()).isEmpty + assertThat(parsedWebhookEvent.accountHolderVerification()).isEmpty + assertThat(parsedWebhookEvent.accountHolderDocumentUpdated()).isEmpty + assertThat(parsedWebhookEvent.cardAuthorizationApprovalRequest()).isEmpty + assertThat(parsedWebhookEvent.cardAuthorizationChallenge()).isEmpty + assertThat(parsedWebhookEvent.cardAuthorizationChallengeResponse()).isEmpty + assertThat(parsedWebhookEvent.authRulesBacktestReportCreated()).isEmpty + assertThat(parsedWebhookEvent.balanceUpdated()).isEmpty + assertThat(parsedWebhookEvent.bookTransferTransactionCreated()).isEmpty + assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty + assertThat(parsedWebhookEvent.cardCreated()).isEmpty + assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).contains(cardPinUpdated) + assertThat(parsedWebhookEvent.cardRenewed()).isEmpty + assertThat(parsedWebhookEvent.cardReissued()).isEmpty + assertThat(parsedWebhookEvent.cardShipped()).isEmpty + assertThat(parsedWebhookEvent.cardUpdated()).isEmpty + assertThat(parsedWebhookEvent.cardTransactionUpdated()).isEmpty + assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()).isEmpty + assertThat(parsedWebhookEvent.cardTransactionEnhancedDataUpdated()).isEmpty + assertThat(parsedWebhookEvent.claimCreated()).isEmpty + assertThat(parsedWebhookEvent.claimUpdated()).isEmpty + assertThat(parsedWebhookEvent.claimDocumentUploaded()).isEmpty + assertThat(parsedWebhookEvent.claimDocumentAccepted()).isEmpty + assertThat(parsedWebhookEvent.claimDocumentRejected()).isEmpty + assertThat(parsedWebhookEvent.digitalWalletTokenizationApprovalRequest()).isEmpty + assertThat(parsedWebhookEvent.digitalWalletTokenizationResult()).isEmpty + assertThat(parsedWebhookEvent.digitalWalletTokenizationTwoFactorAuthenticationCode()) + .isEmpty + assertThat(parsedWebhookEvent.digitalWalletTokenizationTwoFactorAuthenticationCodeSent()) + .isEmpty + assertThat(parsedWebhookEvent.digitalWalletTokenizationUpdated()).isEmpty + assertThat(parsedWebhookEvent.disputeUpdated()).isEmpty + assertThat(parsedWebhookEvent.disputeEvidenceUploadFailed()).isEmpty + assertThat(parsedWebhookEvent.embedSessionGenerated()).isEmpty + assertThat(parsedWebhookEvent.embedViewed()).isEmpty + assertThat(parsedWebhookEvent.externalBankAccountCreated()).isEmpty + assertThat(parsedWebhookEvent.externalBankAccountUpdated()).isEmpty + assertThat(parsedWebhookEvent.externalPaymentCreated()).isEmpty + assertThat(parsedWebhookEvent.externalPaymentUpdated()).isEmpty + assertThat(parsedWebhookEvent.financialAccountCreated()).isEmpty + assertThat(parsedWebhookEvent.financialAccountUpdated()).isEmpty + assertThat(parsedWebhookEvent.fundingEventCreated()).isEmpty + assertThat(parsedWebhookEvent.loanTapeCreated()).isEmpty + assertThat(parsedWebhookEvent.loanTapeUpdated()).isEmpty + assertThat(parsedWebhookEvent.managementOperationCreated()).isEmpty + assertThat(parsedWebhookEvent.managementOperationUpdated()).isEmpty + assertThat(parsedWebhookEvent.internalTransactionCreated()).isEmpty + assertThat(parsedWebhookEvent.internalTransactionUpdated()).isEmpty + assertThat(parsedWebhookEvent.networkTotalCreated()).isEmpty + assertThat(parsedWebhookEvent.networkTotalUpdated()).isEmpty + assertThat(parsedWebhookEvent.paymentTransactionCreated()).isEmpty + assertThat(parsedWebhookEvent.paymentTransactionUpdated()).isEmpty + assertThat(parsedWebhookEvent.settlementReportUpdated()).isEmpty + assertThat(parsedWebhookEvent.statementsCreated()).isEmpty + assertThat(parsedWebhookEvent.threeDSAuthenticationCreated()).isEmpty + assertThat(parsedWebhookEvent.threeDSAuthenticationUpdated()).isEmpty + assertThat(parsedWebhookEvent.threeDSAuthenticationChallenge()).isEmpty + assertThat(parsedWebhookEvent.tokenizationApprovalRequest()).isEmpty + assertThat(parsedWebhookEvent.tokenizationResult()).isEmpty + assertThat(parsedWebhookEvent.tokenizationTwoFactorAuthenticationCode()).isEmpty + assertThat(parsedWebhookEvent.tokenizationTwoFactorAuthenticationCodeSent()).isEmpty + assertThat(parsedWebhookEvent.tokenizationUpdated()).isEmpty + assertThat(parsedWebhookEvent.threeDSAuthenticationApprovalRequest()).isEmpty + assertThat(parsedWebhookEvent.disputeTransactionCreated()).isEmpty + assertThat(parsedWebhookEvent.disputeTransactionUpdated()).isEmpty + } + + @Test + fun ofCardPinUpdatedRoundtrip() { + val jsonMapper = jsonMapper() + val parsedWebhookEvent = + ParsedWebhookEvent.ofCardPinUpdated( + CardPinUpdatedWebhookEvent.builder() + .cardToken("4df9a19c-9e1e-40d1-b27a-05e01152ee07") + .eventType(CardPinUpdatedWebhookEvent.EventType.CARD_PIN_UPDATED) + .pinStatus(CardPinUpdatedWebhookEvent.PinStatus.OK) + .statusReason(CardPinUpdatedWebhookEvent.StatusReason.PIN_SET) + .build() + ) + + val roundtrippedParsedWebhookEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(parsedWebhookEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedParsedWebhookEvent).isEqualTo(parsedWebhookEvent) + } + @Test fun ofCardRenewed() { val cardRenewed = @@ -3099,6 +3219,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).contains(cardRenewed) assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -3203,6 +3324,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).contains(cardReissued) assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -3308,6 +3430,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).contains(cardShipped) @@ -3415,6 +3538,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -3744,6 +3868,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -4141,6 +4266,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -4354,6 +4480,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -4527,6 +4654,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -4661,6 +4789,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -4794,6 +4923,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -4928,6 +5058,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -5062,6 +5193,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -5262,6 +5394,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -5478,6 +5611,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -5638,6 +5772,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -5780,6 +5915,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -5947,6 +6083,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6112,6 +6249,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6238,6 +6376,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6356,6 +6495,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6472,6 +6612,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6613,6 +6754,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6780,6 +6922,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -6943,6 +7086,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -7103,6 +7247,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -7269,6 +7414,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -7440,6 +7586,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -7588,6 +7735,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -7862,6 +8010,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -8304,6 +8453,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -8637,6 +8787,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -8847,6 +8998,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -9027,6 +9179,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -9177,6 +9330,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -9322,6 +9476,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -9458,6 +9613,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -9645,6 +9801,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -9883,6 +10040,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -10074,6 +10232,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -10323,6 +10482,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -10686,6 +10846,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -11068,6 +11229,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -11479,6 +11641,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -11820,6 +11983,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -12022,6 +12186,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -12172,6 +12337,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -12311,6 +12477,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -12473,6 +12640,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -12756,6 +12924,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -13061,6 +13230,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty @@ -13285,6 +13455,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.bookTransferTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardCreated()).isEmpty assertThat(parsedWebhookEvent.cardConverted()).isEmpty + assertThat(parsedWebhookEvent.cardPinUpdated()).isEmpty assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty From 5b862041a8be447059faa1cdf44fabcc82ae5764 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:41:29 +0000 Subject: [PATCH 07/15] feat(api): add psd2Context field to ThreeDSAuthentication responses --- .stats.yml | 4 +- .../api/models/ThreeDSAuthentication.kt | 693 +++++++++++++++++- ...thenticationApprovalRequestWebhookEvent.kt | 57 +- ...hreeDSAuthenticationCreatedWebhookEvent.kt | 57 +- ...hreeDSAuthenticationUpdatedWebhookEvent.kt | 57 +- .../api/models/ParsedWebhookEventTest.kt | 76 ++ ...ticationApprovalRequestWebhookEventTest.kt | 25 + ...AuthenticationChallengeWebhookEventTest.kt | 32 + ...DSAuthenticationCreatedWebhookEventTest.kt | 25 + .../api/models/ThreeDSAuthenticationTest.kt | 25 + ...DSAuthenticationUpdatedWebhookEventTest.kt | 25 + 11 files changed, 1070 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 848bba662..36ae04943 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-6acbf033ded2c03ed5d5c64b6bea9f3250323bf7879a11e9c545aa30e65b3cca.yml -openapi_spec_hash: c6007083223ccff12c5c15bc9e531b41 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-e1085922e2d7ee4ce3122f1d9dfe675877f5551a591630592cfea38bd6fea9ed.yml +openapi_spec_hash: e9ca63bde70f9e3953e0a135e7daf185 config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthentication.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthentication.kt index 7dcfe8843..fa7f6cf2a 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthentication.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthentication.kt @@ -41,6 +41,7 @@ private constructor( private val challengeMetadata: JsonField, private val challengeOrchestratedBy: JsonField, private val decisionMadeBy: JsonField, + private val psd2Context: JsonField, private val threeRiRequestType: JsonField, private val transaction: JsonField, private val additionalProperties: MutableMap, @@ -91,6 +92,9 @@ private constructor( @JsonProperty("decision_made_by") @ExcludeMissing decisionMadeBy: JsonField = JsonMissing.of(), + @JsonProperty("psd2_context") + @ExcludeMissing + psd2Context: JsonField = JsonMissing.of(), @JsonProperty("three_ri_request_type") @ExcludeMissing threeRiRequestType: JsonField = JsonMissing.of(), @@ -116,6 +120,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, mutableMapOf(), @@ -292,6 +297,15 @@ private constructor( */ fun decisionMadeBy(): Optional = decisionMadeBy.getOptional("decision_made_by") + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the transaction + * is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope transactions. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun psd2Context(): Optional = psd2Context.getOptional("psd2_context") + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes place * at the initiation of the merchant rather than the cardholder. The most common example of this @@ -468,6 +482,15 @@ private constructor( @ExcludeMissing fun _decisionMadeBy(): JsonField = decisionMadeBy + /** + * Returns the raw JSON value of [psd2Context]. + * + * Unlike [psd2Context], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("psd2_context") + @ExcludeMissing + fun _psd2Context(): JsonField = psd2Context + /** * Returns the raw JSON value of [threeRiRequestType]. * @@ -546,6 +569,7 @@ private constructor( private var challengeMetadata: JsonField = JsonMissing.of() private var challengeOrchestratedBy: JsonField = JsonMissing.of() private var decisionMadeBy: JsonField = JsonMissing.of() + private var psd2Context: JsonField = JsonMissing.of() private var threeRiRequestType: JsonField = JsonMissing.of() private var transaction: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -571,6 +595,7 @@ private constructor( challengeMetadata = threeDSAuthentication.challengeMetadata challengeOrchestratedBy = threeDSAuthentication.challengeOrchestratedBy decisionMadeBy = threeDSAuthentication.decisionMadeBy + psd2Context = threeDSAuthentication.psd2Context threeRiRequestType = threeDSAuthentication.threeRiRequestType transaction = threeDSAuthentication.transaction additionalProperties = threeDSAuthentication.additionalProperties.toMutableMap() @@ -906,6 +931,27 @@ private constructor( this.decisionMadeBy = decisionMadeBy } + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the + * transaction is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope + * transactions. + */ + fun psd2Context(psd2Context: Psd2Context?) = psd2Context(JsonField.ofNullable(psd2Context)) + + /** Alias for calling [Builder.psd2Context] with `psd2Context.orElse(null)`. */ + fun psd2Context(psd2Context: Optional) = psd2Context(psd2Context.getOrNull()) + + /** + * Sets [Builder.psd2Context] to an arbitrary JSON value. + * + * You should usually call [Builder.psd2Context] with a well-typed [Psd2Context] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun psd2Context(psd2Context: JsonField) = apply { + this.psd2Context = psd2Context + } + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes * place at the initiation of the merchant rather than the cardholder. The most common @@ -1017,6 +1063,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, additionalProperties.toMutableMap(), @@ -1056,6 +1103,7 @@ private constructor( challengeMetadata().ifPresent { it.validate() } challengeOrchestratedBy().ifPresent { it.validate() } decisionMadeBy().ifPresent { it.validate() } + psd2Context().ifPresent { it.validate() } threeRiRequestType().ifPresent { it.validate() } transaction().ifPresent { it.validate() } validated = true @@ -1094,6 +1142,7 @@ private constructor( (challengeMetadata.asKnown().getOrNull()?.validity() ?: 0) + (challengeOrchestratedBy.asKnown().getOrNull()?.validity() ?: 0) + (decisionMadeBy.asKnown().getOrNull()?.validity() ?: 0) + + (psd2Context.asKnown().getOrNull()?.validity() ?: 0) + (threeRiRequestType.asKnown().getOrNull()?.validity() ?: 0) + (transaction.asKnown().getOrNull()?.validity() ?: 0) @@ -7844,6 +7893,646 @@ private constructor( override fun toString() = value.toString() } + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the transaction + * is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope transactions. + */ + class Psd2Context + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val acquirerExemption: JsonField, + private val lithicExemptionValidation: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("acquirer_exemption") + @ExcludeMissing + acquirerExemption: JsonField = JsonMissing.of(), + @JsonProperty("lithic_exemption_validation") + @ExcludeMissing + lithicExemptionValidation: JsonField = JsonMissing.of(), + ) : this(acquirerExemption, lithicExemptionValidation, mutableMapOf()) + + /** + * SCA exemption declared by the acquirer in the 3DS authentication request. + * * `NONE` - No exemption claimed + * * `TRANSACTION_RISK_ANALYSIS` - Transaction Risk Analysis (TRA) exemption; acquirer + * asserts low fraud risk + * * `LOW_VALUE` - Low-value payment exemption; transaction is below the EUR 30 threshold + * * `RECURRING_PAYMENT` - Recurring payment with a fixed amount to the same payee + * * `MERCHANT_INITIATED_TRANSACTION` - Merchant-initiated transaction (MIT); cardholder not + * present + * * `TRUSTED_BENEFICIARY` - Trusted beneficiary; merchant is on cardholder's whitelist + * * `STRONG_CUSTOMER_AUTHENTICATION_DELEGATION` - SCA already performed by a delegated + * third-party authenticator + * * `SECURE_CORPORATE_PAYMENT` - Secure corporate payment using a dedicated corporate card + * or process + * * `AUTHENTICATION_OUTAGE_EXCEPTION` - Authentication outage exception; scheme-level + * fallback during ACS downtime + * * `BUNDLED` - Mastercard only; bundled exemption code where the exact exemption type + * cannot be distinguished + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun acquirerExemption(): Optional = + acquirerExemption.getOptional("acquirer_exemption") + + /** + * Lithic's validation of the acquirer-declared exemption. Absent when no acquirer exemption + * was declared. + * * `ACCEPTED` - Lithic signals support the acquirer's claim + * * `REJECTED` - Lithic signals contradict the claim, or a required signal is missing + * * `NOT_VALIDATED` - Exemption was declared but Lithic has no basis to evaluate it; + * treated as `REJECTED` for challenge purposes + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun lithicExemptionValidation(): Optional = + lithicExemptionValidation.getOptional("lithic_exemption_validation") + + /** + * Returns the raw JSON value of [acquirerExemption]. + * + * Unlike [acquirerExemption], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("acquirer_exemption") + @ExcludeMissing + fun _acquirerExemption(): JsonField = acquirerExemption + + /** + * Returns the raw JSON value of [lithicExemptionValidation]. + * + * Unlike [lithicExemptionValidation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("lithic_exemption_validation") + @ExcludeMissing + fun _lithicExemptionValidation(): JsonField = + lithicExemptionValidation + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Psd2Context]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Psd2Context]. */ + class Builder internal constructor() { + + private var acquirerExemption: JsonField = JsonMissing.of() + private var lithicExemptionValidation: JsonField = + JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(psd2Context: Psd2Context) = apply { + acquirerExemption = psd2Context.acquirerExemption + lithicExemptionValidation = psd2Context.lithicExemptionValidation + additionalProperties = psd2Context.additionalProperties.toMutableMap() + } + + /** + * SCA exemption declared by the acquirer in the 3DS authentication request. + * * `NONE` - No exemption claimed + * * `TRANSACTION_RISK_ANALYSIS` - Transaction Risk Analysis (TRA) exemption; acquirer + * asserts low fraud risk + * * `LOW_VALUE` - Low-value payment exemption; transaction is below the EUR 30 + * threshold + * * `RECURRING_PAYMENT` - Recurring payment with a fixed amount to the same payee + * * `MERCHANT_INITIATED_TRANSACTION` - Merchant-initiated transaction (MIT); cardholder + * not present + * * `TRUSTED_BENEFICIARY` - Trusted beneficiary; merchant is on cardholder's whitelist + * * `STRONG_CUSTOMER_AUTHENTICATION_DELEGATION` - SCA already performed by a delegated + * third-party authenticator + * * `SECURE_CORPORATE_PAYMENT` - Secure corporate payment using a dedicated corporate + * card or process + * * `AUTHENTICATION_OUTAGE_EXCEPTION` - Authentication outage exception; scheme-level + * fallback during ACS downtime + * * `BUNDLED` - Mastercard only; bundled exemption code where the exact exemption type + * cannot be distinguished + */ + fun acquirerExemption(acquirerExemption: AcquirerExemption) = + acquirerExemption(JsonField.of(acquirerExemption)) + + /** + * Sets [Builder.acquirerExemption] to an arbitrary JSON value. + * + * You should usually call [Builder.acquirerExemption] with a well-typed + * [AcquirerExemption] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun acquirerExemption(acquirerExemption: JsonField) = apply { + this.acquirerExemption = acquirerExemption + } + + /** + * Lithic's validation of the acquirer-declared exemption. Absent when no acquirer + * exemption was declared. + * * `ACCEPTED` - Lithic signals support the acquirer's claim + * * `REJECTED` - Lithic signals contradict the claim, or a required signal is missing + * * `NOT_VALIDATED` - Exemption was declared but Lithic has no basis to evaluate it; + * treated as `REJECTED` for challenge purposes + */ + fun lithicExemptionValidation(lithicExemptionValidation: LithicExemptionValidation) = + lithicExemptionValidation(JsonField.of(lithicExemptionValidation)) + + /** + * Sets [Builder.lithicExemptionValidation] to an arbitrary JSON value. + * + * You should usually call [Builder.lithicExemptionValidation] with a well-typed + * [LithicExemptionValidation] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun lithicExemptionValidation( + lithicExemptionValidation: JsonField + ) = apply { this.lithicExemptionValidation = lithicExemptionValidation } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Psd2Context]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Psd2Context = + Psd2Context( + acquirerExemption, + lithicExemptionValidation, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Psd2Context = apply { + if (validated) { + return@apply + } + + acquirerExemption().ifPresent { it.validate() } + lithicExemptionValidation().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (acquirerExemption.asKnown().getOrNull()?.validity() ?: 0) + + (lithicExemptionValidation.asKnown().getOrNull()?.validity() ?: 0) + + /** + * SCA exemption declared by the acquirer in the 3DS authentication request. + * * `NONE` - No exemption claimed + * * `TRANSACTION_RISK_ANALYSIS` - Transaction Risk Analysis (TRA) exemption; acquirer + * asserts low fraud risk + * * `LOW_VALUE` - Low-value payment exemption; transaction is below the EUR 30 threshold + * * `RECURRING_PAYMENT` - Recurring payment with a fixed amount to the same payee + * * `MERCHANT_INITIATED_TRANSACTION` - Merchant-initiated transaction (MIT); cardholder not + * present + * * `TRUSTED_BENEFICIARY` - Trusted beneficiary; merchant is on cardholder's whitelist + * * `STRONG_CUSTOMER_AUTHENTICATION_DELEGATION` - SCA already performed by a delegated + * third-party authenticator + * * `SECURE_CORPORATE_PAYMENT` - Secure corporate payment using a dedicated corporate card + * or process + * * `AUTHENTICATION_OUTAGE_EXCEPTION` - Authentication outage exception; scheme-level + * fallback during ACS downtime + * * `BUNDLED` - Mastercard only; bundled exemption code where the exact exemption type + * cannot be distinguished + */ + class AcquirerExemption + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val NONE = of("NONE") + + @JvmField val TRANSACTION_RISK_ANALYSIS = of("TRANSACTION_RISK_ANALYSIS") + + @JvmField val LOW_VALUE = of("LOW_VALUE") + + @JvmField val RECURRING_PAYMENT = of("RECURRING_PAYMENT") + + @JvmField val MERCHANT_INITIATED_TRANSACTION = of("MERCHANT_INITIATED_TRANSACTION") + + @JvmField val TRUSTED_BENEFICIARY = of("TRUSTED_BENEFICIARY") + + @JvmField + val STRONG_CUSTOMER_AUTHENTICATION_DELEGATION = + of("STRONG_CUSTOMER_AUTHENTICATION_DELEGATION") + + @JvmField val SECURE_CORPORATE_PAYMENT = of("SECURE_CORPORATE_PAYMENT") + + @JvmField + val AUTHENTICATION_OUTAGE_EXCEPTION = of("AUTHENTICATION_OUTAGE_EXCEPTION") + + @JvmField val BUNDLED = of("BUNDLED") + + @JvmStatic fun of(value: String) = AcquirerExemption(JsonField.of(value)) + } + + /** An enum containing [AcquirerExemption]'s known values. */ + enum class Known { + NONE, + TRANSACTION_RISK_ANALYSIS, + LOW_VALUE, + RECURRING_PAYMENT, + MERCHANT_INITIATED_TRANSACTION, + TRUSTED_BENEFICIARY, + STRONG_CUSTOMER_AUTHENTICATION_DELEGATION, + SECURE_CORPORATE_PAYMENT, + AUTHENTICATION_OUTAGE_EXCEPTION, + BUNDLED, + } + + /** + * An enum containing [AcquirerExemption]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AcquirerExemption] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + NONE, + TRANSACTION_RISK_ANALYSIS, + LOW_VALUE, + RECURRING_PAYMENT, + MERCHANT_INITIATED_TRANSACTION, + TRUSTED_BENEFICIARY, + STRONG_CUSTOMER_AUTHENTICATION_DELEGATION, + SECURE_CORPORATE_PAYMENT, + AUTHENTICATION_OUTAGE_EXCEPTION, + BUNDLED, + /** + * An enum member indicating that [AcquirerExemption] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + NONE -> Value.NONE + TRANSACTION_RISK_ANALYSIS -> Value.TRANSACTION_RISK_ANALYSIS + LOW_VALUE -> Value.LOW_VALUE + RECURRING_PAYMENT -> Value.RECURRING_PAYMENT + MERCHANT_INITIATED_TRANSACTION -> Value.MERCHANT_INITIATED_TRANSACTION + TRUSTED_BENEFICIARY -> Value.TRUSTED_BENEFICIARY + STRONG_CUSTOMER_AUTHENTICATION_DELEGATION -> + Value.STRONG_CUSTOMER_AUTHENTICATION_DELEGATION + SECURE_CORPORATE_PAYMENT -> Value.SECURE_CORPORATE_PAYMENT + AUTHENTICATION_OUTAGE_EXCEPTION -> Value.AUTHENTICATION_OUTAGE_EXCEPTION + BUNDLED -> Value.BUNDLED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + NONE -> Known.NONE + TRANSACTION_RISK_ANALYSIS -> Known.TRANSACTION_RISK_ANALYSIS + LOW_VALUE -> Known.LOW_VALUE + RECURRING_PAYMENT -> Known.RECURRING_PAYMENT + MERCHANT_INITIATED_TRANSACTION -> Known.MERCHANT_INITIATED_TRANSACTION + TRUSTED_BENEFICIARY -> Known.TRUSTED_BENEFICIARY + STRONG_CUSTOMER_AUTHENTICATION_DELEGATION -> + Known.STRONG_CUSTOMER_AUTHENTICATION_DELEGATION + SECURE_CORPORATE_PAYMENT -> Known.SECURE_CORPORATE_PAYMENT + AUTHENTICATION_OUTAGE_EXCEPTION -> Known.AUTHENTICATION_OUTAGE_EXCEPTION + BUNDLED -> Known.BUNDLED + else -> throw LithicInvalidDataException("Unknown AcquirerExemption: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): AcquirerExemption = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AcquirerExemption && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * Lithic's validation of the acquirer-declared exemption. Absent when no acquirer exemption + * was declared. + * * `ACCEPTED` - Lithic signals support the acquirer's claim + * * `REJECTED` - Lithic signals contradict the claim, or a required signal is missing + * * `NOT_VALIDATED` - Exemption was declared but Lithic has no basis to evaluate it; + * treated as `REJECTED` for challenge purposes + */ + class LithicExemptionValidation + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ACCEPTED = of("ACCEPTED") + + @JvmField val REJECTED = of("REJECTED") + + @JvmField val NOT_VALIDATED = of("NOT_VALIDATED") + + @JvmStatic fun of(value: String) = LithicExemptionValidation(JsonField.of(value)) + } + + /** An enum containing [LithicExemptionValidation]'s known values. */ + enum class Known { + ACCEPTED, + REJECTED, + NOT_VALIDATED, + } + + /** + * An enum containing [LithicExemptionValidation]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [LithicExemptionValidation] can contain an unknown value in a couple + * of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ACCEPTED, + REJECTED, + NOT_VALIDATED, + /** + * An enum member indicating that [LithicExemptionValidation] was instantiated with + * an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ACCEPTED -> Value.ACCEPTED + REJECTED -> Value.REJECTED + NOT_VALIDATED -> Value.NOT_VALIDATED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ACCEPTED -> Known.ACCEPTED + REJECTED -> Known.REJECTED + NOT_VALIDATED -> Known.NOT_VALIDATED + else -> + throw LithicInvalidDataException( + "Unknown LithicExemptionValidation: $value" + ) + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): LithicExemptionValidation = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LithicExemptionValidation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Psd2Context && + acquirerExemption == other.acquirerExemption && + lithicExemptionValidation == other.lithicExemptionValidation && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(acquirerExemption, lithicExemptionValidation, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Psd2Context{acquirerExemption=$acquirerExemption, lithicExemptionValidation=$lithicExemptionValidation, additionalProperties=$additionalProperties}" + } + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes place * at the initiation of the merchant rather than the cardholder. The most common example of this @@ -8698,6 +9387,7 @@ private constructor( challengeMetadata == other.challengeMetadata && challengeOrchestratedBy == other.challengeOrchestratedBy && decisionMadeBy == other.decisionMadeBy && + psd2Context == other.psd2Context && threeRiRequestType == other.threeRiRequestType && transaction == other.transaction && additionalProperties == other.additionalProperties @@ -8723,6 +9413,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, additionalProperties, @@ -8732,5 +9423,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "ThreeDSAuthentication{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, threeRiRequestType=$threeRiRequestType, transaction=$transaction, additionalProperties=$additionalProperties}" + "ThreeDSAuthentication{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, psd2Context=$psd2Context, threeRiRequestType=$threeRiRequestType, transaction=$transaction, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEvent.kt index 76db24e51..64845e290 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEvent.kt @@ -43,6 +43,7 @@ private constructor( private val challengeMetadata: JsonField, private val challengeOrchestratedBy: JsonField, private val decisionMadeBy: JsonField, + private val psd2Context: JsonField, private val threeRiRequestType: JsonField, private val transaction: JsonField, private val eventType: JsonField, @@ -106,6 +107,9 @@ private constructor( @JsonProperty("decision_made_by") @ExcludeMissing decisionMadeBy: JsonField = JsonMissing.of(), + @JsonProperty("psd2_context") + @ExcludeMissing + psd2Context: JsonField = JsonMissing.of(), @JsonProperty("three_ri_request_type") @ExcludeMissing threeRiRequestType: JsonField = JsonMissing.of(), @@ -134,6 +138,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, eventType, @@ -160,6 +165,7 @@ private constructor( .challengeMetadata(challengeMetadata) .challengeOrchestratedBy(challengeOrchestratedBy) .decisionMadeBy(decisionMadeBy) + .psd2Context(psd2Context) .threeRiRequestType(threeRiRequestType) .transaction(transaction) .build() @@ -341,6 +347,16 @@ private constructor( fun decisionMadeBy(): Optional = decisionMadeBy.getOptional("decision_made_by") + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the transaction + * is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope transactions. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun psd2Context(): Optional = + psd2Context.getOptional("psd2_context") + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes place * at the initiation of the merchant rather than the cardholder. The most common example of this @@ -533,6 +549,15 @@ private constructor( @ExcludeMissing fun _decisionMadeBy(): JsonField = decisionMadeBy + /** + * Returns the raw JSON value of [psd2Context]. + * + * Unlike [psd2Context], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("psd2_context") + @ExcludeMissing + fun _psd2Context(): JsonField = psd2Context + /** * Returns the raw JSON value of [threeRiRequestType]. * @@ -628,6 +653,7 @@ private constructor( JsonMissing.of() private var decisionMadeBy: JsonField = JsonMissing.of() + private var psd2Context: JsonField = JsonMissing.of() private var threeRiRequestType: JsonField = JsonMissing.of() private var transaction: JsonField = JsonMissing.of() @@ -661,6 +687,7 @@ private constructor( challengeOrchestratedBy = threeDSAuthenticationApprovalRequestWebhookEvent.challengeOrchestratedBy decisionMadeBy = threeDSAuthenticationApprovalRequestWebhookEvent.decisionMadeBy + psd2Context = threeDSAuthenticationApprovalRequestWebhookEvent.psd2Context threeRiRequestType = threeDSAuthenticationApprovalRequestWebhookEvent.threeRiRequestType transaction = threeDSAuthenticationApprovalRequestWebhookEvent.transaction eventType = threeDSAuthenticationApprovalRequestWebhookEvent.eventType @@ -1022,6 +1049,29 @@ private constructor( this.decisionMadeBy = decisionMadeBy } + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the + * transaction is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope + * transactions. + */ + fun psd2Context(psd2Context: ThreeDSAuthentication.Psd2Context?) = + psd2Context(JsonField.ofNullable(psd2Context)) + + /** Alias for calling [Builder.psd2Context] with `psd2Context.orElse(null)`. */ + fun psd2Context(psd2Context: Optional) = + psd2Context(psd2Context.getOrNull()) + + /** + * Sets [Builder.psd2Context] to an arbitrary JSON value. + * + * You should usually call [Builder.psd2Context] with a well-typed + * [ThreeDSAuthentication.Psd2Context] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun psd2Context(psd2Context: JsonField) = apply { + this.psd2Context = psd2Context + } + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes * place at the initiation of the merchant rather than the cardholder. The most common @@ -1148,6 +1198,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, checkRequired("eventType", eventType), @@ -1188,6 +1239,7 @@ private constructor( challengeMetadata().ifPresent { it.validate() } challengeOrchestratedBy().ifPresent { it.validate() } decisionMadeBy().ifPresent { it.validate() } + psd2Context().ifPresent { it.validate() } threeRiRequestType().ifPresent { it.validate() } transaction().ifPresent { it.validate() } eventType().validate() @@ -1227,6 +1279,7 @@ private constructor( (challengeMetadata.asKnown().getOrNull()?.validity() ?: 0) + (challengeOrchestratedBy.asKnown().getOrNull()?.validity() ?: 0) + (decisionMadeBy.asKnown().getOrNull()?.validity() ?: 0) + + (psd2Context.asKnown().getOrNull()?.validity() ?: 0) + (threeRiRequestType.asKnown().getOrNull()?.validity() ?: 0) + (transaction.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -1389,6 +1442,7 @@ private constructor( challengeMetadata == other.challengeMetadata && challengeOrchestratedBy == other.challengeOrchestratedBy && decisionMadeBy == other.decisionMadeBy && + psd2Context == other.psd2Context && threeRiRequestType == other.threeRiRequestType && transaction == other.transaction && eventType == other.eventType && @@ -1415,6 +1469,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, eventType, @@ -1425,5 +1480,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "ThreeDSAuthenticationApprovalRequestWebhookEvent{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, threeRiRequestType=$threeRiRequestType, transaction=$transaction, eventType=$eventType, additionalProperties=$additionalProperties}" + "ThreeDSAuthenticationApprovalRequestWebhookEvent{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, psd2Context=$psd2Context, threeRiRequestType=$threeRiRequestType, transaction=$transaction, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEvent.kt index 0417e3cd1..ed48dd89b 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEvent.kt @@ -43,6 +43,7 @@ private constructor( private val challengeMetadata: JsonField, private val challengeOrchestratedBy: JsonField, private val decisionMadeBy: JsonField, + private val psd2Context: JsonField, private val threeRiRequestType: JsonField, private val transaction: JsonField, private val eventType: JsonField, @@ -106,6 +107,9 @@ private constructor( @JsonProperty("decision_made_by") @ExcludeMissing decisionMadeBy: JsonField = JsonMissing.of(), + @JsonProperty("psd2_context") + @ExcludeMissing + psd2Context: JsonField = JsonMissing.of(), @JsonProperty("three_ri_request_type") @ExcludeMissing threeRiRequestType: JsonField = JsonMissing.of(), @@ -134,6 +138,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, eventType, @@ -160,6 +165,7 @@ private constructor( .challengeMetadata(challengeMetadata) .challengeOrchestratedBy(challengeOrchestratedBy) .decisionMadeBy(decisionMadeBy) + .psd2Context(psd2Context) .threeRiRequestType(threeRiRequestType) .transaction(transaction) .build() @@ -341,6 +347,16 @@ private constructor( fun decisionMadeBy(): Optional = decisionMadeBy.getOptional("decision_made_by") + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the transaction + * is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope transactions. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun psd2Context(): Optional = + psd2Context.getOptional("psd2_context") + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes place * at the initiation of the merchant rather than the cardholder. The most common example of this @@ -535,6 +551,15 @@ private constructor( @ExcludeMissing fun _decisionMadeBy(): JsonField = decisionMadeBy + /** + * Returns the raw JSON value of [psd2Context]. + * + * Unlike [psd2Context], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("psd2_context") + @ExcludeMissing + fun _psd2Context(): JsonField = psd2Context + /** * Returns the raw JSON value of [threeRiRequestType]. * @@ -630,6 +655,7 @@ private constructor( JsonMissing.of() private var decisionMadeBy: JsonField = JsonMissing.of() + private var psd2Context: JsonField = JsonMissing.of() private var threeRiRequestType: JsonField = JsonMissing.of() private var transaction: JsonField = JsonMissing.of() @@ -661,6 +687,7 @@ private constructor( challengeOrchestratedBy = threeDSAuthenticationCreatedWebhookEvent.challengeOrchestratedBy decisionMadeBy = threeDSAuthenticationCreatedWebhookEvent.decisionMadeBy + psd2Context = threeDSAuthenticationCreatedWebhookEvent.psd2Context threeRiRequestType = threeDSAuthenticationCreatedWebhookEvent.threeRiRequestType transaction = threeDSAuthenticationCreatedWebhookEvent.transaction eventType = threeDSAuthenticationCreatedWebhookEvent.eventType @@ -1022,6 +1049,29 @@ private constructor( this.decisionMadeBy = decisionMadeBy } + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the + * transaction is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope + * transactions. + */ + fun psd2Context(psd2Context: ThreeDSAuthentication.Psd2Context?) = + psd2Context(JsonField.ofNullable(psd2Context)) + + /** Alias for calling [Builder.psd2Context] with `psd2Context.orElse(null)`. */ + fun psd2Context(psd2Context: Optional) = + psd2Context(psd2Context.getOrNull()) + + /** + * Sets [Builder.psd2Context] to an arbitrary JSON value. + * + * You should usually call [Builder.psd2Context] with a well-typed + * [ThreeDSAuthentication.Psd2Context] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun psd2Context(psd2Context: JsonField) = apply { + this.psd2Context = psd2Context + } + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes * place at the initiation of the merchant rather than the cardholder. The most common @@ -1149,6 +1199,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, checkRequired("eventType", eventType), @@ -1189,6 +1240,7 @@ private constructor( challengeMetadata().ifPresent { it.validate() } challengeOrchestratedBy().ifPresent { it.validate() } decisionMadeBy().ifPresent { it.validate() } + psd2Context().ifPresent { it.validate() } threeRiRequestType().ifPresent { it.validate() } transaction().ifPresent { it.validate() } eventType().validate() @@ -1228,6 +1280,7 @@ private constructor( (challengeMetadata.asKnown().getOrNull()?.validity() ?: 0) + (challengeOrchestratedBy.asKnown().getOrNull()?.validity() ?: 0) + (decisionMadeBy.asKnown().getOrNull()?.validity() ?: 0) + + (psd2Context.asKnown().getOrNull()?.validity() ?: 0) + (threeRiRequestType.asKnown().getOrNull()?.validity() ?: 0) + (transaction.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -1387,6 +1440,7 @@ private constructor( challengeMetadata == other.challengeMetadata && challengeOrchestratedBy == other.challengeOrchestratedBy && decisionMadeBy == other.decisionMadeBy && + psd2Context == other.psd2Context && threeRiRequestType == other.threeRiRequestType && transaction == other.transaction && eventType == other.eventType && @@ -1413,6 +1467,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, eventType, @@ -1423,5 +1478,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "ThreeDSAuthenticationCreatedWebhookEvent{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, threeRiRequestType=$threeRiRequestType, transaction=$transaction, eventType=$eventType, additionalProperties=$additionalProperties}" + "ThreeDSAuthenticationCreatedWebhookEvent{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, psd2Context=$psd2Context, threeRiRequestType=$threeRiRequestType, transaction=$transaction, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEvent.kt index b7e230718..38eb910ba 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEvent.kt @@ -43,6 +43,7 @@ private constructor( private val challengeMetadata: JsonField, private val challengeOrchestratedBy: JsonField, private val decisionMadeBy: JsonField, + private val psd2Context: JsonField, private val threeRiRequestType: JsonField, private val transaction: JsonField, private val eventType: JsonField, @@ -106,6 +107,9 @@ private constructor( @JsonProperty("decision_made_by") @ExcludeMissing decisionMadeBy: JsonField = JsonMissing.of(), + @JsonProperty("psd2_context") + @ExcludeMissing + psd2Context: JsonField = JsonMissing.of(), @JsonProperty("three_ri_request_type") @ExcludeMissing threeRiRequestType: JsonField = JsonMissing.of(), @@ -134,6 +138,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, eventType, @@ -160,6 +165,7 @@ private constructor( .challengeMetadata(challengeMetadata) .challengeOrchestratedBy(challengeOrchestratedBy) .decisionMadeBy(decisionMadeBy) + .psd2Context(psd2Context) .threeRiRequestType(threeRiRequestType) .transaction(transaction) .build() @@ -341,6 +347,16 @@ private constructor( fun decisionMadeBy(): Optional = decisionMadeBy.getOptional("decision_made_by") + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the transaction + * is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope transactions. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun psd2Context(): Optional = + psd2Context.getOptional("psd2_context") + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes place * at the initiation of the merchant rather than the cardholder. The most common example of this @@ -535,6 +551,15 @@ private constructor( @ExcludeMissing fun _decisionMadeBy(): JsonField = decisionMadeBy + /** + * Returns the raw JSON value of [psd2Context]. + * + * Unlike [psd2Context], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("psd2_context") + @ExcludeMissing + fun _psd2Context(): JsonField = psd2Context + /** * Returns the raw JSON value of [threeRiRequestType]. * @@ -630,6 +655,7 @@ private constructor( JsonMissing.of() private var decisionMadeBy: JsonField = JsonMissing.of() + private var psd2Context: JsonField = JsonMissing.of() private var threeRiRequestType: JsonField = JsonMissing.of() private var transaction: JsonField = JsonMissing.of() @@ -661,6 +687,7 @@ private constructor( challengeOrchestratedBy = threeDSAuthenticationUpdatedWebhookEvent.challengeOrchestratedBy decisionMadeBy = threeDSAuthenticationUpdatedWebhookEvent.decisionMadeBy + psd2Context = threeDSAuthenticationUpdatedWebhookEvent.psd2Context threeRiRequestType = threeDSAuthenticationUpdatedWebhookEvent.threeRiRequestType transaction = threeDSAuthenticationUpdatedWebhookEvent.transaction eventType = threeDSAuthenticationUpdatedWebhookEvent.eventType @@ -1022,6 +1049,29 @@ private constructor( this.decisionMadeBy = decisionMadeBy } + /** + * PSD2/SCA context for EEA and UK transactions. Present when Lithic determines the + * transaction is in scope for PSD2 Strong Customer Authentication. Absent for out-of-scope + * transactions. + */ + fun psd2Context(psd2Context: ThreeDSAuthentication.Psd2Context?) = + psd2Context(JsonField.ofNullable(psd2Context)) + + /** Alias for calling [Builder.psd2Context] with `psd2Context.orElse(null)`. */ + fun psd2Context(psd2Context: Optional) = + psd2Context(psd2Context.getOrNull()) + + /** + * Sets [Builder.psd2Context] to an arbitrary JSON value. + * + * You should usually call [Builder.psd2Context] with a well-typed + * [ThreeDSAuthentication.Psd2Context] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun psd2Context(psd2Context: JsonField) = apply { + this.psd2Context = psd2Context + } + /** * Type of 3DS Requestor Initiated (3RI) request — i.e., a 3DS authentication that takes * place at the initiation of the merchant rather than the cardholder. The most common @@ -1149,6 +1199,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, checkRequired("eventType", eventType), @@ -1189,6 +1240,7 @@ private constructor( challengeMetadata().ifPresent { it.validate() } challengeOrchestratedBy().ifPresent { it.validate() } decisionMadeBy().ifPresent { it.validate() } + psd2Context().ifPresent { it.validate() } threeRiRequestType().ifPresent { it.validate() } transaction().ifPresent { it.validate() } eventType().validate() @@ -1228,6 +1280,7 @@ private constructor( (challengeMetadata.asKnown().getOrNull()?.validity() ?: 0) + (challengeOrchestratedBy.asKnown().getOrNull()?.validity() ?: 0) + (decisionMadeBy.asKnown().getOrNull()?.validity() ?: 0) + + (psd2Context.asKnown().getOrNull()?.validity() ?: 0) + (threeRiRequestType.asKnown().getOrNull()?.validity() ?: 0) + (transaction.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -1387,6 +1440,7 @@ private constructor( challengeMetadata == other.challengeMetadata && challengeOrchestratedBy == other.challengeOrchestratedBy && decisionMadeBy == other.decisionMadeBy && + psd2Context == other.psd2Context && threeRiRequestType == other.threeRiRequestType && transaction == other.transaction && eventType == other.eventType && @@ -1413,6 +1467,7 @@ private constructor( challengeMetadata, challengeOrchestratedBy, decisionMadeBy, + psd2Context, threeRiRequestType, transaction, eventType, @@ -1423,5 +1478,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "ThreeDSAuthenticationUpdatedWebhookEvent{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, threeRiRequestType=$threeRiRequestType, transaction=$transaction, eventType=$eventType, additionalProperties=$additionalProperties}" + "ThreeDSAuthenticationUpdatedWebhookEvent{token=$token, accountType=$accountType, authenticationResult=$authenticationResult, cardExpiryCheck=$cardExpiryCheck, cardToken=$cardToken, cardholder=$cardholder, channel=$channel, created=$created, merchant=$merchant, messageCategory=$messageCategory, threeDSRequestorChallengeIndicator=$threeDSRequestorChallengeIndicator, additionalData=$additionalData, app=$app, authenticationRequestType=$authenticationRequestType, browser=$browser, challengeMetadata=$challengeMetadata, challengeOrchestratedBy=$challengeOrchestratedBy, decisionMadeBy=$decisionMadeBy, psd2Context=$psd2Context, threeRiRequestType=$threeRiRequestType, transaction=$transaction, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt index 227d2a165..880bd97c1 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ParsedWebhookEventTest.kt @@ -10811,6 +10811,14 @@ internal class ParsedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -11038,6 +11046,16 @@ internal class ParsedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) @@ -11194,6 +11212,14 @@ internal class ParsedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -11421,6 +11447,16 @@ internal class ParsedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) @@ -11591,6 +11627,17 @@ internal class ParsedWebhookEventTest { ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC ) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation + .ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) @@ -11845,6 +11892,17 @@ internal class ParsedWebhookEventTest { ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC ) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation + .ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) @@ -12887,6 +12945,14 @@ internal class ParsedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -13116,6 +13182,16 @@ internal class ParsedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEventTest.kt index 1fb4a8418..3c08c9126 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationApprovalRequestWebhookEventTest.kt @@ -137,6 +137,14 @@ internal class ThreeDSAuthenticationApprovalRequestWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -290,6 +298,15 @@ internal class ThreeDSAuthenticationApprovalRequestWebhookEventTest { .contains(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) assertThat(threeDSAuthenticationApprovalRequestWebhookEvent.decisionMadeBy()) .contains(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + assertThat(threeDSAuthenticationApprovalRequestWebhookEvent.psd2Context()) + .contains( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) assertThat(threeDSAuthenticationApprovalRequestWebhookEvent.threeRiRequestType()) .contains(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) assertThat(threeDSAuthenticationApprovalRequestWebhookEvent.transaction()) @@ -438,6 +455,14 @@ internal class ThreeDSAuthenticationApprovalRequestWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationChallengeWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationChallengeWebhookEventTest.kt index c67163292..3a2903d59 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationChallengeWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationChallengeWebhookEventTest.kt @@ -151,6 +151,17 @@ internal class ThreeDSAuthenticationChallengeWebhookEventTest { ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC ) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation + .ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) @@ -315,6 +326,16 @@ internal class ThreeDSAuthenticationChallengeWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) @@ -491,6 +512,17 @@ internal class ThreeDSAuthenticationChallengeWebhookEventTest { ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC ) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption( + ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE + ) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation + .ACCEPTED + ) + .build() + ) .threeRiRequestType( ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEventTest.kt index fb4ae18d6..e8197330f 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationCreatedWebhookEventTest.kt @@ -137,6 +137,14 @@ internal class ThreeDSAuthenticationCreatedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -287,6 +295,15 @@ internal class ThreeDSAuthenticationCreatedWebhookEventTest { .contains(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) assertThat(threeDSAuthenticationCreatedWebhookEvent.decisionMadeBy()) .contains(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + assertThat(threeDSAuthenticationCreatedWebhookEvent.psd2Context()) + .contains( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) assertThat(threeDSAuthenticationCreatedWebhookEvent.threeRiRequestType()) .contains(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) assertThat(threeDSAuthenticationCreatedWebhookEvent.transaction()) @@ -434,6 +451,14 @@ internal class ThreeDSAuthenticationCreatedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationTest.kt index e8028ae8a..48db52000 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationTest.kt @@ -137,6 +137,14 @@ internal class ThreeDSAuthenticationTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -282,6 +290,15 @@ internal class ThreeDSAuthenticationTest { .contains(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) assertThat(threeDSAuthentication.decisionMadeBy()) .contains(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + assertThat(threeDSAuthentication.psd2Context()) + .contains( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) assertThat(threeDSAuthentication.threeRiRequestType()) .contains(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) assertThat(threeDSAuthentication.transaction()) @@ -425,6 +442,14 @@ internal class ThreeDSAuthenticationTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEventTest.kt index 18b03f6ea..fe09621d7 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ThreeDSAuthenticationUpdatedWebhookEventTest.kt @@ -137,6 +137,14 @@ internal class ThreeDSAuthenticationUpdatedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() @@ -287,6 +295,15 @@ internal class ThreeDSAuthenticationUpdatedWebhookEventTest { .contains(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) assertThat(threeDSAuthenticationUpdatedWebhookEvent.decisionMadeBy()) .contains(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + assertThat(threeDSAuthenticationUpdatedWebhookEvent.psd2Context()) + .contains( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) assertThat(threeDSAuthenticationUpdatedWebhookEvent.threeRiRequestType()) .contains(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) assertThat(threeDSAuthenticationUpdatedWebhookEvent.transaction()) @@ -434,6 +451,14 @@ internal class ThreeDSAuthenticationUpdatedWebhookEventTest { ) .challengeOrchestratedBy(ThreeDSAuthentication.ChallengeOrchestratedBy.LITHIC) .decisionMadeBy(ThreeDSAuthentication.DecisionMadeBy.LITHIC_RULES) + .psd2Context( + ThreeDSAuthentication.Psd2Context.builder() + .acquirerExemption(ThreeDSAuthentication.Psd2Context.AcquirerExemption.NONE) + .lithicExemptionValidation( + ThreeDSAuthentication.Psd2Context.LithicExemptionValidation.ACCEPTED + ) + .build() + ) .threeRiRequestType(ThreeDSAuthentication.ThreeRiRequestType.ACCOUNT_VERIFICATION) .transaction( ThreeDSAuthentication.Transaction.builder() From 3d90574a2bd217af7a1e3161c55a17c2d3f7b6bc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:59:44 +0000 Subject: [PATCH 08/15] feat: [CARDS-5174] Add reiusse/renew 409 error --- .stats.yml | 4 ++-- .../main/kotlin/com/lithic/api/models/CardReissueParams.kt | 3 ++- .../main/kotlin/com/lithic/api/models/CardRenewParams.kt | 1 + .../com/lithic/api/services/async/CardServiceAsync.kt | 6 ++++-- .../kotlin/com/lithic/api/services/blocking/CardService.kt | 6 ++++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 36ae04943..c5508542e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-e1085922e2d7ee4ce3122f1d9dfe675877f5551a591630592cfea38bd6fea9ed.yml -openapi_spec_hash: e9ca63bde70f9e3953e0a135e7daf185 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-d25e38eb235b2a76fb0920a6316f134eeb541476224cf9d2b8bf7e899d06f9f4.yml +openapi_spec_hash: 7b64684e889ae161a1354dc34f3499dd config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardReissueParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardReissueParams.kt index 09545c5c3..223c54a0e 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardReissueParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardReissueParams.kt @@ -24,7 +24,8 @@ import kotlin.jvm.optionals.getOrNull * Initiate print and shipment of a duplicate physical card (e.g. card is physically damaged). The * PAN, expiry, and CVC2 will remain the same and the original card can continue to be used until * the new card is activated. Only applies to cards of type `PHYSICAL`. A card can be reissued or - * renewed a total of 8 times. + * renewed a total of 8 times. Returns `409` if the card is still ongoing manufacturing when using + * Thales as a manufacturer. */ class CardReissueParams private constructor( diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardRenewParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardRenewParams.kt index 248bcf9d2..ed1de2970 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardRenewParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardRenewParams.kt @@ -29,6 +29,7 @@ import kotlin.jvm.optionals.getOrNull * `PHYSICAL` card can be reissued or renewed a total of 8 times. For `VIRTUAL`, the card will * retain the same card token and PAN and receive an updated expiry and CVC2 code. `product_id`, * `shipping_method`, `shipping_address`, `carrier` are only relevant for renewing `PHYSICAL` cards. + * Returns `409` if the card is still ongoing manufacturing when using Thales as a manufacturer. */ class CardRenewParams private constructor( diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/CardServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/CardServiceAsync.kt index ed2540e26..ed4fb530b 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/CardServiceAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/CardServiceAsync.kt @@ -294,7 +294,8 @@ interface CardServiceAsync { * Initiate print and shipment of a duplicate physical card (e.g. card is physically damaged). * The PAN, expiry, and CVC2 will remain the same and the original card can continue to be used * until the new card is activated. Only applies to cards of type `PHYSICAL`. A card can be - * reissued or renewed a total of 8 times. + * reissued or renewed a total of 8 times. Returns `409` if the card is still ongoing + * manufacturing when using Thales as a manufacturer. */ fun reissue(cardToken: String): CompletableFuture = reissue(cardToken, CardReissueParams.none()) @@ -335,7 +336,8 @@ interface CardServiceAsync { * card is activated. A `PHYSICAL` card can be reissued or renewed a total of 8 times. For * `VIRTUAL`, the card will retain the same card token and PAN and receive an updated expiry and * CVC2 code. `product_id`, `shipping_method`, `shipping_address`, `carrier` are only relevant - * for renewing `PHYSICAL` cards. + * for renewing `PHYSICAL` cards. Returns `409` if the card is still ongoing manufacturing when + * using Thales as a manufacturer. */ fun renew(cardToken: String, params: CardRenewParams): CompletableFuture = renew(cardToken, params, RequestOptions.none()) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/CardService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/CardService.kt index b9ee7580d..51411277c 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/CardService.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/CardService.kt @@ -272,7 +272,8 @@ interface CardService { * Initiate print and shipment of a duplicate physical card (e.g. card is physically damaged). * The PAN, expiry, and CVC2 will remain the same and the original card can continue to be used * until the new card is activated. Only applies to cards of type `PHYSICAL`. A card can be - * reissued or renewed a total of 8 times. + * reissued or renewed a total of 8 times. Returns `409` if the card is still ongoing + * manufacturing when using Thales as a manufacturer. */ fun reissue(cardToken: String): Card = reissue(cardToken, CardReissueParams.none()) @@ -308,7 +309,8 @@ interface CardService { * card is activated. A `PHYSICAL` card can be reissued or renewed a total of 8 times. For * `VIRTUAL`, the card will retain the same card token and PAN and receive an updated expiry and * CVC2 code. `product_id`, `shipping_method`, `shipping_address`, `carrier` are only relevant - * for renewing `PHYSICAL` cards. + * for renewing `PHYSICAL` cards. Returns `409` if the card is still ongoing manufacturing when + * using Thales as a manufacturer. */ fun renew(cardToken: String, params: CardRenewParams): Card = renew(cardToken, params, RequestOptions.none()) From eb203cb3d42ad2e5af7924be34535db8f7ffe936 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 18:30:12 +0000 Subject: [PATCH 09/15] feat(api): add STABLECOIN_REVIEWED simulation type to payment simulate action --- .stats.yml | 4 ++-- .../com/lithic/api/models/PaymentSimulateActionParams.kt | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c5508542e..50c924c0b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-d25e38eb235b2a76fb0920a6316f134eeb541476224cf9d2b8bf7e899d06f9f4.yml -openapi_spec_hash: 7b64684e889ae161a1354dc34f3499dd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-da0eed08089ca63f636cb174cdabe65591f65bb8a16bd5db94439834cc509044.yml +openapi_spec_hash: 2f7de4d9c35540a1d0163b75b4c08f6d config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt index df13ef6b5..39d3fffaa 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt @@ -790,6 +790,8 @@ private constructor( @JvmField val ACH_RETURN_SETTLED = of("ACH_RETURN_SETTLED") + @JvmField val STABLECOIN_REVIEWED = of("STABLECOIN_REVIEWED") + @JvmStatic fun of(value: String) = SupportedSimulationTypes(JsonField.of(value)) } @@ -805,6 +807,7 @@ private constructor( ACH_RETURN_INITIATED, ACH_RETURN_PROCESSED, ACH_RETURN_SETTLED, + STABLECOIN_REVIEWED, } /** @@ -829,6 +832,7 @@ private constructor( ACH_RETURN_INITIATED, ACH_RETURN_PROCESSED, ACH_RETURN_SETTLED, + STABLECOIN_REVIEWED, /** * An enum member indicating that [SupportedSimulationTypes] was instantiated with an * unknown value. @@ -855,6 +859,7 @@ private constructor( ACH_RETURN_INITIATED -> Value.ACH_RETURN_INITIATED ACH_RETURN_PROCESSED -> Value.ACH_RETURN_PROCESSED ACH_RETURN_SETTLED -> Value.ACH_RETURN_SETTLED + STABLECOIN_REVIEWED -> Value.STABLECOIN_REVIEWED else -> Value._UNKNOWN } @@ -879,6 +884,7 @@ private constructor( ACH_RETURN_INITIATED -> Known.ACH_RETURN_INITIATED ACH_RETURN_PROCESSED -> Known.ACH_RETURN_PROCESSED ACH_RETURN_SETTLED -> Known.ACH_RETURN_SETTLED + STABLECOIN_REVIEWED -> Known.STABLECOIN_REVIEWED else -> throw LithicInvalidDataException("Unknown SupportedSimulationTypes: $value") } From 816b3238971ee1e9f6b2997f5a54c7a598959dd9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 19:22:09 +0000 Subject: [PATCH 10/15] feat: AUTH-3759: Add DECLINE_SCA_REQUIRED and SCA_REQUIRED enum entries --- .stats.yml | 4 ++-- .../main/kotlin/com/lithic/api/models/ReportStats.kt | 6 ++++++ .../main/kotlin/com/lithic/api/models/Transaction.kt | 12 ++++++++++++ .../com/lithic/api/models/V2ListResultsResponse.kt | 6 ++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 50c924c0b..d986b0312 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-da0eed08089ca63f636cb174cdabe65591f65bb8a16bd5db94439834cc509044.yml -openapi_spec_hash: 2f7de4d9c35540a1d0163b75b4c08f6d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-22e6715ab0428fcbda66e78f701a4324634ac8934106a450c50a341a4ad75a39.yml +openapi_spec_hash: 3c728da2d5bf1544686a6f09a0e3e393 config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ReportStats.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ReportStats.kt index d2696ce13..956518f40 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ReportStats.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ReportStats.kt @@ -1506,6 +1506,8 @@ private constructor( @JvmField val REVERSAL_UNMATCHED = of("REVERSAL_UNMATCHED") + @JvmField val SCA_REQUIRED = of("SCA_REQUIRED") + @JvmField val SECURITY_VIOLATION = of("SECURITY_VIOLATION") @JvmField @@ -1587,6 +1589,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -1658,6 +1661,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -1738,6 +1742,7 @@ private constructor( PROGRAM_SUSPENDED -> Value.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Value.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Value.REVERSAL_UNMATCHED + SCA_REQUIRED -> Value.SCA_REQUIRED SECURITY_VIOLATION -> Value.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Value.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Value.SUSPECTED_FRAUD @@ -1819,6 +1824,7 @@ private constructor( PROGRAM_SUSPENDED -> Known.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Known.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Known.REVERSAL_UNMATCHED + SCA_REQUIRED -> Known.SCA_REQUIRED SECURITY_VIOLATION -> Known.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Known.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Known.SUSPECTED_FRAUD diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt index 83af9a311..46162af19 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt @@ -8519,6 +8519,8 @@ private constructor( @JvmField val REVERSAL_UNMATCHED = of("REVERSAL_UNMATCHED") + @JvmField val SCA_REQUIRED = of("SCA_REQUIRED") + @JvmField val SECURITY_VIOLATION = of("SECURITY_VIOLATION") @JvmField val SINGLE_USE_CARD_REATTEMPTED = of("SINGLE_USE_CARD_REATTEMPTED") @@ -8597,6 +8599,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -8666,6 +8669,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -8742,6 +8746,7 @@ private constructor( PROGRAM_SUSPENDED -> Value.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Value.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Value.REVERSAL_UNMATCHED + SCA_REQUIRED -> Value.SCA_REQUIRED SECURITY_VIOLATION -> Value.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Value.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Value.SUSPECTED_FRAUD @@ -8818,6 +8823,7 @@ private constructor( PROGRAM_SUSPENDED -> Known.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Known.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Known.REVERSAL_UNMATCHED + SCA_REQUIRED -> Known.SCA_REQUIRED SECURITY_VIOLATION -> Known.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Known.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Known.SUSPECTED_FRAUD @@ -11242,6 +11248,8 @@ private constructor( @JvmField val REVERSAL_UNMATCHED = of("REVERSAL_UNMATCHED") + @JvmField val SCA_REQUIRED = of("SCA_REQUIRED") + @JvmField val SECURITY_VIOLATION = of("SECURITY_VIOLATION") @JvmField val SINGLE_USE_CARD_REATTEMPTED = of("SINGLE_USE_CARD_REATTEMPTED") @@ -11320,6 +11328,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -11391,6 +11400,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -11470,6 +11480,7 @@ private constructor( PROGRAM_SUSPENDED -> Value.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Value.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Value.REVERSAL_UNMATCHED + SCA_REQUIRED -> Value.SCA_REQUIRED SECURITY_VIOLATION -> Value.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Value.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Value.SUSPECTED_FRAUD @@ -11549,6 +11560,7 @@ private constructor( PROGRAM_SUSPENDED -> Known.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Known.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Known.REVERSAL_UNMATCHED + SCA_REQUIRED -> Known.SCA_REQUIRED SECURITY_VIOLATION -> Known.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Known.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Known.SUSPECTED_FRAUD diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResultsResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResultsResponse.kt index e45b8e0fc..12ea4cd15 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResultsResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResultsResponse.kt @@ -1529,6 +1529,8 @@ private constructor( @JvmField val REVERSAL_UNMATCHED = of("REVERSAL_UNMATCHED") + @JvmField val SCA_REQUIRED = of("SCA_REQUIRED") + @JvmField val SECURITY_VIOLATION = of("SECURITY_VIOLATION") @JvmField @@ -1610,6 +1612,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -1681,6 +1684,7 @@ private constructor( PROGRAM_SUSPENDED, PROGRAM_USAGE_RESTRICTION, REVERSAL_UNMATCHED, + SCA_REQUIRED, SECURITY_VIOLATION, SINGLE_USE_CARD_REATTEMPTED, SUSPECTED_FRAUD, @@ -1761,6 +1765,7 @@ private constructor( PROGRAM_SUSPENDED -> Value.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Value.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Value.REVERSAL_UNMATCHED + SCA_REQUIRED -> Value.SCA_REQUIRED SECURITY_VIOLATION -> Value.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Value.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Value.SUSPECTED_FRAUD @@ -1842,6 +1847,7 @@ private constructor( PROGRAM_SUSPENDED -> Known.PROGRAM_SUSPENDED PROGRAM_USAGE_RESTRICTION -> Known.PROGRAM_USAGE_RESTRICTION REVERSAL_UNMATCHED -> Known.REVERSAL_UNMATCHED + SCA_REQUIRED -> Known.SCA_REQUIRED SECURITY_VIOLATION -> Known.SECURITY_VIOLATION SINGLE_USE_CARD_REATTEMPTED -> Known.SINGLE_USE_CARD_REATTEMPTED SUSPECTED_FRAUD -> Known.SUSPECTED_FRAUD From ea12080f1eac92e1a9bdb3c35ed0b67f3bcf3891 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 13:55:56 +0000 Subject: [PATCH 11/15] feat(api): add FEE/FEE_REVERSAL event types to FinancialEvent/ManagementOperation/StatementLineItems --- .stats.yml | 4 ++-- .../kotlin/com/lithic/api/models/FinancialEvent.kt | 12 ++++++++++++ .../api/models/ManagementOperationCreateParams.kt | 12 ++++++++++++ .../api/models/ManagementOperationTransaction.kt | 12 ++++++++++++ .../com/lithic/api/models/StatementLineItems.kt | 12 ++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d986b0312..50b5107a3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-22e6715ab0428fcbda66e78f701a4324634ac8934106a450c50a341a4ad75a39.yml -openapi_spec_hash: 3c728da2d5bf1544686a6f09a0e3e393 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-cc426da9e5047cbcd8e764a20ea1afd35c685ebaedc87128f0a22f9f05ae1537.yml +openapi_spec_hash: 731d6efde305387fde11ba31972f176b config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt index 4b94db71d..0148e166a 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialEvent.kt @@ -585,6 +585,10 @@ private constructor( @JvmField val EXTERNAL_WIRE_SETTLED = of("EXTERNAL_WIRE_SETTLED") + @JvmField val FEE = of("FEE") + + @JvmField val FEE_REVERSAL = of("FEE_REVERSAL") + @JvmField val FINANCIAL_AUTHORIZATION = of("FINANCIAL_AUTHORIZATION") @JvmField val FINANCIAL_CREDIT_AUTHORIZATION = of("FINANCIAL_CREDIT_AUTHORIZATION") @@ -728,6 +732,8 @@ private constructor( EXTERNAL_WIRE_RELEASED, EXTERNAL_WIRE_REVERSED, EXTERNAL_WIRE_SETTLED, + FEE, + FEE_REVERSAL, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, INSTALLMENT_FEE, @@ -843,6 +849,8 @@ private constructor( EXTERNAL_WIRE_RELEASED, EXTERNAL_WIRE_REVERSED, EXTERNAL_WIRE_SETTLED, + FEE, + FEE_REVERSAL, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, INSTALLMENT_FEE, @@ -962,6 +970,8 @@ private constructor( EXTERNAL_WIRE_RELEASED -> Value.EXTERNAL_WIRE_RELEASED EXTERNAL_WIRE_REVERSED -> Value.EXTERNAL_WIRE_REVERSED EXTERNAL_WIRE_SETTLED -> Value.EXTERNAL_WIRE_SETTLED + FEE -> Value.FEE + FEE_REVERSAL -> Value.FEE_REVERSAL FINANCIAL_AUTHORIZATION -> Value.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Value.FINANCIAL_CREDIT_AUTHORIZATION INSTALLMENT_FEE -> Value.INSTALLMENT_FEE @@ -1079,6 +1089,8 @@ private constructor( EXTERNAL_WIRE_RELEASED -> Known.EXTERNAL_WIRE_RELEASED EXTERNAL_WIRE_REVERSED -> Known.EXTERNAL_WIRE_REVERSED EXTERNAL_WIRE_SETTLED -> Known.EXTERNAL_WIRE_SETTLED + FEE -> Known.FEE + FEE_REVERSAL -> Known.FEE_REVERSAL FINANCIAL_AUTHORIZATION -> Known.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Known.FINANCIAL_CREDIT_AUTHORIZATION INSTALLMENT_FEE -> Known.INSTALLMENT_FEE diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt index ba4e95fb7..46c3eecd9 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationCreateParams.kt @@ -1489,6 +1489,10 @@ private constructor( @JvmField val MONTHLY_REVERSAL = of("MONTHLY_REVERSAL") + @JvmField val FEE = of("FEE") + + @JvmField val FEE_REVERSAL = of("FEE_REVERSAL") + @JvmStatic fun of(value: String) = ManagementOperationEventType(JsonField.of(value)) } @@ -1521,6 +1525,8 @@ private constructor( QUARTERLY_REVERSAL, MONTHLY, MONTHLY_REVERSAL, + FEE, + FEE_REVERSAL, } /** @@ -1562,6 +1568,8 @@ private constructor( QUARTERLY_REVERSAL, MONTHLY, MONTHLY_REVERSAL, + FEE, + FEE_REVERSAL, /** * An enum member indicating that [ManagementOperationEventType] was instantiated with * an unknown value. @@ -1605,6 +1613,8 @@ private constructor( QUARTERLY_REVERSAL -> Value.QUARTERLY_REVERSAL MONTHLY -> Value.MONTHLY MONTHLY_REVERSAL -> Value.MONTHLY_REVERSAL + FEE -> Value.FEE + FEE_REVERSAL -> Value.FEE_REVERSAL else -> Value._UNKNOWN } @@ -1646,6 +1656,8 @@ private constructor( QUARTERLY_REVERSAL -> Known.QUARTERLY_REVERSAL MONTHLY -> Known.MONTHLY MONTHLY_REVERSAL -> Known.MONTHLY_REVERSAL + FEE -> Known.FEE + FEE_REVERSAL -> Known.FEE_REVERSAL else -> throw LithicInvalidDataException("Unknown ManagementOperationEventType: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt index aa9c2c882..7820698a4 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ManagementOperationTransaction.kt @@ -2053,6 +2053,10 @@ private constructor( @JvmField val MONTHLY_REVERSAL = of("MONTHLY_REVERSAL") + @JvmField val FEE = of("FEE") + + @JvmField val FEE_REVERSAL = of("FEE_REVERSAL") + @JvmStatic fun of(value: String) = ManagementOperationEventType(JsonField.of(value)) } @@ -2085,6 +2089,8 @@ private constructor( QUARTERLY_REVERSAL, MONTHLY, MONTHLY_REVERSAL, + FEE, + FEE_REVERSAL, } /** @@ -2126,6 +2132,8 @@ private constructor( QUARTERLY_REVERSAL, MONTHLY, MONTHLY_REVERSAL, + FEE, + FEE_REVERSAL, /** * An enum member indicating that [ManagementOperationEventType] was instantiated * with an unknown value. @@ -2169,6 +2177,8 @@ private constructor( QUARTERLY_REVERSAL -> Value.QUARTERLY_REVERSAL MONTHLY -> Value.MONTHLY MONTHLY_REVERSAL -> Value.MONTHLY_REVERSAL + FEE -> Value.FEE + FEE_REVERSAL -> Value.FEE_REVERSAL else -> Value._UNKNOWN } @@ -2210,6 +2220,8 @@ private constructor( QUARTERLY_REVERSAL -> Known.QUARTERLY_REVERSAL MONTHLY -> Known.MONTHLY MONTHLY_REVERSAL -> Known.MONTHLY_REVERSAL + FEE -> Known.FEE + FEE_REVERSAL -> Known.FEE_REVERSAL else -> throw LithicInvalidDataException( "Unknown ManagementOperationEventType: $value" diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt index 08d72aa9d..72a920b32 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt @@ -1369,6 +1369,10 @@ private constructor( @JvmField val EXTERNAL_WIRE_SETTLED = of("EXTERNAL_WIRE_SETTLED") + @JvmField val FEE = of("FEE") + + @JvmField val FEE_REVERSAL = of("FEE_REVERSAL") + @JvmField val FINANCIAL_AUTHORIZATION = of("FINANCIAL_AUTHORIZATION") @JvmField val FINANCIAL_CREDIT_AUTHORIZATION = of("FINANCIAL_CREDIT_AUTHORIZATION") @@ -1512,6 +1516,8 @@ private constructor( EXTERNAL_WIRE_RELEASED, EXTERNAL_WIRE_REVERSED, EXTERNAL_WIRE_SETTLED, + FEE, + FEE_REVERSAL, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, INSTALLMENT_FEE, @@ -1629,6 +1635,8 @@ private constructor( EXTERNAL_WIRE_RELEASED, EXTERNAL_WIRE_REVERSED, EXTERNAL_WIRE_SETTLED, + FEE, + FEE_REVERSAL, FINANCIAL_AUTHORIZATION, FINANCIAL_CREDIT_AUTHORIZATION, INSTALLMENT_FEE, @@ -1748,6 +1756,8 @@ private constructor( EXTERNAL_WIRE_RELEASED -> Value.EXTERNAL_WIRE_RELEASED EXTERNAL_WIRE_REVERSED -> Value.EXTERNAL_WIRE_REVERSED EXTERNAL_WIRE_SETTLED -> Value.EXTERNAL_WIRE_SETTLED + FEE -> Value.FEE + FEE_REVERSAL -> Value.FEE_REVERSAL FINANCIAL_AUTHORIZATION -> Value.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Value.FINANCIAL_CREDIT_AUTHORIZATION INSTALLMENT_FEE -> Value.INSTALLMENT_FEE @@ -1865,6 +1875,8 @@ private constructor( EXTERNAL_WIRE_RELEASED -> Known.EXTERNAL_WIRE_RELEASED EXTERNAL_WIRE_REVERSED -> Known.EXTERNAL_WIRE_REVERSED EXTERNAL_WIRE_SETTLED -> Known.EXTERNAL_WIRE_SETTLED + FEE -> Known.FEE + FEE_REVERSAL -> Known.FEE_REVERSAL FINANCIAL_AUTHORIZATION -> Known.FINANCIAL_AUTHORIZATION FINANCIAL_CREDIT_AUTHORIZATION -> Known.FINANCIAL_CREDIT_AUTHORIZATION INSTALLMENT_FEE -> Known.INSTALLMENT_FEE From 5e294b48832067d094d6c316c239a33bb10a527a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 21:45:29 +0000 Subject: [PATCH 12/15] feat: [TRE-14464] Update /retry payments endpoint to accept method --- .stats.yml | 4 +- .../lithic/api/models/PaymentRetryParams.kt | 417 ++++++++++++++++-- .../services/async/PaymentServiceAsyncImpl.kt | 2 +- .../services/blocking/PaymentServiceImpl.kt | 2 +- .../api/models/PaymentRetryParamsTest.kt | 28 +- .../services/async/PaymentServiceAsyncTest.kt | 9 +- .../services/blocking/PaymentServiceTest.kt | 9 +- 7 files changed, 424 insertions(+), 47 deletions(-) diff --git a/.stats.yml b/.stats.yml index 50b5107a3..ce934163c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-cc426da9e5047cbcd8e764a20ea1afd35c685ebaedc87128f0a22f9f05ae1537.yml -openapi_spec_hash: 731d6efde305387fde11ba31972f176b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-701e31821e8acdd56e8afce852fd2207ef6962cc314fdc1e9d814adf8aae8e1f.yml +openapi_spec_hash: ddf405339b9f603c2ebc58a0a168bfbd config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentRetryParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentRetryParams.kt index eec406072..8b8a42378 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentRetryParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentRetryParams.kt @@ -2,11 +2,20 @@ package com.lithic.api.models +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing import com.lithic.api.core.JsonValue import com.lithic.api.core.Params import com.lithic.api.core.http.Headers import com.lithic.api.core.http.QueryParams -import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -15,15 +24,31 @@ import kotlin.jvm.optionals.getOrNull class PaymentRetryParams private constructor( private val paymentToken: String?, + private val body: RetryPaymentRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, - private val additionalBodyProperties: Map, ) : Params { fun paymentToken(): Optional = Optional.ofNullable(paymentToken) - /** Additional body properties to send with the request. */ - fun _additionalBodyProperties(): Map = additionalBodyProperties + /** + * Settlement speed to retry the payment at. Defaults to the original payment's method. An + * `ACH_SAME_DAY` retry is rejected if the payment is for $1,000,000.00 or more, or if it is + * submitted after the same day ACH cutoff + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun method(): Optional = body.method() + + /** + * Returns the raw JSON value of [method]. + * + * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _method(): JsonField = body._method() + + fun _additionalBodyProperties(): Map = body._additionalProperties() /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -45,16 +70,16 @@ private constructor( class Builder internal constructor() { private var paymentToken: String? = null + private var body: RetryPaymentRequest.Builder = RetryPaymentRequest.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - private var additionalBodyProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(paymentRetryParams: PaymentRetryParams) = apply { paymentToken = paymentRetryParams.paymentToken + body = paymentRetryParams.body.toBuilder() additionalHeaders = paymentRetryParams.additionalHeaders.toBuilder() additionalQueryParams = paymentRetryParams.additionalQueryParams.toBuilder() - additionalBodyProperties = paymentRetryParams.additionalBodyProperties.toMutableMap() } fun paymentToken(paymentToken: String?) = apply { this.paymentToken = paymentToken } @@ -62,6 +87,49 @@ private constructor( /** Alias for calling [Builder.paymentToken] with `paymentToken.orElse(null)`. */ fun paymentToken(paymentToken: Optional) = paymentToken(paymentToken.getOrNull()) + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [method] + */ + fun body(body: RetryPaymentRequest) = apply { this.body = body.toBuilder() } + + /** + * Settlement speed to retry the payment at. Defaults to the original payment's method. An + * `ACH_SAME_DAY` retry is rejected if the payment is for $1,000,000.00 or more, or if it is + * submitted after the same day ACH cutoff + */ + fun method(method: Method) = apply { body.method(method) } + + /** + * Sets [Builder.method] to an arbitrary JSON value. + * + * You should usually call [Builder.method] with a well-typed [Method] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun method(method: JsonField) = apply { body.method(method) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -160,28 +228,6 @@ private constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - this.additionalBodyProperties.clear() - putAllAdditionalBodyProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - additionalBodyProperties.put(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - this.additionalBodyProperties.putAll(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { - additionalBodyProperties.remove(key) - } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalBodyProperty) - } - /** * Returns an immutable instance of [PaymentRetryParams]. * @@ -190,14 +236,13 @@ private constructor( fun build(): PaymentRetryParams = PaymentRetryParams( paymentToken, + body.build(), additionalHeaders.build(), additionalQueryParams.build(), - additionalBodyProperties.toImmutable(), ) } - fun _body(): Optional> = - Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + fun _body(): RetryPaymentRequest = body fun _pathParam(index: Int): String = when (index) { @@ -209,6 +254,303 @@ private constructor( override fun _queryParams(): QueryParams = additionalQueryParams + /** Optional overrides to apply when retrying a returned origination */ + class RetryPaymentRequest + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val method: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of() + ) : this(method, mutableMapOf()) + + /** + * Settlement speed to retry the payment at. Defaults to the original payment's method. An + * `ACH_SAME_DAY` retry is rejected if the payment is for $1,000,000.00 or more, or if it is + * submitted after the same day ACH cutoff + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun method(): Optional = method.getOptional("method") + + /** + * Returns the raw JSON value of [method]. + * + * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [RetryPaymentRequest]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [RetryPaymentRequest]. */ + class Builder internal constructor() { + + private var method: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(retryPaymentRequest: RetryPaymentRequest) = apply { + method = retryPaymentRequest.method + additionalProperties = retryPaymentRequest.additionalProperties.toMutableMap() + } + + /** + * Settlement speed to retry the payment at. Defaults to the original payment's method. + * An `ACH_SAME_DAY` retry is rejected if the payment is for $1,000,000.00 or more, or + * if it is submitted after the same day ACH cutoff + */ + fun method(method: Method) = method(JsonField.of(method)) + + /** + * Sets [Builder.method] to an arbitrary JSON value. + * + * You should usually call [Builder.method] with a well-typed [Method] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun method(method: JsonField) = apply { this.method = method } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [RetryPaymentRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): RetryPaymentRequest = + RetryPaymentRequest(method, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): RetryPaymentRequest = apply { + if (validated) { + return@apply + } + + method().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = (method.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is RetryPaymentRequest && + method == other.method && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(method, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "RetryPaymentRequest{method=$method, additionalProperties=$additionalProperties}" + } + + /** + * Settlement speed to retry the payment at. Defaults to the original payment's method. An + * `ACH_SAME_DAY` retry is rejected if the payment is for $1,000,000.00 or more, or if it is + * submitted after the same day ACH cutoff + */ + class Method @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val ACH_NEXT_DAY = of("ACH_NEXT_DAY") + + @JvmField val ACH_SAME_DAY = of("ACH_SAME_DAY") + + @JvmStatic fun of(value: String) = Method(JsonField.of(value)) + } + + /** An enum containing [Method]'s known values. */ + enum class Known { + ACH_NEXT_DAY, + ACH_SAME_DAY, + } + + /** + * An enum containing [Method]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Method] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + ACH_NEXT_DAY, + ACH_SAME_DAY, + /** An enum member indicating that [Method] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + ACH_NEXT_DAY -> Value.ACH_NEXT_DAY + ACH_SAME_DAY -> Value.ACH_SAME_DAY + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ACH_NEXT_DAY -> Known.ACH_NEXT_DAY + ACH_SAME_DAY -> Known.ACH_SAME_DAY + else -> throw LithicInvalidDataException("Unknown Method: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Method = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Method && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -216,19 +558,14 @@ private constructor( return other is PaymentRetryParams && paymentToken == other.paymentToken && + body == other.body && additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams && - additionalBodyProperties == other.additionalBodyProperties + additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash( - paymentToken, - additionalHeaders, - additionalQueryParams, - additionalBodyProperties, - ) + Objects.hash(paymentToken, body, additionalHeaders, additionalQueryParams) override fun toString() = - "PaymentRetryParams{paymentToken=$paymentToken, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" + "PaymentRetryParams{paymentToken=$paymentToken, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt index 992d731c1..df3cafb89 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/PaymentServiceAsyncImpl.kt @@ -283,7 +283,7 @@ class PaymentServiceAsyncImpl internal constructor(private val clientOptions: Cl .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("v1", "payments", params._pathParam(0), "retry") - .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt index 318f47886..1bb1fa232 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/PaymentServiceImpl.kt @@ -260,7 +260,7 @@ class PaymentServiceImpl internal constructor(private val clientOptions: ClientO .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("v1", "payments", params._pathParam(0), "retry") - .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentRetryParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentRetryParamsTest.kt index 898f466bb..9f1efa388 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentRetryParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/PaymentRetryParamsTest.kt @@ -9,7 +9,10 @@ internal class PaymentRetryParamsTest { @Test fun create() { - PaymentRetryParams.builder().paymentToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() + PaymentRetryParams.builder() + .paymentToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .method(PaymentRetryParams.Method.ACH_SAME_DAY) + .build() } @Test @@ -23,4 +26,27 @@ internal class PaymentRetryParamsTest { // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } + + @Test + fun body() { + val params = + PaymentRetryParams.builder() + .paymentToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .method(PaymentRetryParams.Method.ACH_SAME_DAY) + .build() + + val body = params._body() + + assertThat(body.method()).contains(PaymentRetryParams.Method.ACH_SAME_DAY) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + PaymentRetryParams.builder() + .paymentToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + val body = params._body() + } } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt index db58bab23..6547b2b80 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/PaymentServiceAsyncTest.kt @@ -6,6 +6,7 @@ import com.lithic.api.TestServerExtension import com.lithic.api.client.okhttp.LithicOkHttpClientAsync import com.lithic.api.models.PaymentCreateParams import com.lithic.api.models.PaymentCreateStablecoinParams +import com.lithic.api.models.PaymentRetryParams import com.lithic.api.models.PaymentReturnParams import com.lithic.api.models.PaymentSimulateActionParams import com.lithic.api.models.PaymentSimulateReceiptParams @@ -127,7 +128,13 @@ internal class PaymentServiceAsyncTest { .build() val paymentServiceAsync = client.payments() - val responseFuture = paymentServiceAsync.retry("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + val responseFuture = + paymentServiceAsync.retry( + PaymentRetryParams.builder() + .paymentToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .method(PaymentRetryParams.Method.ACH_SAME_DAY) + .build() + ) val response = responseFuture.get() response.validate() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt index 94df014ab..c7df5d150 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/PaymentServiceTest.kt @@ -6,6 +6,7 @@ import com.lithic.api.TestServerExtension import com.lithic.api.client.okhttp.LithicOkHttpClient import com.lithic.api.models.PaymentCreateParams import com.lithic.api.models.PaymentCreateStablecoinParams +import com.lithic.api.models.PaymentRetryParams import com.lithic.api.models.PaymentReturnParams import com.lithic.api.models.PaymentSimulateActionParams import com.lithic.api.models.PaymentSimulateReceiptParams @@ -123,7 +124,13 @@ internal class PaymentServiceTest { .build() val paymentService = client.payments() - val response = paymentService.retry("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + val response = + paymentService.retry( + PaymentRetryParams.builder() + .paymentToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .method(PaymentRetryParams.Method.ACH_SAME_DAY) + .build() + ) response.validate() } From b0e8d1fba80804352d37aedf40fb809cc4fc2754 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 20:14:24 +0000 Subject: [PATCH 13/15] feat: [TRE-14524] Add Open to buy API spec --- .stats.yml | 8 +- ...FinancialAccountOpenToBuyRetrieveParams.kt | 220 +++++++++++++ .../kotlin/com/lithic/api/models/OpenToBuy.kt | 230 +++++++++++++ .../com/lithic/api/models/OpenToBuySummary.kt | 301 ++++++++++++++++++ .../async/FinancialAccountServiceAsync.kt | 5 + .../async/FinancialAccountServiceAsyncImpl.kt | 14 + .../OpenToBuyServiceAsync.kt | 148 +++++++++ .../OpenToBuyServiceAsyncImpl.kt | 94 ++++++ .../blocking/FinancialAccountService.kt | 5 + .../blocking/FinancialAccountServiceImpl.kt | 12 + .../financialAccounts/OpenToBuyService.kt | 146 +++++++++ .../financialAccounts/OpenToBuyServiceImpl.kt | 90 ++++++ ...ncialAccountOpenToBuyRetrieveParamsTest.kt | 28 ++ .../lithic/api/models/OpenToBuySummaryTest.kt | 44 +++ .../com/lithic/api/models/OpenToBuyTest.kt | 60 ++++ .../OpenToBuyServiceAsyncTest.kt | 27 ++ .../financialAccounts/OpenToBuyServiceTest.kt | 26 ++ 17 files changed, 1454 insertions(+), 4 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuy.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuySummary.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsync.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncImpl.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyService.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceImpl.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuySummaryTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuyTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceTest.kt diff --git a/.stats.yml b/.stats.yml index ce934163c..c48be9d8b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 218 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-701e31821e8acdd56e8afce852fd2207ef6962cc314fdc1e9d814adf8aae8e1f.yml -openapi_spec_hash: ddf405339b9f603c2ebc58a0a168bfbd -config_hash: b314c3c5c82a483d1a7812b31b1d1fc4 +configured_endpoints: 219 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-18e08b593c738bb6a429fe225dac7c4bf5d161a7dbb003e495b87a21d2aff6a8.yml +openapi_spec_hash: b6f308ea5a6d9ad9c22c14e7574d9669 +config_hash: 0cfee7faa13d28e91697e2d79c50935e diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParams.kt new file mode 100644 index 000000000..1802d79dd --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParams.kt @@ -0,0 +1,220 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.Params +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Get the funds available for card spend backed by a given Security Account, along with the + * balances that amount is derived from. + * + * Open to buy is the amount Lithic authorizes card spend against. It is not a stored balance, so it + * is recalculated on every request from the Security Account, the funds held against spend Lithic + * has already paid out to the networks on your behalf, and the spend that has not yet been + * collected. The accounts that feed the calculation depend on your program setup, so + * `summary.settled_funds` is `null` outside Commercial Charge. + * + * Supported for Commercial Charge, Dynamic Reserve, and Secured Charge programs. Returns `404` if + * `financial_account_token` is not a Security Account you own, or if your program setup does not + * use an open to buy calculation. + */ +class FinancialAccountOpenToBuyRetrieveParams +private constructor( + private val financialAccountToken: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun financialAccountToken(): Optional = Optional.ofNullable(financialAccountToken) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): FinancialAccountOpenToBuyRetrieveParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of + * [FinancialAccountOpenToBuyRetrieveParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FinancialAccountOpenToBuyRetrieveParams]. */ + class Builder internal constructor() { + + private var financialAccountToken: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from( + financialAccountOpenToBuyRetrieveParams: FinancialAccountOpenToBuyRetrieveParams + ) = apply { + financialAccountToken = financialAccountOpenToBuyRetrieveParams.financialAccountToken + additionalHeaders = + financialAccountOpenToBuyRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = + financialAccountOpenToBuyRetrieveParams.additionalQueryParams.toBuilder() + } + + fun financialAccountToken(financialAccountToken: String?) = apply { + this.financialAccountToken = financialAccountToken + } + + /** + * Alias for calling [Builder.financialAccountToken] with + * `financialAccountToken.orElse(null)`. + */ + fun financialAccountToken(financialAccountToken: Optional) = + financialAccountToken(financialAccountToken.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [FinancialAccountOpenToBuyRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams( + financialAccountToken, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> financialAccountToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FinancialAccountOpenToBuyRetrieveParams && + financialAccountToken == other.financialAccountToken && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(financialAccountToken, additionalHeaders, additionalQueryParams) + + override fun toString() = + "FinancialAccountOpenToBuyRetrieveParams{financialAccountToken=$financialAccountToken, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuy.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuy.kt new file mode 100644 index 000000000..ff00744f7 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuy.kt @@ -0,0 +1,230 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkRequired +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** Open to Buy */ +class OpenToBuy +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val openToBuy: JsonField, + private val summary: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("open_to_buy") @ExcludeMissing openToBuy: JsonField = JsonMissing.of(), + @JsonProperty("summary") + @ExcludeMissing + summary: JsonField = JsonMissing.of(), + ) : this(openToBuy, summary, mutableMapOf()) + + /** + * Funds available for card spend backed by this Security Account, in the currency's smallest + * unit (e.g., cents for USD). Equal to the sum of the amounts in `summary`, and reaches zero + * once outstanding spend has consumed all available funding + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun openToBuy(): Long = openToBuy.getRequired("open_to_buy") + + /** + * Balances that open to buy is derived from + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun summary(): OpenToBuySummary = summary.getRequired("summary") + + /** + * Returns the raw JSON value of [openToBuy]. + * + * Unlike [openToBuy], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("open_to_buy") @ExcludeMissing fun _openToBuy(): JsonField = openToBuy + + /** + * Returns the raw JSON value of [summary]. + * + * Unlike [summary], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("summary") @ExcludeMissing fun _summary(): JsonField = summary + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [OpenToBuy]. + * + * The following fields are required: + * ```java + * .openToBuy() + * .summary() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OpenToBuy]. */ + class Builder internal constructor() { + + private var openToBuy: JsonField? = null + private var summary: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(openToBuy: OpenToBuy) = apply { + this.openToBuy = openToBuy.openToBuy + summary = openToBuy.summary + additionalProperties = openToBuy.additionalProperties.toMutableMap() + } + + /** + * Funds available for card spend backed by this Security Account, in the currency's + * smallest unit (e.g., cents for USD). Equal to the sum of the amounts in `summary`, and + * reaches zero once outstanding spend has consumed all available funding + */ + fun openToBuy(openToBuy: Long) = openToBuy(JsonField.of(openToBuy)) + + /** + * Sets [Builder.openToBuy] to an arbitrary JSON value. + * + * You should usually call [Builder.openToBuy] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun openToBuy(openToBuy: JsonField) = apply { this.openToBuy = openToBuy } + + /** Balances that open to buy is derived from */ + fun summary(summary: OpenToBuySummary) = summary(JsonField.of(summary)) + + /** + * Sets [Builder.summary] to an arbitrary JSON value. + * + * You should usually call [Builder.summary] with a well-typed [OpenToBuySummary] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun summary(summary: JsonField) = apply { this.summary = summary } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [OpenToBuy]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .openToBuy() + * .summary() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): OpenToBuy = + OpenToBuy( + checkRequired("openToBuy", openToBuy), + checkRequired("summary", summary), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): OpenToBuy = apply { + if (validated) { + return@apply + } + + openToBuy() + summary().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (openToBuy.asKnown().isPresent) 1 else 0) + + (summary.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OpenToBuy && + openToBuy == other.openToBuy && + summary == other.summary && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(openToBuy, summary, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "OpenToBuy{openToBuy=$openToBuy, summary=$summary, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuySummary.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuySummary.kt new file mode 100644 index 000000000..4b028a6f1 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/OpenToBuySummary.kt @@ -0,0 +1,301 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkRequired +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Open to Buy Summary */ +class OpenToBuySummary +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val security: JsonField, + private val settledFunds: JsonField, + private val totalOutstandingSpend: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("security") @ExcludeMissing security: JsonField = JsonMissing.of(), + @JsonProperty("settled_funds") + @ExcludeMissing + settledFunds: JsonField = JsonMissing.of(), + @JsonProperty("total_outstanding_spend") + @ExcludeMissing + totalOutstandingSpend: JsonField = JsonMissing.of(), + ) : this(security, settledFunds, totalOutstandingSpend, mutableMapOf()) + + /** + * Available balance of the Security Account backing card spend, in the currency's smallest unit + * (e.g., cents for USD) + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun security(): Long = security.getRequired("security") + + /** + * Funding that has moved out of the Security Account to cover card spend Lithic has already + * paid out to the networks, in the currency's smallest unit (e.g., cents for USD). Open to buy + * counts it alongside `security`, and it clears once collected from your business clients. Only + * Commercial Charge tracks this separately, so this is `null` for every other program setup + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun settledFunds(): Optional = settledFunds.getOptional("settled_funds") + + /** + * Customer card spend that has not yet been collected, in the currency's smallest unit (e.g., + * cents for USD). Reported as a negative amount, because it reduces open to buy + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun totalOutstandingSpend(): Long = totalOutstandingSpend.getRequired("total_outstanding_spend") + + /** + * Returns the raw JSON value of [security]. + * + * Unlike [security], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("security") @ExcludeMissing fun _security(): JsonField = security + + /** + * Returns the raw JSON value of [settledFunds]. + * + * Unlike [settledFunds], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("settled_funds") + @ExcludeMissing + fun _settledFunds(): JsonField = settledFunds + + /** + * Returns the raw JSON value of [totalOutstandingSpend]. + * + * Unlike [totalOutstandingSpend], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("total_outstanding_spend") + @ExcludeMissing + fun _totalOutstandingSpend(): JsonField = totalOutstandingSpend + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [OpenToBuySummary]. + * + * The following fields are required: + * ```java + * .security() + * .settledFunds() + * .totalOutstandingSpend() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OpenToBuySummary]. */ + class Builder internal constructor() { + + private var security: JsonField? = null + private var settledFunds: JsonField? = null + private var totalOutstandingSpend: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(openToBuySummary: OpenToBuySummary) = apply { + security = openToBuySummary.security + settledFunds = openToBuySummary.settledFunds + totalOutstandingSpend = openToBuySummary.totalOutstandingSpend + additionalProperties = openToBuySummary.additionalProperties.toMutableMap() + } + + /** + * Available balance of the Security Account backing card spend, in the currency's smallest + * unit (e.g., cents for USD) + */ + fun security(security: Long) = security(JsonField.of(security)) + + /** + * Sets [Builder.security] to an arbitrary JSON value. + * + * You should usually call [Builder.security] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun security(security: JsonField) = apply { this.security = security } + + /** + * Funding that has moved out of the Security Account to cover card spend Lithic has already + * paid out to the networks, in the currency's smallest unit (e.g., cents for USD). Open to + * buy counts it alongside `security`, and it clears once collected from your business + * clients. Only Commercial Charge tracks this separately, so this is `null` for every other + * program setup + */ + fun settledFunds(settledFunds: Long?) = settledFunds(JsonField.ofNullable(settledFunds)) + + /** + * Alias for [Builder.settledFunds]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun settledFunds(settledFunds: Long) = settledFunds(settledFunds as Long?) + + /** Alias for calling [Builder.settledFunds] with `settledFunds.orElse(null)`. */ + fun settledFunds(settledFunds: Optional) = settledFunds(settledFunds.getOrNull()) + + /** + * Sets [Builder.settledFunds] to an arbitrary JSON value. + * + * You should usually call [Builder.settledFunds] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun settledFunds(settledFunds: JsonField) = apply { this.settledFunds = settledFunds } + + /** + * Customer card spend that has not yet been collected, in the currency's smallest unit + * (e.g., cents for USD). Reported as a negative amount, because it reduces open to buy + */ + fun totalOutstandingSpend(totalOutstandingSpend: Long) = + totalOutstandingSpend(JsonField.of(totalOutstandingSpend)) + + /** + * Sets [Builder.totalOutstandingSpend] to an arbitrary JSON value. + * + * You should usually call [Builder.totalOutstandingSpend] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun totalOutstandingSpend(totalOutstandingSpend: JsonField) = apply { + this.totalOutstandingSpend = totalOutstandingSpend + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [OpenToBuySummary]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .security() + * .settledFunds() + * .totalOutstandingSpend() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): OpenToBuySummary = + OpenToBuySummary( + checkRequired("security", security), + checkRequired("settledFunds", settledFunds), + checkRequired("totalOutstandingSpend", totalOutstandingSpend), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): OpenToBuySummary = apply { + if (validated) { + return@apply + } + + security() + settledFunds() + totalOutstandingSpend() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (security.asKnown().isPresent) 1 else 0) + + (if (settledFunds.asKnown().isPresent) 1 else 0) + + (if (totalOutstandingSpend.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OpenToBuySummary && + security == other.security && + settledFunds == other.settledFunds && + totalOutstandingSpend == other.totalOutstandingSpend && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(security, settledFunds, totalOutstandingSpend, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "OpenToBuySummary{security=$security, settledFunds=$settledFunds, totalOutstandingSpend=$totalOutstandingSpend, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt index 8d0362c44..d6c58ce1a 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt @@ -20,6 +20,7 @@ import com.lithic.api.services.async.financialAccounts.FinancialTransactionServi import com.lithic.api.services.async.financialAccounts.InterestTierScheduleServiceAsync import com.lithic.api.services.async.financialAccounts.LoanTapeConfigurationServiceAsync import com.lithic.api.services.async.financialAccounts.LoanTapeServiceAsync +import com.lithic.api.services.async.financialAccounts.OpenToBuyServiceAsync import com.lithic.api.services.async.financialAccounts.StatementServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer @@ -40,6 +41,8 @@ interface FinancialAccountServiceAsync { fun balances(): BalanceServiceAsync + fun openToBuy(): OpenToBuyServiceAsync + fun financialTransactions(): FinancialTransactionServiceAsync fun creditConfiguration(): CreditConfigurationServiceAsync @@ -234,6 +237,8 @@ interface FinancialAccountServiceAsync { fun balances(): BalanceServiceAsync.WithRawResponse + fun openToBuy(): OpenToBuyServiceAsync.WithRawResponse + fun financialTransactions(): FinancialTransactionServiceAsync.WithRawResponse fun creditConfiguration(): CreditConfigurationServiceAsync.WithRawResponse diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt index 94d99f449..7843a7983 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt @@ -38,6 +38,8 @@ import com.lithic.api.services.async.financialAccounts.LoanTapeConfigurationServ import com.lithic.api.services.async.financialAccounts.LoanTapeConfigurationServiceAsyncImpl import com.lithic.api.services.async.financialAccounts.LoanTapeServiceAsync import com.lithic.api.services.async.financialAccounts.LoanTapeServiceAsyncImpl +import com.lithic.api.services.async.financialAccounts.OpenToBuyServiceAsync +import com.lithic.api.services.async.financialAccounts.OpenToBuyServiceAsyncImpl import com.lithic.api.services.async.financialAccounts.StatementServiceAsync import com.lithic.api.services.async.financialAccounts.StatementServiceAsyncImpl import java.util.concurrent.CompletableFuture @@ -53,6 +55,10 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun private val balances: BalanceServiceAsync by lazy { BalanceServiceAsyncImpl(clientOptions) } + private val openToBuy: OpenToBuyServiceAsync by lazy { + OpenToBuyServiceAsyncImpl(clientOptions) + } + private val financialTransactions: FinancialTransactionServiceAsync by lazy { FinancialTransactionServiceAsyncImpl(clientOptions) } @@ -84,6 +90,8 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun override fun balances(): BalanceServiceAsync = balances + override fun openToBuy(): OpenToBuyServiceAsync = openToBuy + override fun financialTransactions(): FinancialTransactionServiceAsync = financialTransactions override fun creditConfiguration(): CreditConfigurationServiceAsync = creditConfiguration @@ -148,6 +156,10 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun BalanceServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val openToBuy: OpenToBuyServiceAsync.WithRawResponse by lazy { + OpenToBuyServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val financialTransactions: FinancialTransactionServiceAsync.WithRawResponse by lazy { FinancialTransactionServiceAsyncImpl.WithRawResponseImpl(clientOptions) @@ -183,6 +195,8 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun override fun balances(): BalanceServiceAsync.WithRawResponse = balances + override fun openToBuy(): OpenToBuyServiceAsync.WithRawResponse = openToBuy + override fun financialTransactions(): FinancialTransactionServiceAsync.WithRawResponse = financialTransactions diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsync.kt new file mode 100644 index 000000000..4178ee921 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsync.kt @@ -0,0 +1,148 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async.financialAccounts + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.models.FinancialAccountOpenToBuyRetrieveParams +import com.lithic.api.models.OpenToBuy +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface OpenToBuyServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): OpenToBuyServiceAsync + + /** + * Get the funds available for card spend backed by a given Security Account, along with the + * balances that amount is derived from. + * + * Open to buy is the amount Lithic authorizes card spend against. It is not a stored balance, + * so it is recalculated on every request from the Security Account, the funds held against + * spend Lithic has already paid out to the networks on your behalf, and the spend that has not + * yet been collected. The accounts that feed the calculation depend on your program setup, so + * `summary.settled_funds` is `null` outside Commercial Charge. + * + * Supported for Commercial Charge, Dynamic Reserve, and Secured Charge programs. Returns `404` + * if `financial_account_token` is not a Security Account you own, or if your program setup does + * not use an open to buy calculation. + */ + fun retrieve(financialAccountToken: String): CompletableFuture = + retrieve(financialAccountToken, FinancialAccountOpenToBuyRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + ): CompletableFuture = retrieve(financialAccountToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see retrieve */ + fun retrieve(params: FinancialAccountOpenToBuyRetrieveParams): CompletableFuture = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + requestOptions: RequestOptions, + ): CompletableFuture = + retrieve( + financialAccountToken, + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions, + ) + + /** + * A view of [OpenToBuyServiceAsync] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): OpenToBuyServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/open_to_buy`, but is otherwise the same + * as [OpenToBuyServiceAsync.retrieve]. + */ + fun retrieve(financialAccountToken: String): CompletableFuture> = + retrieve(financialAccountToken, FinancialAccountOpenToBuyRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + ): CompletableFuture> = + retrieve(financialAccountToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams + ): CompletableFuture> = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + retrieve( + financialAccountToken, + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions, + ) + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncImpl.kt new file mode 100644 index 000000000..04811ace7 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncImpl.kt @@ -0,0 +1,94 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async.financialAccounts + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired +import com.lithic.api.core.handlers.errorBodyHandler +import com.lithic.api.core.handlers.errorHandler +import com.lithic.api.core.handlers.jsonHandler +import com.lithic.api.core.http.HttpMethod +import com.lithic.api.core.http.HttpRequest +import com.lithic.api.core.http.HttpResponse +import com.lithic.api.core.http.HttpResponse.Handler +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.core.http.parseable +import com.lithic.api.core.prepareAsync +import com.lithic.api.models.FinancialAccountOpenToBuyRetrieveParams +import com.lithic.api.models.OpenToBuy +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class OpenToBuyServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + OpenToBuyServiceAsync { + + private val withRawResponse: OpenToBuyServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): OpenToBuyServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): OpenToBuyServiceAsync = + OpenToBuyServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /v1/financial_accounts/{financial_account_token}/open_to_buy + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + OpenToBuyServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): OpenToBuyServiceAsync.WithRawResponse = + OpenToBuyServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "v1", + "financial_accounts", + params._pathParam(0), + "open_to_buy", + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt index eee234e38..7f80f2ca0 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt @@ -21,6 +21,7 @@ import com.lithic.api.services.blocking.financialAccounts.FinancialTransactionSe import com.lithic.api.services.blocking.financialAccounts.InterestTierScheduleService import com.lithic.api.services.blocking.financialAccounts.LoanTapeConfigurationService import com.lithic.api.services.blocking.financialAccounts.LoanTapeService +import com.lithic.api.services.blocking.financialAccounts.OpenToBuyService import com.lithic.api.services.blocking.financialAccounts.StatementService import java.util.function.Consumer @@ -40,6 +41,8 @@ interface FinancialAccountService { fun balances(): BalanceService + fun openToBuy(): OpenToBuyService + fun financialTransactions(): FinancialTransactionService fun creditConfiguration(): CreditConfigurationService @@ -221,6 +224,8 @@ interface FinancialAccountService { fun balances(): BalanceService.WithRawResponse + fun openToBuy(): OpenToBuyService.WithRawResponse + fun financialTransactions(): FinancialTransactionService.WithRawResponse fun creditConfiguration(): CreditConfigurationService.WithRawResponse diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt index 27ce794a8..2e03ff8a4 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt @@ -38,6 +38,8 @@ import com.lithic.api.services.blocking.financialAccounts.LoanTapeConfigurationS import com.lithic.api.services.blocking.financialAccounts.LoanTapeConfigurationServiceImpl import com.lithic.api.services.blocking.financialAccounts.LoanTapeService import com.lithic.api.services.blocking.financialAccounts.LoanTapeServiceImpl +import com.lithic.api.services.blocking.financialAccounts.OpenToBuyService +import com.lithic.api.services.blocking.financialAccounts.OpenToBuyServiceImpl import com.lithic.api.services.blocking.financialAccounts.StatementService import com.lithic.api.services.blocking.financialAccounts.StatementServiceImpl import java.util.function.Consumer @@ -52,6 +54,8 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions private val balances: BalanceService by lazy { BalanceServiceImpl(clientOptions) } + private val openToBuy: OpenToBuyService by lazy { OpenToBuyServiceImpl(clientOptions) } + private val financialTransactions: FinancialTransactionService by lazy { FinancialTransactionServiceImpl(clientOptions) } @@ -79,6 +83,8 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions override fun balances(): BalanceService = balances + override fun openToBuy(): OpenToBuyService = openToBuy + override fun financialTransactions(): FinancialTransactionService = financialTransactions override fun creditConfiguration(): CreditConfigurationService = creditConfiguration @@ -144,6 +150,10 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions BalanceServiceImpl.WithRawResponseImpl(clientOptions) } + private val openToBuy: OpenToBuyService.WithRawResponse by lazy { + OpenToBuyServiceImpl.WithRawResponseImpl(clientOptions) + } + private val financialTransactions: FinancialTransactionService.WithRawResponse by lazy { FinancialTransactionServiceImpl.WithRawResponseImpl(clientOptions) } @@ -177,6 +187,8 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions override fun balances(): BalanceService.WithRawResponse = balances + override fun openToBuy(): OpenToBuyService.WithRawResponse = openToBuy + override fun financialTransactions(): FinancialTransactionService.WithRawResponse = financialTransactions diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyService.kt new file mode 100644 index 000000000..56b3674b1 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyService.kt @@ -0,0 +1,146 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking.financialAccounts + +import com.google.errorprone.annotations.MustBeClosed +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.models.FinancialAccountOpenToBuyRetrieveParams +import com.lithic.api.models.OpenToBuy +import java.util.function.Consumer + +interface OpenToBuyService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): OpenToBuyService + + /** + * Get the funds available for card spend backed by a given Security Account, along with the + * balances that amount is derived from. + * + * Open to buy is the amount Lithic authorizes card spend against. It is not a stored balance, + * so it is recalculated on every request from the Security Account, the funds held against + * spend Lithic has already paid out to the networks on your behalf, and the spend that has not + * yet been collected. The accounts that feed the calculation depend on your program setup, so + * `summary.settled_funds` is `null` outside Commercial Charge. + * + * Supported for Commercial Charge, Dynamic Reserve, and Secured Charge programs. Returns `404` + * if `financial_account_token` is not a Security Account you own, or if your program setup does + * not use an open to buy calculation. + */ + fun retrieve(financialAccountToken: String): OpenToBuy = + retrieve(financialAccountToken, FinancialAccountOpenToBuyRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): OpenToBuy = + retrieve( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + ): OpenToBuy = retrieve(financialAccountToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): OpenToBuy + + /** @see retrieve */ + fun retrieve(params: FinancialAccountOpenToBuyRetrieveParams): OpenToBuy = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(financialAccountToken: String, requestOptions: RequestOptions): OpenToBuy = + retrieve( + financialAccountToken, + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions, + ) + + /** A view of [OpenToBuyService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): OpenToBuyService.WithRawResponse + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/open_to_buy`, but is otherwise the same + * as [OpenToBuyService.retrieve]. + */ + @MustBeClosed + fun retrieve(financialAccountToken: String): HttpResponseFor = + retrieve(financialAccountToken, FinancialAccountOpenToBuyRetrieveParams.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + financialAccountToken: String, + params: FinancialAccountOpenToBuyRetrieveParams = + FinancialAccountOpenToBuyRetrieveParams.none(), + ): HttpResponseFor = + retrieve(financialAccountToken, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(params: FinancialAccountOpenToBuyRetrieveParams): HttpResponseFor = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + financialAccountToken: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + retrieve( + financialAccountToken, + FinancialAccountOpenToBuyRetrieveParams.none(), + requestOptions, + ) + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceImpl.kt new file mode 100644 index 000000000..b645b4cc4 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceImpl.kt @@ -0,0 +1,90 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking.financialAccounts + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired +import com.lithic.api.core.handlers.errorBodyHandler +import com.lithic.api.core.handlers.errorHandler +import com.lithic.api.core.handlers.jsonHandler +import com.lithic.api.core.http.HttpMethod +import com.lithic.api.core.http.HttpRequest +import com.lithic.api.core.http.HttpResponse +import com.lithic.api.core.http.HttpResponse.Handler +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.core.http.parseable +import com.lithic.api.core.prepare +import com.lithic.api.models.FinancialAccountOpenToBuyRetrieveParams +import com.lithic.api.models.OpenToBuy +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class OpenToBuyServiceImpl internal constructor(private val clientOptions: ClientOptions) : + OpenToBuyService { + + private val withRawResponse: OpenToBuyService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): OpenToBuyService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): OpenToBuyService = + OpenToBuyServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions, + ): OpenToBuy = + // get /v1/financial_accounts/{financial_account_token}/open_to_buy + withRawResponse().retrieve(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + OpenToBuyService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): OpenToBuyService.WithRawResponse = + OpenToBuyServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: FinancialAccountOpenToBuyRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "v1", + "financial_accounts", + params._pathParam(0), + "open_to_buy", + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParamsTest.kt new file mode 100644 index 000000000..22f322ff6 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountOpenToBuyRetrieveParamsTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class FinancialAccountOpenToBuyRetrieveParamsTest { + + @Test + fun create() { + FinancialAccountOpenToBuyRetrieveParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + } + + @Test + fun pathParams() { + val params = + FinancialAccountOpenToBuyRetrieveParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuySummaryTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuySummaryTest.kt new file mode 100644 index 000000000..166d1b460 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuySummaryTest.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OpenToBuySummaryTest { + + @Test + fun create() { + val openToBuySummary = + OpenToBuySummary.builder() + .security(300000L) + .settledFunds(300000L) + .totalOutstandingSpend(-250000L) + .build() + + assertThat(openToBuySummary.security()).isEqualTo(300000L) + assertThat(openToBuySummary.settledFunds()).contains(300000L) + assertThat(openToBuySummary.totalOutstandingSpend()).isEqualTo(-250000L) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val openToBuySummary = + OpenToBuySummary.builder() + .security(300000L) + .settledFunds(300000L) + .totalOutstandingSpend(-250000L) + .build() + + val roundtrippedOpenToBuySummary = + jsonMapper.readValue( + jsonMapper.writeValueAsString(openToBuySummary), + jacksonTypeRef(), + ) + + assertThat(roundtrippedOpenToBuySummary).isEqualTo(openToBuySummary) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuyTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuyTest.kt new file mode 100644 index 000000000..83030ee46 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/OpenToBuyTest.kt @@ -0,0 +1,60 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OpenToBuyTest { + + @Test + fun create() { + val openToBuy = + OpenToBuy.builder() + .openToBuy(350000L) + .summary( + OpenToBuySummary.builder() + .security(300000L) + .settledFunds(300000L) + .totalOutstandingSpend(-250000L) + .build() + ) + .build() + + assertThat(openToBuy.openToBuy()).isEqualTo(350000L) + assertThat(openToBuy.summary()) + .isEqualTo( + OpenToBuySummary.builder() + .security(300000L) + .settledFunds(300000L) + .totalOutstandingSpend(-250000L) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val openToBuy = + OpenToBuy.builder() + .openToBuy(350000L) + .summary( + OpenToBuySummary.builder() + .security(300000L) + .settledFunds(300000L) + .totalOutstandingSpend(-250000L) + .build() + ) + .build() + + val roundtrippedOpenToBuy = + jsonMapper.readValue( + jsonMapper.writeValueAsString(openToBuy), + jacksonTypeRef(), + ) + + assertThat(roundtrippedOpenToBuy).isEqualTo(openToBuy) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncTest.kt new file mode 100644 index 000000000..cb82aa04a --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/OpenToBuyServiceAsyncTest.kt @@ -0,0 +1,27 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async.financialAccounts + +import com.lithic.api.TestServerExtension +import com.lithic.api.client.okhttp.LithicOkHttpClientAsync +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class OpenToBuyServiceAsyncTest { + + @Test + fun retrieve() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val openToBuyServiceAsync = client.financialAccounts().openToBuy() + + val openToBuyFuture = openToBuyServiceAsync.retrieve("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + val openToBuy = openToBuyFuture.get() + openToBuy.validate() + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceTest.kt new file mode 100644 index 000000000..3b5389d94 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/OpenToBuyServiceTest.kt @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking.financialAccounts + +import com.lithic.api.TestServerExtension +import com.lithic.api.client.okhttp.LithicOkHttpClient +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class OpenToBuyServiceTest { + + @Test + fun retrieve() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val openToBuyService = client.financialAccounts().openToBuy() + + val openToBuy = openToBuyService.retrieve("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + openToBuy.validate() + } +} From d474e8a168c193f57ada6c99cfe20ad09b8a13bf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 17:30:56 +0000 Subject: [PATCH 14/15] feat(api): add retrieve/list installment plan methods to financial_accounts --- .stats.yml | 8 +- ...FinancialAccountInstallmentPlanListPage.kt | 143 ++ ...cialAccountInstallmentPlanListPageAsync.kt | 159 ++ ...lAccountInstallmentPlanListPageResponse.kt | 238 ++ ...nancialAccountInstallmentPlanListParams.kt | 465 ++++ ...ialAccountInstallmentPlanRetrieveParams.kt | 242 ++ .../com/lithic/api/models/InstallmentPlan.kt | 2175 +++++++++++++++++ .../api/models/TransactionCategoryBalances.kt | 279 +++ .../async/FinancialAccountServiceAsync.kt | 5 + .../async/FinancialAccountServiceAsyncImpl.kt | 15 + .../InstallmentPlanServiceAsync.kt | 209 ++ .../InstallmentPlanServiceAsyncImpl.kt | 154 ++ .../blocking/FinancialAccountService.kt | 5 + .../blocking/FinancialAccountServiceImpl.kt | 14 + .../InstallmentPlanService.kt | 213 ++ .../InstallmentPlanServiceImpl.kt | 144 ++ ...ountInstallmentPlanListPageResponseTest.kt | 528 ++++ ...ialAccountInstallmentPlanListParamsTest.kt | 69 + ...ccountInstallmentPlanRetrieveParamsTest.kt | 31 + .../lithic/api/models/InstallmentPlanTest.kt | 481 ++++ .../models/TransactionCategoryBalancesTest.kt | 55 + .../InstallmentPlanServiceAsyncTest.kt | 49 + .../InstallmentPlanServiceTest.kt | 47 + 23 files changed, 5724 insertions(+), 4 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPage.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageAsync.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponse.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/InstallmentPlan.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/TransactionCategoryBalances.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsync.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncImpl.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanService.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceImpl.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponseTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/InstallmentPlanTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionCategoryBalancesTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceTest.kt diff --git a/.stats.yml b/.stats.yml index c48be9d8b..7abf757c6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 219 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-18e08b593c738bb6a429fe225dac7c4bf5d161a7dbb003e495b87a21d2aff6a8.yml -openapi_spec_hash: b6f308ea5a6d9ad9c22c14e7574d9669 -config_hash: 0cfee7faa13d28e91697e2d79c50935e +configured_endpoints: 221 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic/lithic-61a059277e4c1eb58cc145be1639732d3d0d79d969742baff98690faf96dc164.yml +openapi_spec_hash: cc69f6bb4c6d98be95100774de6aff3e +config_hash: f21cef3cf163623883f344efe9032e4f diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPage.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPage.kt new file mode 100644 index 000000000..321d64134 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPage.kt @@ -0,0 +1,143 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.AutoPager +import com.lithic.api.core.Page +import com.lithic.api.core.checkRequired +import com.lithic.api.services.blocking.financialAccounts.InstallmentPlanService +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** @see InstallmentPlanService.list */ +class FinancialAccountInstallmentPlanListPage +private constructor( + private val service: InstallmentPlanService, + private val params: FinancialAccountInstallmentPlanListParams, + private val response: FinancialAccountInstallmentPlanListPageResponse, +) : Page { + + /** + * Delegates to [FinancialAccountInstallmentPlanListPageResponse], but gracefully handles + * missing data. + * + * @see FinancialAccountInstallmentPlanListPageResponse.data + */ + fun data(): List = + response._data().getOptional("data").getOrNull() ?: emptyList() + + /** + * Delegates to [FinancialAccountInstallmentPlanListPageResponse], but gracefully handles + * missing data. + * + * @see FinancialAccountInstallmentPlanListPageResponse.hasMore + */ + fun hasMore(): Optional = response._hasMore().getOptional("has_more") + + override fun items(): List = data() + + override fun hasNextPage(): Boolean = items().isNotEmpty() + + fun nextPageParams(): FinancialAccountInstallmentPlanListParams = + if (params.endingBefore().isPresent) { + params.toBuilder().endingBefore(items().first()._token().getOptional("token")).build() + } else { + params.toBuilder().startingAfter(items().last()._token().getOptional("token")).build() + } + + override fun nextPage(): FinancialAccountInstallmentPlanListPage = + service.list(nextPageParams()) + + fun autoPager(): AutoPager = AutoPager.from(this) + + /** The parameters that were used to request this page. */ + fun params(): FinancialAccountInstallmentPlanListParams = params + + /** The response that this page was parsed from. */ + fun response(): FinancialAccountInstallmentPlanListPageResponse = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [FinancialAccountInstallmentPlanListPage]. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FinancialAccountInstallmentPlanListPage]. */ + class Builder internal constructor() { + + private var service: InstallmentPlanService? = null + private var params: FinancialAccountInstallmentPlanListParams? = null + private var response: FinancialAccountInstallmentPlanListPageResponse? = null + + @JvmSynthetic + internal fun from( + financialAccountInstallmentPlanListPage: FinancialAccountInstallmentPlanListPage + ) = apply { + service = financialAccountInstallmentPlanListPage.service + params = financialAccountInstallmentPlanListPage.params + response = financialAccountInstallmentPlanListPage.response + } + + fun service(service: InstallmentPlanService) = apply { this.service = service } + + /** The parameters that were used to request this page. */ + fun params(params: FinancialAccountInstallmentPlanListParams) = apply { + this.params = params + } + + /** The response that this page was parsed from. */ + fun response(response: FinancialAccountInstallmentPlanListPageResponse) = apply { + this.response = response + } + + /** + * Returns an immutable instance of [FinancialAccountInstallmentPlanListPage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FinancialAccountInstallmentPlanListPage = + FinancialAccountInstallmentPlanListPage( + checkRequired("service", service), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FinancialAccountInstallmentPlanListPage && + service == other.service && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, params, response) + + override fun toString() = + "FinancialAccountInstallmentPlanListPage{service=$service, params=$params, response=$response}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageAsync.kt new file mode 100644 index 000000000..88fa2e211 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageAsync.kt @@ -0,0 +1,159 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.AutoPagerAsync +import com.lithic.api.core.PageAsync +import com.lithic.api.core.checkRequired +import com.lithic.api.services.async.financialAccounts.InstallmentPlanServiceAsync +import java.util.Objects +import java.util.Optional +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import kotlin.jvm.optionals.getOrNull + +/** @see InstallmentPlanServiceAsync.list */ +class FinancialAccountInstallmentPlanListPageAsync +private constructor( + private val service: InstallmentPlanServiceAsync, + private val streamHandlerExecutor: Executor, + private val params: FinancialAccountInstallmentPlanListParams, + private val response: FinancialAccountInstallmentPlanListPageResponse, +) : PageAsync { + + /** + * Delegates to [FinancialAccountInstallmentPlanListPageResponse], but gracefully handles + * missing data. + * + * @see FinancialAccountInstallmentPlanListPageResponse.data + */ + fun data(): List = + response._data().getOptional("data").getOrNull() ?: emptyList() + + /** + * Delegates to [FinancialAccountInstallmentPlanListPageResponse], but gracefully handles + * missing data. + * + * @see FinancialAccountInstallmentPlanListPageResponse.hasMore + */ + fun hasMore(): Optional = response._hasMore().getOptional("has_more") + + override fun items(): List = data() + + override fun hasNextPage(): Boolean = items().isNotEmpty() + + fun nextPageParams(): FinancialAccountInstallmentPlanListParams = + if (params.endingBefore().isPresent) { + params.toBuilder().endingBefore(items().first()._token().getOptional("token")).build() + } else { + params.toBuilder().startingAfter(items().last()._token().getOptional("token")).build() + } + + override fun nextPage(): CompletableFuture = + service.list(nextPageParams()) + + fun autoPager(): AutoPagerAsync = + AutoPagerAsync.from(this, streamHandlerExecutor) + + /** The parameters that were used to request this page. */ + fun params(): FinancialAccountInstallmentPlanListParams = params + + /** The response that this page was parsed from. */ + fun response(): FinancialAccountInstallmentPlanListPageResponse = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [FinancialAccountInstallmentPlanListPageAsync]. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FinancialAccountInstallmentPlanListPageAsync]. */ + class Builder internal constructor() { + + private var service: InstallmentPlanServiceAsync? = null + private var streamHandlerExecutor: Executor? = null + private var params: FinancialAccountInstallmentPlanListParams? = null + private var response: FinancialAccountInstallmentPlanListPageResponse? = null + + @JvmSynthetic + internal fun from( + financialAccountInstallmentPlanListPageAsync: + FinancialAccountInstallmentPlanListPageAsync + ) = apply { + service = financialAccountInstallmentPlanListPageAsync.service + streamHandlerExecutor = + financialAccountInstallmentPlanListPageAsync.streamHandlerExecutor + params = financialAccountInstallmentPlanListPageAsync.params + response = financialAccountInstallmentPlanListPageAsync.response + } + + fun service(service: InstallmentPlanServiceAsync) = apply { this.service = service } + + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + this.streamHandlerExecutor = streamHandlerExecutor + } + + /** The parameters that were used to request this page. */ + fun params(params: FinancialAccountInstallmentPlanListParams) = apply { + this.params = params + } + + /** The response that this page was parsed from. */ + fun response(response: FinancialAccountInstallmentPlanListPageResponse) = apply { + this.response = response + } + + /** + * Returns an immutable instance of [FinancialAccountInstallmentPlanListPageAsync]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FinancialAccountInstallmentPlanListPageAsync = + FinancialAccountInstallmentPlanListPageAsync( + checkRequired("service", service), + checkRequired("streamHandlerExecutor", streamHandlerExecutor), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FinancialAccountInstallmentPlanListPageAsync && + service == other.service && + streamHandlerExecutor == other.streamHandlerExecutor && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, streamHandlerExecutor, params, response) + + override fun toString() = + "FinancialAccountInstallmentPlanListPageAsync{service=$service, streamHandlerExecutor=$streamHandlerExecutor, params=$params, response=$response}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponse.kt new file mode 100644 index 000000000..990d12f8d --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponse.kt @@ -0,0 +1,238 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +class FinancialAccountInstallmentPlanListPageResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val data: JsonField>, + private val hasMore: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("data") + @ExcludeMissing + data: JsonField> = JsonMissing.of(), + @JsonProperty("has_more") @ExcludeMissing hasMore: JsonField = JsonMissing.of(), + ) : this(data, hasMore, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun data(): List = data.getRequired("data") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun hasMore(): Boolean = hasMore.getRequired("has_more") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField> = data + + /** + * Returns the raw JSON value of [hasMore]. + * + * Unlike [hasMore], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("has_more") @ExcludeMissing fun _hasMore(): JsonField = hasMore + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [FinancialAccountInstallmentPlanListPageResponse]. + * + * The following fields are required: + * ```java + * .data() + * .hasMore() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FinancialAccountInstallmentPlanListPageResponse]. */ + class Builder internal constructor() { + + private var data: JsonField>? = null + private var hasMore: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + financialAccountInstallmentPlanListPageResponse: + FinancialAccountInstallmentPlanListPageResponse + ) = apply { + data = financialAccountInstallmentPlanListPageResponse.data.map { it.toMutableList() } + hasMore = financialAccountInstallmentPlanListPageResponse.hasMore + additionalProperties = + financialAccountInstallmentPlanListPageResponse.additionalProperties.toMutableMap() + } + + fun data(data: List) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun data(data: JsonField>) = apply { + this.data = data.map { it.toMutableList() } + } + + /** + * Adds a single [InstallmentPlan] to [Builder.data]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addData(data: InstallmentPlan) = apply { + this.data = + (this.data ?: JsonField.of(mutableListOf())).also { + checkKnown("data", it).add(data) + } + } + + fun hasMore(hasMore: Boolean) = hasMore(JsonField.of(hasMore)) + + /** + * Sets [Builder.hasMore] to an arbitrary JSON value. + * + * You should usually call [Builder.hasMore] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun hasMore(hasMore: JsonField) = apply { this.hasMore = hasMore } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [FinancialAccountInstallmentPlanListPageResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .data() + * .hasMore() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FinancialAccountInstallmentPlanListPageResponse = + FinancialAccountInstallmentPlanListPageResponse( + checkRequired("data", data).map { it.toImmutable() }, + checkRequired("hasMore", hasMore), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FinancialAccountInstallmentPlanListPageResponse = apply { + if (validated) { + return@apply + } + + data().forEach { it.validate() } + hasMore() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (data.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (hasMore.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FinancialAccountInstallmentPlanListPageResponse && + data == other.data && + hasMore == other.hasMore && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(data, hasMore, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "FinancialAccountInstallmentPlanListPageResponse{data=$data, hasMore=$hasMore, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParams.kt new file mode 100644 index 000000000..46f3c53d7 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParams.kt @@ -0,0 +1,465 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonCreator +import com.lithic.api.core.Enum +import com.lithic.api.core.JsonField +import com.lithic.api.core.Params +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** List the installment plans for a given financial account. */ +class FinancialAccountInstallmentPlanListParams +private constructor( + private val financialAccountToken: String?, + private val endingBefore: String?, + private val pageSize: Long?, + private val startingAfter: String?, + private val state: InstallmentPlanState?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Globally unique identifier for financial account. */ + fun financialAccountToken(): Optional = Optional.ofNullable(financialAccountToken) + + /** + * A cursor representing an item's token before which a page of results should end. Used to + * retrieve the previous page of results before this item. + */ + fun endingBefore(): Optional = Optional.ofNullable(endingBefore) + + /** Page size (for pagination). */ + fun pageSize(): Optional = Optional.ofNullable(pageSize) + + /** + * A cursor representing an item's token after which a page of results should begin. Used to + * retrieve the next page of results after this item. + */ + fun startingAfter(): Optional = Optional.ofNullable(startingAfter) + + /** Only installment plans in this state will be included. */ + fun state(): Optional = Optional.ofNullable(state) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): FinancialAccountInstallmentPlanListParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of + * [FinancialAccountInstallmentPlanListParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FinancialAccountInstallmentPlanListParams]. */ + class Builder internal constructor() { + + private var financialAccountToken: String? = null + private var endingBefore: String? = null + private var pageSize: Long? = null + private var startingAfter: String? = null + private var state: InstallmentPlanState? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from( + financialAccountInstallmentPlanListParams: FinancialAccountInstallmentPlanListParams + ) = apply { + financialAccountToken = financialAccountInstallmentPlanListParams.financialAccountToken + endingBefore = financialAccountInstallmentPlanListParams.endingBefore + pageSize = financialAccountInstallmentPlanListParams.pageSize + startingAfter = financialAccountInstallmentPlanListParams.startingAfter + state = financialAccountInstallmentPlanListParams.state + additionalHeaders = + financialAccountInstallmentPlanListParams.additionalHeaders.toBuilder() + additionalQueryParams = + financialAccountInstallmentPlanListParams.additionalQueryParams.toBuilder() + } + + /** Globally unique identifier for financial account. */ + fun financialAccountToken(financialAccountToken: String?) = apply { + this.financialAccountToken = financialAccountToken + } + + /** + * Alias for calling [Builder.financialAccountToken] with + * `financialAccountToken.orElse(null)`. + */ + fun financialAccountToken(financialAccountToken: Optional) = + financialAccountToken(financialAccountToken.getOrNull()) + + /** + * A cursor representing an item's token before which a page of results should end. Used to + * retrieve the previous page of results before this item. + */ + fun endingBefore(endingBefore: String?) = apply { this.endingBefore = endingBefore } + + /** Alias for calling [Builder.endingBefore] with `endingBefore.orElse(null)`. */ + fun endingBefore(endingBefore: Optional) = endingBefore(endingBefore.getOrNull()) + + /** Page size (for pagination). */ + fun pageSize(pageSize: Long?) = apply { this.pageSize = pageSize } + + /** + * Alias for [Builder.pageSize]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun pageSize(pageSize: Long) = pageSize(pageSize as Long?) + + /** Alias for calling [Builder.pageSize] with `pageSize.orElse(null)`. */ + fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) + + /** + * A cursor representing an item's token after which a page of results should begin. Used to + * retrieve the next page of results after this item. + */ + fun startingAfter(startingAfter: String?) = apply { this.startingAfter = startingAfter } + + /** Alias for calling [Builder.startingAfter] with `startingAfter.orElse(null)`. */ + fun startingAfter(startingAfter: Optional) = + startingAfter(startingAfter.getOrNull()) + + /** Only installment plans in this state will be included. */ + fun state(state: InstallmentPlanState?) = apply { this.state = state } + + /** Alias for calling [Builder.state] with `state.orElse(null)`. */ + fun state(state: Optional) = state(state.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [FinancialAccountInstallmentPlanListParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams( + financialAccountToken, + endingBefore, + pageSize, + startingAfter, + state, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> financialAccountToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + endingBefore?.let { put("ending_before", it) } + pageSize?.let { put("page_size", it.toString()) } + startingAfter?.let { put("starting_after", it) } + state?.let { put("state", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + /** Only installment plans in this state will be included. */ + class InstallmentPlanState + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PENDING = of("PENDING") + + @JvmField val ACTIVE = of("ACTIVE") + + @JvmField val REBUILD_IN_PROGRESS = of("REBUILD_IN_PROGRESS") + + @JvmField val FULLY_PAID = of("FULLY_PAID") + + @JvmField val CANCELLED = of("CANCELLED") + + @JvmStatic fun of(value: String) = InstallmentPlanState(JsonField.of(value)) + } + + /** An enum containing [InstallmentPlanState]'s known values. */ + enum class Known { + PENDING, + ACTIVE, + REBUILD_IN_PROGRESS, + FULLY_PAID, + CANCELLED, + } + + /** + * An enum containing [InstallmentPlanState]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [InstallmentPlanState] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PENDING, + ACTIVE, + REBUILD_IN_PROGRESS, + FULLY_PAID, + CANCELLED, + /** + * An enum member indicating that [InstallmentPlanState] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PENDING -> Value.PENDING + ACTIVE -> Value.ACTIVE + REBUILD_IN_PROGRESS -> Value.REBUILD_IN_PROGRESS + FULLY_PAID -> Value.FULLY_PAID + CANCELLED -> Value.CANCELLED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PENDING -> Known.PENDING + ACTIVE -> Known.ACTIVE + REBUILD_IN_PROGRESS -> Known.REBUILD_IN_PROGRESS + FULLY_PAID -> Known.FULLY_PAID + CANCELLED -> Known.CANCELLED + else -> throw LithicInvalidDataException("Unknown InstallmentPlanState: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InstallmentPlanState = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InstallmentPlanState && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FinancialAccountInstallmentPlanListParams && + financialAccountToken == other.financialAccountToken && + endingBefore == other.endingBefore && + pageSize == other.pageSize && + startingAfter == other.startingAfter && + state == other.state && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + financialAccountToken, + endingBefore, + pageSize, + startingAfter, + state, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "FinancialAccountInstallmentPlanListParams{financialAccountToken=$financialAccountToken, endingBefore=$endingBefore, pageSize=$pageSize, startingAfter=$startingAfter, state=$state, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParams.kt new file mode 100644 index 000000000..f3e8cc259 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParams.kt @@ -0,0 +1,242 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.Params +import com.lithic.api.core.checkRequired +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Get a specific installment plan for a given financial account. */ +class FinancialAccountInstallmentPlanRetrieveParams +private constructor( + private val financialAccountToken: String, + private val installmentPlanToken: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Globally unique identifier for financial account. */ + fun financialAccountToken(): String = financialAccountToken + + /** Globally unique identifier for installment plan. */ + fun installmentPlanToken(): Optional = Optional.ofNullable(installmentPlanToken) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [FinancialAccountInstallmentPlanRetrieveParams]. + * + * The following fields are required: + * ```java + * .financialAccountToken() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FinancialAccountInstallmentPlanRetrieveParams]. */ + class Builder internal constructor() { + + private var financialAccountToken: String? = null + private var installmentPlanToken: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from( + financialAccountInstallmentPlanRetrieveParams: + FinancialAccountInstallmentPlanRetrieveParams + ) = apply { + financialAccountToken = + financialAccountInstallmentPlanRetrieveParams.financialAccountToken + installmentPlanToken = + financialAccountInstallmentPlanRetrieveParams.installmentPlanToken + additionalHeaders = + financialAccountInstallmentPlanRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = + financialAccountInstallmentPlanRetrieveParams.additionalQueryParams.toBuilder() + } + + /** Globally unique identifier for financial account. */ + fun financialAccountToken(financialAccountToken: String) = apply { + this.financialAccountToken = financialAccountToken + } + + /** Globally unique identifier for installment plan. */ + fun installmentPlanToken(installmentPlanToken: String?) = apply { + this.installmentPlanToken = installmentPlanToken + } + + /** + * Alias for calling [Builder.installmentPlanToken] with + * `installmentPlanToken.orElse(null)`. + */ + fun installmentPlanToken(installmentPlanToken: Optional) = + installmentPlanToken(installmentPlanToken.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [FinancialAccountInstallmentPlanRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .financialAccountToken() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FinancialAccountInstallmentPlanRetrieveParams = + FinancialAccountInstallmentPlanRetrieveParams( + checkRequired("financialAccountToken", financialAccountToken), + installmentPlanToken, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> financialAccountToken + 1 -> installmentPlanToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FinancialAccountInstallmentPlanRetrieveParams && + financialAccountToken == other.financialAccountToken && + installmentPlanToken == other.installmentPlanToken && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + financialAccountToken, + installmentPlanToken, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "FinancialAccountInstallmentPlanRetrieveParams{financialAccountToken=$financialAccountToken, installmentPlanToken=$installmentPlanToken, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstallmentPlan.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstallmentPlan.kt new file mode 100644 index 000000000..750322b31 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstallmentPlan.kt @@ -0,0 +1,2175 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.time.LocalDate +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class InstallmentPlan +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val token: JsonField, + private val closedAt: JsonField, + private val created: JsonField, + private val feeAmount: JsonField, + private val financialAccountToken: JsonField, + private val installmentPlanTotal: JsonField, + private val installments: JsonField>, + private val installmentsOutstanding: JsonField, + private val installmentsPaid: JsonField, + private val numInstallments: JsonField, + private val principalAmount: JsonField, + private val sourceAmounts: JsonField, + private val sourceId: JsonField, + private val sourceType: JsonField, + private val startDate: JsonField, + private val state: JsonField, + private val totalPaid: JsonField, + private val updated: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("closed_at") + @ExcludeMissing + closedAt: JsonField = JsonMissing.of(), + @JsonProperty("created") + @ExcludeMissing + created: JsonField = JsonMissing.of(), + @JsonProperty("fee_amount") @ExcludeMissing feeAmount: JsonField = JsonMissing.of(), + @JsonProperty("financial_account_token") + @ExcludeMissing + financialAccountToken: JsonField = JsonMissing.of(), + @JsonProperty("installment_plan_total") + @ExcludeMissing + installmentPlanTotal: JsonField = JsonMissing.of(), + @JsonProperty("installments") + @ExcludeMissing + installments: JsonField> = JsonMissing.of(), + @JsonProperty("installments_outstanding") + @ExcludeMissing + installmentsOutstanding: JsonField = JsonMissing.of(), + @JsonProperty("installments_paid") + @ExcludeMissing + installmentsPaid: JsonField = JsonMissing.of(), + @JsonProperty("num_installments") + @ExcludeMissing + numInstallments: JsonField = JsonMissing.of(), + @JsonProperty("principal_amount") + @ExcludeMissing + principalAmount: JsonField = JsonMissing.of(), + @JsonProperty("source_amounts") + @ExcludeMissing + sourceAmounts: JsonField = JsonMissing.of(), + @JsonProperty("source_id") @ExcludeMissing sourceId: JsonField = JsonMissing.of(), + @JsonProperty("source_type") + @ExcludeMissing + sourceType: JsonField = JsonMissing.of(), + @JsonProperty("start_date") + @ExcludeMissing + startDate: JsonField = JsonMissing.of(), + @JsonProperty("state") + @ExcludeMissing + state: JsonField = JsonMissing.of(), + @JsonProperty("total_paid") @ExcludeMissing totalPaid: JsonField = JsonMissing.of(), + @JsonProperty("updated") + @ExcludeMissing + updated: JsonField = JsonMissing.of(), + ) : this( + token, + closedAt, + created, + feeAmount, + financialAccountToken, + installmentPlanTotal, + installments, + installmentsOutstanding, + installmentsPaid, + numInstallments, + principalAmount, + sourceAmounts, + sourceId, + sourceType, + startDate, + state, + totalPaid, + updated, + mutableMapOf(), + ) + + /** + * Globally unique identifier for an installment plan + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun token(): String = token.getRequired("token") + + /** + * Date the plan was paid off or cancelled, or null while it is still open + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun closedAt(): Optional = closedAt.getOptional("closed_at") + + /** + * Timestamp of when the installment plan was created + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun created(): OffsetDateTime = created.getRequired("created") + + /** + * Enrollment fee charged when the plan was created in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun feeAmount(): Long = feeAmount.getRequired("fee_amount") + + /** + * Globally unique identifier for a financial account + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun financialAccountToken(): String = + financialAccountToken.getRequired("financial_account_token") + + /** + * Total owed on the plan in cents, the principal amount plus the enrollment fee + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun installmentPlanTotal(): Long = installmentPlanTotal.getRequired("installment_plan_total") + + /** + * Installments that make up the plan, oldest first + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun installments(): List = installments.getRequired("installments") + + /** + * Number of installments that still carry a balance + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun installmentsOutstanding(): Long = + installmentsOutstanding.getRequired("installments_outstanding") + + /** + * Number of installments that have been paid off + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun installmentsPaid(): Long = installmentsPaid.getRequired("installments_paid") + + /** + * Number of installments the plan is broken into + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun numInstallments(): Long = numInstallments.getRequired("num_installments") + + /** + * Balance the plan was opened on in cents, excluding the enrollment fee + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun principalAmount(): Long = principalAmount.getRequired("principal_amount") + + /** + * Balance the plan was opened on, broken out by category, or null if it was not recorded + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun sourceAmounts(): Optional = + sourceAmounts.getOptional("source_amounts") + + /** + * Identifier of the record the plan was opened from, such as the closing statement for an + * unpaid balance + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun sourceId(): String = sourceId.getRequired("source_id") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun sourceType(): InstallmentPlanSource = sourceType.getRequired("source_type") + + /** + * Date the plan was created + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun startDate(): LocalDate = startDate.getRequired("start_date") + + /** + * State of the installment plan. A plan is REBUILD_IN_PROGRESS while its loan tapes are being + * rebuilt, during which its payment totals are being recomputed and should not be treated as + * final + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun state(): InstallmentPlanState = state.getRequired("state") + + /** + * Amount paid towards the plan to date in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun totalPaid(): Long = totalPaid.getRequired("total_paid") + + /** + * Timestamp of when the installment plan was updated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun updated(): OffsetDateTime = updated.getRequired("updated") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [closedAt]. + * + * Unlike [closedAt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("closed_at") @ExcludeMissing fun _closedAt(): JsonField = closedAt + + /** + * Returns the raw JSON value of [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [feeAmount]. + * + * Unlike [feeAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("fee_amount") @ExcludeMissing fun _feeAmount(): JsonField = feeAmount + + /** + * Returns the raw JSON value of [financialAccountToken]. + * + * Unlike [financialAccountToken], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("financial_account_token") + @ExcludeMissing + fun _financialAccountToken(): JsonField = financialAccountToken + + /** + * Returns the raw JSON value of [installmentPlanTotal]. + * + * Unlike [installmentPlanTotal], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("installment_plan_total") + @ExcludeMissing + fun _installmentPlanTotal(): JsonField = installmentPlanTotal + + /** + * Returns the raw JSON value of [installments]. + * + * Unlike [installments], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("installments") + @ExcludeMissing + fun _installments(): JsonField> = installments + + /** + * Returns the raw JSON value of [installmentsOutstanding]. + * + * Unlike [installmentsOutstanding], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("installments_outstanding") + @ExcludeMissing + fun _installmentsOutstanding(): JsonField = installmentsOutstanding + + /** + * Returns the raw JSON value of [installmentsPaid]. + * + * Unlike [installmentsPaid], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("installments_paid") + @ExcludeMissing + fun _installmentsPaid(): JsonField = installmentsPaid + + /** + * Returns the raw JSON value of [numInstallments]. + * + * Unlike [numInstallments], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("num_installments") + @ExcludeMissing + fun _numInstallments(): JsonField = numInstallments + + /** + * Returns the raw JSON value of [principalAmount]. + * + * Unlike [principalAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("principal_amount") + @ExcludeMissing + fun _principalAmount(): JsonField = principalAmount + + /** + * Returns the raw JSON value of [sourceAmounts]. + * + * Unlike [sourceAmounts], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("source_amounts") + @ExcludeMissing + fun _sourceAmounts(): JsonField = sourceAmounts + + /** + * Returns the raw JSON value of [sourceId]. + * + * Unlike [sourceId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("source_id") @ExcludeMissing fun _sourceId(): JsonField = sourceId + + /** + * Returns the raw JSON value of [sourceType]. + * + * Unlike [sourceType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("source_type") + @ExcludeMissing + fun _sourceType(): JsonField = sourceType + + /** + * Returns the raw JSON value of [startDate]. + * + * Unlike [startDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("start_date") @ExcludeMissing fun _startDate(): JsonField = startDate + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + /** + * Returns the raw JSON value of [totalPaid]. + * + * Unlike [totalPaid], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("total_paid") @ExcludeMissing fun _totalPaid(): JsonField = totalPaid + + /** + * Returns the raw JSON value of [updated]. + * + * Unlike [updated], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated") @ExcludeMissing fun _updated(): JsonField = updated + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InstallmentPlan]. + * + * The following fields are required: + * ```java + * .token() + * .closedAt() + * .created() + * .feeAmount() + * .financialAccountToken() + * .installmentPlanTotal() + * .installments() + * .installmentsOutstanding() + * .installmentsPaid() + * .numInstallments() + * .principalAmount() + * .sourceAmounts() + * .sourceId() + * .sourceType() + * .startDate() + * .state() + * .totalPaid() + * .updated() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InstallmentPlan]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var closedAt: JsonField? = null + private var created: JsonField? = null + private var feeAmount: JsonField? = null + private var financialAccountToken: JsonField? = null + private var installmentPlanTotal: JsonField? = null + private var installments: JsonField>? = null + private var installmentsOutstanding: JsonField? = null + private var installmentsPaid: JsonField? = null + private var numInstallments: JsonField? = null + private var principalAmount: JsonField? = null + private var sourceAmounts: JsonField? = null + private var sourceId: JsonField? = null + private var sourceType: JsonField? = null + private var startDate: JsonField? = null + private var state: JsonField? = null + private var totalPaid: JsonField? = null + private var updated: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(installmentPlan: InstallmentPlan) = apply { + token = installmentPlan.token + closedAt = installmentPlan.closedAt + created = installmentPlan.created + feeAmount = installmentPlan.feeAmount + financialAccountToken = installmentPlan.financialAccountToken + installmentPlanTotal = installmentPlan.installmentPlanTotal + installments = installmentPlan.installments.map { it.toMutableList() } + installmentsOutstanding = installmentPlan.installmentsOutstanding + installmentsPaid = installmentPlan.installmentsPaid + numInstallments = installmentPlan.numInstallments + principalAmount = installmentPlan.principalAmount + sourceAmounts = installmentPlan.sourceAmounts + sourceId = installmentPlan.sourceId + sourceType = installmentPlan.sourceType + startDate = installmentPlan.startDate + state = installmentPlan.state + totalPaid = installmentPlan.totalPaid + updated = installmentPlan.updated + additionalProperties = installmentPlan.additionalProperties.toMutableMap() + } + + /** Globally unique identifier for an installment plan */ + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + /** Date the plan was paid off or cancelled, or null while it is still open */ + fun closedAt(closedAt: LocalDate?) = closedAt(JsonField.ofNullable(closedAt)) + + /** Alias for calling [Builder.closedAt] with `closedAt.orElse(null)`. */ + fun closedAt(closedAt: Optional) = closedAt(closedAt.getOrNull()) + + /** + * Sets [Builder.closedAt] to an arbitrary JSON value. + * + * You should usually call [Builder.closedAt] with a well-typed [LocalDate] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun closedAt(closedAt: JsonField) = apply { this.closedAt = closedAt } + + /** Timestamp of when the installment plan was created */ + fun created(created: OffsetDateTime) = created(JsonField.of(created)) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + /** Enrollment fee charged when the plan was created in cents */ + fun feeAmount(feeAmount: Long) = feeAmount(JsonField.of(feeAmount)) + + /** + * Sets [Builder.feeAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.feeAmount] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun feeAmount(feeAmount: JsonField) = apply { this.feeAmount = feeAmount } + + /** Globally unique identifier for a financial account */ + fun financialAccountToken(financialAccountToken: String) = + financialAccountToken(JsonField.of(financialAccountToken)) + + /** + * Sets [Builder.financialAccountToken] to an arbitrary JSON value. + * + * You should usually call [Builder.financialAccountToken] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun financialAccountToken(financialAccountToken: JsonField) = apply { + this.financialAccountToken = financialAccountToken + } + + /** Total owed on the plan in cents, the principal amount plus the enrollment fee */ + fun installmentPlanTotal(installmentPlanTotal: Long) = + installmentPlanTotal(JsonField.of(installmentPlanTotal)) + + /** + * Sets [Builder.installmentPlanTotal] to an arbitrary JSON value. + * + * You should usually call [Builder.installmentPlanTotal] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun installmentPlanTotal(installmentPlanTotal: JsonField) = apply { + this.installmentPlanTotal = installmentPlanTotal + } + + /** Installments that make up the plan, oldest first */ + fun installments(installments: List) = installments(JsonField.of(installments)) + + /** + * Sets [Builder.installments] to an arbitrary JSON value. + * + * You should usually call [Builder.installments] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun installments(installments: JsonField>) = apply { + this.installments = installments.map { it.toMutableList() } + } + + /** + * Adds a single [Installment] to [installments]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addInstallment(installment: Installment) = apply { + installments = + (installments ?: JsonField.of(mutableListOf())).also { + checkKnown("installments", it).add(installment) + } + } + + /** Number of installments that still carry a balance */ + fun installmentsOutstanding(installmentsOutstanding: Long) = + installmentsOutstanding(JsonField.of(installmentsOutstanding)) + + /** + * Sets [Builder.installmentsOutstanding] to an arbitrary JSON value. + * + * You should usually call [Builder.installmentsOutstanding] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun installmentsOutstanding(installmentsOutstanding: JsonField) = apply { + this.installmentsOutstanding = installmentsOutstanding + } + + /** Number of installments that have been paid off */ + fun installmentsPaid(installmentsPaid: Long) = + installmentsPaid(JsonField.of(installmentsPaid)) + + /** + * Sets [Builder.installmentsPaid] to an arbitrary JSON value. + * + * You should usually call [Builder.installmentsPaid] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun installmentsPaid(installmentsPaid: JsonField) = apply { + this.installmentsPaid = installmentsPaid + } + + /** Number of installments the plan is broken into */ + fun numInstallments(numInstallments: Long) = numInstallments(JsonField.of(numInstallments)) + + /** + * Sets [Builder.numInstallments] to an arbitrary JSON value. + * + * You should usually call [Builder.numInstallments] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun numInstallments(numInstallments: JsonField) = apply { + this.numInstallments = numInstallments + } + + /** Balance the plan was opened on in cents, excluding the enrollment fee */ + fun principalAmount(principalAmount: Long) = principalAmount(JsonField.of(principalAmount)) + + /** + * Sets [Builder.principalAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.principalAmount] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun principalAmount(principalAmount: JsonField) = apply { + this.principalAmount = principalAmount + } + + /** + * Balance the plan was opened on, broken out by category, or null if it was not recorded + */ + fun sourceAmounts(sourceAmounts: TransactionCategoryBalances?) = + sourceAmounts(JsonField.ofNullable(sourceAmounts)) + + /** Alias for calling [Builder.sourceAmounts] with `sourceAmounts.orElse(null)`. */ + fun sourceAmounts(sourceAmounts: Optional) = + sourceAmounts(sourceAmounts.getOrNull()) + + /** + * Sets [Builder.sourceAmounts] to an arbitrary JSON value. + * + * You should usually call [Builder.sourceAmounts] with a well-typed + * [TransactionCategoryBalances] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun sourceAmounts(sourceAmounts: JsonField) = apply { + this.sourceAmounts = sourceAmounts + } + + /** + * Identifier of the record the plan was opened from, such as the closing statement for an + * unpaid balance + */ + fun sourceId(sourceId: String) = sourceId(JsonField.of(sourceId)) + + /** + * Sets [Builder.sourceId] to an arbitrary JSON value. + * + * You should usually call [Builder.sourceId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun sourceId(sourceId: JsonField) = apply { this.sourceId = sourceId } + + fun sourceType(sourceType: InstallmentPlanSource) = sourceType(JsonField.of(sourceType)) + + /** + * Sets [Builder.sourceType] to an arbitrary JSON value. + * + * You should usually call [Builder.sourceType] with a well-typed [InstallmentPlanSource] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun sourceType(sourceType: JsonField) = apply { + this.sourceType = sourceType + } + + /** Date the plan was created */ + fun startDate(startDate: LocalDate) = startDate(JsonField.of(startDate)) + + /** + * Sets [Builder.startDate] to an arbitrary JSON value. + * + * You should usually call [Builder.startDate] with a well-typed [LocalDate] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun startDate(startDate: JsonField) = apply { this.startDate = startDate } + + /** + * State of the installment plan. A plan is REBUILD_IN_PROGRESS while its loan tapes are + * being rebuilt, during which its payment totals are being recomputed and should not be + * treated as final + */ + fun state(state: InstallmentPlanState) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [InstallmentPlanState] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun state(state: JsonField) = apply { this.state = state } + + /** Amount paid towards the plan to date in cents */ + fun totalPaid(totalPaid: Long) = totalPaid(JsonField.of(totalPaid)) + + /** + * Sets [Builder.totalPaid] to an arbitrary JSON value. + * + * You should usually call [Builder.totalPaid] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun totalPaid(totalPaid: JsonField) = apply { this.totalPaid = totalPaid } + + /** Timestamp of when the installment plan was updated */ + fun updated(updated: OffsetDateTime) = updated(JsonField.of(updated)) + + /** + * Sets [Builder.updated] to an arbitrary JSON value. + * + * You should usually call [Builder.updated] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun updated(updated: JsonField) = apply { this.updated = updated } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [InstallmentPlan]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * .closedAt() + * .created() + * .feeAmount() + * .financialAccountToken() + * .installmentPlanTotal() + * .installments() + * .installmentsOutstanding() + * .installmentsPaid() + * .numInstallments() + * .principalAmount() + * .sourceAmounts() + * .sourceId() + * .sourceType() + * .startDate() + * .state() + * .totalPaid() + * .updated() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InstallmentPlan = + InstallmentPlan( + checkRequired("token", token), + checkRequired("closedAt", closedAt), + checkRequired("created", created), + checkRequired("feeAmount", feeAmount), + checkRequired("financialAccountToken", financialAccountToken), + checkRequired("installmentPlanTotal", installmentPlanTotal), + checkRequired("installments", installments).map { it.toImmutable() }, + checkRequired("installmentsOutstanding", installmentsOutstanding), + checkRequired("installmentsPaid", installmentsPaid), + checkRequired("numInstallments", numInstallments), + checkRequired("principalAmount", principalAmount), + checkRequired("sourceAmounts", sourceAmounts), + checkRequired("sourceId", sourceId), + checkRequired("sourceType", sourceType), + checkRequired("startDate", startDate), + checkRequired("state", state), + checkRequired("totalPaid", totalPaid), + checkRequired("updated", updated), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InstallmentPlan = apply { + if (validated) { + return@apply + } + + token() + closedAt() + created() + feeAmount() + financialAccountToken() + installmentPlanTotal() + installments().forEach { it.validate() } + installmentsOutstanding() + installmentsPaid() + numInstallments() + principalAmount() + sourceAmounts().ifPresent { it.validate() } + sourceId() + sourceType().validate() + startDate() + state().validate() + totalPaid() + updated() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (token.asKnown().isPresent) 1 else 0) + + (if (closedAt.asKnown().isPresent) 1 else 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (if (feeAmount.asKnown().isPresent) 1 else 0) + + (if (financialAccountToken.asKnown().isPresent) 1 else 0) + + (if (installmentPlanTotal.asKnown().isPresent) 1 else 0) + + (installments.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (installmentsOutstanding.asKnown().isPresent) 1 else 0) + + (if (installmentsPaid.asKnown().isPresent) 1 else 0) + + (if (numInstallments.asKnown().isPresent) 1 else 0) + + (if (principalAmount.asKnown().isPresent) 1 else 0) + + (sourceAmounts.asKnown().getOrNull()?.validity() ?: 0) + + (if (sourceId.asKnown().isPresent) 1 else 0) + + (sourceType.asKnown().getOrNull()?.validity() ?: 0) + + (if (startDate.asKnown().isPresent) 1 else 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + + (if (totalPaid.asKnown().isPresent) 1 else 0) + + (if (updated.asKnown().isPresent) 1 else 0) + + class Installment + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amountDue: JsonField, + private val amountDueDetails: JsonField, + private val amountOutstanding: JsonField, + private val amountOutstandingDetails: JsonField, + private val amountPaid: JsonField, + private val amountPaidDetails: JsonField, + private val dateAssessed: JsonField, + private val dueDate: JsonField, + private val installmentNum: JsonField, + private val paymentDueDate: JsonField, + private val payments: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount_due") + @ExcludeMissing + amountDue: JsonField = JsonMissing.of(), + @JsonProperty("amount_due_details") + @ExcludeMissing + amountDueDetails: JsonField = JsonMissing.of(), + @JsonProperty("amount_outstanding") + @ExcludeMissing + amountOutstanding: JsonField = JsonMissing.of(), + @JsonProperty("amount_outstanding_details") + @ExcludeMissing + amountOutstandingDetails: JsonField = JsonMissing.of(), + @JsonProperty("amount_paid") + @ExcludeMissing + amountPaid: JsonField = JsonMissing.of(), + @JsonProperty("amount_paid_details") + @ExcludeMissing + amountPaidDetails: JsonField = JsonMissing.of(), + @JsonProperty("date_assessed") + @ExcludeMissing + dateAssessed: JsonField = JsonMissing.of(), + @JsonProperty("due_date") + @ExcludeMissing + dueDate: JsonField = JsonMissing.of(), + @JsonProperty("installment_num") + @ExcludeMissing + installmentNum: JsonField = JsonMissing.of(), + @JsonProperty("payment_due_date") + @ExcludeMissing + paymentDueDate: JsonField = JsonMissing.of(), + @JsonProperty("payments") + @ExcludeMissing + payments: JsonField> = JsonMissing.of(), + ) : this( + amountDue, + amountDueDetails, + amountOutstanding, + amountOutstandingDetails, + amountPaid, + amountPaidDetails, + dateAssessed, + dueDate, + installmentNum, + paymentDueDate, + payments, + mutableMapOf(), + ) + + /** + * Amount the installment was opened for in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amountDue(): Long = amountDue.getRequired("amount_due") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amountDueDetails(): TransactionCategoryBalances = + amountDueDetails.getRequired("amount_due_details") + + /** + * Amount still owed on the installment in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amountOutstanding(): Long = amountOutstanding.getRequired("amount_outstanding") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amountOutstandingDetails(): TransactionCategoryBalances = + amountOutstandingDetails.getRequired("amount_outstanding_details") + + /** + * Amount paid towards the installment in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amountPaid(): Long = amountPaid.getRequired("amount_paid") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amountPaidDetails(): TransactionCategoryBalances = + amountPaidDetails.getRequired("amount_paid_details") + + /** + * Date the installment was actually assessed onto the account, or null if it has not been + * assessed yet + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun dateAssessed(): Optional = dateAssessed.getOptional("date_assessed") + + /** + * Date the installment is scheduled to be assessed onto the account + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun dueDate(): LocalDate = dueDate.getRequired("due_date") + + /** + * Position of this installment within the plan, starting at 0 + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun installmentNum(): Long = installmentNum.getRequired("installment_num") + + /** + * Date the installment must be paid by before it is considered past due + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun paymentDueDate(): LocalDate = paymentDueDate.getRequired("payment_due_date") + + /** + * Payments applied to this installment, oldest first + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun payments(): List = payments.getRequired("payments") + + /** + * Returns the raw JSON value of [amountDue]. + * + * Unlike [amountDue], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount_due") @ExcludeMissing fun _amountDue(): JsonField = amountDue + + /** + * Returns the raw JSON value of [amountDueDetails]. + * + * Unlike [amountDueDetails], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("amount_due_details") + @ExcludeMissing + fun _amountDueDetails(): JsonField = amountDueDetails + + /** + * Returns the raw JSON value of [amountOutstanding]. + * + * Unlike [amountOutstanding], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("amount_outstanding") + @ExcludeMissing + fun _amountOutstanding(): JsonField = amountOutstanding + + /** + * Returns the raw JSON value of [amountOutstandingDetails]. + * + * Unlike [amountOutstandingDetails], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("amount_outstanding_details") + @ExcludeMissing + fun _amountOutstandingDetails(): JsonField = + amountOutstandingDetails + + /** + * Returns the raw JSON value of [amountPaid]. + * + * Unlike [amountPaid], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount_paid") @ExcludeMissing fun _amountPaid(): JsonField = amountPaid + + /** + * Returns the raw JSON value of [amountPaidDetails]. + * + * Unlike [amountPaidDetails], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("amount_paid_details") + @ExcludeMissing + fun _amountPaidDetails(): JsonField = amountPaidDetails + + /** + * Returns the raw JSON value of [dateAssessed]. + * + * Unlike [dateAssessed], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date_assessed") + @ExcludeMissing + fun _dateAssessed(): JsonField = dateAssessed + + /** + * Returns the raw JSON value of [dueDate]. + * + * Unlike [dueDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("due_date") @ExcludeMissing fun _dueDate(): JsonField = dueDate + + /** + * Returns the raw JSON value of [installmentNum]. + * + * Unlike [installmentNum], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("installment_num") + @ExcludeMissing + fun _installmentNum(): JsonField = installmentNum + + /** + * Returns the raw JSON value of [paymentDueDate]. + * + * Unlike [paymentDueDate], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("payment_due_date") + @ExcludeMissing + fun _paymentDueDate(): JsonField = paymentDueDate + + /** + * Returns the raw JSON value of [payments]. + * + * Unlike [payments], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("payments") + @ExcludeMissing + fun _payments(): JsonField> = payments + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Installment]. + * + * The following fields are required: + * ```java + * .amountDue() + * .amountDueDetails() + * .amountOutstanding() + * .amountOutstandingDetails() + * .amountPaid() + * .amountPaidDetails() + * .dateAssessed() + * .dueDate() + * .installmentNum() + * .paymentDueDate() + * .payments() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Installment]. */ + class Builder internal constructor() { + + private var amountDue: JsonField? = null + private var amountDueDetails: JsonField? = null + private var amountOutstanding: JsonField? = null + private var amountOutstandingDetails: JsonField? = null + private var amountPaid: JsonField? = null + private var amountPaidDetails: JsonField? = null + private var dateAssessed: JsonField? = null + private var dueDate: JsonField? = null + private var installmentNum: JsonField? = null + private var paymentDueDate: JsonField? = null + private var payments: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(installment: Installment) = apply { + amountDue = installment.amountDue + amountDueDetails = installment.amountDueDetails + amountOutstanding = installment.amountOutstanding + amountOutstandingDetails = installment.amountOutstandingDetails + amountPaid = installment.amountPaid + amountPaidDetails = installment.amountPaidDetails + dateAssessed = installment.dateAssessed + dueDate = installment.dueDate + installmentNum = installment.installmentNum + paymentDueDate = installment.paymentDueDate + payments = installment.payments.map { it.toMutableList() } + additionalProperties = installment.additionalProperties.toMutableMap() + } + + /** Amount the installment was opened for in cents */ + fun amountDue(amountDue: Long) = amountDue(JsonField.of(amountDue)) + + /** + * Sets [Builder.amountDue] to an arbitrary JSON value. + * + * You should usually call [Builder.amountDue] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amountDue(amountDue: JsonField) = apply { this.amountDue = amountDue } + + fun amountDueDetails(amountDueDetails: TransactionCategoryBalances) = + amountDueDetails(JsonField.of(amountDueDetails)) + + /** + * Sets [Builder.amountDueDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.amountDueDetails] with a well-typed + * [TransactionCategoryBalances] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun amountDueDetails(amountDueDetails: JsonField) = apply { + this.amountDueDetails = amountDueDetails + } + + /** Amount still owed on the installment in cents */ + fun amountOutstanding(amountOutstanding: Long) = + amountOutstanding(JsonField.of(amountOutstanding)) + + /** + * Sets [Builder.amountOutstanding] to an arbitrary JSON value. + * + * You should usually call [Builder.amountOutstanding] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amountOutstanding(amountOutstanding: JsonField) = apply { + this.amountOutstanding = amountOutstanding + } + + fun amountOutstandingDetails(amountOutstandingDetails: TransactionCategoryBalances) = + amountOutstandingDetails(JsonField.of(amountOutstandingDetails)) + + /** + * Sets [Builder.amountOutstandingDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.amountOutstandingDetails] with a well-typed + * [TransactionCategoryBalances] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun amountOutstandingDetails( + amountOutstandingDetails: JsonField + ) = apply { this.amountOutstandingDetails = amountOutstandingDetails } + + /** Amount paid towards the installment in cents */ + fun amountPaid(amountPaid: Long) = amountPaid(JsonField.of(amountPaid)) + + /** + * Sets [Builder.amountPaid] to an arbitrary JSON value. + * + * You should usually call [Builder.amountPaid] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amountPaid(amountPaid: JsonField) = apply { this.amountPaid = amountPaid } + + fun amountPaidDetails(amountPaidDetails: TransactionCategoryBalances) = + amountPaidDetails(JsonField.of(amountPaidDetails)) + + /** + * Sets [Builder.amountPaidDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.amountPaidDetails] with a well-typed + * [TransactionCategoryBalances] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun amountPaidDetails(amountPaidDetails: JsonField) = + apply { + this.amountPaidDetails = amountPaidDetails + } + + /** + * Date the installment was actually assessed onto the account, or null if it has not + * been assessed yet + */ + fun dateAssessed(dateAssessed: LocalDate?) = + dateAssessed(JsonField.ofNullable(dateAssessed)) + + /** Alias for calling [Builder.dateAssessed] with `dateAssessed.orElse(null)`. */ + fun dateAssessed(dateAssessed: Optional) = + dateAssessed(dateAssessed.getOrNull()) + + /** + * Sets [Builder.dateAssessed] to an arbitrary JSON value. + * + * You should usually call [Builder.dateAssessed] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun dateAssessed(dateAssessed: JsonField) = apply { + this.dateAssessed = dateAssessed + } + + /** Date the installment is scheduled to be assessed onto the account */ + fun dueDate(dueDate: LocalDate) = dueDate(JsonField.of(dueDate)) + + /** + * Sets [Builder.dueDate] to an arbitrary JSON value. + * + * You should usually call [Builder.dueDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun dueDate(dueDate: JsonField) = apply { this.dueDate = dueDate } + + /** Position of this installment within the plan, starting at 0 */ + fun installmentNum(installmentNum: Long) = installmentNum(JsonField.of(installmentNum)) + + /** + * Sets [Builder.installmentNum] to an arbitrary JSON value. + * + * You should usually call [Builder.installmentNum] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun installmentNum(installmentNum: JsonField) = apply { + this.installmentNum = installmentNum + } + + /** Date the installment must be paid by before it is considered past due */ + fun paymentDueDate(paymentDueDate: LocalDate) = + paymentDueDate(JsonField.of(paymentDueDate)) + + /** + * Sets [Builder.paymentDueDate] to an arbitrary JSON value. + * + * You should usually call [Builder.paymentDueDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun paymentDueDate(paymentDueDate: JsonField) = apply { + this.paymentDueDate = paymentDueDate + } + + /** Payments applied to this installment, oldest first */ + fun payments(payments: List) = payments(JsonField.of(payments)) + + /** + * Sets [Builder.payments] to an arbitrary JSON value. + * + * You should usually call [Builder.payments] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun payments(payments: JsonField>) = apply { + this.payments = payments.map { it.toMutableList() } + } + + /** + * Adds a single [InstallmentPayment] to [payments]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addPayment(payment: InstallmentPayment) = apply { + payments = + (payments ?: JsonField.of(mutableListOf())).also { + checkKnown("payments", it).add(payment) + } + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Installment]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .amountDue() + * .amountDueDetails() + * .amountOutstanding() + * .amountOutstandingDetails() + * .amountPaid() + * .amountPaidDetails() + * .dateAssessed() + * .dueDate() + * .installmentNum() + * .paymentDueDate() + * .payments() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Installment = + Installment( + checkRequired("amountDue", amountDue), + checkRequired("amountDueDetails", amountDueDetails), + checkRequired("amountOutstanding", amountOutstanding), + checkRequired("amountOutstandingDetails", amountOutstandingDetails), + checkRequired("amountPaid", amountPaid), + checkRequired("amountPaidDetails", amountPaidDetails), + checkRequired("dateAssessed", dateAssessed), + checkRequired("dueDate", dueDate), + checkRequired("installmentNum", installmentNum), + checkRequired("paymentDueDate", paymentDueDate), + checkRequired("payments", payments).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Installment = apply { + if (validated) { + return@apply + } + + amountDue() + amountDueDetails().validate() + amountOutstanding() + amountOutstandingDetails().validate() + amountPaid() + amountPaidDetails().validate() + dateAssessed() + dueDate() + installmentNum() + paymentDueDate() + payments().forEach { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amountDue.asKnown().isPresent) 1 else 0) + + (amountDueDetails.asKnown().getOrNull()?.validity() ?: 0) + + (if (amountOutstanding.asKnown().isPresent) 1 else 0) + + (amountOutstandingDetails.asKnown().getOrNull()?.validity() ?: 0) + + (if (amountPaid.asKnown().isPresent) 1 else 0) + + (amountPaidDetails.asKnown().getOrNull()?.validity() ?: 0) + + (if (dateAssessed.asKnown().isPresent) 1 else 0) + + (if (dueDate.asKnown().isPresent) 1 else 0) + + (if (installmentNum.asKnown().isPresent) 1 else 0) + + (if (paymentDueDate.asKnown().isPresent) 1 else 0) + + (payments.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + class InstallmentPayment + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val amountDetails: JsonField, + private val date: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("amount_details") + @ExcludeMissing + amountDetails: JsonField = JsonMissing.of(), + @JsonProperty("date") @ExcludeMissing date: JsonField = JsonMissing.of(), + ) : this(amount, amountDetails, date, mutableMapOf()) + + /** + * Amount applied to the installment in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun amount(): Long = amount.getRequired("amount") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun amountDetails(): TransactionCategoryBalances = + amountDetails.getRequired("amount_details") + + /** + * Date the payment was applied to the installment + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected + * value). + */ + fun date(): LocalDate = date.getRequired("date") + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [amountDetails]. + * + * Unlike [amountDetails], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("amount_details") + @ExcludeMissing + fun _amountDetails(): JsonField = amountDetails + + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InstallmentPayment]. + * + * The following fields are required: + * ```java + * .amount() + * .amountDetails() + * .date() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [InstallmentPayment]. */ + class Builder internal constructor() { + + private var amount: JsonField? = null + private var amountDetails: JsonField? = null + private var date: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(installmentPayment: InstallmentPayment) = apply { + amount = installmentPayment.amount + amountDetails = installmentPayment.amountDetails + date = installmentPayment.date + additionalProperties = installmentPayment.additionalProperties.toMutableMap() + } + + /** Amount applied to the installment in cents */ + fun amount(amount: Long) = amount(JsonField.of(amount)) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + fun amountDetails(amountDetails: TransactionCategoryBalances) = + amountDetails(JsonField.of(amountDetails)) + + /** + * Sets [Builder.amountDetails] to an arbitrary JSON value. + * + * You should usually call [Builder.amountDetails] with a well-typed + * [TransactionCategoryBalances] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun amountDetails(amountDetails: JsonField) = apply { + this.amountDetails = amountDetails + } + + /** Date the payment was applied to the installment */ + fun date(date: LocalDate) = date(JsonField.of(date)) + + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [InstallmentPayment]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .amount() + * .amountDetails() + * .date() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InstallmentPayment = + InstallmentPayment( + checkRequired("amount", amount), + checkRequired("amountDetails", amountDetails), + checkRequired("date", date), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InstallmentPayment = apply { + if (validated) { + return@apply + } + + amount() + amountDetails().validate() + date() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (amount.asKnown().isPresent) 1 else 0) + + (amountDetails.asKnown().getOrNull()?.validity() ?: 0) + + (if (date.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InstallmentPayment && + amount == other.amount && + amountDetails == other.amountDetails && + date == other.date && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(amount, amountDetails, date, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InstallmentPayment{amount=$amount, amountDetails=$amountDetails, date=$date, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Installment && + amountDue == other.amountDue && + amountDueDetails == other.amountDueDetails && + amountOutstanding == other.amountOutstanding && + amountOutstandingDetails == other.amountOutstandingDetails && + amountPaid == other.amountPaid && + amountPaidDetails == other.amountPaidDetails && + dateAssessed == other.dateAssessed && + dueDate == other.dueDate && + installmentNum == other.installmentNum && + paymentDueDate == other.paymentDueDate && + payments == other.payments && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amountDue, + amountDueDetails, + amountOutstanding, + amountOutstandingDetails, + amountPaid, + amountPaidDetails, + dateAssessed, + dueDate, + installmentNum, + paymentDueDate, + payments, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Installment{amountDue=$amountDue, amountDueDetails=$amountDueDetails, amountOutstanding=$amountOutstanding, amountOutstandingDetails=$amountOutstandingDetails, amountPaid=$amountPaid, amountPaidDetails=$amountPaidDetails, dateAssessed=$dateAssessed, dueDate=$dueDate, installmentNum=$installmentNum, paymentDueDate=$paymentDueDate, payments=$payments, additionalProperties=$additionalProperties}" + } + + class InstallmentPlanSource + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val UNPAID_BALANCE = of("UNPAID_BALANCE") + + @JvmField val TRANSACTION = of("TRANSACTION") + + @JvmStatic fun of(value: String) = InstallmentPlanSource(JsonField.of(value)) + } + + /** An enum containing [InstallmentPlanSource]'s known values. */ + enum class Known { + UNPAID_BALANCE, + TRANSACTION, + } + + /** + * An enum containing [InstallmentPlanSource]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [InstallmentPlanSource] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + UNPAID_BALANCE, + TRANSACTION, + /** + * An enum member indicating that [InstallmentPlanSource] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + UNPAID_BALANCE -> Value.UNPAID_BALANCE + TRANSACTION -> Value.TRANSACTION + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + UNPAID_BALANCE -> Known.UNPAID_BALANCE + TRANSACTION -> Known.TRANSACTION + else -> throw LithicInvalidDataException("Unknown InstallmentPlanSource: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InstallmentPlanSource = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InstallmentPlanSource && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** + * State of the installment plan. A plan is REBUILD_IN_PROGRESS while its loan tapes are being + * rebuilt, during which its payment totals are being recomputed and should not be treated as + * final + */ + class InstallmentPlanState + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PENDING = of("PENDING") + + @JvmField val ACTIVE = of("ACTIVE") + + @JvmField val REBUILD_IN_PROGRESS = of("REBUILD_IN_PROGRESS") + + @JvmField val FULLY_PAID = of("FULLY_PAID") + + @JvmField val CANCELLED = of("CANCELLED") + + @JvmStatic fun of(value: String) = InstallmentPlanState(JsonField.of(value)) + } + + /** An enum containing [InstallmentPlanState]'s known values. */ + enum class Known { + PENDING, + ACTIVE, + REBUILD_IN_PROGRESS, + FULLY_PAID, + CANCELLED, + } + + /** + * An enum containing [InstallmentPlanState]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [InstallmentPlanState] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PENDING, + ACTIVE, + REBUILD_IN_PROGRESS, + FULLY_PAID, + CANCELLED, + /** + * An enum member indicating that [InstallmentPlanState] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PENDING -> Value.PENDING + ACTIVE -> Value.ACTIVE + REBUILD_IN_PROGRESS -> Value.REBUILD_IN_PROGRESS + FULLY_PAID -> Value.FULLY_PAID + CANCELLED -> Value.CANCELLED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PENDING -> Known.PENDING + ACTIVE -> Known.ACTIVE + REBUILD_IN_PROGRESS -> Known.REBUILD_IN_PROGRESS + FULLY_PAID -> Known.FULLY_PAID + CANCELLED -> Known.CANCELLED + else -> throw LithicInvalidDataException("Unknown InstallmentPlanState: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InstallmentPlanState = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InstallmentPlanState && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is InstallmentPlan && + token == other.token && + closedAt == other.closedAt && + created == other.created && + feeAmount == other.feeAmount && + financialAccountToken == other.financialAccountToken && + installmentPlanTotal == other.installmentPlanTotal && + installments == other.installments && + installmentsOutstanding == other.installmentsOutstanding && + installmentsPaid == other.installmentsPaid && + numInstallments == other.numInstallments && + principalAmount == other.principalAmount && + sourceAmounts == other.sourceAmounts && + sourceId == other.sourceId && + sourceType == other.sourceType && + startDate == other.startDate && + state == other.state && + totalPaid == other.totalPaid && + updated == other.updated && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + token, + closedAt, + created, + feeAmount, + financialAccountToken, + installmentPlanTotal, + installments, + installmentsOutstanding, + installmentsPaid, + numInstallments, + principalAmount, + sourceAmounts, + sourceId, + sourceType, + startDate, + state, + totalPaid, + updated, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "InstallmentPlan{token=$token, closedAt=$closedAt, created=$created, feeAmount=$feeAmount, financialAccountToken=$financialAccountToken, installmentPlanTotal=$installmentPlanTotal, installments=$installments, installmentsOutstanding=$installmentsOutstanding, installmentsPaid=$installmentsPaid, numInstallments=$numInstallments, principalAmount=$principalAmount, sourceAmounts=$sourceAmounts, sourceId=$sourceId, sourceType=$sourceType, startDate=$startDate, state=$state, totalPaid=$totalPaid, updated=$updated, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/TransactionCategoryBalances.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/TransactionCategoryBalances.kt new file mode 100644 index 000000000..8426b3dd4 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/TransactionCategoryBalances.kt @@ -0,0 +1,279 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkRequired +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +class TransactionCategoryBalances +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val balanceTransfers: JsonField, + private val cashAdvances: JsonField, + private val purchases: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("balance_transfers") + @ExcludeMissing + balanceTransfers: JsonField = JsonMissing.of(), + @JsonProperty("cash_advances") + @ExcludeMissing + cashAdvances: JsonField = JsonMissing.of(), + @JsonProperty("purchases") + @ExcludeMissing + purchases: JsonField = JsonMissing.of(), + ) : this(balanceTransfers, cashAdvances, purchases, mutableMapOf()) + + /** + * Amounts attributable to balance transfers + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun balanceTransfers(): CategoryBalances = balanceTransfers.getRequired("balance_transfers") + + /** + * Amounts attributable to cash advances + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun cashAdvances(): CategoryBalances = cashAdvances.getRequired("cash_advances") + + /** + * Amounts attributable to purchases + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun purchases(): CategoryBalances = purchases.getRequired("purchases") + + /** + * Returns the raw JSON value of [balanceTransfers]. + * + * Unlike [balanceTransfers], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("balance_transfers") + @ExcludeMissing + fun _balanceTransfers(): JsonField = balanceTransfers + + /** + * Returns the raw JSON value of [cashAdvances]. + * + * Unlike [cashAdvances], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cash_advances") + @ExcludeMissing + fun _cashAdvances(): JsonField = cashAdvances + + /** + * Returns the raw JSON value of [purchases]. + * + * Unlike [purchases], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("purchases") + @ExcludeMissing + fun _purchases(): JsonField = purchases + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TransactionCategoryBalances]. + * + * The following fields are required: + * ```java + * .balanceTransfers() + * .cashAdvances() + * .purchases() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TransactionCategoryBalances]. */ + class Builder internal constructor() { + + private var balanceTransfers: JsonField? = null + private var cashAdvances: JsonField? = null + private var purchases: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(transactionCategoryBalances: TransactionCategoryBalances) = apply { + balanceTransfers = transactionCategoryBalances.balanceTransfers + cashAdvances = transactionCategoryBalances.cashAdvances + purchases = transactionCategoryBalances.purchases + additionalProperties = transactionCategoryBalances.additionalProperties.toMutableMap() + } + + /** Amounts attributable to balance transfers */ + fun balanceTransfers(balanceTransfers: CategoryBalances) = + balanceTransfers(JsonField.of(balanceTransfers)) + + /** + * Sets [Builder.balanceTransfers] to an arbitrary JSON value. + * + * You should usually call [Builder.balanceTransfers] with a well-typed [CategoryBalances] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun balanceTransfers(balanceTransfers: JsonField) = apply { + this.balanceTransfers = balanceTransfers + } + + /** Amounts attributable to cash advances */ + fun cashAdvances(cashAdvances: CategoryBalances) = cashAdvances(JsonField.of(cashAdvances)) + + /** + * Sets [Builder.cashAdvances] to an arbitrary JSON value. + * + * You should usually call [Builder.cashAdvances] with a well-typed [CategoryBalances] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun cashAdvances(cashAdvances: JsonField) = apply { + this.cashAdvances = cashAdvances + } + + /** Amounts attributable to purchases */ + fun purchases(purchases: CategoryBalances) = purchases(JsonField.of(purchases)) + + /** + * Sets [Builder.purchases] to an arbitrary JSON value. + * + * You should usually call [Builder.purchases] with a well-typed [CategoryBalances] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun purchases(purchases: JsonField) = apply { this.purchases = purchases } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [TransactionCategoryBalances]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .balanceTransfers() + * .cashAdvances() + * .purchases() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TransactionCategoryBalances = + TransactionCategoryBalances( + checkRequired("balanceTransfers", balanceTransfers), + checkRequired("cashAdvances", cashAdvances), + checkRequired("purchases", purchases), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws LithicInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): TransactionCategoryBalances = apply { + if (validated) { + return@apply + } + + balanceTransfers().validate() + cashAdvances().validate() + purchases().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (balanceTransfers.asKnown().getOrNull()?.validity() ?: 0) + + (cashAdvances.asKnown().getOrNull()?.validity() ?: 0) + + (purchases.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TransactionCategoryBalances && + balanceTransfers == other.balanceTransfers && + cashAdvances == other.cashAdvances && + purchases == other.purchases && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(balanceTransfers, cashAdvances, purchases, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "TransactionCategoryBalances{balanceTransfers=$balanceTransfers, cashAdvances=$cashAdvances, purchases=$purchases, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt index d6c58ce1a..0405a8c45 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsync.kt @@ -17,6 +17,7 @@ import com.lithic.api.models.FinancialAccountUpdateStatusParams import com.lithic.api.services.async.financialAccounts.BalanceServiceAsync import com.lithic.api.services.async.financialAccounts.CreditConfigurationServiceAsync import com.lithic.api.services.async.financialAccounts.FinancialTransactionServiceAsync +import com.lithic.api.services.async.financialAccounts.InstallmentPlanServiceAsync import com.lithic.api.services.async.financialAccounts.InterestTierScheduleServiceAsync import com.lithic.api.services.async.financialAccounts.LoanTapeConfigurationServiceAsync import com.lithic.api.services.async.financialAccounts.LoanTapeServiceAsync @@ -51,6 +52,8 @@ interface FinancialAccountServiceAsync { fun loanTapes(): LoanTapeServiceAsync + fun installmentPlans(): InstallmentPlanServiceAsync + fun loanTapeConfiguration(): LoanTapeConfigurationServiceAsync fun interestTierSchedule(): InterestTierScheduleServiceAsync @@ -247,6 +250,8 @@ interface FinancialAccountServiceAsync { fun loanTapes(): LoanTapeServiceAsync.WithRawResponse + fun installmentPlans(): InstallmentPlanServiceAsync.WithRawResponse + fun loanTapeConfiguration(): LoanTapeConfigurationServiceAsync.WithRawResponse fun interestTierSchedule(): InterestTierScheduleServiceAsync.WithRawResponse diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt index 7843a7983..907f49f8d 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncImpl.kt @@ -32,6 +32,8 @@ import com.lithic.api.services.async.financialAccounts.CreditConfigurationServic import com.lithic.api.services.async.financialAccounts.CreditConfigurationServiceAsyncImpl import com.lithic.api.services.async.financialAccounts.FinancialTransactionServiceAsync import com.lithic.api.services.async.financialAccounts.FinancialTransactionServiceAsyncImpl +import com.lithic.api.services.async.financialAccounts.InstallmentPlanServiceAsync +import com.lithic.api.services.async.financialAccounts.InstallmentPlanServiceAsyncImpl import com.lithic.api.services.async.financialAccounts.InterestTierScheduleServiceAsync import com.lithic.api.services.async.financialAccounts.InterestTierScheduleServiceAsyncImpl import com.lithic.api.services.async.financialAccounts.LoanTapeConfigurationServiceAsync @@ -73,6 +75,10 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun private val loanTapes: LoanTapeServiceAsync by lazy { LoanTapeServiceAsyncImpl(clientOptions) } + private val installmentPlans: InstallmentPlanServiceAsync by lazy { + InstallmentPlanServiceAsyncImpl(clientOptions) + } + private val loanTapeConfiguration: LoanTapeConfigurationServiceAsync by lazy { LoanTapeConfigurationServiceAsyncImpl(clientOptions) } @@ -100,6 +106,8 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun override fun loanTapes(): LoanTapeServiceAsync = loanTapes + override fun installmentPlans(): InstallmentPlanServiceAsync = installmentPlans + override fun loanTapeConfiguration(): LoanTapeConfigurationServiceAsync = loanTapeConfiguration override fun interestTierSchedule(): InterestTierScheduleServiceAsync = interestTierSchedule @@ -177,6 +185,10 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun LoanTapeServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val installmentPlans: InstallmentPlanServiceAsync.WithRawResponse by lazy { + InstallmentPlanServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val loanTapeConfiguration: LoanTapeConfigurationServiceAsync.WithRawResponse by lazy { LoanTapeConfigurationServiceAsyncImpl.WithRawResponseImpl(clientOptions) @@ -207,6 +219,9 @@ internal constructor(private val clientOptions: ClientOptions) : FinancialAccoun override fun loanTapes(): LoanTapeServiceAsync.WithRawResponse = loanTapes + override fun installmentPlans(): InstallmentPlanServiceAsync.WithRawResponse = + installmentPlans + override fun loanTapeConfiguration(): LoanTapeConfigurationServiceAsync.WithRawResponse = loanTapeConfiguration diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsync.kt new file mode 100644 index 000000000..3b63f9ce9 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsync.kt @@ -0,0 +1,209 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async.financialAccounts + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.models.FinancialAccountInstallmentPlanListPageAsync +import com.lithic.api.models.FinancialAccountInstallmentPlanListParams +import com.lithic.api.models.FinancialAccountInstallmentPlanRetrieveParams +import com.lithic.api.models.InstallmentPlan +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface InstallmentPlanServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): InstallmentPlanServiceAsync + + /** Get a specific installment plan for a given financial account. */ + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + ): CompletableFuture = + retrieve(installmentPlanToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve( + params.toBuilder().installmentPlanToken(installmentPlanToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams + ): CompletableFuture = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** List the installment plans for a given financial account. */ + fun list( + financialAccountToken: String + ): CompletableFuture = + list(financialAccountToken, FinancialAccountInstallmentPlanListParams.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + ): CompletableFuture = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see list */ + fun list( + params: FinancialAccountInstallmentPlanListParams + ): CompletableFuture = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): CompletableFuture = + list( + financialAccountToken, + FinancialAccountInstallmentPlanListParams.none(), + requestOptions, + ) + + /** + * A view of [InstallmentPlanServiceAsync] that provides access to raw HTTP responses for each + * method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): InstallmentPlanServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/installment_plans/{installment_plan_token}`, + * but is otherwise the same as [InstallmentPlanServiceAsync.retrieve]. + */ + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + ): CompletableFuture> = + retrieve(installmentPlanToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve( + params.toBuilder().installmentPlanToken(installmentPlanToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/installment_plans`, but is otherwise the + * same as [InstallmentPlanServiceAsync.list]. + */ + fun list( + financialAccountToken: String + ): CompletableFuture> = + list(financialAccountToken, FinancialAccountInstallmentPlanListParams.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + ): CompletableFuture> = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see list */ + fun list( + params: FinancialAccountInstallmentPlanListParams + ): CompletableFuture> = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + list( + financialAccountToken, + FinancialAccountInstallmentPlanListParams.none(), + requestOptions, + ) + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncImpl.kt new file mode 100644 index 000000000..0b6b5d5a1 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncImpl.kt @@ -0,0 +1,154 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async.financialAccounts + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired +import com.lithic.api.core.handlers.errorBodyHandler +import com.lithic.api.core.handlers.errorHandler +import com.lithic.api.core.handlers.jsonHandler +import com.lithic.api.core.http.HttpMethod +import com.lithic.api.core.http.HttpRequest +import com.lithic.api.core.http.HttpResponse +import com.lithic.api.core.http.HttpResponse.Handler +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.core.http.parseable +import com.lithic.api.core.prepareAsync +import com.lithic.api.models.FinancialAccountInstallmentPlanListPageAsync +import com.lithic.api.models.FinancialAccountInstallmentPlanListPageResponse +import com.lithic.api.models.FinancialAccountInstallmentPlanListParams +import com.lithic.api.models.FinancialAccountInstallmentPlanRetrieveParams +import com.lithic.api.models.InstallmentPlan +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class InstallmentPlanServiceAsyncImpl +internal constructor(private val clientOptions: ClientOptions) : InstallmentPlanServiceAsync { + + private val withRawResponse: InstallmentPlanServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): InstallmentPlanServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions( + modifier: Consumer + ): InstallmentPlanServiceAsync = + InstallmentPlanServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get + // /v1/financial_accounts/{financial_account_token}/installment_plans/{installment_plan_token} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + override fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /v1/financial_accounts/{financial_account_token}/installment_plans + withRawResponse().list(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + InstallmentPlanServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): InstallmentPlanServiceAsync.WithRawResponse = + InstallmentPlanServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("installmentPlanToken", params.installmentPlanToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "v1", + "financial_accounts", + params._pathParam(0), + "installment_plans", + params._pathParam(1), + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "v1", + "financial_accounts", + params._pathParam(0), + "installment_plans", + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + .let { + FinancialAccountInstallmentPlanListPageAsync.builder() + .service(InstallmentPlanServiceAsyncImpl(clientOptions)) + .streamHandlerExecutor(clientOptions.streamHandlerExecutor) + .params(params) + .response(it) + .build() + } + } + } + } + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt index 7f80f2ca0..3f27fccae 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountService.kt @@ -18,6 +18,7 @@ import com.lithic.api.models.FinancialAccountUpdateStatusParams import com.lithic.api.services.blocking.financialAccounts.BalanceService import com.lithic.api.services.blocking.financialAccounts.CreditConfigurationService import com.lithic.api.services.blocking.financialAccounts.FinancialTransactionService +import com.lithic.api.services.blocking.financialAccounts.InstallmentPlanService import com.lithic.api.services.blocking.financialAccounts.InterestTierScheduleService import com.lithic.api.services.blocking.financialAccounts.LoanTapeConfigurationService import com.lithic.api.services.blocking.financialAccounts.LoanTapeService @@ -51,6 +52,8 @@ interface FinancialAccountService { fun loanTapes(): LoanTapeService + fun installmentPlans(): InstallmentPlanService + fun loanTapeConfiguration(): LoanTapeConfigurationService fun interestTierSchedule(): InterestTierScheduleService @@ -234,6 +237,8 @@ interface FinancialAccountService { fun loanTapes(): LoanTapeService.WithRawResponse + fun installmentPlans(): InstallmentPlanService.WithRawResponse + fun loanTapeConfiguration(): LoanTapeConfigurationService.WithRawResponse fun interestTierSchedule(): InterestTierScheduleService.WithRawResponse diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt index 2e03ff8a4..3037aa334 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceImpl.kt @@ -32,6 +32,8 @@ import com.lithic.api.services.blocking.financialAccounts.CreditConfigurationSer import com.lithic.api.services.blocking.financialAccounts.CreditConfigurationServiceImpl import com.lithic.api.services.blocking.financialAccounts.FinancialTransactionService import com.lithic.api.services.blocking.financialAccounts.FinancialTransactionServiceImpl +import com.lithic.api.services.blocking.financialAccounts.InstallmentPlanService +import com.lithic.api.services.blocking.financialAccounts.InstallmentPlanServiceImpl import com.lithic.api.services.blocking.financialAccounts.InterestTierScheduleService import com.lithic.api.services.blocking.financialAccounts.InterestTierScheduleServiceImpl import com.lithic.api.services.blocking.financialAccounts.LoanTapeConfigurationService @@ -68,6 +70,10 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions private val loanTapes: LoanTapeService by lazy { LoanTapeServiceImpl(clientOptions) } + private val installmentPlans: InstallmentPlanService by lazy { + InstallmentPlanServiceImpl(clientOptions) + } + private val loanTapeConfiguration: LoanTapeConfigurationService by lazy { LoanTapeConfigurationServiceImpl(clientOptions) } @@ -93,6 +99,8 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions override fun loanTapes(): LoanTapeService = loanTapes + override fun installmentPlans(): InstallmentPlanService = installmentPlans + override fun loanTapeConfiguration(): LoanTapeConfigurationService = loanTapeConfiguration override fun interestTierSchedule(): InterestTierScheduleService = interestTierSchedule @@ -170,6 +178,10 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions LoanTapeServiceImpl.WithRawResponseImpl(clientOptions) } + private val installmentPlans: InstallmentPlanService.WithRawResponse by lazy { + InstallmentPlanServiceImpl.WithRawResponseImpl(clientOptions) + } + private val loanTapeConfiguration: LoanTapeConfigurationService.WithRawResponse by lazy { LoanTapeConfigurationServiceImpl.WithRawResponseImpl(clientOptions) } @@ -199,6 +211,8 @@ class FinancialAccountServiceImpl internal constructor(private val clientOptions override fun loanTapes(): LoanTapeService.WithRawResponse = loanTapes + override fun installmentPlans(): InstallmentPlanService.WithRawResponse = installmentPlans + override fun loanTapeConfiguration(): LoanTapeConfigurationService.WithRawResponse = loanTapeConfiguration diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanService.kt new file mode 100644 index 000000000..1bf24f171 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanService.kt @@ -0,0 +1,213 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking.financialAccounts + +import com.google.errorprone.annotations.MustBeClosed +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.models.FinancialAccountInstallmentPlanListPage +import com.lithic.api.models.FinancialAccountInstallmentPlanListParams +import com.lithic.api.models.FinancialAccountInstallmentPlanRetrieveParams +import com.lithic.api.models.InstallmentPlan +import java.util.function.Consumer + +interface InstallmentPlanService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): InstallmentPlanService + + /** Get a specific installment plan for a given financial account. */ + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + ): InstallmentPlan = retrieve(installmentPlanToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): InstallmentPlan = + retrieve( + params.toBuilder().installmentPlanToken(installmentPlanToken).build(), + requestOptions, + ) + + /** @see retrieve */ + fun retrieve(params: FinancialAccountInstallmentPlanRetrieveParams): InstallmentPlan = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): InstallmentPlan + + /** List the installment plans for a given financial account. */ + fun list(financialAccountToken: String): FinancialAccountInstallmentPlanListPage = + list(financialAccountToken, FinancialAccountInstallmentPlanListParams.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): FinancialAccountInstallmentPlanListPage = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + ): FinancialAccountInstallmentPlanListPage = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): FinancialAccountInstallmentPlanListPage + + /** @see list */ + fun list( + params: FinancialAccountInstallmentPlanListParams + ): FinancialAccountInstallmentPlanListPage = list(params, RequestOptions.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): FinancialAccountInstallmentPlanListPage = + list( + financialAccountToken, + FinancialAccountInstallmentPlanListParams.none(), + requestOptions, + ) + + /** + * A view of [InstallmentPlanService] that provides access to raw HTTP responses for each + * method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): InstallmentPlanService.WithRawResponse + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/installment_plans/{installment_plan_token}`, + * but is otherwise the same as [InstallmentPlanService.retrieve]. + */ + @MustBeClosed + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + ): HttpResponseFor = + retrieve(installmentPlanToken, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + installmentPlanToken: String, + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve( + params.toBuilder().installmentPlanToken(installmentPlanToken).build(), + requestOptions, + ) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams + ): HttpResponseFor = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/installment_plans`, but is otherwise the + * same as [InstallmentPlanService.list]. + */ + @MustBeClosed + fun list( + financialAccountToken: String + ): HttpResponseFor = + list(financialAccountToken, FinancialAccountInstallmentPlanListParams.none()) + + /** @see list */ + @MustBeClosed + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + @MustBeClosed + fun list( + financialAccountToken: String, + params: FinancialAccountInstallmentPlanListParams = + FinancialAccountInstallmentPlanListParams.none(), + ): HttpResponseFor = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see list */ + @MustBeClosed + fun list( + params: FinancialAccountInstallmentPlanListParams + ): HttpResponseFor = + list(params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + list( + financialAccountToken, + FinancialAccountInstallmentPlanListParams.none(), + requestOptions, + ) + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceImpl.kt new file mode 100644 index 000000000..695185189 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceImpl.kt @@ -0,0 +1,144 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking.financialAccounts + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired +import com.lithic.api.core.handlers.errorBodyHandler +import com.lithic.api.core.handlers.errorHandler +import com.lithic.api.core.handlers.jsonHandler +import com.lithic.api.core.http.HttpMethod +import com.lithic.api.core.http.HttpRequest +import com.lithic.api.core.http.HttpResponse +import com.lithic.api.core.http.HttpResponse.Handler +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.core.http.parseable +import com.lithic.api.core.prepare +import com.lithic.api.models.FinancialAccountInstallmentPlanListPage +import com.lithic.api.models.FinancialAccountInstallmentPlanListPageResponse +import com.lithic.api.models.FinancialAccountInstallmentPlanListParams +import com.lithic.api.models.FinancialAccountInstallmentPlanRetrieveParams +import com.lithic.api.models.InstallmentPlan +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class InstallmentPlanServiceImpl internal constructor(private val clientOptions: ClientOptions) : + InstallmentPlanService { + + private val withRawResponse: InstallmentPlanService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): InstallmentPlanService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): InstallmentPlanService = + InstallmentPlanServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions, + ): InstallmentPlan = + // get + // /v1/financial_accounts/{financial_account_token}/installment_plans/{installment_plan_token} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions, + ): FinancialAccountInstallmentPlanListPage = + // get /v1/financial_accounts/{financial_account_token}/installment_plans + withRawResponse().list(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + InstallmentPlanService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): InstallmentPlanService.WithRawResponse = + InstallmentPlanServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: FinancialAccountInstallmentPlanRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("installmentPlanToken", params.installmentPlanToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "v1", + "financial_accounts", + params._pathParam(0), + "installment_plans", + params._pathParam(1), + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: FinancialAccountInstallmentPlanListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "v1", + "financial_accounts", + params._pathParam(0), + "installment_plans", + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + .let { + FinancialAccountInstallmentPlanListPage.builder() + .service(InstallmentPlanServiceImpl(clientOptions)) + .params(params) + .response(it) + .build() + } + } + } + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponseTest.kt new file mode 100644 index 000000000..a22504fbd --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListPageResponseTest.kt @@ -0,0 +1,528 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import java.time.LocalDate +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class FinancialAccountInstallmentPlanListPageResponseTest { + + @Test + fun create() { + val financialAccountInstallmentPlanListPageResponse = + FinancialAccountInstallmentPlanListPageResponse.builder() + .addData( + InstallmentPlan.builder() + .token("token") + .closedAt(LocalDate.parse("2019-12-27")) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .feeAmount(0L) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanTotal(0L) + .addInstallment( + InstallmentPlan.Installment.builder() + .amountDue(0L) + .amountDueDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountOutstanding(0L) + .amountOutstandingDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountPaid(0L) + .amountPaidDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .dateAssessed(LocalDate.parse("2019-12-27")) + .dueDate(LocalDate.parse("2019-12-27")) + .installmentNum(0L) + .paymentDueDate(LocalDate.parse("2019-12-27")) + .addPayment( + InstallmentPlan.Installment.InstallmentPayment.builder() + .amount(0L) + .amountDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .date(LocalDate.parse("2019-12-27")) + .build() + ) + .build() + ) + .installmentsOutstanding(0L) + .installmentsPaid(0L) + .numInstallments(0L) + .principalAmount(0L) + .sourceAmounts( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .sourceId("source_id") + .sourceType(InstallmentPlan.InstallmentPlanSource.UNPAID_BALANCE) + .startDate(LocalDate.parse("2019-12-27")) + .state(InstallmentPlan.InstallmentPlanState.PENDING) + .totalPaid(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + ) + .hasMore(true) + .build() + + assertThat(financialAccountInstallmentPlanListPageResponse.data()) + .containsExactly( + InstallmentPlan.builder() + .token("token") + .closedAt(LocalDate.parse("2019-12-27")) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .feeAmount(0L) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanTotal(0L) + .addInstallment( + InstallmentPlan.Installment.builder() + .amountDue(0L) + .amountDueDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountOutstanding(0L) + .amountOutstandingDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountPaid(0L) + .amountPaidDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .dateAssessed(LocalDate.parse("2019-12-27")) + .dueDate(LocalDate.parse("2019-12-27")) + .installmentNum(0L) + .paymentDueDate(LocalDate.parse("2019-12-27")) + .addPayment( + InstallmentPlan.Installment.InstallmentPayment.builder() + .amount(0L) + .amountDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .date(LocalDate.parse("2019-12-27")) + .build() + ) + .build() + ) + .installmentsOutstanding(0L) + .installmentsPaid(0L) + .numInstallments(0L) + .principalAmount(0L) + .sourceAmounts( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .sourceId("source_id") + .sourceType(InstallmentPlan.InstallmentPlanSource.UNPAID_BALANCE) + .startDate(LocalDate.parse("2019-12-27")) + .state(InstallmentPlan.InstallmentPlanState.PENDING) + .totalPaid(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + ) + assertThat(financialAccountInstallmentPlanListPageResponse.hasMore()).isEqualTo(true) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val financialAccountInstallmentPlanListPageResponse = + FinancialAccountInstallmentPlanListPageResponse.builder() + .addData( + InstallmentPlan.builder() + .token("token") + .closedAt(LocalDate.parse("2019-12-27")) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .feeAmount(0L) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanTotal(0L) + .addInstallment( + InstallmentPlan.Installment.builder() + .amountDue(0L) + .amountDueDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountOutstanding(0L) + .amountOutstandingDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountPaid(0L) + .amountPaidDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .dateAssessed(LocalDate.parse("2019-12-27")) + .dueDate(LocalDate.parse("2019-12-27")) + .installmentNum(0L) + .paymentDueDate(LocalDate.parse("2019-12-27")) + .addPayment( + InstallmentPlan.Installment.InstallmentPayment.builder() + .amount(0L) + .amountDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .date(LocalDate.parse("2019-12-27")) + .build() + ) + .build() + ) + .installmentsOutstanding(0L) + .installmentsPaid(0L) + .numInstallments(0L) + .principalAmount(0L) + .sourceAmounts( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .sourceId("source_id") + .sourceType(InstallmentPlan.InstallmentPlanSource.UNPAID_BALANCE) + .startDate(LocalDate.parse("2019-12-27")) + .state(InstallmentPlan.InstallmentPlanState.PENDING) + .totalPaid(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + ) + .hasMore(true) + .build() + + val roundtrippedFinancialAccountInstallmentPlanListPageResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(financialAccountInstallmentPlanListPageResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedFinancialAccountInstallmentPlanListPageResponse) + .isEqualTo(financialAccountInstallmentPlanListPageResponse) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParamsTest.kt new file mode 100644 index 000000000..a21855221 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanListParamsTest.kt @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class FinancialAccountInstallmentPlanListParamsTest { + + @Test + fun create() { + FinancialAccountInstallmentPlanListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .endingBefore("ending_before") + .pageSize(1L) + .startingAfter("starting_after") + .state(FinancialAccountInstallmentPlanListParams.InstallmentPlanState.PENDING) + .build() + } + + @Test + fun pathParams() { + val params = + FinancialAccountInstallmentPlanListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + FinancialAccountInstallmentPlanListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .endingBefore("ending_before") + .pageSize(1L) + .startingAfter("starting_after") + .state(FinancialAccountInstallmentPlanListParams.InstallmentPlanState.PENDING) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("ending_before", "ending_before") + .put("page_size", "1") + .put("starting_after", "starting_after") + .put("state", "PENDING") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = + FinancialAccountInstallmentPlanListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParamsTest.kt new file mode 100644 index 000000000..cab5e46cf --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountInstallmentPlanRetrieveParamsTest.kt @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class FinancialAccountInstallmentPlanRetrieveParamsTest { + + @Test + fun create() { + FinancialAccountInstallmentPlanRetrieveParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanToken("installment_plan_token") + .build() + } + + @Test + fun pathParams() { + val params = + FinancialAccountInstallmentPlanRetrieveParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanToken("installment_plan_token") + .build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(params._pathParam(1)).isEqualTo("installment_plan_token") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/InstallmentPlanTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/InstallmentPlanTest.kt new file mode 100644 index 000000000..f245628dc --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/InstallmentPlanTest.kt @@ -0,0 +1,481 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import java.time.LocalDate +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class InstallmentPlanTest { + + @Test + fun create() { + val installmentPlan = + InstallmentPlan.builder() + .token("token") + .closedAt(LocalDate.parse("2019-12-27")) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .feeAmount(0L) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanTotal(0L) + .addInstallment( + InstallmentPlan.Installment.builder() + .amountDue(0L) + .amountDueDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountOutstanding(0L) + .amountOutstandingDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountPaid(0L) + .amountPaidDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .dateAssessed(LocalDate.parse("2019-12-27")) + .dueDate(LocalDate.parse("2019-12-27")) + .installmentNum(0L) + .paymentDueDate(LocalDate.parse("2019-12-27")) + .addPayment( + InstallmentPlan.Installment.InstallmentPayment.builder() + .amount(0L) + .amountDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .date(LocalDate.parse("2019-12-27")) + .build() + ) + .build() + ) + .installmentsOutstanding(0L) + .installmentsPaid(0L) + .numInstallments(0L) + .principalAmount(0L) + .sourceAmounts( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .cashAdvances( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .purchases( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .build() + ) + .sourceId("source_id") + .sourceType(InstallmentPlan.InstallmentPlanSource.UNPAID_BALANCE) + .startDate(LocalDate.parse("2019-12-27")) + .state(InstallmentPlan.InstallmentPlanState.PENDING) + .totalPaid(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + + assertThat(installmentPlan.token()).isEqualTo("token") + assertThat(installmentPlan.closedAt()).contains(LocalDate.parse("2019-12-27")) + assertThat(installmentPlan.created()) + .isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(installmentPlan.feeAmount()).isEqualTo(0L) + assertThat(installmentPlan.financialAccountToken()) + .isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(installmentPlan.installmentPlanTotal()).isEqualTo(0L) + assertThat(installmentPlan.installments()) + .containsExactly( + InstallmentPlan.Installment.builder() + .amountDue(0L) + .amountDueDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountOutstanding(0L) + .amountOutstandingDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountPaid(0L) + .amountPaidDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .dateAssessed(LocalDate.parse("2019-12-27")) + .dueDate(LocalDate.parse("2019-12-27")) + .installmentNum(0L) + .paymentDueDate(LocalDate.parse("2019-12-27")) + .addPayment( + InstallmentPlan.Installment.InstallmentPayment.builder() + .amount(0L) + .amountDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .date(LocalDate.parse("2019-12-27")) + .build() + ) + .build() + ) + assertThat(installmentPlan.installmentsOutstanding()).isEqualTo(0L) + assertThat(installmentPlan.installmentsPaid()).isEqualTo(0L) + assertThat(installmentPlan.numInstallments()).isEqualTo(0L) + assertThat(installmentPlan.principalAmount()).isEqualTo(0L) + assertThat(installmentPlan.sourceAmounts()) + .contains( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .cashAdvances( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .purchases( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .build() + ) + assertThat(installmentPlan.sourceId()).isEqualTo("source_id") + assertThat(installmentPlan.sourceType()) + .isEqualTo(InstallmentPlan.InstallmentPlanSource.UNPAID_BALANCE) + assertThat(installmentPlan.startDate()).isEqualTo(LocalDate.parse("2019-12-27")) + assertThat(installmentPlan.state()).isEqualTo(InstallmentPlan.InstallmentPlanState.PENDING) + assertThat(installmentPlan.totalPaid()).isEqualTo(0L) + assertThat(installmentPlan.updated()) + .isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val installmentPlan = + InstallmentPlan.builder() + .token("token") + .closedAt(LocalDate.parse("2019-12-27")) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .feeAmount(0L) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanTotal(0L) + .addInstallment( + InstallmentPlan.Installment.builder() + .amountDue(0L) + .amountDueDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountOutstanding(0L) + .amountOutstandingDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .amountPaid(0L) + .amountPaidDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .dateAssessed(LocalDate.parse("2019-12-27")) + .dueDate(LocalDate.parse("2019-12-27")) + .installmentNum(0L) + .paymentDueDate(LocalDate.parse("2019-12-27")) + .addPayment( + InstallmentPlan.Installment.InstallmentPayment.builder() + .amount(0L) + .amountDetails( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .cashAdvances( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .purchases( + CategoryBalances.builder() + .fees(0L) + .interest(0L) + .principal(0L) + .build() + ) + .build() + ) + .date(LocalDate.parse("2019-12-27")) + .build() + ) + .build() + ) + .installmentsOutstanding(0L) + .installmentsPaid(0L) + .numInstallments(0L) + .principalAmount(0L) + .sourceAmounts( + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .cashAdvances( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .purchases( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .build() + ) + .sourceId("source_id") + .sourceType(InstallmentPlan.InstallmentPlanSource.UNPAID_BALANCE) + .startDate(LocalDate.parse("2019-12-27")) + .state(InstallmentPlan.InstallmentPlanState.PENDING) + .totalPaid(0L) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .build() + + val roundtrippedInstallmentPlan = + jsonMapper.readValue( + jsonMapper.writeValueAsString(installmentPlan), + jacksonTypeRef(), + ) + + assertThat(roundtrippedInstallmentPlan).isEqualTo(installmentPlan) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionCategoryBalancesTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionCategoryBalancesTest.kt new file mode 100644 index 000000000..3fd277fbf --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionCategoryBalancesTest.kt @@ -0,0 +1,55 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TransactionCategoryBalancesTest { + + @Test + fun create() { + val transactionCategoryBalances = + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .cashAdvances( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .purchases(CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build()) + .build() + + assertThat(transactionCategoryBalances.balanceTransfers()) + .isEqualTo(CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build()) + assertThat(transactionCategoryBalances.cashAdvances()) + .isEqualTo(CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build()) + assertThat(transactionCategoryBalances.purchases()) + .isEqualTo(CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build()) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val transactionCategoryBalances = + TransactionCategoryBalances.builder() + .balanceTransfers( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .cashAdvances( + CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build() + ) + .purchases(CategoryBalances.builder().fees(0L).interest(0L).principal(0L).build()) + .build() + + val roundtrippedTransactionCategoryBalances = + jsonMapper.readValue( + jsonMapper.writeValueAsString(transactionCategoryBalances), + jacksonTypeRef(), + ) + + assertThat(roundtrippedTransactionCategoryBalances).isEqualTo(transactionCategoryBalances) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncTest.kt new file mode 100644 index 000000000..8fbe44312 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/financialAccounts/InstallmentPlanServiceAsyncTest.kt @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async.financialAccounts + +import com.lithic.api.TestServerExtension +import com.lithic.api.client.okhttp.LithicOkHttpClientAsync +import com.lithic.api.models.FinancialAccountInstallmentPlanRetrieveParams +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class InstallmentPlanServiceAsyncTest { + + @Test + fun retrieve() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val installmentPlanServiceAsync = client.financialAccounts().installmentPlans() + + val installmentPlanFuture = + installmentPlanServiceAsync.retrieve( + FinancialAccountInstallmentPlanRetrieveParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanToken("installment_plan_token") + .build() + ) + + val installmentPlan = installmentPlanFuture.get() + installmentPlan.validate() + } + + @Test + fun list() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val installmentPlanServiceAsync = client.financialAccounts().installmentPlans() + + val pageFuture = installmentPlanServiceAsync.list("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + val page = pageFuture.get() + page.response().validate() + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceTest.kt new file mode 100644 index 000000000..e9faece2b --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/financialAccounts/InstallmentPlanServiceTest.kt @@ -0,0 +1,47 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking.financialAccounts + +import com.lithic.api.TestServerExtension +import com.lithic.api.client.okhttp.LithicOkHttpClient +import com.lithic.api.models.FinancialAccountInstallmentPlanRetrieveParams +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class InstallmentPlanServiceTest { + + @Test + fun retrieve() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val installmentPlanService = client.financialAccounts().installmentPlans() + + val installmentPlan = + installmentPlanService.retrieve( + FinancialAccountInstallmentPlanRetrieveParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .installmentPlanToken("installment_plan_token") + .build() + ) + + installmentPlan.validate() + } + + @Test + fun list() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val installmentPlanService = client.financialAccounts().installmentPlans() + + val page = installmentPlanService.list("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + page.response().validate() + } +} From 14e4de99cf84a939b0c62a92d0ce2a1c474e577e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 17:31:36 +0000 Subject: [PATCH 15/15] release: 0.134.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 21 +++++++++++++++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4a1242df8..774500bfb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.133.0" + ".": "0.134.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b82c81f37..97965c2ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 0.134.0 (2026-09-18) + +Full Changelog: [v0.133.0...v0.134.0](https://github.com/lithic-com/lithic-java/compare/v0.133.0...v0.134.0) + +### Features + +* [CARDS-5174] Add reiusse/renew 409 error ([3d90574](https://github.com/lithic-com/lithic-java/commit/3d90574a2bd217af7a1e3161c55a17c2d3f7b6bc)) +* [TRE-14464] Update /retry payments endpoint to accept method ([5e294b4](https://github.com/lithic-com/lithic-java/commit/5e294b48832067d094d6c316c239a33bb10a527a)) +* [TRE-14524] Add Open to buy API spec ([b0e8d1f](https://github.com/lithic-com/lithic-java/commit/b0e8d1fba80804352d37aedf40fb809cc4fc2754)) +* Add missing blockchain/stablecoin endpoints to the spec ([5cdc715](https://github.com/lithic-com/lithic-java/commit/5cdc715990d26e494c33d6dfd5bd6581ce21b6c7)) +* **api:** add card.pin_updated webhook event ([8ab17b8](https://github.com/lithic-com/lithic-java/commit/8ab17b8600e670de5baedfb831bf3aa327c3163a)) +* **api:** add EXTERNAL_STABLECOIN category/events to payments and account activity models ([71a8dc7](https://github.com/lithic-com/lithic-java/commit/71a8dc7df0db29dc489ba45c3c677e3d1dbeafa1)) +* **api:** add FEE/FEE_REVERSAL event types to FinancialEvent/ManagementOperation/StatementLineItems ([ea12080](https://github.com/lithic-com/lithic-java/commit/ea12080f1eac92e1a9bdb3c35ed0b67f3bcf3891)) +* **api:** add psd2Context field to ThreeDSAuthentication responses ([5b86204](https://github.com/lithic-com/lithic-java/commit/5b862041a8be447059faa1cdf44fabcc82ae5764)) +* **api:** add retrieve/list installment plan methods to financial_accounts ([d474e8a](https://github.com/lithic-com/lithic-java/commit/d474e8a168c193f57ada6c99cfe20ad09b8a13bf)) +* **api:** add STABLECOIN_REVIEWED simulation type to payment simulate action ([eb203cb](https://github.com/lithic-com/lithic-java/commit/eb203cb3d42ad2e5af7924be34535db8f7ffe936)) +* AUTH-3759: Add DECLINE_SCA_REQUIRED and SCA_REQUIRED enum entries ([816b323](https://github.com/lithic-com/lithic-java/commit/816b3238971ee1e9f6b2997f5a54c7a598959dd9)) +* TRE-14349: add installment plan management operation event types ([97fabed](https://github.com/lithic-com/lithic-java/commit/97fabed2eefe8fe7c76fa4c45a66ed8495a28f9d)) +* TRE-14429: Document the stablecoin payments endpoint ([585fdd5](https://github.com/lithic-com/lithic-java/commit/585fdd50392d686c01877f07189ed696345267c8)) +* **types:** add OTHER enum value to AuthRuleType ([498c5fe](https://github.com/lithic-com/lithic-java/commit/498c5fe9b52733f1723a1f5014b354c0b52a3d3b)) + ## 0.133.0 (2026-08-31) Full Changelog: [v0.132.0...v0.133.0](https://github.com/lithic-com/lithic-java/compare/v0.132.0...v0.133.0) diff --git a/README.md b/README.md index 6843416bd..0c2c1a907 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.lithic.api/lithic-java)](https://central.sonatype.com/artifact/com.lithic.api/lithic-java/0.133.0) -[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.133.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.lithic.api/lithic-java)](https://central.sonatype.com/artifact/com.lithic.api/lithic-java/0.134.0) +[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.134.0) @@ -22,7 +22,7 @@ Use the Lithic MCP Server to enable AI assistants to interact with this API, all -The REST API documentation can be found on [docs.lithic.com](https://docs.lithic.com). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.lithic.api/lithic-java/0.133.0). +The REST API documentation can be found on [docs.lithic.com](https://docs.lithic.com). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.lithic.api/lithic-java/0.134.0). @@ -33,7 +33,7 @@ The REST API documentation can be found on [docs.lithic.com](https://docs.lithic ### Gradle ```kotlin -implementation("com.lithic.api:lithic-java:0.133.0") +implementation("com.lithic.api:lithic-java:0.134.0") ``` ### Maven @@ -42,7 +42,7 @@ implementation("com.lithic.api:lithic-java:0.133.0") com.lithic.api lithic-java - 0.133.0 + 0.134.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 9d85f0e19..1dda877a1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.lithic.api" - version = "0.133.0" // x-release-please-version + version = "0.134.0" // x-release-please-version } subprojects {