-
Notifications
You must be signed in to change notification settings - Fork 0
feat(s3): Stripe PSP adapter + WireMock stubs (STA-124) #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,44 @@ | ||
| package com.stablecoin.payments.onramp.config; | ||
|
|
||
| import com.stablecoin.payments.onramp.domain.port.PspGateway; | ||
| import com.stablecoin.payments.onramp.domain.port.PspPaymentResult; | ||
| import com.stablecoin.payments.onramp.domain.port.PspRefundResult; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| /** | ||
| * Provides fallback (dev/test) implementations of outbound ports | ||
| * via {@code @ConditionalOnMissingBean}. Real adapters are registered | ||
| * by provider-specific configurations under | ||
| * {@code infrastructure/provider/<name>/}. | ||
| * | ||
| * <p>Adapters will be added here as domain ports are defined. | ||
| */ | ||
| @Slf4j | ||
| @Configuration | ||
| public class FallbackAdaptersConfig { | ||
|
|
||
| // Fallback beans will be added as domain ports are implemented. | ||
| // Pattern: @Bean @ConditionalOnMissingBean public <Port> fallback<Port>() { ... } | ||
| @Bean | ||
| @ConditionalOnMissingBean | ||
| public PspGateway fallbackPspGateway() { | ||
| return new PspGateway() { | ||
| @Override | ||
| public PspPaymentResult initiatePayment( | ||
| com.stablecoin.payments.onramp.domain.port.PspPaymentRequest request) { | ||
| log.warn("[FALLBACK-PSP] Using dev PSP gateway for payment collectionId={}", | ||
| request.collectionId()); | ||
| return new PspPaymentResult("dev-pi-" + UUID.randomUUID(), "succeeded"); | ||
| } | ||
|
|
||
| @Override | ||
| public PspRefundResult initiateRefund( | ||
| com.stablecoin.payments.onramp.domain.port.PspRefundRequest request) { | ||
| log.warn("[FALLBACK-PSP] Using dev PSP gateway for refund collectionId={}", | ||
| request.collectionId()); | ||
| return new PspRefundResult("dev-re-" + UUID.randomUUID(), "succeeded"); | ||
| } | ||
| }; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||||||||||||||||||||||||||||||
| package com.stablecoin.payments.onramp.infrastructure.provider.stripe; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| record StripePaymentIntentResponse( | ||||||||||||||||||||||||||||||||||
| String id, | ||||||||||||||||||||||||||||||||||
| String status, | ||||||||||||||||||||||||||||||||||
| Long amount, | ||||||||||||||||||||||||||||||||||
| String currency, | ||||||||||||||||||||||||||||||||||
| String clientSecret | ||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing Same issue as Proposed fix package com.stablecoin.payments.onramp.infrastructure.provider.stripe;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
record StripePaymentIntentResponse(
String id,
String status,
Long amount,
String currency,
- String clientSecret
+ `@JsonProperty`("client_secret") String clientSecret
) {
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package com.stablecoin.payments.onramp.infrastructure.provider.stripe; | ||
|
|
||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
|
||
| @ConfigurationProperties(prefix = "app.psp.stripe") | ||
| public record StripeProperties(String baseUrl, String apiKey, int timeoutSeconds) { | ||
|
|
||
| public StripeProperties { | ||
| if (baseUrl == null || baseUrl.isBlank()) { | ||
| baseUrl = "https://api.stripe.com"; | ||
| } | ||
| if (apiKey == null || apiKey.isBlank()) { | ||
| apiKey = "sk_test_default"; | ||
| } | ||
| if (timeoutSeconds <= 0) { | ||
| timeoutSeconds = 10; | ||
| } | ||
| } | ||
|
Comment on lines
+8
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Silent fallback to default API key may mask production misconfiguration. Defaulting Consider using Alternative: fail-fast validation package com.stablecoin.payments.onramp.infrastructure.provider.stripe;
+import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+@Validated
`@ConfigurationProperties`(prefix = "app.psp.stripe")
-public record StripeProperties(String baseUrl, String apiKey, int timeoutSeconds) {
+public record StripeProperties(
+ String baseUrl,
+ `@NotBlank`(message = "Stripe API key must be configured") String apiKey,
+ int timeoutSeconds) {
public StripeProperties {
if (baseUrl == null || baseUrl.isBlank()) {
baseUrl = "https://api.stripe.com";
}
- if (apiKey == null || apiKey.isBlank()) {
- apiKey = "sk_test_default";
- }
if (timeoutSeconds <= 0) {
timeoutSeconds = 10;
}
}
}🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,120 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.stablecoin.payments.onramp.infrastructure.provider.stripe; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.stablecoin.payments.onramp.domain.port.PspGateway; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.stablecoin.payments.onramp.domain.port.PspPaymentRequest; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.stablecoin.payments.onramp.domain.port.PspPaymentResult; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.stablecoin.payments.onramp.domain.port.PspRefundRequest; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.stablecoin.payments.onramp.domain.port.PspRefundResult; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.http.HttpHeaders; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.http.MediaType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.http.client.JdkClientHttpRequestFactory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Component; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.util.LinkedMultiValueMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.util.MultiValueMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.web.client.RestClient; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.net.http.HttpClient; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.net.http.HttpClient.Version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.Duration; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @ConditionalOnProperty(name = "app.psp.provider", havingValue = "stripe") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @EnableConfigurationProperties(StripeProperties.class) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class StripePspAdapter implements PspGateway { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final RestClient restClient; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public StripePspAdapter(StripeProperties properties) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var httpClient = HttpClient.newBuilder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .version(Version.HTTP_1_1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .connectTimeout(Duration.ofSeconds(properties.timeoutSeconds())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var requestFactory = new JdkClientHttpRequestFactory(httpClient); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requestFactory.setReadTimeout(Duration.ofSeconds(properties.timeoutSeconds())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.restClient = RestClient.builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .baseUrl(properties.baseUrl()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + properties.apiKey()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requestFactory(requestFactory) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @CircuitBreaker(name = "stripe", fallbackMethod = "initiatePaymentFallback") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public PspPaymentResult initiatePayment(PspPaymentRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("[STRIPE] Initiating payment collectionId={} amount={} currency={}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.collectionId(), request.amount().amount(), request.amount().currency()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("amount", toMinorUnits(request)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("currency", request.amount().currency().toLowerCase()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("payment_method_types[]", "us_bank_account"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("confirm", "true"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("metadata[collection_id]", request.collectionId().toString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var response = restClient.post() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .uri("/v1/payment_intents") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .contentType(MediaType.APPLICATION_FORM_URLENCODED) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(formData) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .retrieve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(StripePaymentIntentResponse.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("[STRIPE] Payment initiated collectionId={} pspRef={} status={}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.collectionId(), response.id(), response.status()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new PspPaymentResult(response.id(), response.status()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+61
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential NPE if
Defensive approach var response = restClient.post()
.uri("/v1/payment_intents")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(formData)
.retrieve()
.body(StripePaymentIntentResponse.class);
+ if (response == null || response.id() == null) {
+ throw new IllegalStateException("Empty response from Stripe payment intent API");
+ }
+
log.info("[STRIPE] Payment initiated collectionId={} pspRef={} status={}",
request.collectionId(), response.id(), response.status());📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @CircuitBreaker(name = "stripe", fallbackMethod = "initiateRefundFallback") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public PspRefundResult initiateRefund(PspRefundRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("[STRIPE] Initiating refund collectionId={} pspRef={} amount={}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.collectionId(), request.pspReference(), request.refundAmount().amount()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("payment_intent", request.pspReference()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("amount", toMinorUnitsFromRefund(request)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("reason", "requested_by_customer"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.add("metadata[collection_id]", request.collectionId().toString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+80
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refund reason from request is ignored.
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var response = restClient.post() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .uri("/v1/refunds") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .contentType(MediaType.APPLICATION_FORM_URLENCODED) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(formData) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .retrieve() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .body(StripeRefundResponse.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("[STRIPE] Refund initiated collectionId={} refundRef={} status={}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.collectionId(), response.id(), response.status()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new PspRefundResult(response.id(), response.status()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @SuppressWarnings("unused") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private PspPaymentResult initiatePaymentFallback(PspPaymentRequest request, Exception ex) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.error("[STRIPE] Circuit breaker open — payment initiation failed collectionId={}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.collectionId(), ex); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new IllegalStateException("Stripe payment initiation unavailable", ex); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @SuppressWarnings("unused") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private PspRefundResult initiateRefundFallback(PspRefundRequest request, Exception ex) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.error("[STRIPE] Circuit breaker open — refund initiation failed collectionId={}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request.collectionId(), ex); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new IllegalStateException("Stripe refund initiation unavailable", ex); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private String toMinorUnits(PspPaymentRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return String.valueOf(request.amount().amount().movePointRight(2).longValueExact()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private String toMinorUnitsFromRefund(PspRefundRequest request) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return String.valueOf(request.refundAmount().amount().movePointRight(2).longValueExact()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+113
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Stripe “zero-decimal currencies” (currencies where you don’t multiply by 100—the Source references: Stripe’s general rule for zero-decimal currencies is documented in their “Supported currencies” guide (even if the list rendering can vary by page/view). [1] References: 🏁 Script executed: cat -n fiat-on-ramp/fiat-on-ramp/src/main/java/com/stablecoin/payments/onramp/infrastructure/provider/stripe/StripePspAdapter.java | head -150Repository: Puneethkumarck/stablebridge-platform Length of output: 6491 🏁 Script executed: find . -name "*.java" -type f | xargs grep -l "interface PspRefundRequest\|class PspRefundRequest" 2>/dev/null | head -5Repository: Puneethkumarck/stablebridge-platform Length of output: 62 🏁 Script executed: rg "PspRefundRequest" --type java -A 10 | head -50Repository: Puneethkumarck/stablebridge-platform Length of output: 7001 🏁 Script executed: rg "class Money|record Money" --type java -A 5 | head -30Repository: Puneethkumarck/stablebridge-platform Length of output: 3926 Minor units conversion fails for zero-decimal and special-decimal currencies.
Both 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||||||||||||||||||||||||||||||
| package com.stablecoin.payments.onramp.infrastructure.provider.stripe; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| record StripeRefundResponse( | ||||||||||||||||||||||||||||||||||
| String id, | ||||||||||||||||||||||||||||||||||
| String status, | ||||||||||||||||||||||||||||||||||
| Long amount, | ||||||||||||||||||||||||||||||||||
| String currency, | ||||||||||||||||||||||||||||||||||
| String paymentIntent | ||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result:
Citations:
🏁 Script executed: #!/bin/bash
# Search for Jackson configuration classes
find . -type f -name "*.java" | xargs grep -l "PropertyNamingStrategy\|PropertyNamingStrategies\|@JsonNaming" 2>/dev/null | head -20
# Look for Spring configuration files
find . -type f -name "*.java" | xargs grep -l "ObjectMapper\|RestClient\|HttpMessageConverter" 2>/dev/null | grep -i config | head -10
# Search for any Jackson related bean configurations
rg -t java "ObjectMapper|@Configuration|@Bean" -A 3 | grep -A 3 "ObjectMapper" | head -30Repository: Puneethkumarck/stablebridge-platform Length of output: 4290 🏁 Script executed: #!/bin/bash
# Check if there's any global naming strategy configuration in application properties
find . -type f \( -name "application*.properties" -o -name "application*.yml" -o -name "application*.yaml" \) -exec cat {} \; 2>/dev/null | grep -i "jackson\|naming"
# Look for any test files that show how StripeRefundResponse is deserialized
find . -path "*/test*" -name "*.java" | xargs grep -l "StripeRefundResponse" 2>/dev/nullRepository: Puneethkumarck/stablebridge-platform Length of output: 64 🏁 Script executed: #!/bin/bash
# Find StripeRefundResponse usage in the codebase
find . -type f -name "*.java" | xargs grep -l "StripeRefundResponse" 2>/dev/null
# Check the actual imports in StripeRefundResponse.java
find . -path "*stripe*" -name "StripeRefundResponse.java" -exec head -20 {} \;
# Look for Stripe client configuration
find . -type f -name "*.java" | xargs grep -l "Stripe\|stripe" 2>/dev/null | grep -i config | head -5
# Search for any Stripe API response mapping examples
find . -type f -name "*.java" | xargs grep -B 3 -A 3 "payment_intent\|paymentIntent" 2>/dev/null | head -40Repository: Puneethkumarck/stablebridge-platform Length of output: 7360 🏁 Script executed: #!/bin/bash
# Check for Jackson dependencies in pom.xml or build.gradle files
find . -name "pom.xml" -o -name "build.gradle" | xargs grep -i "jackson" 2>/dev/null | head -20
# Look for any RestClient usage with StripeRefundResponse
rg -t java "StripeRefundResponse" -B 5 -A 5 | head -50Repository: Puneethkumarck/stablebridge-platform Length of output: 3176 🏁 Script executed: #!/bin/bash
# Check StripePspAdapter.java to see the full refund method and how RestClient is configured
find . -path "*stripe*" -name "StripePspAdapter.java" -exec cat {} \;
# Look for any tests that verify StripeRefundResponse deserialization
find . -path "*/test*" -name "*.java" | xargs grep -l "StripeRefundResponse\|StripePspAdapter" 2>/dev/null | head -5Repository: Puneethkumarck/stablebridge-platform Length of output: 5781 🏁 Script executed: #!/bin/bash
# Check if there are any JSON test fixtures or mocked Stripe responses
find . -name "*.json" | xargs grep -l "payment_intent\|refund" 2>/dev/null | head -10
# Look for RestClient configuration or ObjectMapper bean definitions
rg -t java "@Bean|ObjectMapper|RestClient" -B 2 -A 5 --max-count=50 | head -80Repository: Puneethkumarck/stablebridge-platform Length of output: 13392 🏁 Script executed: #!/bin/bash
# Check the test file for StripeRefundResponse to see if deserialization is tested
cat ./fiat-on-ramp/fiat-on-ramp/src/test/java/com/stablecoin/payments/onramp/infrastructure/provider/stripe/StripePspAdapterTest.java
# Look for WireMock stripe mappings and response files to see actual API response format
find . -path "*wiremock*" -name "*stripe*.json" -exec echo "=== {} ===" \; -exec cat {} \;Repository: Puneethkumarck/stablebridge-platform Length of output: 11589 🏁 Script executed: #!/bin/bash
# Check if there's a parent Spring Boot config or application properties file
find . -name "application*.properties" -o -name "application*.yml" | head -10 | xargs grep -l "jackson\|objectMapper" 2>/dev/null
# Look for any RestClient or Jackson configuration in the fiat-on-ramp module
find ./fiat-on-ramp -name "*.java" | xargs grep -l "ObjectMapper\|@Configuration" 2>/dev/null | head -5Repository: Puneethkumarck/stablebridge-platform Length of output: 513 🏁 Script executed: #!/bin/bash
# Look at the full StripePaymentIntentResponse to see if it also has this issue
find . -path "*stripe*" -name "StripePaymentIntentResponse.java" -exec cat {} \;
# Check if there's any global Jackson configuration in Spring Boot auto-config
find ./fiat-on-ramp -name "*.java" | xargs grep -B 5 -A 5 "objectMapper\|Jackson\|PropertyNamingStrategy" 2>/dev/null | head -40Repository: Puneethkumarck/stablebridge-platform Length of output: 309 🏁 Script executed: #!/bin/bash
# Verify that the test actually expects the paymentIntent field to be deserialized
# by checking if the test asserts on it
grep -A 10 -B 5 "paymentIntent\|payment_intent" ./fiat-on-ramp/fiat-on-ramp/src/test/java/com/stablecoin/payments/onramp/infrastructure/provider/stripe/StripePspAdapterTest.java
# Check the StripePaymentIntentResponse also
find . -type f -name "*.java" -path "*stripe*" | xargs grep -l "StripePaymentIntentResponse" | head -1 | xargs catRepository: Puneethkumarck/stablebridge-platform Length of output: 6717 Add Stripe API returns Proposed fix package com.stablecoin.payments.onramp.infrastructure.provider.stripe;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
record StripeRefundResponse(
String id,
String status,
Long amount,
String currency,
- String paymentIntent
+ `@JsonProperty`("payment_intent") String paymentIntent
) {
} package com.stablecoin.payments.onramp.infrastructure.provider.stripe;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
record StripePaymentIntentResponse(
String id,
String status,
Long amount,
String currency,
- String clientSecret
+ `@JsonProperty`("client_secret") String clientSecret
) {
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Use imported types instead of fully-qualified class names.
PspPaymentRequestandPspRefundRequestshould be imported at the top of the file rather than using FQCNs inline.Proposed fix
Add to imports:
Then update the method signatures:
🤖 Prompt for AI Agents