0
votes

I have successfully created a customer on my Stripe platform account. Now I want to create an invoice for that customer from one of my connect accounts.

The connect account delivered a service to the customer and now will be invoicing the customer for payment - I am using the Stripe Invoice capability.

However, I am getting the error "No such customer: cus_XXXX" even after following examples to associate the connect account with the customer account.

I have followed https://stripe.com/docs/connect/shared-customers#making-tokens to create a token for my platform customer and then use that token to create a connect account customer as indicated at https://lorenzosfarra.com/2017/09/19/stripe-shared-customers/ but am still getting the same error message. Even though it seems that the connect account reference is created successfully - as there are no errors returned, the resulting customer ID is not found.

Here is my Create Invoice Method

public static async Task<string> CreateCustomerInvoice(string secretKey, string customerId, TenantBillHeaderModel billHeader)
        {
            StripeConfiguration.ApiKey = secretKey;

            var fees = await Database.GetAdminFees();
            var salesTax = await Database.GetCountrySalesTax(13);// Hardcoded for launch
            var billLines = await Database.GetTenantBillDetailForHeaderId(billHeader.TenantBillHeaderId);
            var stripeContact = await Database.GetStripeContact(UserInfo.Instance.Organisation.OrganisationId);
            InvoiceItemCreateOptions invoiceItemOptions = null;

            // Find Fee Percentage
            var tFee = billHeader.GrossAmount * (fees.FirstOrDefault(f => f.AdminFeeId == (int)Persistence.Enums.AdminFeeEnum.ConnectCut)).Percentage / 100;

            // Create token so that customer can be shared with Connect account - See https://stripe.com/docs/connect/shared-customers
            var customerTokenId = await CreateCustomerToken(secretKey, customerId, stripeContact.StripeConnectToken);

            //Associates customer with connect account so that it is shared with platform account
            var connectCustId = await CreateCustomerInConnectAccount(secretKey, customerTokenId, stripeContact.StripeConnectToken);

            foreach (var l in billLines)
            {
                invoiceItemOptions = new InvoiceItemCreateOptions
                {
                    Quantity = l.Quantity,
                    UnitAmount = Convert.ToInt64(l.Amount * 100), // Converting to cents for Stripe
                    Currency = "aud", // Hardcoded for launch
                    CustomerId = connectCustId,
                    Description = l.Name + " (" + l.Description + ")",
                    TaxRates = new List<string> {
                        salesTax.StripeTaxRateId
                      },
                };
                var itemService = new InvoiceItemService();
                InvoiceItem invoiceItem = await itemService.CreateAsync(invoiceItemOptions);
            }

            var invoiceOptions = new InvoiceCreateOptions
            {
                CustomerId = connectCustId,
                AutoAdvance = false, // do not auto-finalize this draft after ~1 hour
                CollectionMethod = "send_invoice", // Stripe will progress the a send state. However it will not email as this is trurned off in portal https://stripe.com/docs/billing/invoices/customizing
                ApplicationFeeAmount = Convert.ToInt64(tFee),
                Description = "Invoice for Advizr Bill: " + billHeader.BillNumber,
                DueDate = billHeader.DueDate
            };

            var service = new InvoiceService();
            Invoice invoice = await service.CreateAsync(invoiceOptions);

            return invoice.Id;
        }

Here I create a customer token

public static async Task<string> CreateCustomerToken(string secretKey, string customerId, string stripeContactId)
        {
            StripeConfiguration.ApiKey = secretKey;
            RequestOptions requestOptions = null;

            var options = new TokenCreateOptions
            {
                CustomerId = customerId,
            };

            if (stripeContactId != null)
            {
                requestOptions = new RequestOptions
                {
                    StripeAccount = stripeContactId
                };
            }
            var service = new TokenService();
            Token token = await service.CreateAsync(options, requestOptions);

            return token.Id;
        }

and here I create / associate the customer with the connect account

public static async Task<string> CreateCustomerInConnectAccount(string secretKey, string customerToken, string connectAccount)
        {
            StripeConfiguration.ApiKey = secretKey;

            var options = new CustomerCreateOptions
            {
                Source = customerToken
            };

            var requestOptions = new RequestOptions
            {
                StripeAccount = connectAccount
            };
            var service = new CustomerService();
            Customer customer = await service.CreateAsync(options, requestOptions);

            return customer.Id;
        }

Any guidance on how to create an invoice for a shared customer (Exists in platform account and is associated with the connect account) will be appreciated.

The customer will then pay the invoice and I will use a destination to pay the connect account after deducting the Application Fee.

Thanks

1

1 Answers

0
votes

After logging and issue with Stripe Support, they provided me with the answer.

To resolve this issue, the connect Account

var requestOptions = new RequestOptions
{
    StripeAccount = stripeContact.StripeConnectToken
};

must be provided when creating an invoice line item

var itemService = new InvoiceItemService();
InvoiceItem invoiceItem = await itemService.CreateAsync(invoiceItemOptions, requestOptions);

and when creating the invoice.

var service = new InvoiceService();
Invoice invoice = await service.CreateAsync(invoiceOptions, requestOptions);

Hope this helps someone.