Skip to content

Commit

Permalink
[WIP] handle stripe test accounts when switching from stripe to anoth…
Browse files Browse the repository at this point in the history
…er psp
  • Loading branch information
nlsteers committed Feb 14, 2025
1 parent ce44adb commit 328c304
Show file tree
Hide file tree
Showing 10 changed files with 308 additions and 192 deletions.
24 changes: 12 additions & 12 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -140,70 +140,70 @@
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "48ca4a65970b54002939b02e8d8c1b0167de7e4b",
"is_verified": false,
"line_number": 1247
"line_number": 1288
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "7aaebcf1d5950305be73fbdda70fa0c55c6c8542",
"is_verified": false,
"line_number": 1902
"line_number": 1943
},
{
"type": "Base64 High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "313fa62b7b90790ca0e8c4b9752a0e3cf5d40421",
"is_verified": false,
"line_number": 3411
"line_number": 3412
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "a269701da90143c626af966dfdaa775d848858b1",
"is_verified": false,
"line_number": 3455
"line_number": 3456
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "a1f69fc9bf1984c89e57ee993c7392c3d702bb93",
"is_verified": false,
"line_number": 3924
"line_number": 3925
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "b7b82fee3d8bb620476c30e98864525528a30dc5",
"is_verified": false,
"line_number": 4337
"line_number": 4338
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "4e2117d267bb6ba687414034ca6f7699e03d0098",
"is_verified": false,
"line_number": 4373
"line_number": 4374
},
{
"type": "Base64 High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "1af9a059666b095ca066171bfa93b84e895134d8",
"is_verified": false,
"line_number": 5301
"line_number": 5302
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "40a714e4a70aa9b75e73dc27be3a978fa98ee4e3",
"is_verified": false,
"line_number": 5803
"line_number": 5804
},
{
"type": "Hex High Entropy String",
"filename": "openapi/connector_spec.yaml",
"hashed_secret": "ec969b7613112e3df2b11d8f64ce37f0d20bf29d",
"is_verified": false,
"line_number": 5814
"line_number": 5815
}
],
"src/main/java/uk/gov/pay/connector/agreement/resource/AgreementsApiResource.java": [
Expand Down Expand Up @@ -323,7 +323,7 @@
"filename": "src/main/java/uk/gov/pay/connector/gatewayaccount/resource/GatewayAccountResource.java",
"hashed_secret": "48ca4a65970b54002939b02e8d8c1b0167de7e4b",
"is_verified": false,
"line_number": 135
"line_number": 136
}
],
"src/main/java/uk/gov/pay/connector/gatewayaccount/resource/StripeAccountResource.java": [
Expand Down Expand Up @@ -1101,5 +1101,5 @@
}
]
},
"generated_at": "2025-02-12T11:28:02Z"
"generated_at": "2025-02-14T19:09:58Z"
}
85 changes: 43 additions & 42 deletions openapi/connector_spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,47 @@ paths:
summary: Handle Worldpay notifications
tags:
- Notifications
/v1/api/service/{serviceExternalId}/account/{accountType}/switch-psp:
post:
operationId: switchPaymentProviderByServiceIdAndAccountType
parameters:
- description: Service External Id
example: 1
in: path
name: serviceExternalId
required: true
schema:
type: string
- description: Account type
example: test
in: path
name: accountType
required: true
schema:
type: string
enum:
- test
- live
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/GatewayAccountSwitchPaymentProviderRequest"
required: true
responses:
"200":
description: OK
"400":
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
description: Bad request
"404":
description: Not found
summary: Switch payment provider of a gateway account
tags:
- Gateway accounts
/v1/api/service/{serviceId}/account/{accountType}:
get:
description: "Get gateway account by service external ID and account type (test|live).\
Expand Down Expand Up @@ -2089,47 +2130,6 @@ paths:
given service ID and account type
tags:
- Gateway accounts
/v1/api/service/{serviceId}/account/{accountType}/switch-psp:
post:
operationId: switchPaymentProviderByServiceIdAndAcountType
parameters:
- description: Service ID
example: 1
in: path
name: serviceId
required: true
schema:
type: string
- description: Account type
example: test
in: path
name: accountType
required: true
schema:
type: string
enum:
- test
- live
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/GatewayAccountSwitchPaymentProviderRequest"
required: true
responses:
"200":
description: OK
"400":
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
description: Bad request
"404":
description: Not found
summary: Switch payment provider of a gateway account
tags:
- Gateway accounts
/v1/api/service/{serviceId}/account/{accountType}/telephone-charges:
post:
description: "Create a new telephone charge for a service and account type.\
Expand Down Expand Up @@ -2279,7 +2279,8 @@ paths:
description: The response body will contain either 'valid' or 'invalid'
to indicate if the supplied credentials are valid or not.
"404":
description: Not found - account not found or not a Worldpay gateway account
description: "Not found - account not found, not a Worldpay gateway account\
\ or not a gateway account switching to Worldpay"
"422":
content:
application/json:
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/uk/gov/pay/connector/common/dao/JpaDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.inject.persist.Transactional;

import javax.persistence.EntityManager;
import java.util.Collection;
import java.util.Optional;

@Transactional
Expand Down Expand Up @@ -35,6 +36,12 @@ public T merge(final T object) {
return entityManager.get().merge(object);
}

public void mergeInSequence(final Collection<T> objects) {
for (T object : objects) {
entityManager.get().merge(object);
}
}

public void forceRefresh(final T object) {
EntityManager anEntityManager = entityManager.get();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ public GatewayAccountNotFoundException(String message) {
super(notFoundResponse(message));
}

public GatewayAccountNotFoundException(String serviceId, GatewayAccountType accountType) {
this(format("Gateway account not found for service ID [%s] and account type [%s]", serviceId, accountType));
public GatewayAccountNotFoundException(String serviceExternalId, GatewayAccountType accountType) {
this(format("Gateway account not found for service external id [%s] and account type [%s]", serviceExternalId, accountType));
}

public static GatewayAccountNotFoundException forNonWorldpayAccount(String serviceId, GatewayAccountType accountType) {
return new GatewayAccountNotFoundException(format("Gateway account for service ID [%s] and account type [%s] is not a Worldpay account.", serviceId, accountType));
public static GatewayAccountNotFoundException forNonWorldpayAccount(String serviceExternalId, GatewayAccountType accountType) {
return new GatewayAccountNotFoundException(format("Gateway account for service external id [%s] and account type [%s] is not a Worldpay account and does not have a pending Worldpay credential.", serviceExternalId, accountType));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum GatewayAccountType {
this.value = value;
}

@Override
public String toString() {
return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
public class GatewayAccountResource {

private static final Logger logger = LoggerFactory.getLogger(GatewayAccountResource.class);
private static final String SWITCHING_PROVIDER_ERROR = "Switching Payment Provider failure: {}";
private static final String SERVICE_NAME_FIELD_NAME = "service_name";
private static final String REQUIRES_3DS_FIELD_NAME = "toggle_3ds";
private static final String CARD_TYPES_FIELD_NAME = "card_types";
Expand Down Expand Up @@ -628,7 +629,7 @@ private List<String> extractNotFoundCardTypeIds(List<UUID> cardTypeIds, List<Car
}

@POST
@Path("/v1/api/service/{serviceId}/account/{accountType}/switch-psp")
@Path("/v1/api/service/{serviceExternalId}/account/{accountType}/switch-psp")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@Operation(
Expand All @@ -641,28 +642,34 @@ private List<String> extractNotFoundCardTypeIds(List<UUID> cardTypeIds, List<Car
@ApiResponse(responseCode = "404", description = "Not found")
}
)
public Response switchPaymentProviderByServiceIdAndAcountType(
@Parameter(example = "1", description = "Service ID") @PathParam("serviceId") String serviceId,
public Response switchPaymentProviderByServiceIdAndAccountType(
@Parameter(example = "1", description = "Service External Id") @PathParam("serviceExternalId") String serviceExternalId,
@Parameter(example = "test", description = "Account type") @PathParam("accountType") GatewayAccountType accountType,
@NotNull @Valid GatewayAccountSwitchPaymentProviderRequest request) {

return gatewayAccountService.getGatewayAccountByServiceIdAndAccountType(serviceId, accountType)
return gatewayAccountService.getGatewayAccountByServiceIdAndAccountType(serviceExternalId, accountType)
.map(gatewayAccountEntity -> {
if (!gatewayAccountEntity.isProviderSwitchEnabled()) {
return badRequestResponse("Account is not configured to switch PSP or already switched PSP.");
}
try {
gatewayAccountSwitchPaymentProviderService.switchPaymentProviderForAccount(gatewayAccountEntity, request);
} catch (BadRequestException ex) {
logger.error("Switching Payment Provider failure: {}", ex.getMessage());
return badRequestResponse(ex.getMessage());
} catch (NotFoundException ex) {
logger.error("Switching Payment Provider failure: {}", ex.getMessage());
return notFoundResponse(ex.getMessage());
// if the gateway account type is live, we need to clean up the test account as well
if (GatewayAccountType.LIVE.equals(GatewayAccountType.fromString(gatewayAccountEntity.getType()))) {
Optional<GatewayAccountEntity> maybeTestAccountEntity = gatewayAccountService.getGatewayAccountByServiceIdAndAccountType(serviceExternalId, GatewayAccountType.TEST);
maybeTestAccountEntity.ifPresent(testAccountEntity -> {
if (testAccountEntity.isStripeTestAccount()) {
gatewayAccountSwitchPaymentProviderService.revertStripeTestAccountToSandbox(testAccountEntity, request);
}
});
}
} catch (BadRequestException | NotFoundException ex) {
logger.error(SWITCHING_PROVIDER_ERROR, ex.getMessage());
return ex instanceof BadRequestException ? badRequestResponse(ex.getMessage()) : notFoundResponse(ex.getMessage());
}
return Response.ok().build();
})
.orElseThrow(() -> new GatewayAccountNotFoundException(serviceId, accountType));
.orElseThrow(() -> new GatewayAccountNotFoundException(serviceExternalId, accountType));
}

@POST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public Response requestStripeTestAccount(
stripeCredentials.setStripeAccountId(stripeTestConnectAccount.getId());
StripeGatewayAccountRequest stripeGatewayAccountRequest = StripeGatewayAccountRequest.Builder.aStripeGatewayAccountRequest()
.withProviderAccountType(TEST.toString())
.withDescription(String.format("Stripe test account for service %s", sandboxGatewayAccount.getServiceName()))
.withServiceName(sandboxGatewayAccount.getServiceName())
.withServiceId(sandboxGatewayAccount.getServiceId())
.withDescription(sandboxGatewayAccount.getDescription())
Expand All @@ -91,7 +90,7 @@ public Response requestStripeTestAccount(

GatewayAccountEntity stripeTestGatewayAccount = gatewayAccountService.createGatewayAccount(stripeGatewayAccountRequest);
stripeAccountSetupService.completeTestAccountSetup(stripeTestGatewayAccount);
gatewayAccountService.disableAccount(sandboxGatewayAccount.getId(), String.format("Superseded by Stripe test account [ext id: %s]", stripeTestGatewayAccount.getExternalId()));
gatewayAccountService.disableAccount(sandboxGatewayAccount.getId(), String.format("Superseded by newer test account [gateway_account_id: %s]", stripeTestGatewayAccount.getId()));

Map<String, String> response = Map.of("stripe_connect_account_id", stripeTestConnectAccount.getId(),
"gateway_account_id", stripeTestGatewayAccount.getId().toString(),
Expand Down
Loading

0 comments on commit 328c304

Please sign in to comment.