mirror of
https://github.com/bitwarden/server.git
synced 2024-11-22 12:15:36 +01:00
API updates for tax info collection
This commit is contained in:
parent
cad7cf0200
commit
d88838f19e
@ -618,5 +618,38 @@ namespace Bit.Api.Controllers
|
|||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("tax")]
|
||||||
|
[SelfHosted(NotSelfHostedOnly = true)]
|
||||||
|
public async Task<TaxInfoResponseModel> GetTaxInfo()
|
||||||
|
{
|
||||||
|
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var taxInfo = await _paymentService.GetTaxInfoAsync(user);
|
||||||
|
return new TaxInfoResponseModel(taxInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("tax")]
|
||||||
|
[HttpPost("tax")]
|
||||||
|
[SelfHosted(NotSelfHostedOnly = true)]
|
||||||
|
public async Task PutTaxInfo([FromBody]TaxInfoUpdateRequestModel model)
|
||||||
|
{
|
||||||
|
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var taxInfo = new TaxInfo
|
||||||
|
{
|
||||||
|
BillingAddressPostalCode = model.PostalCode,
|
||||||
|
BillingAddressCountry = model.Country,
|
||||||
|
};
|
||||||
|
await _paymentService.SaveTaxInfoAsync(user, taxInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,5 +462,55 @@ namespace Bit.Api.Controllers
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}/tax")]
|
||||||
|
[SelfHosted(NotSelfHostedOnly = true)]
|
||||||
|
public async Task<TaxInfoResponseModel> GetTaxInfo(string id)
|
||||||
|
{
|
||||||
|
var orgIdGuid = new Guid(id);
|
||||||
|
if (!_currentContext.OrganizationOwner(orgIdGuid))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(orgIdGuid);
|
||||||
|
if (organization == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var taxInfo = await _paymentService.GetTaxInfoAsync(organization);
|
||||||
|
return new TaxInfoResponseModel(taxInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}/tax")]
|
||||||
|
[HttpPost("{id}/tax")]
|
||||||
|
[SelfHosted(NotSelfHostedOnly = true)]
|
||||||
|
public async Task PutTaxInfo(string id, [FromBody]OrganizationTaxInfoUpdateRequestModel model)
|
||||||
|
{
|
||||||
|
var orgIdGuid = new Guid(id);
|
||||||
|
if (!_currentContext.OrganizationOwner(orgIdGuid))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(orgIdGuid);
|
||||||
|
if (organization == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var taxInfo = new TaxInfo
|
||||||
|
{
|
||||||
|
TaxIdNumber = model.TaxId,
|
||||||
|
BillingAddressLine1 = model.Line1,
|
||||||
|
BillingAddressLine2 = model.Line2,
|
||||||
|
BillingAddressCity = model.City,
|
||||||
|
BillingAddressState = model.State,
|
||||||
|
BillingAddressPostalCode = model.PostalCode,
|
||||||
|
BillingAddressCountry = model.Country,
|
||||||
|
};
|
||||||
|
await _paymentService.SaveTaxInfoAsync(organization, taxInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Api
|
||||||
|
{
|
||||||
|
public class TaxInfoUpdateRequestModel : IValidatableObject
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Country { get; set; }
|
||||||
|
public string PostalCode { get; set; }
|
||||||
|
|
||||||
|
public virtual IEnumerable<ValidationResult> Validate (ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
|
||||||
|
{
|
||||||
|
yield return new ValidationResult("Zip / postal code is required.",
|
||||||
|
new string[] { nameof(PostalCode) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,15 @@ namespace Bit.Core.Models.Api
|
|||||||
[EncryptedString]
|
[EncryptedString]
|
||||||
[EncryptedStringLength(1000)]
|
[EncryptedStringLength(1000)]
|
||||||
public string CollectionName { get; set; }
|
public string CollectionName { get; set; }
|
||||||
|
public string TaxIdNumber { get; set; }
|
||||||
|
public string BillingAddressLine1 { get; set; }
|
||||||
|
public string BillingAddressLine2 { get; set; }
|
||||||
|
public string BillingAddressCity { get; set; }
|
||||||
|
public string BillingAddressState { get; set; }
|
||||||
|
public string BillingAddressPostalCode { get; set; }
|
||||||
|
[Required]
|
||||||
|
[StringLength(2)]
|
||||||
|
public string BillingAddressCountry { get; set; }
|
||||||
|
|
||||||
public virtual OrganizationSignup ToOrganizationSignup(User user)
|
public virtual OrganizationSignup ToOrganizationSignup(User user)
|
||||||
{
|
{
|
||||||
@ -47,7 +56,17 @@ namespace Bit.Core.Models.Api
|
|||||||
PremiumAccessAddon = PremiumAccessAddon,
|
PremiumAccessAddon = PremiumAccessAddon,
|
||||||
BillingEmail = BillingEmail,
|
BillingEmail = BillingEmail,
|
||||||
BusinessName = BusinessName,
|
BusinessName = BusinessName,
|
||||||
CollectionName = CollectionName
|
CollectionName = CollectionName,
|
||||||
|
TaxInfo = new TaxInfo
|
||||||
|
{
|
||||||
|
TaxIdNumber = TaxIdNumber,
|
||||||
|
BillingAddressLine1 = BillingAddressLine1,
|
||||||
|
BillingAddressLine2 = BillingAddressLine2,
|
||||||
|
BillingAddressCity = BillingAddressCity,
|
||||||
|
BillingAddressState = BillingAddressState,
|
||||||
|
BillingAddressPostalCode = BillingAddressPostalCode,
|
||||||
|
BillingAddressCountry = BillingAddressCountry,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +81,17 @@ namespace Bit.Core.Models.Api
|
|||||||
yield return new ValidationResult("Payment method type required.",
|
yield return new ValidationResult("Payment method type required.",
|
||||||
new string[] { nameof(PaymentMethodType) });
|
new string[] { nameof(PaymentMethodType) });
|
||||||
}
|
}
|
||||||
|
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(BillingAddressCountry))
|
||||||
|
{
|
||||||
|
yield return new ValidationResult("Country required.",
|
||||||
|
new string[] { nameof(BillingAddressCountry) });
|
||||||
|
}
|
||||||
|
if (PlanType != PlanType.Free && BillingAddressCountry == "US" &&
|
||||||
|
string.IsNullOrWhiteSpace(BillingAddressPostalCode))
|
||||||
|
{
|
||||||
|
yield return new ValidationResult("Zip / postal code is required.",
|
||||||
|
new string[] { nameof(BillingAddressPostalCode) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace Bit.Core.Models.Api
|
||||||
|
{
|
||||||
|
public class OrganizationTaxInfoUpdateRequestModel : TaxInfoUpdateRequestModel
|
||||||
|
{
|
||||||
|
public string TaxId { get; set; }
|
||||||
|
public string Line1 { get; set; }
|
||||||
|
public string Line2 { get; set; }
|
||||||
|
public string City { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
}
|
||||||
|
}
|
34
src/Core/Models/Api/Response/TaxInfoResponseModel.cs
Normal file
34
src/Core/Models/Api/Response/TaxInfoResponseModel.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using Bit.Core.Models.Business;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Api
|
||||||
|
{
|
||||||
|
public class TaxInfoResponseModel
|
||||||
|
{
|
||||||
|
public TaxInfoResponseModel () { }
|
||||||
|
public TaxInfoResponseModel(TaxInfo taxInfo)
|
||||||
|
{
|
||||||
|
if (taxInfo == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaxIdNumber = taxInfo.TaxIdNumber;
|
||||||
|
TaxIdType = taxInfo.TaxIdType;
|
||||||
|
Line1 = taxInfo.BillingAddressLine1;
|
||||||
|
Line2 = taxInfo.BillingAddressLine2;
|
||||||
|
City = taxInfo.BillingAddressCity;
|
||||||
|
State = taxInfo.BillingAddressState;
|
||||||
|
PostalCode = taxInfo.BillingAddressPostalCode;
|
||||||
|
Country = taxInfo.BillingAddressCountry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TaxIdNumber { get; set; }
|
||||||
|
public string TaxIdType { get; set; }
|
||||||
|
public string Line1 { get; set; }
|
||||||
|
public string Line2 { get; set; }
|
||||||
|
public string City { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
public string PostalCode { get; set; }
|
||||||
|
public string Country { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -12,5 +12,6 @@ namespace Bit.Core.Models.Business
|
|||||||
public string CollectionName { get; set; }
|
public string CollectionName { get; set; }
|
||||||
public PaymentMethodType? PaymentMethodType { get; set; }
|
public PaymentMethodType? PaymentMethodType { get; set; }
|
||||||
public string PaymentToken { get; set; }
|
public string PaymentToken { get; set; }
|
||||||
|
public TaxInfo TaxInfo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
140
src/Core/Models/Business/TaxInfo.cs
Normal file
140
src/Core/Models/Business/TaxInfo.cs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
namespace Bit.Core.Models.Business
|
||||||
|
{
|
||||||
|
public class TaxInfo
|
||||||
|
{
|
||||||
|
private string _taxIdNumber = null;
|
||||||
|
private string _taxIdType = null;
|
||||||
|
|
||||||
|
public string TaxIdNumber
|
||||||
|
{
|
||||||
|
get => _taxIdNumber;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_taxIdNumber = value;
|
||||||
|
_taxIdType = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string BillingAddressLine1 { get; set; }
|
||||||
|
public string BillingAddressLine2 { get; set; }
|
||||||
|
public string BillingAddressCity { get; set; }
|
||||||
|
public string BillingAddressState { get; set; }
|
||||||
|
public string BillingAddressPostalCode { get; set; }
|
||||||
|
public string BillingAddressCountry { get; set; } = "US";
|
||||||
|
public string TaxIdType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(BillingAddressCountry) ||
|
||||||
|
string.IsNullOrWhiteSpace(TaxIdNumber))
|
||||||
|
return null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(_taxIdType))
|
||||||
|
return _taxIdType;
|
||||||
|
|
||||||
|
switch (BillingAddressCountry)
|
||||||
|
{
|
||||||
|
case "AE":
|
||||||
|
_taxIdType = "ae_trn";
|
||||||
|
break;
|
||||||
|
case "AU":
|
||||||
|
_taxIdType = "au_abn";
|
||||||
|
break;
|
||||||
|
case "BR":
|
||||||
|
_taxIdType = "br_cnpj";
|
||||||
|
break;
|
||||||
|
case "CA":
|
||||||
|
// May break for those in Québec given the assumption of QST
|
||||||
|
if (BillingAddressState?.Contains("bec") ?? false)
|
||||||
|
_taxIdType = "ca_qst";
|
||||||
|
_taxIdType = "ca_bn";
|
||||||
|
break;
|
||||||
|
case "CL":
|
||||||
|
_taxIdType = "cl_tin";
|
||||||
|
break;
|
||||||
|
case "AT":
|
||||||
|
case "BE":
|
||||||
|
case "BG":
|
||||||
|
case "CY":
|
||||||
|
case "CZ":
|
||||||
|
case "DE":
|
||||||
|
case "DK":
|
||||||
|
case "EE":
|
||||||
|
case "ES":
|
||||||
|
case "FI":
|
||||||
|
case "FR":
|
||||||
|
case "GB":
|
||||||
|
case "GR":
|
||||||
|
case "HR":
|
||||||
|
case "HU":
|
||||||
|
case "IE":
|
||||||
|
case "IT":
|
||||||
|
case "LT":
|
||||||
|
case "LU":
|
||||||
|
case "LV":
|
||||||
|
case "MT":
|
||||||
|
case "NL":
|
||||||
|
case "PL":
|
||||||
|
case "PT":
|
||||||
|
case "RO":
|
||||||
|
case "SE":
|
||||||
|
case "SI":
|
||||||
|
case "SK":
|
||||||
|
_taxIdType = "eu_vat";
|
||||||
|
break;
|
||||||
|
case "HK":
|
||||||
|
_taxIdType = "hk_br";
|
||||||
|
break;
|
||||||
|
case "IN":
|
||||||
|
_taxIdType = "in_gst";
|
||||||
|
break;
|
||||||
|
case "JP":
|
||||||
|
_taxIdType = "jp_cn";
|
||||||
|
break;
|
||||||
|
case "KR":
|
||||||
|
_taxIdType = "kr_brn";
|
||||||
|
break;
|
||||||
|
case "LI":
|
||||||
|
_taxIdType = "li_uid";
|
||||||
|
break;
|
||||||
|
case "MX":
|
||||||
|
_taxIdType = "mx_rfc";
|
||||||
|
break;
|
||||||
|
case "MY":
|
||||||
|
_taxIdType = "my_sst";
|
||||||
|
break;
|
||||||
|
case "NO":
|
||||||
|
_taxIdType = "no_vat";
|
||||||
|
break;
|
||||||
|
case "NZ":
|
||||||
|
_taxIdType = "nz_gst";
|
||||||
|
break;
|
||||||
|
case "RU":
|
||||||
|
_taxIdType = "ru_inn";
|
||||||
|
break;
|
||||||
|
case "SA":
|
||||||
|
_taxIdType = "sa_vat";
|
||||||
|
break;
|
||||||
|
case "SG":
|
||||||
|
_taxIdType = "sg_gst";
|
||||||
|
break;
|
||||||
|
case "TH":
|
||||||
|
_taxIdType = "th_vat";
|
||||||
|
break;
|
||||||
|
case "TW":
|
||||||
|
_taxIdType = "tw_vat";
|
||||||
|
break;
|
||||||
|
case "US":
|
||||||
|
_taxIdType = "us_ein";
|
||||||
|
break;
|
||||||
|
case "ZA":
|
||||||
|
_taxIdType = "za_vat";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_taxIdType = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _taxIdType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ namespace Bit.Core.Services
|
|||||||
Task CancelAndRecoverChargesAsync(ISubscriber subscriber);
|
Task CancelAndRecoverChargesAsync(ISubscriber subscriber);
|
||||||
Task<string> PurchaseOrganizationAsync(Organization org, PaymentMethodType paymentMethodType,
|
Task<string> PurchaseOrganizationAsync(Organization org, PaymentMethodType paymentMethodType,
|
||||||
string paymentToken, Models.StaticStore.Plan plan, short additionalStorageGb, short additionalSeats,
|
string paymentToken, Models.StaticStore.Plan plan, short additionalStorageGb, short additionalSeats,
|
||||||
bool premiumAccessAddon);
|
bool premiumAccessAddon, TaxInfo taxInfo);
|
||||||
Task<string> UpgradeFreeOrganizationAsync(Organization org, Models.StaticStore.Plan plan,
|
Task<string> UpgradeFreeOrganizationAsync(Organization org, Models.StaticStore.Plan plan,
|
||||||
short additionalStorageGb, short additionalSeats, bool premiumAccessAddon);
|
short additionalStorageGb, short additionalSeats, bool premiumAccessAddon);
|
||||||
Task<string> PurchasePremiumAsync(User user, PaymentMethodType paymentMethodType, string paymentToken,
|
Task<string> PurchasePremiumAsync(User user, PaymentMethodType paymentMethodType, string paymentToken,
|
||||||
@ -24,5 +24,7 @@ namespace Bit.Core.Services
|
|||||||
Task<bool> CreditAccountAsync(ISubscriber subscriber, decimal creditAmount);
|
Task<bool> CreditAccountAsync(ISubscriber subscriber, decimal creditAmount);
|
||||||
Task<BillingInfo> GetBillingAsync(ISubscriber subscriber);
|
Task<BillingInfo> GetBillingAsync(ISubscriber subscriber);
|
||||||
Task<SubscriptionInfo> GetSubscriptionAsync(ISubscriber subscriber);
|
Task<SubscriptionInfo> GetSubscriptionAsync(ISubscriber subscriber);
|
||||||
|
Task<TaxInfo> GetTaxInfoAsync(ISubscriber subscriber);
|
||||||
|
Task SaveTaxInfoAsync(ISubscriber subscriber, TaxInfo taxInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,7 @@ namespace Bit.Core.Services
|
|||||||
{
|
{
|
||||||
await _paymentService.PurchaseOrganizationAsync(organization, signup.PaymentMethodType.Value,
|
await _paymentService.PurchaseOrganizationAsync(organization, signup.PaymentMethodType.Value,
|
||||||
signup.PaymentToken, plan, signup.AdditionalStorageGb, signup.AdditionalSeats,
|
signup.PaymentToken, plan, signup.AdditionalStorageGb, signup.AdditionalSeats,
|
||||||
signup.PremiumAccessAddon);
|
signup.PremiumAccessAddon, signup.TaxInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await SignUpAsync(organization, signup.Owner.Id, signup.OwnerKey, signup.CollectionName, true);
|
return await SignUpAsync(organization, signup.Owner.Id, signup.OwnerKey, signup.CollectionName, true);
|
||||||
|
@ -49,7 +49,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
public async Task<string> PurchaseOrganizationAsync(Organization org, PaymentMethodType paymentMethodType,
|
public async Task<string> PurchaseOrganizationAsync(Organization org, PaymentMethodType paymentMethodType,
|
||||||
string paymentToken, Models.StaticStore.Plan plan, short additionalStorageGb,
|
string paymentToken, Models.StaticStore.Plan plan, short additionalStorageGb,
|
||||||
short additionalSeats, bool premiumAccessAddon)
|
short additionalSeats, bool premiumAccessAddon, TaxInfo taxInfo)
|
||||||
{
|
{
|
||||||
var customerService = new CustomerService();
|
var customerService = new CustomerService();
|
||||||
|
|
||||||
@ -159,7 +159,21 @@ namespace Bit.Core.Services
|
|||||||
InvoiceSettings = new CustomerInvoiceSettingsOptions
|
InvoiceSettings = new CustomerInvoiceSettingsOptions
|
||||||
{
|
{
|
||||||
DefaultPaymentMethod = stipeCustomerPaymentMethodId
|
DefaultPaymentMethod = stipeCustomerPaymentMethodId
|
||||||
}
|
},
|
||||||
|
// TODO: Address info for zip code and country, optional other address info and tax ID
|
||||||
|
Address = new AddressOptions
|
||||||
|
{
|
||||||
|
Country = null,
|
||||||
|
PostalCode = null,
|
||||||
|
},
|
||||||
|
TaxIdData = new List<CustomerTaxIdDataOptions>
|
||||||
|
{
|
||||||
|
new CustomerTaxIdDataOptions
|
||||||
|
{
|
||||||
|
Type = "",
|
||||||
|
Value = null,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
subCreateOptions.AddExpand("latest_invoice.payment_intent");
|
subCreateOptions.AddExpand("latest_invoice.payment_intent");
|
||||||
subCreateOptions.Customer = customer.Id;
|
subCreateOptions.Customer = customer.Id;
|
||||||
@ -1501,6 +1515,76 @@ namespace Bit.Core.Services
|
|||||||
return subscriptionInfo;
|
return subscriptionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<TaxInfo> GetTaxInfoAsync(ISubscriber subscriber)
|
||||||
|
{
|
||||||
|
if (subscriber != null && !string.IsNullOrWhiteSpace(subscriber.GatewayCustomerId))
|
||||||
|
{
|
||||||
|
var customerService = new CustomerService();
|
||||||
|
var customer = await customerService.GetAsync(subscriber.GatewayCustomerId);
|
||||||
|
|
||||||
|
if (customer == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var address = customer.Address;
|
||||||
|
var taxId = customer.TaxIds?.FirstOrDefault();
|
||||||
|
|
||||||
|
return new TaxInfo
|
||||||
|
{
|
||||||
|
TaxIdNumber = taxId?.Value,
|
||||||
|
BillingAddressLine1 = address?.Line1,
|
||||||
|
BillingAddressLine2 = address?.Line2,
|
||||||
|
BillingAddressCity = address?.City,
|
||||||
|
BillingAddressState = address?.State,
|
||||||
|
BillingAddressPostalCode = address?.PostalCode,
|
||||||
|
BillingAddressCountry = address?.Country,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveTaxInfoAsync(ISubscriber subscriber, TaxInfo taxInfo)
|
||||||
|
{
|
||||||
|
if (subscriber != null && !string.IsNullOrWhiteSpace(subscriber.GatewayCustomerId))
|
||||||
|
{
|
||||||
|
var customerService = new CustomerService();
|
||||||
|
var customer = await customerService.UpdateAsync(subscriber.GatewayCustomerId, new CustomerUpdateOptions
|
||||||
|
{
|
||||||
|
Address = new AddressOptions
|
||||||
|
{
|
||||||
|
Line1 = taxInfo.BillingAddressLine1,
|
||||||
|
Line2 = taxInfo.BillingAddressLine2,
|
||||||
|
City = taxInfo.BillingAddressCity,
|
||||||
|
State = taxInfo.BillingAddressState,
|
||||||
|
PostalCode = taxInfo.BillingAddressPostalCode,
|
||||||
|
Country = taxInfo.BillingAddressCountry,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!subscriber.IsUser() && customer != null)
|
||||||
|
{
|
||||||
|
var taxIdService = new TaxIdService();
|
||||||
|
var taxId = customer.TaxIds?.FirstOrDefault();
|
||||||
|
|
||||||
|
if (taxId != null)
|
||||||
|
{
|
||||||
|
await taxIdService.DeleteAsync(customer.Id, taxId.Id);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(taxInfo.TaxIdNumber) &&
|
||||||
|
!string.IsNullOrWhiteSpace(taxInfo.TaxIdType))
|
||||||
|
{
|
||||||
|
await taxIdService.CreateAsync(customer.Id, new TaxIdCreateOptions
|
||||||
|
{
|
||||||
|
Type = taxInfo.TaxIdType,
|
||||||
|
Value = taxInfo.TaxIdNumber,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private PaymentMethod GetLatestCardPaymentMethod(string customerId)
|
private PaymentMethod GetLatestCardPaymentMethod(string customerId)
|
||||||
{
|
{
|
||||||
var paymentMethodService = new PaymentMethodService();
|
var paymentMethodService = new PaymentMethodService();
|
||||||
|
Loading…
Reference in New Issue
Block a user