Skip to content

Commit ea5e4cd

Browse files
[ACL-196] Add support for SchemeSelection in Payouts (#241)
1 parent 214b1f3 commit ea5e4cd

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed

src/TrueLayer/Payouts/Model/CreatePayoutRequest.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace TrueLayer.Payouts.Model
66
{
77
using BeneficiaryUnion = OneOf<PaymentSource, ExternalAccount, BusinessAccount>;
8+
using SchemeSelectionUnion = OneOf<SchemeSelection.InstantPreferred, SchemeSelection.InstantOnly, SchemeSelection.Preselected>;
89

910
/// <summary>
1011
/// Represents a request for payout
@@ -19,18 +20,21 @@ public record CreatePayoutRequest
1920
/// <param name="currency">The three-letter ISO alpha currency code</param>
2021
/// <param name="beneficiary">The payout beneficiary details</param>
2122
/// <param name="metadata">Metadata</param>
23+
/// <param name="schemeSelection">Metadata</param>
2224
public CreatePayoutRequest(
2325
string merchantAccountId,
2426
long amountInMinor,
2527
string currency,
2628
BeneficiaryUnion beneficiary,
27-
Dictionary<string, string>? metadata = null)
29+
Dictionary<string, string>? metadata = null,
30+
SchemeSelectionUnion? schemeSelection = null)
2831
{
2932
MerchantAccountId = merchantAccountId;
3033
AmountInMinor = amountInMinor.GreaterThan(0, nameof(amountInMinor));
3134
Currency = currency.NotNullOrWhiteSpace(nameof(currency));
3235
Beneficiary = beneficiary;
3336
Metadata = metadata;
37+
SchemeSelection = schemeSelection;
3438
}
3539

3640
/// <summary>
@@ -54,6 +58,14 @@ public CreatePayoutRequest(
5458
/// </summary>
5559
public BeneficiaryUnion Beneficiary { get; }
5660

61+
/// <summary>
62+
/// Gets the metadata
63+
/// </summary>
5764
public Dictionary<string, string>? Metadata { get; }
65+
66+
/// <summary>
67+
/// Gets the scheme selection
68+
/// </summary>
69+
public SchemeSelectionUnion? SchemeSelection { get; }
5870
}
5971
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using TrueLayer.Serialization;
2+
3+
namespace TrueLayer.Payouts.Model;
4+
5+
/// <summary>
6+
/// Payout scheme selection types
7+
/// </summary>
8+
public static class SchemeSelection
9+
{
10+
/// <summary>
11+
/// Automatically select a payment scheme that supports instant payments based on currency and geography.
12+
/// </summary>
13+
[JsonDiscriminator("instant_only")]
14+
public record InstantOnly : IDiscriminated
15+
{
16+
/// <summary>
17+
/// Gets the scheme selection type
18+
/// </summary>
19+
public string Type => "instant_only";
20+
}
21+
22+
/// <summary>
23+
/// Automatically select a payment scheme that supports instant payments based on currency and geography,
24+
/// with a fallback to a non-instant scheme if instant payment is unavailable.
25+
/// The payout_executed webhook will specify the actual scheme used.
26+
/// This is optimal when slow settlement is not a concern. This is used by default if no scheme_selection is provided.
27+
/// </summary>
28+
[JsonDiscriminator("instant_preferred")]
29+
public record InstantPreferred : IDiscriminated
30+
{
31+
/// <summary>
32+
/// Gets the scheme selection type
33+
/// </summary>
34+
public string Type => "instant_preferred";
35+
}
36+
37+
38+
/// <summary>
39+
/// Represents that the scheme for the payout is preselected.
40+
/// </summary>
41+
[JsonDiscriminator("preselected")]
42+
public record Preselected : IDiscriminated
43+
{
44+
/// <summary>
45+
/// Gets the scheme selection type
46+
/// </summary>
47+
public string Type => "preselected";
48+
49+
/// <summary>
50+
/// Select a payment scheme compatible with the currency and geographic region to avoid payout failures after submission.
51+
/// This helps with payouts by selecting the better-performing scheme between two similar options in a region, based on various criteria
52+
/// </summary>
53+
public string? SchemeId { get; init; }
54+
}
55+
}

test/TrueLayer.AcceptanceTests/PayoutTests.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ public async Task Can_create_payout()
2323
{
2424
CreatePayoutRequest payoutRequest = CreatePayoutRequest();
2525

26-
var response = await _fixture.TlClients[0].Payouts.CreatePayout(
27-
payoutRequest, idempotencyKey: Guid.NewGuid().ToString());
26+
var response = await _fixture.TlClients[0].Payouts.CreatePayout(payoutRequest);
2827

2928
response.StatusCode.Should().Be(HttpStatusCode.Accepted);
3029
response.Data.Should().NotBeNull();
@@ -81,8 +80,8 @@ private CreatePayoutRequest CreatePayoutRequest()
8180
new AccountIdentifier.Iban("GB33BUKB20201555555555"),
8281
dateOfBirth: new DateTime(1970, 12, 31),
8382
address: new Address("London", "England", "EC1R 4RB", "GB", "1 Hardwick St")),
84-
metadata: new() { { "a", "b" } }
83+
metadata: new() { { "a", "b" } },
84+
schemeSelection: new SchemeSelection.InstantOnly()
8585
);
86-
8786
}
8887
}

test/TrueLayer.Tests/Payouts/PayoutsApiTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ private static CreatePayoutRequest CreatePayoutRequest(PayoutBeneficiary benefic
107107
100,
108108
Currencies.GBP,
109109
beneficiary,
110-
metadata: new() { { "a", "b" } });
110+
metadata: new() { { "a", "b" } },
111+
schemeSelection: new SchemeSelection.InstantPreferred());
111112

112113
public static IEnumerable<object[]> TestData =>
113114
new List<object[]>

0 commit comments

Comments
 (0)