public async Task <PaymentGatewayResult <IPaymentInvoice> > CreateInvoiceManualAsync(long amount, string customerId) { try { var invoiceItem = await _invoiceItemService.CreateAsync(new InvoiceItemCreateOptions { Amount = amount * 100, Currency = "usd", CustomerId = customerId, }); var invoiceOptions = new InvoiceCreateOptions { CustomerId = customerId, AutoAdvance = false, // auto-finalize this draft after ~1 hour CollectionMethod = "send_invoice", DaysUntilDue = _appSettings.Stripe.InvoiceDueDays, Footer = $"{Extensions.ApplicationName} Invoices" }; var invoice = await _invoiceService.CreateAsync(invoiceOptions); return(PaymentGatewayResult <IPaymentInvoice> .Success(_mapper.Map <IPaymentInvoice>(invoice))); } catch (StripeException e) { return(PaymentGatewayResult <IPaymentInvoice> .Failed(e)); } }
public async Task <bool> PreviewUpcomingInvoiceAndPayAsync(ISubscriber subscriber, string planId, List <InvoiceSubscriptionItemOptions> subItemOptions, int prorateThreshold = 500) { var invoiceService = new InvoiceService(); var invoiceItemService = new InvoiceItemService(); var pendingInvoiceItems = invoiceItemService.ListAutoPaging(new InvoiceItemListOptions { CustomerId = subscriber.GatewayCustomerId }).ToList().Where(i => i.InvoiceId == null); var pendingInvoiceItemsDict = pendingInvoiceItems.ToDictionary(pii => pii.Id); var upcomingPreview = await invoiceService.UpcomingAsync(new UpcomingInvoiceOptions { CustomerId = subscriber.GatewayCustomerId, SubscriptionId = subscriber.GatewaySubscriptionId, SubscriptionItems = subItemOptions }); var itemsForInvoice = upcomingPreview.Lines?.Data? .Where(i => pendingInvoiceItemsDict.ContainsKey(i.Id) || (i.Plan.Id == planId && i.Proration)); var invoiceAmount = itemsForInvoice?.Sum(i => i.Amount) ?? 0; var invoiceNow = invoiceAmount >= prorateThreshold; if (invoiceNow) { // Owes more than prorateThreshold on next invoice. // Invoice them and pay now instead of waiting until next billing cycle. Invoice invoice = null; var createdInvoiceItems = new List <InvoiceItem>(); Braintree.Transaction braintreeTransaction = null; try { foreach (var ii in itemsForInvoice) { if (pendingInvoiceItemsDict.ContainsKey(ii.Id)) { continue; } var invoiceItem = await invoiceItemService.CreateAsync(new InvoiceItemCreateOptions { Currency = ii.Currency, Description = ii.Description, CustomerId = subscriber.GatewayCustomerId, SubscriptionId = ii.SubscriptionId, Discountable = ii.Discountable, Amount = ii.Amount }); createdInvoiceItems.Add(invoiceItem); } invoice = await invoiceService.CreateAsync(new InvoiceCreateOptions { Billing = Billing.SendInvoice, DaysUntilDue = 1, CustomerId = subscriber.GatewayCustomerId, SubscriptionId = subscriber.GatewaySubscriptionId }); var invoicePayOptions = new InvoicePayOptions(); var customerService = new CustomerService(); var customer = await customerService.GetAsync(subscriber.GatewayCustomerId); if (customer != null) { if (customer.Metadata.ContainsKey("btCustomerId")) { invoicePayOptions.PaidOutOfBand = true; var btInvoiceAmount = (invoiceAmount / 100M); var transactionResult = await _btGateway.Transaction.SaleAsync( new Braintree.TransactionRequest { Amount = btInvoiceAmount, CustomerId = customer.Metadata["btCustomerId"], Options = new Braintree.TransactionOptionsRequest { SubmitForSettlement = true, PayPal = new Braintree.TransactionOptionsPayPalRequest { CustomField = $"{subscriber.BraintreeIdField()}:{subscriber.Id}" } }, CustomFields = new Dictionary <string, string> { [subscriber.BraintreeIdField()] = subscriber.Id.ToString() } }); if (!transactionResult.IsSuccess()) { throw new GatewayException("Failed to charge PayPal customer."); } braintreeTransaction = transactionResult.Target; await invoiceService.UpdateAsync(invoice.Id, new InvoiceUpdateOptions { Metadata = new Dictionary <string, string> { ["btTransactionId"] = braintreeTransaction.Id, ["btPayPalTransactionId"] = braintreeTransaction.PayPalDetails.AuthorizationId } }); } } await invoiceService.PayAsync(invoice.Id, invoicePayOptions); } catch (Exception e) { if (braintreeTransaction != null) { await _btGateway.Transaction.RefundAsync(braintreeTransaction.Id); } if (invoice != null) { await invoiceService.DeleteAsync(invoice.Id); // Restore invoice items that were brought in foreach (var item in pendingInvoiceItems) { var i = new InvoiceItemCreateOptions { Currency = item.Currency, Description = item.Description, CustomerId = item.CustomerId, SubscriptionId = item.SubscriptionId, Discountable = item.Discountable, Metadata = item.Metadata, Quantity = item.Quantity, UnitAmount = item.UnitAmount }; await invoiceItemService.CreateAsync(i); } } else { foreach (var ii in createdInvoiceItems) { await invoiceItemService.DeleteAsync(ii.Id); } } throw e; } } return(invoiceNow); }
public async Task <Invoice> CreateInvoice( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "invoice/create")] CreatePaymentRequest request, ILogger log) { // このサンプルでは input validation をしていません。 // 既存の Customer に紐づけることもできますが、今回は毎回 Customer を作成します。 var customerCreateOptions = new CustomerCreateOptions { Email = request.Email, PaymentMethod = request.PaymentMethodId, InvoiceSettings = new CustomerInvoiceSettingsOptions { DefaultPaymentMethod = request.PaymentMethodId } }; var customer = await _customerService.CreateAsync(customerCreateOptions); // Attach payment method: // 新規作成した Customer に PaymentMethod を紐づけます。 // paymentMethodMethod は既に別の customer に紐づけられている場合エラーになります。 var options = new PaymentMethodAttachOptions { Customer = customer.Id }; var paymentMethod = await _paymentMethodService.AttachAsync(request.PaymentMethodId, options); // Update customer's default payment method. var customerOptions = new CustomerUpdateOptions { InvoiceSettings = new CustomerInvoiceSettingsOptions { DefaultPaymentMethod = paymentMethod.Id, } }; await _customerService.UpdateAsync(customer.Id, customerOptions); // Create InvoiceItem. var createOptions = new InvoiceItemCreateOptions { Customer = customer.Id, Price = request.PriceId }; await _invoiceItemService.CreateAsync(createOptions); // Create Invoice var invoiceOptions = new InvoiceCreateOptions { Customer = customer.Id, AutoAdvance = true, }; var invoiceResult = await _invoiceService.CreateAsync(invoiceOptions); //ここで、Stripe の Dashboard > Billing > インボイスにインボイスが追加されます。 return(invoiceResult); }