Skip to content

Commit

Permalink
Add support for managing External Accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
remi-stripe committed Dec 15, 2017
1 parent 5257021 commit 3c7a82d
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 1 deletion.
63 changes: 63 additions & 0 deletions src/Stripe.Tests.XUnit/external_accounts/_fixtures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Stripe.Tests.Xunit
{
public class account_fixture : IDisposable
{
public StripeExternalAccountCreateOptions ExernalAccountCreateOptionsBankAccount { get; }
public StripeExternalAccountUpdateOptions ExernalAccountUpdateOptions { get; }

public StripeAccount Account { get; }
public StripeExternalAccount ExternalAccountCard { get; }
public StripeExternalAccount ExternalAccountBankAccount { get; }
public StripeExternalAccount ExternalAccountUpdated { get; }
public StripeExternalAccount ExternalAccountRetrieved { get; }
public StripeList<StripeExternalAccount> ExternalAccountList { get; }

public account_fixture()
{
Account = new StripeAccountService(Cache.ApiKey).Create(new StripeAccountCreateOptions
{
Country = "US",
Type = StripeAccountType.Custom
});

ExernalAccountCreateOptionsBankAccount = new StripeExternalAccountCreateOptions
{
ExternalAccountBankAccount = new StripeAccountBankAccountOptions
{
AccountNumber = "000123456789",
Country = "US",
Currency = "usd",
RoutingNumber = "110000000"
}
}

ExernalAccountUpdateOptions = new StripeExternalAccountCreateOptions
{
Metadata = new Dictionary<string, string>()
{
{ "some-key", "some-value" }
}
};

var service = new StripeExternalAccountService(Cache.ApiKey);

ExternalAccountCard = service.Create(Account.Id, new StripeExternalAccountCreateOptions
{
ExternalAccountTokenId = "tok_visa_debit"
});
ExternalAccountBankAccount = service.Create(Account.Id, ExernalAccountCreateOptionsBankAccount);
ExternalAccountUpdated = service.Update(Account.Id, ExternalAccountCard.Id, ExernalAccountUpdateOptions);
ExternalAccountRetrieved = service.Get(Account.Id, ExternalAccountCard.Id);
ExternalAccountList = service.List(Account.Id);
}

public void Dispose()
{
new StripeAccountService(Cache.ApiKey).Delete(Account.Id);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;

namespace Stripe.Tests.Xunit
{
public class creating_and_updating_external_accounts : IClassFixture<external_account_fixture>
{
private readonly external_account_fixture fixture;

public creating_and_updating_external_accounts(external_account_fixture fixture)
{
this.fixture = fixture;
}

[Fact]
public void created_card_has_the_right_info()
{
fixture.ExternalAccountCard.Type.Should().Be(SourceType.Card);
}

[Fact]
public void created_bank_account_has_the_right_info()
{
fixture.ExternalAccountBankAccount.Type.Should().Be(SourceType.BankAccount);
fixture.ExternalAccountBankAccount.AccountId.Should().Be(fixture.Account.Id);
fixture.ExternalAccountBankAccount.RoutingNumber.Should().Be(fixture.ExernalAccountCreateOptionsBankAccount.RoutingNumber);
}
}
}

2 changes: 1 addition & 1 deletion src/Stripe.net/Entities/StripeAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class StripeAccount : StripeEntityWithId
public string Email { get; set; }

[JsonProperty("external_accounts")]
public StripeList<Source> ExternalAccounts { get; set; }
public StripeList<StripeExternalAccount> ExternalAccounts { get; set; }

[JsonProperty("legal_entity")]
public StripeLegalEntity LegalEntity { get; set; }
Expand Down
22 changes: 22 additions & 0 deletions src/Stripe.net/Entities/StripeExternalAccount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Newtonsoft.Json;
using Stripe.Infrastructure;

namespace Stripe
{
public enum ExternalAccountType
{
Card,
BankAccount,
Deleted
}

[JsonConverter(typeof(ExternalAccountConverter))]
public class StripeExternalAccount : StripeEntityWithId
{
public ExternalAccountType Type { get; set; }

public StripeDeleted Deleted { get; set; }
public StripeCard Card { get; set; }
public StripeBankAccount BankAccount { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Stripe.Infrastructure
{
internal class ExternalAccountConverter : JsonConverter
{
public override bool CanWrite => false;

public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var incoming = JObject.FromObject(value);

incoming.WriteTo(writer);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var incoming = JObject.Load(reader);

var externalAccount = new StripeExternalAccount
{
Id = incoming.SelectToken("id").ToString()
};

if (incoming.SelectToken("object")?.ToString() == "bank_account")
{
externalAccount.Type = ExternalAccountType.BankAccount;
externalAccount.BankAccount = Mapper<StripeBankAccount>.MapFromJson(incoming.ToString());
}

if (incoming.SelectToken("object")?.ToString() == "card")
{
externalAccount.Type = ExternalAccountType.Card;
externalAccount.Card = Mapper<StripeCard>.MapFromJson(incoming.ToString());
}

if (incoming.SelectToken("deleted")?.ToString() == "true")
{
externalAccount.Type = ExternalAccountType.Deleted;
externalAccount.Deleted = Mapper<StripeDeleted>.MapFromJson(incoming.ToString());
}

return externalAccount;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Stripe
{
public class StripeExternalAccountCreateOptions : StripeBaseOptions
{
[JsonProperty("external_account")]
public string ExternalAccountTokenId { get; set; }

[JsonProperty("external_account")]
public StripeAccountBankAccountOptions ExternalAccountBankAccount { get; set; }

[JsonProperty("metadata")]
public Dictionary<string, string> Metadata { get; set; }

[JsonProperty("default_for_currency")]
public bool? DefaultForCurrency { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Newtonsoft.Json;

namespace Stripe
{
public class StripeExternalAccountListOptions : StripeListOptions
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@ public StripeExternalAccountService(string apiKey = null) : base(apiKey) { }


// Sync
public virtual StripeExternalAccount Create(string accountId, StripeExternalAccountCreateOptions options, StripeRequestOptions requestOptions = null)
{
return Post($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts", requestOptions, options);
}

public virtual StripeExternalAccount Get(string accountId, string externalAccountId, StripeRequestOptions requestOptions = null)
{
return GetEntity($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts/{externalAccountId}", requestOptions);
}

public virtual StripeExternalAccount Update(string accountId, string externalAccountId, StripeExternalAccountUpdateOptions options, StripeRequestOptions requestOptions = null)
{
return Post($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts/{externalAccountId}", requestOptions, options);
}

public virtual StripeList<StripeExternalAccount> List(string accountId, StripeListOptions listOptions = null, StripeRequestOptions requestOptions = null)
{
return GetEntityList($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts", requestOptions, listOptions);
}

public virtual StripeDeleted Delete(string accountId, string externalAccountId, StripeRequestOptions requestOptions = null)
{
return DeleteEntity($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts/{externalAccountId}", requestOptions);
Expand All @@ -21,6 +41,26 @@ public virtual StripeDeleted Delete(string accountId, string externalAccountId,


// Async
public virtual Task<StripeExternalAccount> CreateAsync(string accountId, StripeExternalAccountCreateOptions options, StripeRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
return PostAsync($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts", requestOptions, cancellationToken, options);
}

public virtual Task<StripeExternalAccount> GetAsync(string accountId, string externalAccountId, StripeRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
return GetEntityAsync($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts/{externalAccountId}", requestOptions, cancellationToken);
}

public virtual Task<StripeExternalAccount> UpdateAsync(string accountId, string externalAccountId, StripeExternalAccountUpdateOptions options, StripeRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
return PostAsync($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts/{externalAccountId}", requestOptions, cancellationToken, options);
}

public virtual Task<StripeList<StripeExternalAccount>> ListAsync(string accountId, StripeListOptions listOptions = null, StripeRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
return GetEntityListAsync($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts", requestOptions, cancellationToken, listOptions);
}

public virtual Task<StripeDeleted> DeleteAsync(string accountId, string externalAccountId, StripeRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
return DeleteEntityAsync($"{Urls.BaseUrl}/accounts/{accountId}/external_accounts/{externalAccountId}", requestOptions, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Stripe
{
public class StripeExternalAccountUpdateOptions : StripeBaseOptions
{
[JsonProperty("metadata")]
public Dictionary<string, string> Metadata { get; set; }

[JsonProperty("default_for_currency")]
public bool? DefaultForCurrency { get; set; }
}
}

0 comments on commit 3c7a82d

Please sign in to comment.