Persist onetime donation payment success timestamps for Braintree transactions

This commit is contained in:
Katherine 2023-12-14 19:48:29 -05:00 committed by GitHub
parent bb347999ce
commit 9cfc2ba09a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 12 additions and 15 deletions

View File

@ -780,8 +780,9 @@ public class SubscriptionController {
})
.thenCompose(unused -> braintreeManager.captureOneTimePayment(request.payerId, request.paymentId,
request.paymentToken, request.currency, request.amount, request.level))
.thenApply(chargeSuccessDetails -> Response.ok(
new ConfirmPayPalBoostResponse(chargeSuccessDetails.paymentId())).build());
.thenCompose(chargeSuccessDetails -> oneTimeDonationsManager.putPaidAt(chargeSuccessDetails.paymentId(), Instant.now()))
.thenApply(paymentId -> Response.ok(
new ConfirmPayPalBoostResponse(paymentId)).build());
}
public static class CreateBoostReceiptCredentialsRequest {

View File

@ -7,7 +7,6 @@ package org.whispersystems.textsecuregcm.storage;
import static com.codahale.metrics.MetricRegistry.name;
import com.google.common.annotations.VisibleForTesting;
import io.micrometer.core.instrument.Metrics;
import java.time.Instant;
import java.util.Map;
@ -15,13 +14,12 @@ import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import org.whispersystems.textsecuregcm.util.AttributeValues;
import org.whispersystems.textsecuregcm.util.Util;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
public class OneTimeDonationsManager {
public static final String KEY_PAYMENT_INTENT_ID = "P"; // S
public static final String KEY_PAYMENT_ID = "P"; // S
public static final String ATTR_PAID_AT = "A"; // N
private static final String ONETIME_DONATION_NOT_FOUND_COUNTER_NAME = name(OneTimeDonationsManager.class, "onetimeDonationNotFound");
private final String table;
@ -34,11 +32,11 @@ public class OneTimeDonationsManager {
this.dynamoDbAsyncClient = Objects.requireNonNull(dynamoDbAsyncClient);
}
public CompletableFuture<Instant> getPaidAt(final String paymentIntentId, final Instant fallbackTimestamp) {
public CompletableFuture<Instant> getPaidAt(final String paymentId, final Instant fallbackTimestamp) {
final GetItemRequest getItemRequest = GetItemRequest.builder()
.consistentRead(Boolean.TRUE)
.tableName(table)
.key(Map.of(KEY_PAYMENT_INTENT_ID, AttributeValues.fromString(paymentIntentId)))
.key(Map.of(KEY_PAYMENT_ID, AttributeValues.fromString(paymentId)))
.projectionExpression(ATTR_PAID_AT)
.build();
@ -52,15 +50,13 @@ public class OneTimeDonationsManager {
});
}
@VisibleForTesting
CompletableFuture<Void> putPaidAt(final String paymentIntentId, final Instant paidAt) {
public CompletableFuture<String> putPaidAt(final String paymentId, final Instant paidAt) {
return dynamoDbAsyncClient.putItem(PutItemRequest.builder()
.tableName(table)
.item(Map.of(
KEY_PAYMENT_INTENT_ID, AttributeValues.fromString(paymentIntentId),
KEY_PAYMENT_ID, AttributeValues.fromString(paymentId),
ATTR_PAID_AT, AttributeValues.fromLong(paidAt.getEpochSecond())))
.build())
.thenRun(Util.NOOP);
.thenApply(unused -> paymentId);
}
}

View File

@ -243,10 +243,10 @@ public final class DynamoDbExtensionSchema {
.build())),
ONETIME_DONATIONS("onetime_donations_test",
OneTimeDonationsManager.KEY_PAYMENT_INTENT_ID,
OneTimeDonationsManager.KEY_PAYMENT_ID,
null,
List.of(AttributeDefinition.builder()
.attributeName(OneTimeDonationsManager.KEY_PAYMENT_INTENT_ID)
.attributeName(OneTimeDonationsManager.KEY_PAYMENT_ID)
.attributeType(ScalarAttributeType.S)
.build()),
List.of(), List.of()),

View File

@ -25,7 +25,7 @@ public class OnetimeDonationsManagerTest {
}
@Test
void testGetPaidAtTimestamp() {
void testSetGetPaidAtTimestamp() {
final String validPaymentIntentId = "abc";
final Instant paidAt = Instant.ofEpochSecond(1_000_000);
final Instant fallBackTimestamp = Instant.ofEpochSecond(2_000_000);