diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6e0ed7db..620a05d92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,10 +20,10 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -40,14 +40,17 @@ jobs: build: timeout-minutes: 15 name: build + permissions: + contents: read + id-token: write runs-on: ${{ github.repository == 'stainless-sdks/lithic-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -61,16 +64,31 @@ jobs: - name: Build SDK run: ./scripts/build + - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/lithic-java' + id: github-oidc + uses: actions/github-script@v8 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Build and upload Maven artifacts + if: github.repository == 'stainless-sdks/lithic-java' + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + PROJECT: lithic-java + run: ./scripts/upload-artifacts test: timeout-minutes: 15 name: test runs-on: ${{ github.repository == 'stainless-sdks/lithic-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index cd7b92eec..68a62dbb2 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 445c0f6f3..8cee17619 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'lithic-com/lithic-java' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d3dc9f51b..988e843fd 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.115.0" + ".": "0.116.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index ddb484b7e..30dea04f0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 176 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-4ecc06edca2cfad4eaf11573611e89823fda5f56370bac5cd02a498a6b277d09.yml -openapi_spec_hash: 8f4a30bec4348cbde85b1e65bef9189a -config_hash: 9dddee5f7af579864599849cb28a0770 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-a6c56df3bc156ac1e6ee5d635c6cd964f0d60836fe17a97deec8af8429bd339c.yml +openapi_spec_hash: c563acd10d96ddabe6c9643b592bd509 +config_hash: 31d71922d7838f34ae0875c9b8026d99 diff --git a/CHANGELOG.md b/CHANGELOG.md index c879280ae..d4d67af45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,58 @@ # Changelog +## 0.116.0 (2026-01-26) + +Full Changelog: [v0.115.0...v0.116.0](https://github.com/lithic-com/lithic-java/compare/v0.115.0...v0.116.0) + +### Features + +* **api:** Add card.updated event ([08c0ec5](https://github.com/lithic-com/lithic-java/commit/08c0ec5b07c9904a446496fbef297c3958b33adf)) +* **api:** Add idempotency key to cards POST and PATCH endpoints ([e4de24f](https://github.com/lithic-com/lithic-java/commit/e4de24f1c5a533c8d8074fac447d64236d276dc4)) +* **api:** Add tags field to card transactions ([746ee7f](https://github.com/lithic-com/lithic-java/commit/746ee7fd9f55ea61a20c2d14f2486036b7d6211a)) +* **api:** make filter optional for Spend Velocity Auth Rules ([6122ecc](https://github.com/lithic-com/lithic-java/commit/6122eccf30d48db7aaba2fd6f8e94bf76fc7ceb4)) +* **client:** send `X-Stainless-Kotlin-Version` header ([aa06e8d](https://github.com/lithic-com/lithic-java/commit/aa06e8dc2309292773fbd45a3f655709f3bdf550)) + + +### Bug Fixes + +* **api:** Correct field name from ach_hold__period to ach_hold_period ([e9f3ae9](https://github.com/lithic-com/lithic-java/commit/e9f3ae9d5e5797a6458138d27e3b7a21fee0e9bd)) +* **api:** mark AppleWebPushProvisioningResponse fields required ([464fcae](https://github.com/lithic-com/lithic-java/commit/464fcaeefe3040303874976e8746601fb1d2cb0b)) +* **api:** rename WIRE_DRAWDOWN_REQUEST to WIRE_INBOUND_DRAWDOWN_REQUEST ([6122ecc](https://github.com/lithic-com/lithic-java/commit/6122eccf30d48db7aaba2fd6f8e94bf76fc7ceb4)) +* **client:** disallow coercion from float to int ([126f812](https://github.com/lithic-com/lithic-java/commit/126f8126438b97c2cc516aba5d85bf4abbe08352)) +* **client:** fully respect max retries ([bd0a9da](https://github.com/lithic-com/lithic-java/commit/bd0a9da6fc8e2d9b4ed83a0c16b9e9afd5ceb42a)) +* **client:** preserve time zone in lenient date-time parsing ([b82b025](https://github.com/lithic-com/lithic-java/commit/b82b025bc29fc0454d1db1f790185309548cb4f0)) +* **client:** send retry count header for max retries 0 ([bd0a9da](https://github.com/lithic-com/lithic-java/commit/bd0a9da6fc8e2d9b4ed83a0c16b9e9afd5ceb42a)) +* date time deserialization leniency ([ad467a4](https://github.com/lithic-com/lithic-java/commit/ad467a4ae4e51a2dfd5e9b7be5800ae9d4ca56fc)) +* deserialization order ([0e39fef](https://github.com/lithic-com/lithic-java/commit/0e39fefef9ef8651a56b5689e24e7965be4fbcbf)) + + +### Chores + +* Add spec linter for YAML and folded style multiline strings ([b437e45](https://github.com/lithic-com/lithic-java/commit/b437e45c988dfb6b2844b2d02ca397b2688d3521)) +* **ci:** upgrade `actions/github-script` ([ccebfa3](https://github.com/lithic-com/lithic-java/commit/ccebfa38275538c52ef8c62041351abc1ec68c27)) +* **ci:** upgrade `actions/setup-java` ([4e7e0b2](https://github.com/lithic-com/lithic-java/commit/4e7e0b23375dcad5eda7626fd6f5dc83d774f4b7)) +* configure new SDK language ([3dc7d3f](https://github.com/lithic-com/lithic-java/commit/3dc7d3f2903edec88f307dfa5d17e6b5f377e3f0)) +* fix build error ([d9046f9](https://github.com/lithic-com/lithic-java/commit/d9046f9a5eca4e5d4b8964c70a1c2144941d9b6a)) +* fix build error ([ee7c05b](https://github.com/lithic-com/lithic-java/commit/ee7c05b2ab02d8cef3e3283ef2b4a1007d997e95)) +* fix test ([29f6004](https://github.com/lithic-com/lithic-java/commit/29f6004a8cbba567f64ce4f0f681d4d5c7ef94f3)) +* **internal:** clean up maven repo artifact script and add html documentation to repo root ([7838ba8](https://github.com/lithic-com/lithic-java/commit/7838ba8e1c5a14df27507a5aa6b7fb6444531a98)) +* **internal:** codegen related update ([4373405](https://github.com/lithic-com/lithic-java/commit/437340526d2b30ef5f07989118dfef51360dfa0c)) +* **internal:** codegen related update ([6b3f7ee](https://github.com/lithic-com/lithic-java/commit/6b3f7ee38b9f387e28cce9d19d5fec3a6718cfbf)) +* **internal:** correct cache invalidation for `SKIP_MOCK_TESTS` ([ad49965](https://github.com/lithic-com/lithic-java/commit/ad49965c5aad1d8d310cd5fc47a15557d2aa1aa6)) +* **internal:** depend on packages directly in example ([bd0a9da](https://github.com/lithic-com/lithic-java/commit/bd0a9da6fc8e2d9b4ed83a0c16b9e9afd5ceb42a)) +* **internal:** improve maven repo docs ([737c025](https://github.com/lithic-com/lithic-java/commit/737c025a59820d23176d4e45c50f9ab0781a791c)) +* **internal:** support uploading Maven repo artifacts to stainless package server ([da51092](https://github.com/lithic-com/lithic-java/commit/da510920d18bdd6b4e2a655755e9fe21f145bf9f)) +* **internal:** update `actions/checkout` version ([6764fb4](https://github.com/lithic-com/lithic-java/commit/6764fb4c842d48cffa5a6742f4c0a9ef132e0329)) +* **internal:** update maven repo doc to include authentication ([00cccfb](https://github.com/lithic-com/lithic-java/commit/00cccfb7f68e4216728dd54d98f1de1deaab35ed)) +* Rework event type generation to support spec splitting ([bb604fb](https://github.com/lithic-com/lithic-java/commit/bb604fbee3a368cfbe5c4e132f5974b691121255)) +* test on Jackson 2.14.0 to avoid encountering FasterXML/jackson-databind[#3240](https://github.com/lithic-com/lithic-java/issues/3240) in tests ([ad467a4](https://github.com/lithic-com/lithic-java/commit/ad467a4ae4e51a2dfd5e9b7be5800ae9d4ca56fc)) + + +### Documentation + +* add comment for arbitrary value fields ([da7b625](https://github.com/lithic-com/lithic-java/commit/da7b625d33dd3b68d657fbe34fd41e0b6f0aa564)) +* Remove deprecated tag from MERCHANT_LOCKED card type ([5bf8022](https://github.com/lithic-com/lithic-java/commit/5bf802286350906c6b6c27de3987bcce86a0090c)) + ## 0.115.0 (2026-01-08) Full Changelog: [v0.114.0...v0.115.0](https://github.com/lithic-com/lithic-java/compare/v0.114.0...v0.115.0) diff --git a/README.md b/README.md index 234c6d0f2..7829b8532 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.115.0) -[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/0.115.0/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.115.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.116.0) +[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/0.116.0/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.116.0) @@ -13,7 +13,7 @@ The Lithic Java SDK is similar to the Lithic Kotlin SDK but with minor differenc -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.115.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.116.0). @@ -24,7 +24,7 @@ The REST API documentation can be found on [docs.lithic.com](https://docs.lithic ### Gradle ```kotlin -implementation("com.lithic.api:lithic-java:0.115.0") +implementation("com.lithic.api:lithic-java:0.116.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.lithic.api:lithic-java:0.115.0") com.lithic.api lithic-java - 0.115.0 + 0.116.0 ``` @@ -416,6 +416,8 @@ If the SDK threw an exception, but you're _certain_ the version is compatible, t > [!CAUTION] > We make no guarantee that the SDK works correctly when the Jackson version check is disabled. +Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead. + ## Network options ### Retries diff --git a/build.gradle.kts b/build.gradle.kts index 1c30b48af..72a101ec2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.lithic.api" - version = "0.115.0" // x-release-please-version + version = "0.116.0" // x-release-please-version } subprojects { diff --git a/buildSrc/src/main/kotlin/lithic.kotlin.gradle.kts b/buildSrc/src/main/kotlin/lithic.kotlin.gradle.kts index 911f27dd7..e09a84b24 100644 --- a/buildSrc/src/main/kotlin/lithic.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/lithic.kotlin.gradle.kts @@ -33,6 +33,9 @@ kotlin { tasks.withType().configureEach { systemProperty("junit.jupiter.execution.parallel.enabled", true) systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") + + // `SKIP_MOCK_TESTS` affects which tests run so it must be added as input for proper cache invalidation. + inputs.property("skipMockTests", System.getenv("SKIP_MOCK_TESTS")).optional(true) } val ktfmt by configurations.creating diff --git a/buildSrc/src/main/kotlin/lithic.publish.gradle.kts b/buildSrc/src/main/kotlin/lithic.publish.gradle.kts index e5ca4e7e8..bda852fea 100644 --- a/buildSrc/src/main/kotlin/lithic.publish.gradle.kts +++ b/buildSrc/src/main/kotlin/lithic.publish.gradle.kts @@ -7,6 +7,17 @@ plugins { id("com.vanniktech.maven.publish") } +publishing { + repositories { + if (project.hasProperty("publishLocal")) { + maven { + name = "LocalFileSystem" + url = uri("${rootProject.layout.buildDirectory.get()}/local-maven-repo") + } + } + } +} + repositories { gradlePluginPortal() mavenCentral() @@ -17,8 +28,10 @@ extra["signingInMemoryKeyId"] = System.getenv("GPG_SIGNING_KEY_ID") extra["signingInMemoryKeyPassword"] = System.getenv("GPG_SIGNING_PASSWORD") configure { - signAllPublications() - publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) + if (!project.hasProperty("publishLocal")) { + signAllPublications() + publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) + } coordinates(project.group.toString(), project.name, project.version.toString()) configure( diff --git a/examples/.keep b/examples/.keep deleted file mode 100644 index d8c73e937..000000000 --- a/examples/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store example files demonstrating usage of this SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClient.kt b/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClient.kt index 1eb00e26b..ac00e64a5 100644 --- a/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClient.kt +++ b/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClient.kt @@ -18,6 +18,7 @@ import java.time.Clock import java.time.Duration import java.util.Optional import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -46,11 +47,31 @@ class LithicOkHttpClient private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + /** + * Alias for calling [Builder.dispatcherExecutorService] with + * `dispatcherExecutorService.orElse(null)`. + */ + fun dispatcherExecutorService(dispatcherExecutorService: Optional) = + dispatcherExecutorService(dispatcherExecutorService.getOrNull()) + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ @@ -323,6 +344,7 @@ class LithicOkHttpClient private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClientAsync.kt b/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClientAsync.kt index 0f0acb3ed..aebe796ed 100644 --- a/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClientAsync.kt +++ b/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/LithicOkHttpClientAsync.kt @@ -18,6 +18,7 @@ import java.time.Clock import java.time.Duration import java.util.Optional import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -46,11 +47,31 @@ class LithicOkHttpClientAsync private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + /** + * Alias for calling [Builder.dispatcherExecutorService] with + * `dispatcherExecutorService.orElse(null)`. + */ + fun dispatcherExecutorService(dispatcherExecutorService: Optional) = + dispatcherExecutorService(dispatcherExecutorService.getOrNull()) + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ @@ -323,6 +344,7 @@ class LithicOkHttpClientAsync private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/OkHttpClient.kt b/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/OkHttpClient.kt index 1b37107b8..02e255154 100644 --- a/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/OkHttpClient.kt +++ b/lithic-java-client-okhttp/src/main/kotlin/com/lithic/api/client/okhttp/OkHttpClient.kt @@ -15,11 +15,13 @@ import java.net.Proxy import java.time.Duration import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager import okhttp3.Call import okhttp3.Callback +import okhttp3.Dispatcher import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -198,6 +200,7 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien private var timeout: Timeout = Timeout.default() private var proxy: Proxy? = null + private var dispatcherExecutorService: ExecutorService? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null @@ -208,6 +211,10 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { this.sslSocketFactory = sslSocketFactory } @@ -223,12 +230,16 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien fun build(): OkHttpClient = OkHttpClient( okhttp3.OkHttpClient.Builder() + // `RetryingHttpClient` handles retries if the user enabled them. + .retryOnConnectionFailure(false) .connectTimeout(timeout.connect()) .readTimeout(timeout.read()) .writeTimeout(timeout.write()) .callTimeout(timeout.request()) .proxy(proxy) .apply { + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } + val sslSocketFactory = sslSocketFactory val trustManager = trustManager if (sslSocketFactory != null && trustManager != null) { diff --git a/lithic-java-core/build.gradle.kts b/lithic-java-core/build.gradle.kts index 477ecb78f..151c17eb0 100644 --- a/lithic-java-core/build.gradle.kts +++ b/lithic-java-core/build.gradle.kts @@ -5,14 +5,16 @@ plugins { configurations.all { resolutionStrategy { - // Compile and test against a lower Jackson version to ensure we're compatible with it. - // We publish with a higher version (see below) to ensure users depend on a secure version by default. - force("com.fasterxml.jackson.core:jackson-core:2.13.4") - force("com.fasterxml.jackson.core:jackson-databind:2.13.4") - force("com.fasterxml.jackson.core:jackson-annotations:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4") - force("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + // Compile and test against a lower Jackson version to ensure we're compatible with it. Note that + // we generally support 2.13.4, but test against 2.14.0 because 2.13.4 has some annoying (but + // niche) bugs (users should upgrade if they encounter them). We publish with a higher version + // (see below) to ensure users depend on a secure version by default. + force("com.fasterxml.jackson.core:jackson-core:2.14.0") + force("com.fasterxml.jackson.core:jackson-databind:2.14.0") + force("com.fasterxml.jackson.core:jackson-annotations:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0") + force("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/core/ClientOptions.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/core/ClientOptions.kt index 0db2163ff..87d897b8b 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/core/ClientOptions.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/core/ClientOptions.kt @@ -475,6 +475,7 @@ private constructor( headers.put("X-Stainless-Package-Version", getPackageVersion()) headers.put("X-Stainless-Runtime", "JRE") headers.put("X-Stainless-Runtime-Version", getJavaVersion()) + headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString()) apiKey.let { if (!it.isEmpty()) { headers.put("Authorization", it) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/core/ObjectMappers.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/core/ObjectMappers.kt index 1154cadf6..c40847243 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/core/ObjectMappers.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/core/ObjectMappers.kt @@ -25,7 +25,7 @@ import java.time.DateTimeException import java.time.LocalDate import java.time.LocalDateTime import java.time.OffsetDateTime -import java.time.ZonedDateTime +import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField @@ -37,7 +37,6 @@ fun jsonMapper(): JsonMapper = .addModule( SimpleModule() .addSerializer(InputStreamSerializer) - .addDeserializer(LocalDateTime::class.java, LenientLocalDateTimeDeserializer()) .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer()) ) .withCoercionConfig(LogicalType.Boolean) { @@ -49,6 +48,7 @@ fun jsonMapper(): JsonMapper = } .withCoercionConfig(LogicalType.Integer) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) .setCoercion(CoercionInputShape.String, CoercionAction.Fail) .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) @@ -66,6 +66,12 @@ fun jsonMapper(): JsonMapper = .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) } + .withCoercionConfig(LogicalType.DateTime) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } .withCoercionConfig(LogicalType.Array) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -126,10 +132,10 @@ private object InputStreamSerializer : BaseSerializer(InputStream:: } /** - * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes. + * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes. */ -private class LenientLocalDateTimeDeserializer : - StdDeserializer(LocalDateTime::class.java) { +private class LenientOffsetDateTimeDeserializer : + StdDeserializer(OffsetDateTime::class.java) { companion object { @@ -143,7 +149,7 @@ private class LenientLocalDateTimeDeserializer : override fun logicalType(): LogicalType = LogicalType.DateTime - override fun deserialize(p: JsonParser, context: DeserializationContext?): LocalDateTime { + override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime { val exceptions = mutableListOf() for (formatter in DATE_TIME_FORMATTERS) { @@ -152,44 +158,19 @@ private class LenientLocalDateTimeDeserializer : return when { !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> - LocalDate.from(temporal).atStartOfDay() + LocalDate.from(temporal) + .atStartOfDay() + .atZone(ZoneId.of("UTC")) + .toOffsetDateTime() !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> - LocalDateTime.from(temporal) - else -> ZonedDateTime.from(temporal).toLocalDateTime() + LocalDateTime.from(temporal).atZone(ZoneId.of("UTC")).toOffsetDateTime() + else -> OffsetDateTime.from(temporal) } } catch (e: DateTimeException) { exceptions.add(e) } } - throw JsonParseException(p, "Cannot parse `LocalDateTime` from value: ${p.text}").apply { - exceptions.forEach { addSuppressed(it) } - } - } -} - -/** - * A deserializer that can deserialize [OffsetDateTime], assuming UTC when a timezone isn't given. - */ -private class LenientOffsetDateTimeDeserializer : - StdDeserializer(OffsetDateTime::class.java) { - override fun logicalType(): LogicalType = LogicalType.DateTime - - override fun deserialize(p: JsonParser, context: DeserializationContext?): OffsetDateTime { - val exceptions = mutableListOf() - - try { - return OffsetDateTime.parse(p.text) - } catch (e: DateTimeException) { - exceptions.add(e) - } - - try { - return OffsetDateTime.parse(p.text + 'Z') - } catch (e: DateTimeException) { - exceptions.add(e) - } - throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply { exceptions.forEach { addSuppressed(it) } } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt index e9c964004..5d2ac94fa 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt @@ -31,10 +31,6 @@ private constructor( ) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.execute(request, requestOptions) - } - var modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -48,6 +44,10 @@ private constructor( modifiedRequest = setRetryCountHeader(modifiedRequest, retries) } + if (!isRetryable(modifiedRequest)) { + return httpClient.execute(modifiedRequest, requestOptions) + } + val response = try { val response = httpClient.execute(modifiedRequest, requestOptions) @@ -75,10 +75,6 @@ private constructor( request: HttpRequest, requestOptions: RequestOptions, ): CompletableFuture { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.executeAsync(request, requestOptions) - } - val modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -94,8 +90,12 @@ private constructor( val requestWithRetryCount = if (shouldSendRetryCount) setRetryCountHeader(request, retries) else request - return httpClient - .executeAsync(requestWithRetryCount, requestOptions) + val responseFuture = httpClient.executeAsync(requestWithRetryCount, requestOptions) + if (!isRetryable(requestWithRetryCount)) { + return responseFuture + } + + return responseFuture .handleAsync( fun( response: HttpResponse?, 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 24b758684..93a1516f1 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 @@ -1732,6 +1732,7 @@ private constructor( private val result: JsonField, private val settledAmount: JsonField, private val status: JsonField, + private val tags: JsonField, private val tokenInfo: JsonField, private val updated: JsonField, private val events: JsonField>, @@ -1802,6 +1803,9 @@ private constructor( @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("tags") + @ExcludeMissing + tags: JsonField = JsonMissing.of(), @JsonProperty("token_info") @ExcludeMissing tokenInfo: JsonField = JsonMissing.of(), @@ -1836,6 +1840,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -1868,6 +1873,7 @@ private constructor( .result(result) .settledAmount(settledAmount) .status(status) + .tags(tags) .tokenInfo(tokenInfo) .updated(updated) .events(events) @@ -2066,6 +2072,15 @@ private constructor( */ fun status(): Transaction.Status = status.getRequired("status") + /** + * 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tags(): Transaction.Tags = tags.getRequired("tags") + /** * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -2308,6 +2323,13 @@ private constructor( @ExcludeMissing fun _status(): JsonField = status + /** + * 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 [tokenInfo]. * @@ -2382,6 +2404,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * .family() @@ -2416,6 +2439,7 @@ private constructor( private var result: JsonField? = null private var settledAmount: JsonField? = null private var status: JsonField? = null + private var tags: JsonField? = null private var tokenInfo: JsonField? = null private var updated: JsonField? = null private var events: JsonField>? = null @@ -2447,6 +2471,7 @@ private constructor( result = cardTransaction.result settledAmount = cardTransaction.settledAmount status = cardTransaction.status + tags = cardTransaction.tags tokenInfo = cardTransaction.tokenInfo updated = cardTransaction.updated events = cardTransaction.events.map { it.toMutableList() } @@ -2902,6 +2927,21 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata + * with a resource for your own purposes. + */ + fun tags(tags: Transaction.Tags) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed [Transaction.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 tokenInfo(tokenInfo: TokenInfo?) = tokenInfo(JsonField.ofNullable(tokenInfo)) /** Alias for calling [Builder.tokenInfo] with `tokenInfo.orElse(null)`. */ @@ -3014,6 +3054,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * .family() @@ -3046,6 +3087,7 @@ private constructor( checkRequired("result", result), checkRequired("settledAmount", settledAmount), checkRequired("status", status), + checkRequired("tags", tags), checkRequired("tokenInfo", tokenInfo), checkRequired("updated", updated), (events ?: JsonMissing.of()).map { it.toImmutable() }, @@ -3084,6 +3126,7 @@ private constructor( result().validate() settledAmount() status().validate() + tags().validate() tokenInfo().ifPresent { it.validate() } updated() events().ifPresent { it.forEach { it.validate() } } @@ -3130,6 +3173,7 @@ private constructor( (result.asKnown().getOrNull()?.validity() ?: 0) + (if (settledAmount.asKnown().isPresent) 1 else 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.validity() ?: 0) + (tokenInfo.asKnown().getOrNull()?.validity() ?: 0) + (if (updated.asKnown().isPresent) 1 else 0) + (events.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + @@ -3446,6 +3490,7 @@ private constructor( result == other.result && settledAmount == other.settledAmount && status == other.status && + tags == other.tags && tokenInfo == other.tokenInfo && updated == other.updated && events == other.events && @@ -3478,6 +3523,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -3489,6 +3535,6 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "CardTransaction{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tokenInfo=$tokenInfo, updated=$updated, events=$events, family=$family, additionalProperties=$additionalProperties}" + "CardTransaction{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tags=$tags, tokenInfo=$tokenInfo, updated=$updated, events=$events, family=$family, additionalProperties=$additionalProperties}" } } 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 fd6f20446..8691ebef3 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 @@ -1754,6 +1754,7 @@ private constructor( private val result: JsonField, private val settledAmount: JsonField, private val status: JsonField, + private val tags: JsonField, private val tokenInfo: JsonField, private val updated: JsonField, private val events: JsonField>, @@ -1824,6 +1825,9 @@ private constructor( @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("tags") + @ExcludeMissing + tags: JsonField = JsonMissing.of(), @JsonProperty("token_info") @ExcludeMissing tokenInfo: JsonField = JsonMissing.of(), @@ -1858,6 +1862,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -1890,6 +1895,7 @@ private constructor( .result(result) .settledAmount(settledAmount) .status(status) + .tags(tags) .tokenInfo(tokenInfo) .updated(updated) .events(events) @@ -2088,6 +2094,15 @@ private constructor( */ fun status(): Transaction.Status = status.getRequired("status") + /** + * 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tags(): Transaction.Tags = tags.getRequired("tags") + /** * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -2330,6 +2345,13 @@ private constructor( @ExcludeMissing fun _status(): JsonField = status + /** + * 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 [tokenInfo]. * @@ -2404,6 +2426,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * .family() @@ -2438,6 +2461,7 @@ private constructor( private var result: JsonField? = null private var settledAmount: JsonField? = null private var status: JsonField? = null + private var tags: JsonField? = null private var tokenInfo: JsonField? = null private var updated: JsonField? = null private var events: JsonField>? = null @@ -2469,6 +2493,7 @@ private constructor( result = cardTransaction.result settledAmount = cardTransaction.settledAmount status = cardTransaction.status + tags = cardTransaction.tags tokenInfo = cardTransaction.tokenInfo updated = cardTransaction.updated events = cardTransaction.events.map { it.toMutableList() } @@ -2924,6 +2949,21 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata + * with a resource for your own purposes. + */ + fun tags(tags: Transaction.Tags) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed [Transaction.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 tokenInfo(tokenInfo: TokenInfo?) = tokenInfo(JsonField.ofNullable(tokenInfo)) /** Alias for calling [Builder.tokenInfo] with `tokenInfo.orElse(null)`. */ @@ -3036,6 +3076,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * .family() @@ -3068,6 +3109,7 @@ private constructor( checkRequired("result", result), checkRequired("settledAmount", settledAmount), checkRequired("status", status), + checkRequired("tags", tags), checkRequired("tokenInfo", tokenInfo), checkRequired("updated", updated), (events ?: JsonMissing.of()).map { it.toImmutable() }, @@ -3106,6 +3148,7 @@ private constructor( result().validate() settledAmount() status().validate() + tags().validate() tokenInfo().ifPresent { it.validate() } updated() events().ifPresent { it.forEach { it.validate() } } @@ -3152,6 +3195,7 @@ private constructor( (result.asKnown().getOrNull()?.validity() ?: 0) + (if (settledAmount.asKnown().isPresent) 1 else 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.validity() ?: 0) + (tokenInfo.asKnown().getOrNull()?.validity() ?: 0) + (if (updated.asKnown().isPresent) 1 else 0) + (events.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + @@ -3468,6 +3512,7 @@ private constructor( result == other.result && settledAmount == other.settledAmount && status == other.status && + tags == other.tags && tokenInfo == other.tokenInfo && updated == other.updated && events == other.events && @@ -3500,6 +3545,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -3511,6 +3557,6 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "CardTransaction{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tokenInfo=$tokenInfo, updated=$updated, events=$events, family=$family, additionalProperties=$additionalProperties}" + "CardTransaction{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tags=$tags, tokenInfo=$tokenInfo, updated=$updated, events=$events, family=$family, additionalProperties=$additionalProperties}" } } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Card.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Card.kt index 086c5724d..605ca9af2 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Card.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Card.kt @@ -279,10 +279,10 @@ private constructor( * wallet like Apple Pay or Google Pay (if the card program is digital wallet-enabled). * * `PHYSICAL` - Manufactured and sent to the cardholder. We offer white label branding, credit, * ATM, PIN debit, chip/EMV, NFC and magstripe functionality. * `SINGLE_USE` - Card is closed - * upon first successful authorization. * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to - * the first merchant that successfully authorizes the card. * `UNLOCKED` - *[Deprecated]* - * Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * `DIGITAL_WALLET` - - * *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL instead. + * upon first successful authorization. * `MERCHANT_LOCKED` - Card is locked to the first + * merchant that successfully authorizes the card. * `UNLOCKED` - *[Deprecated]* Similar + * behavior to VIRTUAL cards, please use VIRTUAL instead. * `DIGITAL_WALLET` - *[Deprecated]* + * Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * * @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). @@ -936,8 +936,8 @@ private constructor( * wallet-enabled). * `PHYSICAL` - Manufactured and sent to the cardholder. We offer white * label branding, credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. * * `SINGLE_USE` - Card is closed upon first successful authorization. * `MERCHANT_LOCKED` - - * *[Deprecated]* Card is locked to the first merchant that successfully authorizes the - * card. * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL + * Card is locked to the first merchant that successfully authorizes the card. * + * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please * use VIRTUAL instead. */ diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrder.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrder.kt index 46e3f2d7e..7de48325a 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrder.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrder.kt @@ -103,7 +103,14 @@ private constructor( */ fun customerProductId(): Optional = customerProductId.getOptional("customer_product_id") - /** Shipping address for all cards in this bulk order */ + /** + * Shipping address for all cards in this bulk order + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = cardBulkOrder.shippingAddress().convert(MyClass.class); + * ``` + */ @JsonProperty("shipping_address") @ExcludeMissing fun _shippingAddress(): JsonValue = shippingAddress diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrderCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrderCreateParams.kt index d285b23c5..98a6abe3f 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrderCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardBulkOrderCreateParams.kt @@ -43,7 +43,14 @@ private constructor( */ fun customerProductId(): String = body.customerProductId() - /** Shipping address for all cards in this bulk order */ + /** + * Shipping address for all cards in this bulk order + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = cardBulkOrderCreateParams.shippingAddress().convert(MyClass.class); + * ``` + */ fun _shippingAddress(): JsonValue = body._shippingAddress() /** @@ -340,7 +347,14 @@ private constructor( */ fun customerProductId(): String = customerProductId.getRequired("customer_product_id") - /** Shipping address for all cards in this bulk order */ + /** + * Shipping address for all cards in this bulk order + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = createBulkOrderRequest.shippingAddress().convert(MyClass.class); + * ``` + */ @JsonProperty("shipping_address") @ExcludeMissing fun _shippingAddress(): JsonValue = shippingAddress diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardCreateParams.kt index dfb0bfaa2..552485e71 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardCreateParams.kt @@ -27,11 +27,14 @@ import kotlin.jvm.optionals.getOrNull */ class CardCreateParams private constructor( + private val idempotencyKey: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + /** * Card types: * * `VIRTUAL` - Card will authorize at any merchant and can be added to a digital wallet like @@ -40,8 +43,8 @@ private constructor( * credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. Reach out at * [lithic.com/contact](https://lithic.com/contact) for more information. * * `SINGLE_USE` - Card is closed upon first successful authorization. - * * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to the first merchant that successfully - * authorizes the card. + * * `MERCHANT_LOCKED` - Card is locked to the first merchant that successfully authorizes the + * card. * * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. @@ -437,17 +440,25 @@ private constructor( /** A builder for [CardCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(cardCreateParams: CardCreateParams) = apply { + idempotencyKey = cardCreateParams.idempotencyKey body = cardCreateParams.body.toBuilder() additionalHeaders = cardCreateParams.additionalHeaders.toBuilder() additionalQueryParams = cardCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + /** * Sets the entire request body. * @@ -470,8 +481,8 @@ private constructor( * credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. Reach out at * [lithic.com/contact](https://lithic.com/contact) for more information. * * `SINGLE_USE` - Card is closed upon first successful authorization. - * * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to the first merchant that - * successfully authorizes the card. + * * `MERCHANT_LOCKED` - Card is locked to the first merchant that successfully authorizes + * the card. * * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. * * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL @@ -974,12 +985,23 @@ private constructor( * @throws IllegalStateException if any required field is unset. */ fun build(): CardCreateParams = - CardCreateParams(body.build(), additionalHeaders.build(), additionalQueryParams.build()) + CardCreateParams( + idempotencyKey, + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) } fun _body(): Body = body - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -1091,8 +1113,8 @@ private constructor( * credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. Reach out at * [lithic.com/contact](https://lithic.com/contact) for more information. * * `SINGLE_USE` - Card is closed upon first successful authorization. - * * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to the first merchant that - * successfully authorizes the card. + * * `MERCHANT_LOCKED` - Card is locked to the first merchant that successfully authorizes + * the card. * * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. * * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL @@ -1586,8 +1608,8 @@ private constructor( * branding, credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. Reach * out at [lithic.com/contact](https://lithic.com/contact) for more information. * * `SINGLE_USE` - Card is closed upon first successful authorization. - * * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to the first merchant that - * successfully authorizes the card. + * * `MERCHANT_LOCKED` - Card is locked to the first merchant that successfully + * authorizes the card. * * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. * * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use @@ -2164,8 +2186,8 @@ private constructor( * credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. Reach out at * [lithic.com/contact](https://lithic.com/contact) for more information. * * `SINGLE_USE` - Card is closed upon first successful authorization. - * * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to the first merchant that successfully - * authorizes the card. + * * `MERCHANT_LOCKED` - Card is locked to the first merchant that successfully authorizes the + * card. * * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. @@ -2835,13 +2857,15 @@ private constructor( } return other is CardCreateParams && + idempotencyKey == other.idempotencyKey && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + override fun hashCode(): Int = + Objects.hash(idempotencyKey, body, additionalHeaders, additionalQueryParams) override fun toString() = - "CardCreateParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "CardCreateParams{idempotencyKey=$idempotencyKey, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardProvisionResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardProvisionResponse.kt index bdbfb8a85..8382e238f 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardProvisionResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardProvisionResponse.kt @@ -364,7 +364,7 @@ private constructor( .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from array). + // all the possible variants (e.g. deserializing from boolean). 0 -> ProvisioningPayload(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the first diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEvent.kt index 56b57bd5d..6b7fce493 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEvent.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEvent.kt @@ -47,6 +47,7 @@ private constructor( private val result: JsonField, private val settledAmount: JsonField, private val status: JsonField, + private val tags: JsonField, private val tokenInfo: JsonField, private val updated: JsonField, private val events: JsonField>, @@ -113,6 +114,7 @@ private constructor( @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField = JsonMissing.of(), @JsonProperty("token_info") @ExcludeMissing tokenInfo: JsonField = JsonMissing.of(), @@ -149,6 +151,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -181,6 +184,7 @@ private constructor( .result(result) .settledAmount(settledAmount) .status(status) + .tags(tags) .tokenInfo(tokenInfo) .updated(updated) .events(events) @@ -378,6 +382,15 @@ private constructor( */ fun status(): Transaction.Status = status.getRequired("status") + /** + * 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tags(): Transaction.Tags = tags.getRequired("tags") + /** * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -612,6 +625,13 @@ private constructor( */ @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + /** + * 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 [tokenInfo]. * @@ -685,6 +705,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * .eventType() @@ -719,6 +740,7 @@ private constructor( private var result: JsonField? = null private var settledAmount: JsonField? = null private var status: JsonField? = null + private var tags: JsonField? = null private var tokenInfo: JsonField? = null private var updated: JsonField? = null private var events: JsonField>? = null @@ -753,6 +775,7 @@ private constructor( result = cardTransactionUpdatedWebhookEvent.result settledAmount = cardTransactionUpdatedWebhookEvent.settledAmount status = cardTransactionUpdatedWebhookEvent.status + tags = cardTransactionUpdatedWebhookEvent.tags tokenInfo = cardTransactionUpdatedWebhookEvent.tokenInfo updated = cardTransactionUpdatedWebhookEvent.updated events = cardTransactionUpdatedWebhookEvent.events.map { it.toMutableList() } @@ -1196,6 +1219,21 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata + * with a resource for your own purposes. + */ + fun tags(tags: Transaction.Tags) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed [Transaction.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 tokenInfo(tokenInfo: TokenInfo?) = tokenInfo(JsonField.ofNullable(tokenInfo)) /** Alias for calling [Builder.tokenInfo] with `tokenInfo.orElse(null)`. */ @@ -1308,6 +1346,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * .eventType() @@ -1340,6 +1379,7 @@ private constructor( checkRequired("result", result), checkRequired("settledAmount", settledAmount), checkRequired("status", status), + checkRequired("tags", tags), checkRequired("tokenInfo", tokenInfo), checkRequired("updated", updated), (events ?: JsonMissing.of()).map { it.toImmutable() }, @@ -1378,6 +1418,7 @@ private constructor( result().validate() settledAmount() status().validate() + tags().validate() tokenInfo().ifPresent { it.validate() } updated() events().ifPresent { it.forEach { it.validate() } } @@ -1423,6 +1464,7 @@ private constructor( (result.asKnown().getOrNull()?.validity() ?: 0) + (if (settledAmount.asKnown().isPresent) 1 else 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.validity() ?: 0) + (tokenInfo.asKnown().getOrNull()?.validity() ?: 0) + (if (updated.asKnown().isPresent) 1 else 0) + (events.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + @@ -1579,6 +1621,7 @@ private constructor( result == other.result && settledAmount == other.settledAmount && status == other.status && + tags == other.tags && tokenInfo == other.tokenInfo && updated == other.updated && events == other.events && @@ -1611,6 +1654,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -1622,5 +1666,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "CardTransactionUpdatedWebhookEvent{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tokenInfo=$tokenInfo, updated=$updated, events=$events, eventType=$eventType, additionalProperties=$additionalProperties}" + "CardTransactionUpdatedWebhookEvent{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tags=$tags, tokenInfo=$tokenInfo, updated=$updated, events=$events, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardUpdatedWebhookEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardUpdatedWebhookEvent.kt new file mode 100644 index 000000000..ee5b33230 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardUpdatedWebhookEvent.kt @@ -0,0 +1,404 @@ +// 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 CardUpdatedWebhookEvent +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val cardToken: JsonField, + private val eventType: JsonField, + private val previousFields: JsonValue, + private val state: 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("previous_fields") + @ExcludeMissing + previousFields: JsonValue = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + ) : this(cardToken, eventType, previousFields, state, mutableMapOf()) + + /** + * The token of the card that 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 previous values of the fields that were updated. + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = cardUpdatedWebhookEvent.previousFields().convert(MyClass.class); + * ``` + */ + @JsonProperty("previous_fields") + @ExcludeMissing + fun _previousFields(): JsonValue = previousFields + + /** + * The current state of the card. + * + * @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(): String = state.getRequired("state") + + /** + * 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 [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + @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 [CardUpdatedWebhookEvent]. + * + * The following fields are required: + * ```java + * .cardToken() + * .eventType() + * .previousFields() + * .state() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CardUpdatedWebhookEvent]. */ + class Builder internal constructor() { + + private var cardToken: JsonField? = null + private var eventType: JsonField? = null + private var previousFields: JsonValue? = null + private var state: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(cardUpdatedWebhookEvent: CardUpdatedWebhookEvent) = apply { + cardToken = cardUpdatedWebhookEvent.cardToken + eventType = cardUpdatedWebhookEvent.eventType + previousFields = cardUpdatedWebhookEvent.previousFields + state = cardUpdatedWebhookEvent.state + additionalProperties = cardUpdatedWebhookEvent.additionalProperties.toMutableMap() + } + + /** The token of the card that 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 previous values of the fields that were updated. */ + fun previousFields(previousFields: JsonValue) = apply { + this.previousFields = previousFields + } + + /** The current state of the card. */ + fun state(state: String) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [String] 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 } + + 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 [CardUpdatedWebhookEvent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .cardToken() + * .eventType() + * .previousFields() + * .state() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CardUpdatedWebhookEvent = + CardUpdatedWebhookEvent( + checkRequired("cardToken", cardToken), + checkRequired("eventType", eventType), + checkRequired("previousFields", previousFields), + checkRequired("state", state), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): CardUpdatedWebhookEvent = apply { + if (validated) { + return@apply + } + + cardToken() + eventType().validate() + state() + 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) + + (if (state.asKnown().isPresent) 1 else 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_UPDATED = of("card.updated") + + @JvmStatic fun of(value: String) = EventType(JsonField.of(value)) + } + + /** An enum containing [EventType]'s known values. */ + enum class Known { + CARD_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_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_UPDATED -> Value.CARD_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_UPDATED -> Known.CARD_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 + + 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() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CardUpdatedWebhookEvent && + cardToken == other.cardToken && + eventType == other.eventType && + previousFields == other.previousFields && + state == other.state && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(cardToken, eventType, previousFields, state, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CardUpdatedWebhookEvent{cardToken=$cardToken, eventType=$eventType, previousFields=$previousFields, state=$state, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardWebProvisionResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardWebProvisionResponse.kt index 687d915ae..28fece954 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardWebProvisionResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/CardWebProvisionResponse.kt @@ -20,6 +20,7 @@ import com.lithic.api.core.JsonField import com.lithic.api.core.JsonMissing import com.lithic.api.core.JsonValue import com.lithic.api.core.allMaxBy +import com.lithic.api.core.checkRequired import com.lithic.api.core.getOrThrow import com.lithic.api.errors.LithicInvalidDataException import java.util.Collections @@ -256,18 +257,18 @@ private constructor( /** * JWS object required for handoff to Apple's script. * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * @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 jws(): Optional = jws.getOptional("jws") + fun jws(): WebPushProvisioningResponseJws = jws.getRequired("jws") /** * A unique identifier for the JWS object. * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * @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(): Optional = state.getOptional("state") + fun state(): String = state.getRequired("state") /** * Returns the raw JSON value of [jws]. @@ -302,6 +303,12 @@ private constructor( /** * Returns a mutable builder for constructing an instance of * [AppleWebPushProvisioningResponse]. + * + * The following fields are required: + * ```java + * .jws() + * .state() + * ``` */ @JvmStatic fun builder() = Builder() } @@ -309,8 +316,8 @@ private constructor( /** A builder for [AppleWebPushProvisioningResponse]. */ class Builder internal constructor() { - private var jws: JsonField = JsonMissing.of() - private var state: JsonField = JsonMissing.of() + private var jws: JsonField? = null + private var state: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -369,9 +376,21 @@ private constructor( * Returns an immutable instance of [AppleWebPushProvisioningResponse]. * * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .jws() + * .state() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ fun build(): AppleWebPushProvisioningResponse = - AppleWebPushProvisioningResponse(jws, state, additionalProperties.toMutableMap()) + AppleWebPushProvisioningResponse( + checkRequired("jws", jws), + checkRequired("state", state), + additionalProperties.toMutableMap(), + ) } private var validated: Boolean = false @@ -381,7 +400,7 @@ private constructor( return@apply } - jws().ifPresent { it.validate() } + jws().validate() state() validated = true } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ConditionalValue.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ConditionalValue.kt index 228c85045..dcaacaad2 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/ConditionalValue.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/ConditionalValue.kt @@ -219,35 +219,25 @@ private constructor( val bestMatches = sequenceOf( - if (node.isNumber) { - tryDeserialize(node, jacksonTypeRef())?.let { - ConditionalValue(number = it, _json = json) - } - } else null, - if (node.isArray) { - tryDeserialize(node, jacksonTypeRef>())?.let { - ConditionalValue(listOfStrings = it, _json = json) - } - } else null, - // Try timestamp before generic string, since timestamps serialize as - // strings - if (node.isTextual) { - tryDeserialize(node, jacksonTypeRef())?.let { - ConditionalValue(timestamp = it, _json = json) - } - } else null, - if (node.isTextual) { - tryDeserialize(node, jacksonTypeRef())?.let { - ConditionalValue(regex = it, _json = json) - } - } else null, + tryDeserialize(node, jacksonTypeRef())?.let { + ConditionalValue(timestamp = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ConditionalValue(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ConditionalValue(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + ConditionalValue(listOfStrings = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } .toList() return when (bestMatches.size) { // This can happen if what we're deserializing is completely incompatible with all - // the possible variants (e.g. deserializing from object). + // the possible variants (e.g. deserializing from boolean). 0 -> ConditionalValue(_json = json) 1 -> bestMatches.single() // If there's more than one match with the highest validity, then use the first 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 25fd19a25..59395bc22 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 @@ -82,6 +82,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval request * is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -280,6 +281,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval * request is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -467,6 +469,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval request * is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -584,6 +587,8 @@ private constructor( @JvmField val CARD_SHIPPED = of("card.shipped") + @JvmField val CARD_UPDATED = of("card.updated") + @JvmField val DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST = of("digital_wallet.tokenization_approval_request") @@ -690,6 +695,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -754,6 +760,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -823,6 +830,7 @@ private constructor( CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED + CARD_UPDATED -> Value.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Value.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Value.DIGITAL_WALLET_TOKENIZATION_RESULT @@ -896,6 +904,7 @@ private constructor( CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED + CARD_UPDATED -> Known.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Known.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Known.DIGITAL_WALLET_TOKENIZATION_RESULT 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 befbe9779..cd560478b 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 @@ -340,6 +340,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval request * is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -457,6 +458,8 @@ private constructor( @JvmField val CARD_SHIPPED = of("card.shipped") + @JvmField val CARD_UPDATED = of("card.updated") + @JvmField val DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST = of("digital_wallet.tokenization_approval_request") @@ -563,6 +566,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -627,6 +631,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -696,6 +701,7 @@ private constructor( CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED + CARD_UPDATED -> Value.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Value.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Value.DIGITAL_WALLET_TOKENIZATION_RESULT @@ -769,6 +775,7 @@ private constructor( CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED + CARD_UPDATED -> Known.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Known.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Known.DIGITAL_WALLET_TOKENIZATION_RESULT 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 15bf5914e..dac8945df 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 @@ -342,6 +342,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval request * is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -459,6 +460,8 @@ private constructor( @JvmField val CARD_SHIPPED = of("card.shipped") + @JvmField val CARD_UPDATED = of("card.updated") + @JvmField val DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST = of("digital_wallet.tokenization_approval_request") @@ -565,6 +568,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -629,6 +633,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -698,6 +703,7 @@ private constructor( CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED + CARD_UPDATED -> Value.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Value.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Value.DIGITAL_WALLET_TOKENIZATION_RESULT @@ -771,6 +777,7 @@ private constructor( CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED + CARD_UPDATED -> Known.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Known.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Known.DIGITAL_WALLET_TOKENIZATION_RESULT 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 9f7a4530d..fb8b9362a 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 @@ -664,6 +664,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval request * is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -781,6 +782,8 @@ private constructor( @JvmField val CARD_SHIPPED = of("card.shipped") + @JvmField val CARD_UPDATED = of("card.updated") + @JvmField val DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST = of("digital_wallet.tokenization_approval_request") @@ -887,6 +890,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -951,6 +955,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -1020,6 +1025,7 @@ private constructor( CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED + CARD_UPDATED -> Value.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Value.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Value.DIGITAL_WALLET_TOKENIZATION_RESULT @@ -1093,6 +1099,7 @@ private constructor( CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED + CARD_UPDATED -> Known.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Known.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Known.DIGITAL_WALLET_TOKENIZATION_RESULT 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 77147dd4a..7781df703 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 @@ -463,6 +463,8 @@ private constructor( @JvmField val CARD_SHIPPED = of("card.shipped") + @JvmField val CARD_UPDATED = of("card.updated") + @JvmField val DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST = of("digital_wallet.tokenization_approval_request") @@ -569,6 +571,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -633,6 +636,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -702,6 +706,7 @@ private constructor( CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED + CARD_UPDATED -> Value.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Value.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Value.DIGITAL_WALLET_TOKENIZATION_RESULT @@ -775,6 +780,7 @@ private constructor( CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED + CARD_UPDATED -> Known.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Known.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Known.DIGITAL_WALLET_TOKENIZATION_RESULT 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 0b45c8ae7..d7b19ebf0 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 @@ -687,6 +687,7 @@ private constructor( * - card.reissued: Occurs when a card is reissued. * - card.renewed: Occurs when a card is renewed. * - card.shipped: Occurs when a card is shipped. + * - card.updated: Occurs when a card is updated. * - digital_wallet.tokenization_approval_request: Occurs when a tokenization approval request * is made. This event will be deprecated in the future. We recommend using * `tokenization.approval_request` instead. @@ -804,6 +805,8 @@ private constructor( @JvmField val CARD_SHIPPED = of("card.shipped") + @JvmField val CARD_UPDATED = of("card.updated") + @JvmField val DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST = of("digital_wallet.tokenization_approval_request") @@ -910,6 +913,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -974,6 +978,7 @@ private constructor( CARD_REISSUED, CARD_RENEWED, CARD_SHIPPED, + CARD_UPDATED, DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST, DIGITAL_WALLET_TOKENIZATION_RESULT, DIGITAL_WALLET_TOKENIZATION_TWO_FACTOR_AUTHENTICATION_CODE, @@ -1043,6 +1048,7 @@ private constructor( CARD_REISSUED -> Value.CARD_REISSUED CARD_RENEWED -> Value.CARD_RENEWED CARD_SHIPPED -> Value.CARD_SHIPPED + CARD_UPDATED -> Value.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Value.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Value.DIGITAL_WALLET_TOKENIZATION_RESULT @@ -1116,6 +1122,7 @@ private constructor( CARD_REISSUED -> Known.CARD_REISSUED CARD_RENEWED -> Known.CARD_RENEWED CARD_SHIPPED -> Known.CARD_SHIPPED + CARD_UPDATED -> Known.CARD_UPDATED DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST -> Known.DIGITAL_WALLET_TOKENIZATION_APPROVAL_REQUEST DIGITAL_WALLET_TOKENIZATION_RESULT -> Known.DIGITAL_WALLET_TOKENIZATION_RESULT diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialTransaction.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialTransaction.kt index d82a2df00..36cb09116 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialTransaction.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialTransaction.kt @@ -132,8 +132,9 @@ private constructor( /** * Pending amount of the transaction in the currency's smallest unit (e.g., cents), including - * any acquirer fees. The value of this field will go to zero over time once the financial - * transaction is settled. + * any acquirer fees. + * + * The value of this field will go to zero over time once the financial transaction is settled. * * @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). @@ -423,8 +424,10 @@ private constructor( /** * Pending amount of the transaction in the currency's smallest unit (e.g., cents), - * including any acquirer fees. The value of this field will go to zero over time once the - * financial transaction is settled. + * including any acquirer fees. + * + * The value of this field will go to zero over time once the financial transaction is + * settled. */ fun pendingAmount(pendingAmount: Long) = pendingAmount(JsonField.of(pendingAmount)) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/NonPciCard.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/NonPciCard.kt index c9a3056f7..b736b2c5a 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/NonPciCard.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/NonPciCard.kt @@ -243,10 +243,10 @@ private constructor( * wallet like Apple Pay or Google Pay (if the card program is digital wallet-enabled). * * `PHYSICAL` - Manufactured and sent to the cardholder. We offer white label branding, credit, * ATM, PIN debit, chip/EMV, NFC and magstripe functionality. * `SINGLE_USE` - Card is closed - * upon first successful authorization. * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to - * the first merchant that successfully authorizes the card. * `UNLOCKED` - *[Deprecated]* - * Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * `DIGITAL_WALLET` - - * *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL instead. + * upon first successful authorization. * `MERCHANT_LOCKED` - Card is locked to the first + * merchant that successfully authorizes the card. * `UNLOCKED` - *[Deprecated]* Similar + * behavior to VIRTUAL cards, please use VIRTUAL instead. * `DIGITAL_WALLET` - *[Deprecated]* + * Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * * @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). @@ -854,8 +854,8 @@ private constructor( * wallet-enabled). * `PHYSICAL` - Manufactured and sent to the cardholder. We offer white * label branding, credit, ATM, PIN debit, chip/EMV, NFC and magstripe functionality. * * `SINGLE_USE` - Card is closed upon first successful authorization. * `MERCHANT_LOCKED` - - * *[Deprecated]* Card is locked to the first merchant that successfully authorizes the - * card. * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL + * Card is locked to the first merchant that successfully authorizes the card. * + * `UNLOCKED` - *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL * instead. * `DIGITAL_WALLET` - *[Deprecated]* Similar behavior to VIRTUAL cards, please * use VIRTUAL instead. */ @@ -2279,10 +2279,10 @@ private constructor( * wallet like Apple Pay or Google Pay (if the card program is digital wallet-enabled). * * `PHYSICAL` - Manufactured and sent to the cardholder. We offer white label branding, credit, * ATM, PIN debit, chip/EMV, NFC and magstripe functionality. * `SINGLE_USE` - Card is closed - * upon first successful authorization. * `MERCHANT_LOCKED` - *[Deprecated]* Card is locked to - * the first merchant that successfully authorizes the card. * `UNLOCKED` - *[Deprecated]* - * Similar behavior to VIRTUAL cards, please use VIRTUAL instead. * `DIGITAL_WALLET` - - * *[Deprecated]* Similar behavior to VIRTUAL cards, please use VIRTUAL instead. + * upon first successful authorization. * `MERCHANT_LOCKED` - Card is locked to the first + * merchant that successfully authorizes the card. * `UNLOCKED` - *[Deprecated]* Similar + * behavior to VIRTUAL cards, please use VIRTUAL instead. * `DIGITAL_WALLET` - *[Deprecated]* + * Similar behavior to VIRTUAL cards, please use VIRTUAL instead. */ class Type @JsonCreator private constructor(private val value: JsonField) : Enum { 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 ef5b9831d..9444b8ad1 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 cardRenewed: CardRenewedWebhookEvent? = null, private val cardReissued: CardReissuedWebhookEvent? = null, private val cardShipped: CardShippedWebhookEvent? = null, + private val cardUpdated: CardUpdatedWebhookEvent? = null, private val cardTransactionUpdated: CardTransactionUpdatedWebhookEvent? = null, private val cardTransactionEnhancedDataCreated: CardTransactionEnhancedDataCreatedWebhookEvent? = @@ -164,6 +165,8 @@ private constructor( fun cardShipped(): Optional = Optional.ofNullable(cardShipped) + fun cardUpdated(): Optional = Optional.ofNullable(cardUpdated) + fun cardTransactionUpdated(): Optional = Optional.ofNullable(cardTransactionUpdated) @@ -334,6 +337,8 @@ private constructor( fun isCardShipped(): Boolean = cardShipped != null + fun isCardUpdated(): Boolean = cardUpdated != null + fun isCardTransactionUpdated(): Boolean = cardTransactionUpdated != null fun isCardTransactionEnhancedDataCreated(): Boolean = cardTransactionEnhancedDataCreated != null @@ -468,6 +473,8 @@ private constructor( fun asCardShipped(): CardShippedWebhookEvent = cardShipped.getOrThrow("cardShipped") + fun asCardUpdated(): CardUpdatedWebhookEvent = cardUpdated.getOrThrow("cardUpdated") + fun asCardTransactionUpdated(): CardTransactionUpdatedWebhookEvent = cardTransactionUpdated.getOrThrow("cardTransactionUpdated") @@ -639,6 +646,7 @@ private constructor( cardRenewed != null -> visitor.visitCardRenewed(cardRenewed) cardReissued != null -> visitor.visitCardReissued(cardReissued) cardShipped != null -> visitor.visitCardShipped(cardShipped) + cardUpdated != null -> visitor.visitCardUpdated(cardUpdated) cardTransactionUpdated != null -> visitor.visitCardTransactionUpdated(cardTransactionUpdated) cardTransactionEnhancedDataCreated != null -> @@ -818,6 +826,10 @@ private constructor( cardShipped.validate() } + override fun visitCardUpdated(cardUpdated: CardUpdatedWebhookEvent) { + cardUpdated.validate() + } + override fun visitCardTransactionUpdated( cardTransactionUpdated: CardTransactionUpdatedWebhookEvent ) { @@ -1138,6 +1150,9 @@ private constructor( override fun visitCardShipped(cardShipped: CardShippedWebhookEvent) = cardShipped.validity() + override fun visitCardUpdated(cardUpdated: CardUpdatedWebhookEvent) = + cardUpdated.validity() + override fun visitCardTransactionUpdated( cardTransactionUpdated: CardTransactionUpdatedWebhookEvent ) = cardTransactionUpdated.validity() @@ -1330,6 +1345,7 @@ private constructor( cardRenewed == other.cardRenewed && cardReissued == other.cardReissued && cardShipped == other.cardShipped && + cardUpdated == other.cardUpdated && cardTransactionUpdated == other.cardTransactionUpdated && cardTransactionEnhancedDataCreated == other.cardTransactionEnhancedDataCreated && cardTransactionEnhancedDataUpdated == other.cardTransactionEnhancedDataUpdated && @@ -1396,6 +1412,7 @@ private constructor( cardRenewed, cardReissued, cardShipped, + cardUpdated, cardTransactionUpdated, cardTransactionEnhancedDataCreated, cardTransactionEnhancedDataUpdated, @@ -1465,6 +1482,7 @@ private constructor( cardRenewed != null -> "ParsedWebhookEvent{cardRenewed=$cardRenewed}" cardReissued != null -> "ParsedWebhookEvent{cardReissued=$cardReissued}" cardShipped != null -> "ParsedWebhookEvent{cardShipped=$cardShipped}" + cardUpdated != null -> "ParsedWebhookEvent{cardUpdated=$cardUpdated}" cardTransactionUpdated != null -> "ParsedWebhookEvent{cardTransactionUpdated=$cardTransactionUpdated}" cardTransactionEnhancedDataCreated != null -> @@ -1626,6 +1644,10 @@ private constructor( fun ofCardShipped(cardShipped: CardShippedWebhookEvent) = ParsedWebhookEvent(cardShipped = cardShipped) + @JvmStatic + fun ofCardUpdated(cardUpdated: CardUpdatedWebhookEvent) = + ParsedWebhookEvent(cardUpdated = cardUpdated) + @JvmStatic fun ofCardTransactionUpdated(cardTransactionUpdated: CardTransactionUpdatedWebhookEvent) = ParsedWebhookEvent(cardTransactionUpdated = cardTransactionUpdated) @@ -1916,6 +1938,8 @@ private constructor( fun visitCardShipped(cardShipped: CardShippedWebhookEvent): T + fun visitCardUpdated(cardUpdated: CardUpdatedWebhookEvent): T + fun visitCardTransactionUpdated( cardTransactionUpdated: CardTransactionUpdatedWebhookEvent ): T @@ -2187,6 +2211,9 @@ private constructor( tryDeserialize(node, jacksonTypeRef())?.let { ParsedWebhookEvent(cardShipped = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + ParsedWebhookEvent(cardUpdated = it, _json = json) + }, tryDeserialize(node, jacksonTypeRef()) ?.let { ParsedWebhookEvent(cardTransactionUpdated = it, _json = json) }, tryDeserialize( @@ -2494,6 +2521,7 @@ private constructor( value.cardRenewed != null -> generator.writeObject(value.cardRenewed) value.cardReissued != null -> generator.writeObject(value.cardReissued) value.cardShipped != null -> generator.writeObject(value.cardShipped) + value.cardUpdated != null -> generator.writeObject(value.cardUpdated) value.cardTransactionUpdated != null -> generator.writeObject(value.cardTransactionUpdated) value.cardTransactionEnhancedDataCreated != null -> 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 5927991a5..f10797765 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 @@ -4769,7 +4769,7 @@ private constructor( @JvmField val WIRE_OUTBOUND_ADMIN = of("WIRE_OUTBOUND_ADMIN") - @JvmField val WIRE_DRAWDOWN_REQUEST = of("WIRE_DRAWDOWN_REQUEST") + @JvmField val WIRE_INBOUND_DRAWDOWN_REQUEST = of("WIRE_INBOUND_DRAWDOWN_REQUEST") @JvmStatic fun of(value: String) = TransferType(JsonField.of(value)) } @@ -4784,7 +4784,7 @@ private constructor( WIRE_INBOUND_ADMIN, WIRE_OUTBOUND_PAYMENT, WIRE_OUTBOUND_ADMIN, - WIRE_DRAWDOWN_REQUEST, + WIRE_INBOUND_DRAWDOWN_REQUEST, } /** @@ -4805,7 +4805,7 @@ private constructor( WIRE_INBOUND_ADMIN, WIRE_OUTBOUND_PAYMENT, WIRE_OUTBOUND_ADMIN, - WIRE_DRAWDOWN_REQUEST, + WIRE_INBOUND_DRAWDOWN_REQUEST, /** * An enum member indicating that [TransferType] was instantiated with an unknown value. */ @@ -4829,7 +4829,7 @@ private constructor( WIRE_INBOUND_ADMIN -> Value.WIRE_INBOUND_ADMIN WIRE_OUTBOUND_PAYMENT -> Value.WIRE_OUTBOUND_PAYMENT WIRE_OUTBOUND_ADMIN -> Value.WIRE_OUTBOUND_ADMIN - WIRE_DRAWDOWN_REQUEST -> Value.WIRE_DRAWDOWN_REQUEST + WIRE_INBOUND_DRAWDOWN_REQUEST -> Value.WIRE_INBOUND_DRAWDOWN_REQUEST else -> Value._UNKNOWN } @@ -4852,7 +4852,7 @@ private constructor( WIRE_INBOUND_ADMIN -> Known.WIRE_INBOUND_ADMIN WIRE_OUTBOUND_PAYMENT -> Known.WIRE_OUTBOUND_PAYMENT WIRE_OUTBOUND_ADMIN -> Known.WIRE_OUTBOUND_ADMIN - WIRE_DRAWDOWN_REQUEST -> Known.WIRE_DRAWDOWN_REQUEST + WIRE_INBOUND_DRAWDOWN_REQUEST -> Known.WIRE_INBOUND_DRAWDOWN_REQUEST else -> throw LithicInvalidDataException("Unknown TransferType: $value") } 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 5c7703b56..1769e7802 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 @@ -1097,7 +1097,7 @@ private constructor( @JsonProperty("sec_code") @ExcludeMissing secCode: JsonField = JsonMissing.of(), - @JsonProperty("ach_hold__period") + @JsonProperty("ach_hold_period") @ExcludeMissing achHoldPeriod: JsonField = JsonMissing.of(), @JsonProperty("addenda") @ExcludeMissing addenda: JsonField = JsonMissing.of(), @@ -1115,7 +1115,7 @@ private constructor( * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ - fun achHoldPeriod(): Optional = achHoldPeriod.getOptional("ach_hold__period") + fun achHoldPeriod(): Optional = achHoldPeriod.getOptional("ach_hold_period") /** * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -1136,7 +1136,7 @@ private constructor( * Unlike [achHoldPeriod], this method doesn't throw if the JSON field has an unexpected * type. */ - @JsonProperty("ach_hold__period") + @JsonProperty("ach_hold_period") @ExcludeMissing fun _achHoldPeriod(): JsonField = achHoldPeriod diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementTotals.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementTotals.kt index cbabdf772..5316d13ce 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementTotals.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementTotals.kt @@ -130,13 +130,34 @@ private constructor( */ fun purchases(): Long = purchases.getRequired("purchases") - /** Breakdown of credits */ + /** + * Breakdown of credits + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = statementTotals.creditDetails().convert(MyClass.class); + * ``` + */ @JsonProperty("credit_details") @ExcludeMissing fun _creditDetails(): JsonValue = creditDetails - /** Breakdown of debits */ + /** + * Breakdown of debits + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = statementTotals.debitDetails().convert(MyClass.class); + * ``` + */ @JsonProperty("debit_details") @ExcludeMissing fun _debitDetails(): JsonValue = debitDetails - /** Breakdown of payments */ + /** + * Breakdown of payments + * + * This arbitrary value can be deserialized into a custom type using the `convert` method: + * ```java + * MyClass myObject = statementTotals.paymentDetails().convert(MyClass.class); + * ``` + */ @JsonProperty("payment_details") @ExcludeMissing fun _paymentDetails(): JsonValue = paymentDetails 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 ca86c905e..1ccc1b31e 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 @@ -47,6 +47,7 @@ private constructor( private val result: JsonField, private val settledAmount: JsonField, private val status: JsonField, + private val tags: JsonField, private val tokenInfo: JsonField, private val updated: JsonField, private val events: JsonField>, @@ -106,6 +107,7 @@ private constructor( @ExcludeMissing settledAmount: JsonField = JsonMissing.of(), @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField = JsonMissing.of(), @JsonProperty("token_info") @ExcludeMissing tokenInfo: JsonField = JsonMissing.of(), @@ -139,6 +141,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -337,6 +340,15 @@ private constructor( */ fun status(): Status = status.getRequired("status") + /** + * 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tags(): Tags = tags.getRequired("tags") + /** * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -557,6 +569,13 @@ private constructor( */ @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + /** + * 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 [tokenInfo]. * @@ -622,6 +641,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * ``` @@ -655,6 +675,7 @@ private constructor( private var result: JsonField? = null private var settledAmount: JsonField? = null private var status: JsonField? = null + private var tags: JsonField? = null private var tokenInfo: JsonField? = null private var updated: JsonField? = null private var events: JsonField>? = null @@ -685,6 +706,7 @@ private constructor( result = transaction.result settledAmount = transaction.settledAmount status = transaction.status + tags = transaction.tags tokenInfo = transaction.tokenInfo updated = transaction.updated events = transaction.events.map { it.toMutableList() } @@ -1120,6 +1142,20 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata + * with a resource for your own purposes. + */ + fun tags(tags: Tags) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed [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 tokenInfo(tokenInfo: TokenInfo?) = tokenInfo(JsonField.ofNullable(tokenInfo)) /** Alias for calling [Builder.tokenInfo] with `tokenInfo.orElse(null)`. */ @@ -1220,6 +1256,7 @@ private constructor( * .result() * .settledAmount() * .status() + * .tags() * .tokenInfo() * .updated() * ``` @@ -1251,6 +1288,7 @@ private constructor( checkRequired("result", result), checkRequired("settledAmount", settledAmount), checkRequired("status", status), + checkRequired("tags", tags), checkRequired("tokenInfo", tokenInfo), checkRequired("updated", updated), (events ?: JsonMissing.of()).map { it.toImmutable() }, @@ -1288,6 +1326,7 @@ private constructor( result().validate() settledAmount() status().validate() + tags().validate() tokenInfo().ifPresent { it.validate() } updated() events().ifPresent { it.forEach { it.validate() } } @@ -1332,6 +1371,7 @@ private constructor( (result.asKnown().getOrNull()?.validity() ?: 0) + (if (settledAmount.asKnown().isPresent) 1 else 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.validity() ?: 0) + (tokenInfo.asKnown().getOrNull()?.validity() ?: 0) + (if (updated.asKnown().isPresent) 1 else 0) + (events.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) @@ -5361,6 +5401,109 @@ private constructor( override fun toString() = value.toString() } + /** + * Key-value pairs for tagging resources. Tags allow you to associate arbitrary metadata with a + * resource for your own purposes. + */ + class Tags + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Tags]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Tags]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(tags: Tags) = apply { + additionalProperties = tags.additionalProperties.toMutableMap() + } + + 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 [Tags]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Tags = Tags(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Tags = apply { + if (validated) { + return@apply + } + + 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 = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tags && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Tags{additionalProperties=$additionalProperties}" + } + class TransactionEvent @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( @@ -11572,6 +11715,7 @@ private constructor( result == other.result && settledAmount == other.settledAmount && status == other.status && + tags == other.tags && tokenInfo == other.tokenInfo && updated == other.updated && events == other.events && @@ -11603,6 +11747,7 @@ private constructor( result, settledAmount, status, + tags, tokenInfo, updated, events, @@ -11613,5 +11758,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Transaction{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tokenInfo=$tokenInfo, updated=$updated, events=$events, additionalProperties=$additionalProperties}" + "Transaction{token=$token, accountToken=$accountToken, acquirerFee=$acquirerFee, acquirerReferenceNumber=$acquirerReferenceNumber, amount=$amount, amounts=$amounts, authorizationAmount=$authorizationAmount, authorizationCode=$authorizationCode, avs=$avs, cardToken=$cardToken, cardholderAuthentication=$cardholderAuthentication, created=$created, financialAccountToken=$financialAccountToken, merchant=$merchant, merchantAmount=$merchantAmount, merchantAuthorizationAmount=$merchantAuthorizationAmount, merchantCurrency=$merchantCurrency, network=$network, networkRiskScore=$networkRiskScore, pos=$pos, result=$result, settledAmount=$settledAmount, status=$status, tags=$tags, tokenInfo=$tokenInfo, updated=$updated, events=$events, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt index 4ec1ed19d..5f98fc8db 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt @@ -23,9 +23,9 @@ import kotlin.jvm.optionals.getOrNull class VelocityLimitParams @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val filters: JsonField, private val period: JsonField, private val scope: JsonField, + private val filters: JsonField, private val limitAmount: JsonField, private val limitCount: JsonField, private val additionalProperties: MutableMap, @@ -33,24 +33,18 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("filters") - @ExcludeMissing - filters: JsonField = JsonMissing.of(), @JsonProperty("period") @ExcludeMissing period: JsonField = JsonMissing.of(), @JsonProperty("scope") @ExcludeMissing scope: JsonField = JsonMissing.of(), + @JsonProperty("filters") + @ExcludeMissing + filters: JsonField = JsonMissing.of(), @JsonProperty("limit_amount") @ExcludeMissing limitAmount: JsonField = JsonMissing.of(), @JsonProperty("limit_count") @ExcludeMissing limitCount: JsonField = JsonMissing.of(), - ) : this(filters, period, scope, limitAmount, limitCount, 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 filters(): VelocityLimitFilters = filters.getRequired("filters") + ) : this(period, scope, filters, limitAmount, limitCount, mutableMapOf()) /** * Velocity over the current day since 00:00 / 12 AM in Eastern Time @@ -68,6 +62,12 @@ private constructor( */ fun scope(): VelocityScope = scope.getRequired("scope") + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun filters(): Optional = filters.getOptional("filters") + /** * The maximum amount of spend velocity allowed in the period in minor units (the smallest unit * of a currency, e.g. cents for USD). Transactions exceeding this limit will be declined. @@ -88,15 +88,6 @@ private constructor( */ fun limitCount(): Optional = limitCount.getOptional("limit_count") - /** - * Returns the raw JSON value of [filters]. - * - * Unlike [filters], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("filters") - @ExcludeMissing - fun _filters(): JsonField = filters - /** * Returns the raw JSON value of [period]. * @@ -111,6 +102,15 @@ private constructor( */ @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + /** + * Returns the raw JSON value of [filters]. + * + * Unlike [filters], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("filters") + @ExcludeMissing + fun _filters(): JsonField = filters + /** * Returns the raw JSON value of [limitAmount]. * @@ -144,7 +144,6 @@ private constructor( * * The following fields are required: * ```java - * .filters() * .period() * .scope() * ``` @@ -155,34 +154,23 @@ private constructor( /** A builder for [VelocityLimitParams]. */ class Builder internal constructor() { - private var filters: JsonField? = null private var period: JsonField? = null private var scope: JsonField? = null + private var filters: JsonField = JsonMissing.of() private var limitAmount: JsonField = JsonMissing.of() private var limitCount: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(velocityLimitParams: VelocityLimitParams) = apply { - filters = velocityLimitParams.filters period = velocityLimitParams.period scope = velocityLimitParams.scope + filters = velocityLimitParams.filters limitAmount = velocityLimitParams.limitAmount limitCount = velocityLimitParams.limitCount additionalProperties = velocityLimitParams.additionalProperties.toMutableMap() } - fun filters(filters: VelocityLimitFilters) = filters(JsonField.of(filters)) - - /** - * Sets [Builder.filters] to an arbitrary JSON value. - * - * You should usually call [Builder.filters] with a well-typed [VelocityLimitFilters] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun filters(filters: JsonField) = apply { this.filters = filters } - /** Velocity over the current day since 00:00 / 12 AM in Eastern Time */ fun period(period: VelocityLimitPeriod) = period(JsonField.of(period)) @@ -239,6 +227,17 @@ private constructor( */ fun scope(scope: JsonField) = apply { this.scope = scope } + fun filters(filters: VelocityLimitFilters) = filters(JsonField.of(filters)) + + /** + * Sets [Builder.filters] to an arbitrary JSON value. + * + * You should usually call [Builder.filters] with a well-typed [VelocityLimitFilters] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun filters(filters: JsonField) = apply { this.filters = filters } + /** * The maximum amount of spend velocity allowed in the period in minor units (the smallest * unit of a currency, e.g. cents for USD). Transactions exceeding this limit will be @@ -317,7 +316,6 @@ private constructor( * * The following fields are required: * ```java - * .filters() * .period() * .scope() * ``` @@ -326,9 +324,9 @@ private constructor( */ fun build(): VelocityLimitParams = VelocityLimitParams( - checkRequired("filters", filters), checkRequired("period", period), checkRequired("scope", scope), + filters, limitAmount, limitCount, additionalProperties.toMutableMap(), @@ -342,9 +340,9 @@ private constructor( return@apply } - filters().validate() period().validate() scope().validate() + filters().ifPresent { it.validate() } limitAmount() limitCount() validated = true @@ -365,12 +363,142 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (filters.asKnown().getOrNull()?.validity() ?: 0) + - (period.asKnown().getOrNull()?.validity() ?: 0) + + (period.asKnown().getOrNull()?.validity() ?: 0) + (scope.asKnown().getOrNull()?.validity() ?: 0) + + (filters.asKnown().getOrNull()?.validity() ?: 0) + (if (limitAmount.asKnown().isPresent) 1 else 0) + (if (limitCount.asKnown().isPresent) 1 else 0) + /** The scope the velocity is calculated for */ + class VelocityScope @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 = of("CARD") + + @JvmField val ACCOUNT = of("ACCOUNT") + + @JvmStatic fun of(value: String) = VelocityScope(JsonField.of(value)) + } + + /** An enum containing [VelocityScope]'s known values. */ + enum class Known { + CARD, + ACCOUNT, + } + + /** + * An enum containing [VelocityScope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [VelocityScope] 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, + ACCOUNT, + /** + * An enum member indicating that [VelocityScope] 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 -> Value.CARD + ACCOUNT -> Value.ACCOUNT + 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 -> Known.CARD + ACCOUNT -> Known.ACCOUNT + else -> throw LithicInvalidDataException("Unknown VelocityScope: $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 + + fun validate(): VelocityScope = 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 VelocityScope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + class VelocityLimitFilters @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( @@ -1037,156 +1165,26 @@ private constructor( "VelocityLimitFilters{excludeCountries=$excludeCountries, excludeMccs=$excludeMccs, includeCountries=$includeCountries, includeMccs=$includeMccs, includePanEntryModes=$includePanEntryModes, additionalProperties=$additionalProperties}" } - /** The scope the velocity is calculated for */ - class VelocityScope @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 = of("CARD") - - @JvmField val ACCOUNT = of("ACCOUNT") - - @JvmStatic fun of(value: String) = VelocityScope(JsonField.of(value)) - } - - /** An enum containing [VelocityScope]'s known values. */ - enum class Known { - CARD, - ACCOUNT, - } - - /** - * An enum containing [VelocityScope]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [VelocityScope] 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, - ACCOUNT, - /** - * An enum member indicating that [VelocityScope] 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 -> Value.CARD - ACCOUNT -> Value.ACCOUNT - 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 -> Known.CARD - ACCOUNT -> Known.ACCOUNT - else -> throw LithicInvalidDataException("Unknown VelocityScope: $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 - - fun validate(): VelocityScope = 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 VelocityScope && 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 VelocityLimitParams && - filters == other.filters && period == other.period && scope == other.scope && + filters == other.filters && limitAmount == other.limitAmount && limitCount == other.limitCount && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(filters, period, scope, limitAmount, limitCount, additionalProperties) + Objects.hash(period, scope, filters, limitAmount, limitCount, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "VelocityLimitParams{filters=$filters, period=$period, scope=$scope, limitAmount=$limitAmount, limitCount=$limitCount, additionalProperties=$additionalProperties}" + "VelocityLimitParams{period=$period, scope=$scope, filters=$filters, limitAmount=$limitAmount, limitCount=$limitCount, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/core/ObjectMappersTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/core/ObjectMappersTest.kt index 3977f5171..154843860 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/core/ObjectMappersTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/core/ObjectMappersTest.kt @@ -3,13 +3,14 @@ package com.lithic.api.core import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.readValue -import java.time.LocalDateTime +import java.time.LocalDate +import java.time.LocalTime import java.time.OffsetDateTime +import java.time.ZoneOffset import kotlin.reflect.KClass import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.catchThrowable import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource import org.junitpioneer.jupiter.cartesian.CartesianTest @@ -47,11 +48,7 @@ internal class ObjectMappersTest { val VALID_CONVERSIONS = listOf( FLOAT to DOUBLE, - FLOAT to INTEGER, - FLOAT to LONG, DOUBLE to FLOAT, - DOUBLE to INTEGER, - DOUBLE to LONG, INTEGER to FLOAT, INTEGER to DOUBLE, INTEGER to LONG, @@ -59,14 +56,6 @@ internal class ObjectMappersTest { LONG to DOUBLE, LONG to INTEGER, CLASS to MAP, - // These aren't actually valid, but coercion configs don't work for String until - // v2.14.0: https://github.com/FasterXML/jackson-databind/issues/3240 - // We currently test on v2.13.4. - BOOLEAN to STRING, - FLOAT to STRING, - DOUBLE to STRING, - INTEGER to STRING, - LONG to STRING, ) } } @@ -85,26 +74,34 @@ internal class ObjectMappersTest { } } - enum class LenientLocalDateTimeTestCase(val string: String) { - DATE("1998-04-21"), - DATE_TIME("1998-04-21T04:00:00"), - ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), - ZONED_DATE_TIME_2("1998-04-21T04:00:00Z"), - } - - @ParameterizedTest - @EnumSource - fun readLocalDateTime_lenient(testCase: LenientLocalDateTimeTestCase) { - val jsonMapper = jsonMapper() - val json = jsonMapper.writeValueAsString(testCase.string) - - assertDoesNotThrow { jsonMapper().readValue(json) } - } - - enum class LenientOffsetDateTimeTestCase(val string: String) { - DATE_TIME("1998-04-21T04:00:00"), - ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), - ZONED_DATE_TIME_2("1998-04-21T04:00:00Z"), + enum class LenientOffsetDateTimeTestCase( + val string: String, + val expectedOffsetDateTime: OffsetDateTime, + ) { + DATE( + "1998-04-21", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(0, 0), ZoneOffset.UTC), + ), + DATE_TIME( + "1998-04-21T04:00:00", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), + ZONED_DATE_TIME_1( + "1998-04-21T04:00:00+03:00", + expectedOffsetDateTime = + OffsetDateTime.of( + LocalDate.of(1998, 4, 21), + LocalTime.of(4, 0), + ZoneOffset.ofHours(3), + ), + ), + ZONED_DATE_TIME_2( + "1998-04-21T04:00:00Z", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), } @ParameterizedTest @@ -113,6 +110,8 @@ internal class ObjectMappersTest { val jsonMapper = jsonMapper() val json = jsonMapper.writeValueAsString(testCase.string) - assertDoesNotThrow { jsonMapper().readValue(json) } + val offsetDateTime = jsonMapper().readValue(json) + + assertThat(offsetDateTime).isEqualTo(testCase.expectedOffsetDateTime) } } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt index 9e26b11e8..13e75cc7c 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt @@ -327,6 +327,11 @@ internal class AccountActivityListResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) .addEvent( @@ -561,6 +566,11 @@ internal class AccountActivityListResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo( TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build() ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt index d632243da..367dcbcdf 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt @@ -354,6 +354,11 @@ internal class AccountActivityRetrieveTransactionResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) .addEvent( @@ -589,6 +594,11 @@ internal class AccountActivityRetrieveTransactionResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo( TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build() ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardCreateParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardCreateParamsTest.kt index d570ffb86..a46f5a6d2 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardCreateParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardCreateParamsTest.kt @@ -2,6 +2,7 @@ package com.lithic.api.models +import com.lithic.api.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -10,6 +11,7 @@ internal class CardCreateParamsTest { @Test fun create() { CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -47,10 +49,71 @@ internal class CardCreateParamsTest { .build() } + @Test + fun headers() { + val params = + CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") + .type(CardCreateParams.Type.VIRTUAL) + .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") + .cardProgramToken("5e9483eb-8103-4e16-9794-2106111b2eca") + .carrier(Carrier.builder().qrCodeUrl("qr_code_url").build()) + .digitalCardArtToken("5e9483eb-8103-4e16-9794-2106111b2eca") + .expMonth("06") + .expYear("2027") + .memo("New Card") + .pin("pin") + .productId("1") + .replacementAccountToken("5e9483eb-8103-4e16-9794-2106111b2eca") + .replacementComment("replacement_comment") + .replacementFor("5e9483eb-8103-4e16-9794-2106111b2eca") + .replacementSubstatus(CardCreateParams.ReplacementSubstatus.LOST) + .shippingAddress( + ShippingAddress.builder() + .address1("5 Broad Street") + .city("NEW YORK") + .country("USA") + .firstName("Michael") + .lastName("Bluth") + .postalCode("10001-1809") + .state("NY") + .address2("Unit 25A") + .email("johnny@appleseed.com") + .line2Text("The Bluth Company") + .phoneNumber("+15555555555") + .build() + ) + .shippingMethod(CardCreateParams.ShippingMethod._2_DAY) + .spendLimit(1000L) + .spendLimitDuration(SpendLimitDuration.TRANSACTION) + .state(CardCreateParams.State.OPEN) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "65a9dad4-1b60-4686-83fd-65b25078a4b4") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = CardCreateParams.builder().type(CardCreateParams.Type.VIRTUAL).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEventTest.kt index abfc1db79..39da2228b 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEventTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardTransactionUpdatedWebhookEventTest.kt @@ -3,6 +3,7 @@ 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 kotlin.jvm.optionals.getOrNull @@ -116,6 +117,11 @@ internal class CardTransactionUpdatedWebhookEventTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2023-08-03T18:42:30Z")) .addEvent( @@ -338,6 +344,12 @@ internal class CardTransactionUpdatedWebhookEventTest { assertThat(cardTransactionUpdatedWebhookEvent.settledAmount()).isEqualTo(0L) assertThat(cardTransactionUpdatedWebhookEvent.status()) .isEqualTo(Transaction.Status.PENDING) + assertThat(cardTransactionUpdatedWebhookEvent.tags()) + .isEqualTo( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) assertThat(cardTransactionUpdatedWebhookEvent.tokenInfo()) .contains(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) assertThat(cardTransactionUpdatedWebhookEvent.updated()) @@ -559,6 +571,11 @@ internal class CardTransactionUpdatedWebhookEventTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2023-08-03T18:42:30Z")) .addEvent( diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardUpdatedWebhookEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardUpdatedWebhookEventTest.kt new file mode 100644 index 000000000..399d1e82f --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/CardUpdatedWebhookEventTest.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.JsonValue +import com.lithic.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class CardUpdatedWebhookEventTest { + + @Test + fun create() { + val cardUpdatedWebhookEvent = + CardUpdatedWebhookEvent.builder() + .cardToken("00000000-0000-0000-0000-000000000000") + .eventType(CardUpdatedWebhookEvent.EventType.CARD_UPDATED) + .previousFields(JsonValue.from(mapOf("state" to "PAUSED"))) + .state("OPEN") + .build() + + assertThat(cardUpdatedWebhookEvent.cardToken()) + .isEqualTo("00000000-0000-0000-0000-000000000000") + assertThat(cardUpdatedWebhookEvent.eventType()) + .isEqualTo(CardUpdatedWebhookEvent.EventType.CARD_UPDATED) + assertThat(cardUpdatedWebhookEvent._previousFields()) + .isEqualTo(JsonValue.from(mapOf("state" to "PAUSED"))) + assertThat(cardUpdatedWebhookEvent.state()).isEqualTo("OPEN") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val cardUpdatedWebhookEvent = + CardUpdatedWebhookEvent.builder() + .cardToken("00000000-0000-0000-0000-000000000000") + .eventType(CardUpdatedWebhookEvent.EventType.CARD_UPDATED) + .previousFields(JsonValue.from(mapOf("state" to "PAUSED"))) + .state("OPEN") + .build() + + val roundtrippedCardUpdatedWebhookEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(cardUpdatedWebhookEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedCardUpdatedWebhookEvent).isEqualTo(cardUpdatedWebhookEvent) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ConditionalValueTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ConditionalValueTest.kt index 2c02b8bd8..62d660561 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/ConditionalValueTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/ConditionalValueTest.kt @@ -10,6 +10,8 @@ import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource internal class ConditionalValueTest { @@ -118,10 +120,17 @@ internal class ConditionalValueTest { assertThat(roundtrippedConditionalValue).isEqualTo(conditionalValue) } - @Test - fun incompatibleJsonShapeDeserializesToUnknown() { - val value = JsonValue.from(mapOf("invalid" to "object")) - val conditionalValue = jsonMapper().convertValue(value, jacksonTypeRef()) + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { + BOOLEAN(JsonValue.from(false)), + FLOAT(JsonValue.from(3.14)), + OBJECT(JsonValue.from(mapOf("invalid" to "object"))), + } + + @ParameterizedTest + @EnumSource + fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { + val conditionalValue = + jsonMapper().convertValue(testCase.value, jacksonTypeRef()) val e = assertThrows { conditionalValue.validate() } assertThat(e).hasMessageStartingWith("Unknown ") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountCreateParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountCreateParamsTest.kt index ddb3a1545..e536da765 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountCreateParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/FinancialAccountCreateParamsTest.kt @@ -11,7 +11,7 @@ internal class FinancialAccountCreateParamsTest { @Test fun create() { FinancialAccountCreateParams.builder() - .idempotencyKey("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .nickname("nickname") .type(FinancialAccountCreateParams.Type.OPERATING) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") @@ -23,7 +23,7 @@ internal class FinancialAccountCreateParamsTest { fun headers() { val params = FinancialAccountCreateParams.builder() - .idempotencyKey("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .nickname("nickname") .type(FinancialAccountCreateParams.Type.OPERATING) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") @@ -35,7 +35,7 @@ internal class FinancialAccountCreateParamsTest { assertThat(headers) .isEqualTo( Headers.builder() - .put("Idempotency-Key", "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .put("Idempotency-Key", "65a9dad4-1b60-4686-83fd-65b25078a4b4") .build() ) } @@ -57,7 +57,7 @@ internal class FinancialAccountCreateParamsTest { fun body() { val params = FinancialAccountCreateParams.builder() - .idempotencyKey("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .nickname("nickname") .type(FinancialAccountCreateParams.Type.OPERATING) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") 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 88c470259..92718683d 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 @@ -54,6 +54,7 @@ internal class ParsedWebhookEventTest { 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 @@ -241,6 +242,7 @@ internal class ParsedWebhookEventTest { 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 @@ -446,6 +448,7 @@ internal class ParsedWebhookEventTest { 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 @@ -571,6 +574,7 @@ internal class ParsedWebhookEventTest { 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 @@ -678,6 +682,7 @@ internal class ParsedWebhookEventTest { 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 @@ -804,6 +809,7 @@ internal class ParsedWebhookEventTest { 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 @@ -1112,6 +1118,7 @@ internal class ParsedWebhookEventTest { 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 @@ -1456,6 +1463,7 @@ internal class ParsedWebhookEventTest { 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 @@ -1654,6 +1662,7 @@ internal class ParsedWebhookEventTest { 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 @@ -1808,6 +1817,7 @@ internal class ParsedWebhookEventTest { 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 @@ -1961,6 +1971,7 @@ internal class ParsedWebhookEventTest { 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 @@ -2148,6 +2159,7 @@ internal class ParsedWebhookEventTest { 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 @@ -2287,6 +2299,7 @@ internal class ParsedWebhookEventTest { 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 @@ -2379,6 +2392,7 @@ internal class ParsedWebhookEventTest { 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 @@ -2474,6 +2488,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.cardRenewed()).contains(cardRenewed) assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty + assertThat(parsedWebhookEvent.cardUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataUpdated()).isEmpty @@ -2569,6 +2584,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).contains(cardReissued) assertThat(parsedWebhookEvent.cardShipped()).isEmpty + assertThat(parsedWebhookEvent.cardUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataUpdated()).isEmpty @@ -2665,6 +2681,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).contains(cardShipped) + assertThat(parsedWebhookEvent.cardUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataUpdated()).isEmpty @@ -2734,6 +2751,102 @@ internal class ParsedWebhookEventTest { assertThat(roundtrippedParsedWebhookEvent).isEqualTo(parsedWebhookEvent) } + @Test + fun ofCardUpdated() { + val cardUpdated = + CardUpdatedWebhookEvent.builder() + .cardToken("00000000-0000-0000-0000-000000000000") + .eventType(CardUpdatedWebhookEvent.EventType.CARD_UPDATED) + .previousFields(JsonValue.from(mapOf("state" to "PAUSED"))) + .state("OPEN") + .build() + + val parsedWebhookEvent = ParsedWebhookEvent.ofCardUpdated(cardUpdated) + + 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.tokenizationDecisioningRequest()).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.cardRenewed()).isEmpty + assertThat(parsedWebhookEvent.cardReissued()).isEmpty + assertThat(parsedWebhookEvent.cardShipped()).isEmpty + assertThat(parsedWebhookEvent.cardUpdated()).contains(cardUpdated) + assertThat(parsedWebhookEvent.cardTransactionUpdated()).isEmpty + assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()).isEmpty + assertThat(parsedWebhookEvent.cardTransactionEnhancedDataUpdated()).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.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 ofCardUpdatedRoundtrip() { + val jsonMapper = jsonMapper() + val parsedWebhookEvent = + ParsedWebhookEvent.ofCardUpdated( + CardUpdatedWebhookEvent.builder() + .cardToken("00000000-0000-0000-0000-000000000000") + .eventType(CardUpdatedWebhookEvent.EventType.CARD_UPDATED) + .previousFields(JsonValue.from(mapOf("state" to "PAUSED"))) + .state("OPEN") + .build() + ) + + val roundtrippedParsedWebhookEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(parsedWebhookEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedParsedWebhookEvent).isEqualTo(parsedWebhookEvent) + } + @Test fun ofCardTransactionUpdated() { val cardTransactionUpdated = @@ -2839,6 +2952,11 @@ internal class ParsedWebhookEventTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2023-08-03T18:42:30Z")) .addEvent( @@ -2971,6 +3089,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty + assertThat(parsedWebhookEvent.cardUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionUpdated()).contains(cardTransactionUpdated) assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataUpdated()).isEmpty @@ -3126,6 +3245,11 @@ internal class ParsedWebhookEventTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo( TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build() ) @@ -3342,6 +3466,7 @@ internal class ParsedWebhookEventTest { assertThat(parsedWebhookEvent.cardRenewed()).isEmpty assertThat(parsedWebhookEvent.cardReissued()).isEmpty assertThat(parsedWebhookEvent.cardShipped()).isEmpty + assertThat(parsedWebhookEvent.cardUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionUpdated()).isEmpty assertThat(parsedWebhookEvent.cardTransactionEnhancedDataCreated()) .contains(cardTransactionEnhancedDataCreated) @@ -3546,6 +3671,7 @@ internal class ParsedWebhookEventTest { 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()) @@ -3774,6 +3900,7 @@ internal class ParsedWebhookEventTest { 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 @@ -3981,6 +4108,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4132,6 +4260,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4265,6 +4394,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4423,6 +4553,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4579,6 +4710,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4696,6 +4828,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4830,6 +4963,7 @@ internal class ParsedWebhookEventTest { 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 @@ -4988,6 +5122,7 @@ internal class ParsedWebhookEventTest { 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 @@ -5142,6 +5277,7 @@ internal class ParsedWebhookEventTest { 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 @@ -5293,6 +5429,7 @@ internal class ParsedWebhookEventTest { 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 @@ -5442,6 +5579,7 @@ internal class ParsedWebhookEventTest { 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 @@ -5588,6 +5726,7 @@ internal class ParsedWebhookEventTest { 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 @@ -5719,6 +5858,7 @@ internal class ParsedWebhookEventTest { 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 @@ -5983,6 +6123,7 @@ internal class ParsedWebhookEventTest { 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 @@ -6414,6 +6555,7 @@ internal class ParsedWebhookEventTest { 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 @@ -6737,6 +6879,7 @@ internal class ParsedWebhookEventTest { 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 @@ -6938,6 +7081,7 @@ internal class ParsedWebhookEventTest { 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 @@ -7109,6 +7253,7 @@ internal class ParsedWebhookEventTest { 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 @@ -7250,6 +7395,7 @@ internal class ParsedWebhookEventTest { 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 @@ -7386,6 +7532,7 @@ internal class ParsedWebhookEventTest { 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 @@ -7513,6 +7660,7 @@ internal class ParsedWebhookEventTest { 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 @@ -7683,6 +7831,7 @@ internal class ParsedWebhookEventTest { 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 @@ -7896,6 +8045,7 @@ internal class ParsedWebhookEventTest { 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 @@ -8070,6 +8220,7 @@ internal class ParsedWebhookEventTest { 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 @@ -8295,6 +8446,7 @@ internal class ParsedWebhookEventTest { 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 @@ -8634,6 +8786,7 @@ internal class ParsedWebhookEventTest { 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 @@ -9007,6 +9160,7 @@ internal class ParsedWebhookEventTest { 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 @@ -9409,6 +9563,7 @@ internal class ParsedWebhookEventTest { 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 @@ -9742,6 +9897,7 @@ internal class ParsedWebhookEventTest { 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 @@ -9939,6 +10095,7 @@ internal class ParsedWebhookEventTest { 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 @@ -10080,6 +10237,7 @@ internal class ParsedWebhookEventTest { 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 @@ -10210,6 +10368,7 @@ internal class ParsedWebhookEventTest { 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 @@ -10363,6 +10522,7 @@ internal class ParsedWebhookEventTest { 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 @@ -10637,6 +10797,7 @@ internal class ParsedWebhookEventTest { 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 @@ -10929,6 +11090,7 @@ internal class ParsedWebhookEventTest { 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 @@ -11134,6 +11296,7 @@ internal class ParsedWebhookEventTest { 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 diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionListPageResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionListPageResponseTest.kt index 4f9b292ac..ad0113dfa 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionListPageResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionListPageResponseTest.kt @@ -3,6 +3,7 @@ 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 kotlin.jvm.optionals.getOrNull @@ -124,6 +125,11 @@ internal class TransactionListPageResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo( TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build() ) @@ -359,6 +365,11 @@ internal class TransactionListPageResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo( TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build() ) @@ -595,6 +606,11 @@ internal class TransactionListPageResponseTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo( TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build() ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionTest.kt index ff471573f..215d9a20d 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TransactionTest.kt @@ -3,6 +3,7 @@ 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 kotlin.jvm.optionals.getOrNull @@ -116,6 +117,11 @@ internal class TransactionTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2023-08-03T18:42:30Z")) .addEvent( @@ -330,6 +336,12 @@ internal class TransactionTest { assertThat(transaction.result()).isEqualTo(Transaction.DeclineResult.APPROVED) assertThat(transaction.settledAmount()).isEqualTo(0L) assertThat(transaction.status()).isEqualTo(Transaction.Status.PENDING) + assertThat(transaction.tags()) + .isEqualTo( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) assertThat(transaction.tokenInfo()) .contains(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) assertThat(transaction.updated()).isEqualTo(OffsetDateTime.parse("2023-08-03T18:42:30Z")) @@ -548,6 +560,11 @@ internal class TransactionTest { .result(Transaction.DeclineResult.APPROVED) .settledAmount(0L) .status(Transaction.Status.PENDING) + .tags( + Transaction.Tags.builder() + .putAdditionalProperty("risk-level", JsonValue.from("high")) + .build() + ) .tokenInfo(TokenInfo.builder().walletType(TokenInfo.WalletType.APPLE_PAY).build()) .updated(OffsetDateTime.parse("2023-08-03T18:42:30Z")) .addEvent( diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt index aa7693fbd..7d219a89a 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt @@ -13,6 +13,13 @@ internal class VelocityLimitParamsTest { fun create() { val velocityLimitParams = VelocityLimitParams.builder() + .period( + VelocityLimitPeriod.TrailingWindowObject.builder() + .duration(10L) + .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) + .build() + ) + .scope(VelocityLimitParams.VelocityScope.CARD) .filters( VelocityLimitParams.VelocityLimitFilters.builder() .addExcludeCountry("USD") @@ -24,19 +31,22 @@ internal class VelocityLimitParamsTest { ) .build() ) - .period( + .limitAmount(10000L) + .limitCount(0L) + .build() + + assertThat(velocityLimitParams.period()) + .isEqualTo( + VelocityLimitPeriod.ofTrailingWindowObject( VelocityLimitPeriod.TrailingWindowObject.builder() .duration(10L) .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) .build() ) - .scope(VelocityLimitParams.VelocityScope.CARD) - .limitAmount(10000L) - .limitCount(0L) - .build() - + ) + assertThat(velocityLimitParams.scope()).isEqualTo(VelocityLimitParams.VelocityScope.CARD) assertThat(velocityLimitParams.filters()) - .isEqualTo( + .contains( VelocityLimitParams.VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") @@ -47,16 +57,6 @@ internal class VelocityLimitParamsTest { ) .build() ) - assertThat(velocityLimitParams.period()) - .isEqualTo( - VelocityLimitPeriod.ofTrailingWindowObject( - VelocityLimitPeriod.TrailingWindowObject.builder() - .duration(10L) - .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) - .build() - ) - ) - assertThat(velocityLimitParams.scope()).isEqualTo(VelocityLimitParams.VelocityScope.CARD) assertThat(velocityLimitParams.limitAmount()).contains(10000L) assertThat(velocityLimitParams.limitCount()).contains(0L) } @@ -66,6 +66,13 @@ internal class VelocityLimitParamsTest { val jsonMapper = jsonMapper() val velocityLimitParams = VelocityLimitParams.builder() + .period( + VelocityLimitPeriod.TrailingWindowObject.builder() + .duration(10L) + .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) + .build() + ) + .scope(VelocityLimitParams.VelocityScope.CARD) .filters( VelocityLimitParams.VelocityLimitFilters.builder() .addExcludeCountry("USD") @@ -77,13 +84,6 @@ internal class VelocityLimitParamsTest { ) .build() ) - .period( - VelocityLimitPeriod.TrailingWindowObject.builder() - .duration(10L) - .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) - .build() - ) - .scope(VelocityLimitParams.VelocityScope.CARD) .limitAmount(10000L) .limitCount(0L) .build() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/ErrorHandlingTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/ErrorHandlingTest.kt index 29d4f88bb..d9911f25a 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/ErrorHandlingTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/ErrorHandlingTest.kt @@ -75,6 +75,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -132,6 +133,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -189,6 +191,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -246,6 +249,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -303,6 +307,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -360,6 +365,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -417,6 +423,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -474,6 +481,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -531,6 +539,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -588,6 +597,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -645,6 +655,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -702,6 +713,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -759,6 +771,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -816,6 +829,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -873,6 +887,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -930,6 +945,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") @@ -985,6 +1001,7 @@ internal class ErrorHandlingTest { assertThrows { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/ServiceParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/ServiceParamsTest.kt index 4e1916e3c..43908cda8 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/ServiceParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/ServiceParamsTest.kt @@ -45,6 +45,7 @@ internal class ServiceParamsTest { cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/CardServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/CardServiceAsyncTest.kt index 0c172028d..04ab7e359 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/CardServiceAsyncTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/CardServiceAsyncTest.kt @@ -34,6 +34,7 @@ internal class CardServiceAsyncTest { val cardFuture = cardServiceAsync.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncTest.kt index 3635d8fa1..e7d77c8c2 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/FinancialAccountServiceAsyncTest.kt @@ -26,7 +26,7 @@ internal class FinancialAccountServiceAsyncTest { val financialAccountFuture = financialAccountServiceAsync.create( FinancialAccountCreateParams.builder() - .idempotencyKey("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .nickname("nickname") .type(FinancialAccountCreateParams.Type.OPERATING) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/CardServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/CardServiceTest.kt index 133e2da41..e24c6e1d6 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/CardServiceTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/CardServiceTest.kt @@ -34,6 +34,7 @@ internal class CardServiceTest { val card = cardService.create( CardCreateParams.builder() + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .type(CardCreateParams.Type.VIRTUAL) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .bulkOrderToken("5e9483eb-8103-4e16-9794-2106111b2eca") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceTest.kt index e67c7c0f5..3ecb6bad6 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/FinancialAccountServiceTest.kt @@ -26,7 +26,7 @@ internal class FinancialAccountServiceTest { val financialAccount = financialAccountService.create( FinancialAccountCreateParams.builder() - .idempotencyKey("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .idempotencyKey("65a9dad4-1b60-4686-83fd-65b25078a4b4") .nickname("nickname") .type(FinancialAccountCreateParams.Type.OPERATING) .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") diff --git a/lithic-java-example/build.gradle.kts b/lithic-java-example/build.gradle.kts index ac0add4e9..f6bd5bde3 100644 --- a/lithic-java-example/build.gradle.kts +++ b/lithic-java-example/build.gradle.kts @@ -8,7 +8,8 @@ repositories { } dependencies { - implementation(project(":lithic-java")) + implementation(project(":lithic-java-core")) + implementation(project(":lithic-java-client-okhttp")) } tasks.withType().configureEach { diff --git a/lithic-java-proguard-test/build.gradle.kts b/lithic-java-proguard-test/build.gradle.kts index d4d64f681..9f9c7fba2 100644 --- a/lithic-java-proguard-test/build.gradle.kts +++ b/lithic-java-proguard-test/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") testImplementation("org.assertj:assertj-core:3.25.3") - testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } tasks.shadowJar { diff --git a/scripts/upload-artifacts b/scripts/upload-artifacts new file mode 100755 index 000000000..10f3c7055 --- /dev/null +++ b/scripts/upload-artifacts @@ -0,0 +1,193 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# ANSI Color Codes +GREEN='\033[32m' +RED='\033[31m' +NC='\033[0m' # No Color + +MAVEN_REPO_PATH="./build/local-maven-repo" + +log_error() { + local msg="$1" + local headers="$2" + local body="$3" + echo -e "${RED}${msg}${NC}" + [[ -f "$headers" ]] && echo -e "${RED}Headers:$(cat "$headers")${NC}" + echo -e "${RED}Body: ${body}${NC}" + exit 1 +} + +upload_file() { + local file_name="$1" + local tmp_headers + tmp_headers=$(mktemp) + + if [ -f "$file_name" ]; then + echo -e "${GREEN}Processing file: $file_name${NC}" + pkg_file_name="mvn${file_name#"${MAVEN_REPO_PATH}"}" + + # Get signed URL for uploading artifact file + signed_url_response=$(curl -X POST -G "$URL" \ + -sS --retry 5 \ + -D "$tmp_headers" \ + --data-urlencode "filename=$pkg_file_name" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + + # Validate JSON and extract URL + if ! signed_url=$(echo "$signed_url_response" | jq -e -r '.url' 2>/dev/null) || [[ "$signed_url" == "null" ]]; then + log_error "Failed to get valid signed URL" "$tmp_headers" "$signed_url_response" + fi + + # Set content-type based on file extension + local extension="${file_name##*.}" + local content_type + case "$extension" in + jar) content_type="application/java-archive" ;; + md5|sha1|sha256|sha512) content_type="text/plain" ;; + module) content_type="application/json" ;; + pom|xml) content_type="application/xml" ;; + html) content_type="text/html" ;; + *) content_type="application/octet-stream" ;; + esac + + # Upload file + upload_response=$(curl -v -X PUT \ + --retry 5 \ + --retry-all-errors \ + -D "$tmp_headers" \ + -H "Content-Type: $content_type" \ + --data-binary "@${file_name}" "$signed_url" 2>&1) + + if ! echo "$upload_response" | grep -q "HTTP/[0-9.]* 200"; then + log_error "Failed to upload artifact file" "$tmp_headers" "$upload_response" + fi + + # Insert small throttle to reduce rate limiting risk + sleep 0.1 + fi +} + +walk_tree() { + local current_dir="$1" + + for entry in "$current_dir"/*; do + # Check that entry is valid + [ -e "$entry" ] || [ -h "$entry" ] || continue + + if [ -d "$entry" ]; then + walk_tree "$entry" + else + upload_file "$entry" + fi + done +} + +generate_instructions() { + cat << EOF > "$MAVEN_REPO_PATH/index.html" + + + + Maven Repo + + +

Stainless SDK Maven Repository

+

This is the Maven repository for your Stainless Java SDK build.

+ +

Project configuration

+ +

The details depend on whether you're using Maven or Gradle as your build tool.

+ +

Maven

+ +

Add the following to your project's pom.xml:

+
<repositories>
+    <repository>
+        <id>stainless-sdk-repo</id>
+        <url>https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn</url>
+    </repository>
+</repositories>
+ +

Gradle

+

Add the following to your build.gradle file:

+
repositories {
+    maven {
+        url "https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn"
+    }
+}
+ +
+

Configuring authentication (if required)

+ +

Some accounts may require authentication to access the repository. If so, use the + following instructions, replacing YOUR_STAINLESS_API_TOKEN with your actual token.

+ +

Maven with authentication

+ +

First, ensure you have the following in your Maven settings.xml for repo authentication:

+
<servers>
+    <server>
+        <id>stainless-sdk-repo</id>
+        <configuration>
+            <httpHeaders>
+                <property>
+                    <name>Authorization</name>
+                    <value>Bearer YOUR_STAINLESS_API_TOKEN</value>
+                </property>
+            </httpHeaders>
+        </configuration>
+    </server>
+</servers>
+ +

Then, add the following to your project's pom.xml:

+
<repositories>
+    <repository>
+        <id>stainless-sdk-repo</id>
+        <url>https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn</url>
+    </repository>
+</repositories>
+ +

Gradle with authentication

+

Add the following to your build.gradle file:

+
repositories {
+    maven {
+        url "https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn"
+        credentials(HttpHeaderCredentials) {
+            name = "Authorization"
+            value = "Bearer YOUR_STAINLESS_API_TOKEN"
+        }
+        authentication {
+            header(HttpHeaderAuthentication)
+        }
+    }
+}
+
+ +

Using the repository

+

Once you've configured the repository, you can include dependencies from it as usual. See your + project README + for more details.

+ + +EOF + upload_file "${MAVEN_REPO_PATH}/index.html" + + echo "Configure maven or gradle to use the repo located at 'https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn'" + echo "For more details, see the directions in https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn/index.html" +} + +cd "$(dirname "$0")/.." + +echo "::group::Creating local Maven content" +./gradlew publishMavenPublicationToLocalFileSystemRepository -PpublishLocal +echo "::endgroup::" + +echo "::group::Uploading to pkg.stainless.com" +walk_tree "$MAVEN_REPO_PATH" +echo "::endgroup::" + +echo "::group::Generating instructions" +generate_instructions +echo "::endgroup::"