Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/com/checkout/OAuthScope.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public enum OAuthScope {
ACCOUNTS("accounts"),
BALANCES("balances"),
BALANCES_VIEW("balances:view"),
BALANCES_TOP_UP_INSTRUCTIONS("balances:top-up-instructions"),
CARD_MANAGEMENT("card-management"),
DISPUTES("disputes"),
DISPUTES_ACCEPT("disputes:accept"),
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/checkout/balances/Balances.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,45 @@

import lombok.Data;

/**
* The balance values held by a currency account (sub-account).
*/
@Data
public final class Balances {

/**
* The total incoming funds that will be added to the Available balance once cleared.
* [Optional]
*/
private Long pending;

/**
* The funds that are available for processing.
* [Optional]
*/
private Long available;

/**
* The funds reserved from the Available balance for outgoing transactions that are yet to
* clear.
* [Optional]
*/
private Long payable;

/**
* The funds held by Checkout.com to cover potential liabilities and risk events associated
* with your account.
* [Optional]
*/
private Long collateral;

/**
* The funds held for processing Payouts and Issuing payments when the Available balance is
* insufficient.
* [Optional]
*/
private Long operational;

/**
* A breakdown of the funds held in the {@code collateral} balance.
* [Optional]
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/com/checkout/balances/BalancesClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,50 @@

public interface BalancesClient {

/**
* Retrieves the balances for each sub-account belonging to an entity.
*
* @param entityId the ID of the entity
* @param balancesQuery the query filter
* @return a future with the balances response
*/
CompletableFuture<BalancesResponse> retrieveEntityBalances(String entityId, BalancesQuery balancesQuery);

/**
* Retrieves the bank details required to top up a sub-account, along with the payment
* reference that attributes an incoming payment to that sub-account.
* Note: The sub-account is referred to as currency account in the API.
*
* @param entityId the ID of the entity that owns the sub-account, or of an entity
* above it in your hierarchy. A platform can use its own entity ID
* to reach the sub-accounts of any entity beneath it
* @param currencyAccountId the ID of the sub-account to retrieve top-up instructions for
* @return a future with the top-up instructions response
*/
CompletableFuture<TopUpInstructionsResponse> retrieveTopUpInstructions(String entityId, String currencyAccountId);

// Synchronous methods

/**
* Retrieves the balances for each sub-account belonging to an entity.
*
* @param entityId the ID of the entity
* @param balancesQuery the query filter
* @return the balances response
*/
BalancesResponse retrieveEntityBalancesSync(String entityId, BalancesQuery balancesQuery);

/**
* Retrieves the bank details required to top up a sub-account, along with the payment
* reference that attributes an incoming payment to that sub-account.
* Note: The sub-account is referred to as currency account in the API.
*
* @param entityId the ID of the entity that owns the sub-account, or of an entity
* above it in your hierarchy. A platform can use its own entity ID
* to reach the sub-accounts of any entity beneath it
* @param currencyAccountId the ID of the sub-account to retrieve top-up instructions for
* @return the top-up instructions response
*/
TopUpInstructionsResponse retrieveTopUpInstructionsSync(String entityId, String currencyAccountId);

}
23 changes: 23 additions & 0 deletions src/main/java/com/checkout/balances/BalancesClientImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
public class BalancesClientImpl extends AbstractClient implements BalancesClient {

private static final String BALANCES_PATH = "balances";
private static final String ENTITIES_PATH = "entities";
private static final String CURRENCY_ACCOUNTS_PATH = "currency-accounts";
private static final String TOP_UP_INSTRUCTIONS_PATH = "top-up-instructions";

public BalancesClientImpl(final ApiClient apiClient,
final CheckoutConfiguration configuration) {
Expand All @@ -22,15 +25,35 @@ public CompletableFuture<BalancesResponse> retrieveEntityBalances(final String e
return apiClient.queryAsync(buildPath(BALANCES_PATH, entityId), sdkAuthorization(), balancesQuery, BalancesResponse.class);
}

@Override
public CompletableFuture<TopUpInstructionsResponse> retrieveTopUpInstructions(final String entityId, final String currencyAccountId) {
validateEntityIdAndCurrencyAccountId(entityId, currencyAccountId);
return apiClient.getAsync(topUpInstructionsPath(entityId, currencyAccountId), sdkAuthorization(), TopUpInstructionsResponse.class);
}

// Synchronous methods
@Override
public BalancesResponse retrieveEntityBalancesSync(final String entityId, final BalancesQuery balancesQuery) {
validateEntityIdAndBalancesQuery(entityId, balancesQuery);
return apiClient.query(buildPath(BALANCES_PATH, entityId), sdkAuthorization(), balancesQuery, BalancesResponse.class);
}

@Override
public TopUpInstructionsResponse retrieveTopUpInstructionsSync(final String entityId, final String currencyAccountId) {
validateEntityIdAndCurrencyAccountId(entityId, currencyAccountId);
return apiClient.get(topUpInstructionsPath(entityId, currencyAccountId), sdkAuthorization(), TopUpInstructionsResponse.class);
}

// Common methods
protected void validateEntityIdAndBalancesQuery(final String entityId, final BalancesQuery balancesQuery) {
com.checkout.common.CheckoutUtils.validateParams("entityId", entityId, "balancesQuery", balancesQuery);
}

private void validateEntityIdAndCurrencyAccountId(final String entityId, final String currencyAccountId) {
com.checkout.common.CheckoutUtils.validateParams("entityId", entityId, "currencyAccountId", currencyAccountId);
}

private static String topUpInstructionsPath(final String entityId, final String currencyAccountId) {
return buildPath(ENTITIES_PATH, entityId, CURRENCY_ACCOUNTS_PATH, currencyAccountId, TOP_UP_INSTRUCTIONS_PATH);
}
}
7 changes: 7 additions & 0 deletions src/main/java/com/checkout/balances/BalancesResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@

import java.util.List;

/**
* The balances for each currency account (sub-account) belonging to an entity.
*/
@Data
@EqualsAndHashCode(callSuper = true)
public final class BalancesResponse extends HttpMetadata {

/**
* The balances for each currency account that matched the query.
* [Optional]
*/
List<CurrencyAccountBalance> data;

}
15 changes: 15 additions & 0 deletions src/main/java/com/checkout/balances/CurrencyAccountBalance.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

import java.time.Instant;

/**
* The balances held by a single currency account (sub-account).
*/
@Data
public final class CurrencyAccountBalance {

Expand All @@ -15,10 +18,22 @@ public final class CurrencyAccountBalance {
*/
private String currencyAccountId;

/**
* A descriptor for the currency account.
* [Optional]
*/
private String descriptor;

/**
* The holding currency of the currency account (the three character ISO 4217 code).
* [Optional]
*/
private Currency holdingCurrency;

/**
* The balance values for the currency account.
* [Optional]
*/
private Balances balances;

/**
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/checkout/balances/TopUpBankDetails.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.checkout.balances;

import lombok.Data;

/**
* The bank details for each available funding rail.
* Both {@code domestic} and {@code international} are optional, and their availability depends on
* the sub-account's holding currency, jurisdiction, and banking partner. Do not assume that both
* rails are always available.
*/
@Data
public final class TopUpBankDetails {

/**
* The bank details for the domestic funding rail.
* [Optional]
*/
private TopUpFundingDetails domestic;

/**
* The bank details for the international funding rail.
* [Optional]
*/
private TopUpFundingDetails international;

}
68 changes: 68 additions & 0 deletions src/main/java/com/checkout/balances/TopUpFundingDetails.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.checkout.balances;

import lombok.Data;

/**
* The bank details for a single funding rail.
* {@code beneficiaryAccountName} and {@code bankName} are the only fields always returned. The
* remaining fields vary by rail and the receiving bank's jurisdiction, and are omitted when they
* do not apply.
*/
@Data
public final class TopUpFundingDetails {

/**
* The name of the account that receives the funds.
* [Required]
*/
private String beneficiaryAccountName;

/**
* The address of the beneficiary, if the rail requires it.
* [Optional]
*/
private String beneficiaryAddress;

/**
* The name of the bank that receives the funds.
* [Required]
*/
private String bankName;

/**
* The address of the receiving bank, if the rail requires it.
* [Optional]
*/
private String bankAddress;

/**
* The account number of the receiving account.
* [Optional]
*/
private String accountNumber;

/**
* The sort code of the receiving bank. Returned for United Kingdom domestic transfers.
* [Optional]
*/
private String sortCode;

/**
* The routing number of the receiving bank. Returned for United States domestic transfers.
* [Optional]
*/
private String routingNumber;

/**
* The International Bank Account Number of the receiving account.
* [Optional]
*/
private String iban;

/**
* The SWIFT or BIC code of the receiving bank. Returned for international transfers.
* [Optional]
*/
private String swiftCode;

}
42 changes: 42 additions & 0 deletions src/main/java/com/checkout/balances/TopUpInstructionsResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.checkout.balances;

import com.checkout.HttpMetadata;
import com.checkout.common.Currency;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
* The bank details and payment reference used to top up a sub-account.
*/
@Data
@EqualsAndHashCode(callSuper = true)
Comment thread
david-ruiz-cko marked this conversation as resolved.
Dismissed
public final class TopUpInstructionsResponse extends HttpMetadata {

/**
* The unique identifier of the sub-account that the instructions apply to.
* [Required]
*/
private String currencyAccountId;

/**
* The currency that funds must be sent in, as a three-letter ISO 4217 currency code.
* This is the sub-account's holding currency, returned as {@code holding_currency} by the
* Retrieve entity balances endpoint.
* [Required]
*/
private Currency currency;

/**
* The reference that must be quoted on the payment. It is how an incoming payment is
* attributed to the sub-account. A payment sent without this reference may not be credited.
* [Required]
*/
private String paymentReference;

/**
* The bank details for each available funding rail.
* [Required]
*/
private TopUpBankDetails bankDetails;

}
26 changes: 26 additions & 0 deletions src/test/java/com/checkout/OAuthScopeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.checkout;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class OAuthScopeTest {

/**
* The enum constant's String is the only place a scope's wire value is written down, and
* OAuthSdkCredentials builds the token request from getScope() rather than from the constant
* name. A typo is therefore invisible at compile time and surfaces only at the token endpoint,
* which rejects the whole request when one requested scope is undefined -- so a caller would
* lose every scope it asked for alongside the bad one.
*
* Values come from components.securitySchemes.OAuth.flows.clientCredentials.scopes in
* shared/swagger-latest.json.
*/
@Test
void shouldExposeDocumentedBalancesScopeValues() {
assertEquals("balances", OAuthScope.BALANCES.getScope());
assertEquals("balances:view", OAuthScope.BALANCES_VIEW.getScope());
assertEquals("balances:top-up-instructions", OAuthScope.BALANCES_TOP_UP_INSTRUCTIONS.getScope());
}

}
1 change: 1 addition & 0 deletions src/test/java/com/checkout/SandboxTestFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public SandboxTestFixture(final PlatformType platformType) {
OAuthScope.ACCOUNTS, OAuthScope.SESSIONS_APP, OAuthScope.SESSIONS_BROWSER,
OAuthScope.VAULT, OAuthScope.PAYOUTS_BANK_DETAILS, OAuthScope.DISPUTES,
OAuthScope.TRANSFERS_CREATE, OAuthScope.TRANSFERS_VIEW, OAuthScope.BALANCES_VIEW,
OAuthScope.BALANCES_TOP_UP_INSTRUCTIONS,
OAuthScope.VAULT_CARD_METADATA, OAuthScope.FINANCIAL_ACTIONS, OAuthScope.FORWARD,
OAuthScope.FORWARD_SECRETS, OAuthScope.PAYMENTS_SEARCH)
.environment(Environment.SANDBOX)
Expand Down
Loading
Loading