public async Task <PaymentGatewayResult <IPaymentSubscription> > CreateSubscriptionAsync(string planId, string customerId, ChargeType type, string?coupon)
        {
            try
            {
                var options = new SubscriptionCreateOptions
                {
                    CustomerId = customerId,
                    Items      = new List <SubscriptionItemOption> {
                        new SubscriptionItemOption {
                            PlanId = planId
                        }
                    },
                    CollectionMethod = _chargeTypes[(int)type],
                    CouponId         = coupon
                };
                if ((int)type == 1)
                {
                    options.DaysUntilDue = _appSettings.Stripe.InvoiceDueDays;
                }

                var subscription = await _subscriptionService.CreateAsync(options);

                return(PaymentGatewayResult <IPaymentSubscription> .Success(_mapper.Map <IPaymentSubscription>(subscription)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentSubscription> .Failed(e));
            }
        }
        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 <PaymentGatewayResult <IPaymentCard> > DeleteCardAsync(string paymentCustomerId, string paymentCardId)
        {
            try
            {
                var result = await _cardService.DeleteAsync(paymentCustomerId, paymentCardId);

                return(PaymentGatewayResult <IPaymentCard> .Success(_mapper.Map <IPaymentCard>(result)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCard> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentSubscription> > GetSubscriptionByIdAsync(string id)
        {
            try
            {
                var subscription = await _subscriptionService.GetAsync(id);

                return(PaymentGatewayResult <IPaymentSubscription> .Success(_mapper.Map <IPaymentSubscription>(subscription)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentSubscription> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCoupon> > UpdateCouponAsync(string id, CouponUpdateOptions options)
        {
            try
            {
                var coupon = await _couponService.GetAsync(id);

                coupon = await _couponService.UpdateAsync(coupon.Id, options);

                return(PaymentGatewayResult <IPaymentCoupon> .Success(_mapper.Map <IPaymentCoupon>(coupon)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCoupon> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <List <IPaymentSubscription> > > GetAllSubscriptionsAsync()
        {
            try
            {
                var subscriptions = await _subscriptionService.ListAsync(new SubscriptionListOptions
                {
                });

                return(PaymentGatewayResult <List <IPaymentSubscription> > .Success(_mapper.Map <List <IPaymentSubscription> >(subscriptions)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <List <IPaymentSubscription> > .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCard> > CreateCardAsync(string paymentCustomerId, string paymentCardToken)
        {
            try
            {
                var card = await _cardService.CreateAsync(paymentCustomerId, new CardCreateOptions
                {
                    Source = paymentCardToken,
                });

                return(PaymentGatewayResult <IPaymentCard> .Success(_mapper.Map <IPaymentCard>(card)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCard> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentRefund> > RefundChargeAsync(string chargeId, long?amount)
        {
            try
            {
                var refund = await _refundService.CreateAsync(new RefundCreateOptions
                {
                    Amount   = amount / 100,
                    ChargeId = chargeId,
                });

                return(PaymentGatewayResult <IPaymentRefund> .Success(_mapper.Map <IPaymentRefund>(refund)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentRefund> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCustomer> > CreateCustomerAsync(string email, string paymentCardToken)
        {
            try
            {
                var paymentCustomer = await _customerSer.CreateAsync(new CustomerCreateOptions
                {
                    Email  = email,
                    Source = paymentCardToken,
                });

                return(PaymentGatewayResult <IPaymentCustomer> .Success(_mapper.Map <IPaymentCustomer>(paymentCustomer)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCustomer> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentSubscription> > CancelSubscriptionAsync(string subscriptionId, bool?invoiceNow, bool?prorate)
        {
            try
            {
                var subscription = await _subscriptionService.CancelAsync(subscriptionId,
                                                                          new SubscriptionCancelOptions()
                {
                    InvoiceNow = invoiceNow,
                    Prorate    = prorate,
                });

                return(PaymentGatewayResult <IPaymentSubscription> .Success(_mapper.Map <IPaymentSubscription>(subscription)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentSubscription> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCard> > UpdateCardAsync(string paymentCustomerId, IPaymentCard card)
        {
            if (string.IsNullOrEmpty(card.Id))
            {
                return(PaymentGatewayResult <IPaymentCard> .Failed(HttpStatusCode.NotFound, "Card ID not Found"));
            }

            try
            {
                var result = await _cardService.UpdateAsync(paymentCustomerId, card.Id, _mapper.Map <CardUpdateOptions>(card));

                return(PaymentGatewayResult <IPaymentCard> .Success(_mapper.Map <IPaymentCard>(result)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCard> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCoupon> > DeleteCouponAsync(string id)
        {
            try
            {
                var coupon = await _couponService.GetAsync(id);

                if (coupon == null)
                {
                    throw new Exception("Coupon not found");
                }
                coupon = await _couponService.DeleteAsync(id);

                return(PaymentGatewayResult <IPaymentCoupon> .Success(_mapper.Map <IPaymentCoupon>(coupon)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCoupon> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentSubscription> > UpdateSubscriptionAsync(string planId, ChargeType type,
                                                                                                 string subscriptionId, string?coupon)
        {
            try
            {
                var subscription = await _subscriptionService.GetAsync(subscriptionId);

                if (subscription == null)
                {
                    throw new StripeException("Subscription Not Found")
                          {
                              HttpStatusCode = HttpStatusCode.NotFound
                          }
                }
                ;
                var opt = new SubscriptionUpdateOptions
                {
                    CancelAtPeriodEnd = false,
                    Items             = new List <SubscriptionItemUpdateOption> {
                        new SubscriptionItemUpdateOption {
                            Id     = subscription.Items.Data.FirstOrDefault()?.Id,
                            PlanId = planId
                        },
                    },
                    CouponId         = coupon,
                    Prorate          = true,
                    ProrationDate    = DateTime.UtcNow,
                    CollectionMethod = _chargeTypes[(int)type],
                };
                if (type == ChargeType.Manual)
                {
                    opt.DaysUntilDue = _appSettings.Stripe.InvoiceDueDays;
                }

                subscription = await _subscriptionService.UpdateAsync(subscription.Id, opt);

                return(PaymentGatewayResult <IPaymentSubscription> .Success(_mapper.Map <IPaymentSubscription>(subscription)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentSubscription> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentInvoice> > GetLatestInvoiceBySubscription(string subscriptionId, string customerId)
        {
            try
            {
                var prorationDate = DateTimeOffset.UtcNow;
                var options       = new InvoiceListOptions
                {
                    CustomerId     = customerId,
                    SubscriptionId = subscriptionId,
                };
                var invoices = await _invoiceService.ListAsync(options);

                var inv = invoices.Data.OrderByDescending(x => x.Created);
                return(PaymentGatewayResult <IPaymentInvoice> .Success(
                           _mapper.Map <IPaymentInvoice>(inv.FirstOrDefault())));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentInvoice> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCoupon> > GetCouponByIdAsync(string id)
        {
            try
            {
                var coupon = await _couponService.GetAsync(id);

                if (coupon.PercentOff != null)
                {
                    if (coupon.Duration == "once")
                    {
                        if (coupon.DurationInMonths == 1)
                        {
                            coupon.Object = coupon.PercentOff + "% off " + coupon.Duration + " for " + coupon.DurationInMonths + " month";
                        }
                        else
                        {
                            coupon.Object = coupon.PercentOff + "% off " + coupon.Duration + " for " + coupon.DurationInMonths + " months";
                        }
                    }
                    else if (coupon.Duration == "forever")
                    {
                        coupon.Object = coupon.PercentOff + "% off " + coupon.Duration;
                    }

                    else if (coupon.Duration == "repeating")
                    {
                        if (coupon.DurationInMonths == 1)
                        {
                            coupon.Object = coupon.PercentOff + "% off every Year for 1 month";
                        }
                        else
                        {
                            coupon.Object = coupon.PercentOff + "% off every Year for " + coupon.DurationInMonths + " months";
                        }
                    }
                }

                if (coupon.AmountOff != null)
                {
                    coupon.AmountOff = coupon.AmountOff / 100;
                    if (coupon.Duration == "once")
                    {
                        coupon.Object = "$" + coupon.AmountOff + " off once";
                    }

                    else if (coupon.Duration == "forever")
                    {
                        coupon.Object = "$" + coupon.AmountOff + " off " + coupon.Duration;
                    }

                    else if (coupon.Duration == "repeating")
                    {
                        if (coupon.DurationInMonths == 1)
                        {
                            coupon.Object = coupon.Currency.ToUpper() + coupon.AmountOff + " off every Year for 1 month";
                        }
                        else
                        {
                            coupon.Object = "$" + coupon.AmountOff + " off every Year for " + coupon.DurationInMonths + " months";
                        }
                    }
                }
                return(PaymentGatewayResult <IPaymentCoupon> .Success(_mapper.Map <IPaymentCoupon>(coupon)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCoupon> .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <List <IPaymentCoupon> > > GetAllCouponsAsync()
        {
            try
            {
                var options = new CouponListOptions
                {
                    Limit = 100,
                };
                var coupons = await _couponService.ListAsync(options);

                foreach (var item in coupons.Data)
                {
                    if (item.PercentOff != null)
                    {
                        if (item.Duration == "once")
                        {
                            item.Object = item.PercentOff + "% off " + item.Duration;
                        }
                        else if (item.Duration == "forever")
                        {
                            item.Object = item.PercentOff + "% off " + item.Duration;
                        }

                        else if (item.Duration == "repeating")
                        {
                            if (item.DurationInMonths == 1)
                            {
                                item.Object = item.PercentOff + "% off every Year for 1 month";
                            }
                            else
                            {
                                item.Object = item.PercentOff + "% off every Year for " + item.DurationInMonths + " months";
                            }
                        }
                    }

                    if (item.AmountOff != null)
                    {
                        item.AmountOff = item.AmountOff / 100;
                        if (item.Duration == "once")
                        {
                            item.Object = "$" + item.AmountOff + " off once";
                        }

                        else if (item.Duration == "forever")
                        {
                            item.Object = "$" + item.AmountOff + " off " + item.Duration;
                        }

                        else if (item.Duration == "repeating")
                        {
                            if (item.DurationInMonths == 1)
                            {
                                item.Object = "$" + item.AmountOff + " off every Year for 1 month";
                            }
                            else
                            {
                                item.Object = "$" + item.AmountOff + " off every Year for " + item.DurationInMonths + " months";
                            }
                        }
                    }
                }
                return(PaymentGatewayResult <List <IPaymentCoupon> > .Success(_mapper.Map <List <IPaymentCoupon> >(coupons)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <List <IPaymentCoupon> > .Failed(e));
            }
        }
        public async Task <PaymentGatewayResult <IPaymentCoupon> > CreateCouponAsync(CreateCouponViewModel model)
        {
            try
            {
                var options = new CouponCreateOptions();

                if (model.Duration != "repeating")
                {
                    model.DurationInMonths = null;
                }

                model.Currency       = "usd";
                model.MaxRedemptions = model.MaxRedemptions > 0 ? model.MaxRedemptions : null;
                model.PercentOff     = model.PercentOff > 0 ? model.PercentOff : null;
                model.AmountOff      = model.AmountOff > 0 ? model.AmountOff * 100 : null;

                options = _mapper.Map <CouponCreateOptions>(model);

                var coupon = await _couponService.CreateAsync(options);

                if (coupon.PercentOff != null)
                {
                    if (coupon.Duration == "once")
                    {
                        coupon.Object = coupon.PercentOff + "% off " + coupon.Duration;
                    }
                    else if (coupon.Duration == "forever")
                    {
                        coupon.Object = coupon.PercentOff + "% off " + coupon.Duration;
                    }

                    else if (coupon.Duration == "repeating")
                    {
                        if (coupon.DurationInMonths == 1)
                        {
                            coupon.Object = coupon.PercentOff + "% off every Year for 1 month";
                        }
                        else
                        {
                            coupon.Object = coupon.PercentOff + "% off every Year for " + coupon.DurationInMonths + " months";
                        }
                    }
                }

                if (coupon.AmountOff != null)
                {
                    if (coupon.Duration == "once")
                    {
                        coupon.Object = "$" + coupon.AmountOff + " off once";
                    }

                    else if (coupon.Duration == "forever")
                    {
                        coupon.Object = "$" + coupon.AmountOff + " off " + coupon.Duration;
                    }

                    else if (coupon.Duration == "repeating")
                    {
                        if (coupon.DurationInMonths == 1)
                        {
                            coupon.Object = coupon.Currency.ToUpper() + coupon.AmountOff + " off every Year for 1 month";
                        }
                        else
                        {
                            coupon.Object = "$" + coupon.AmountOff + " off every Year for " + coupon.DurationInMonths + " months";
                        }
                    }
                }
                return(PaymentGatewayResult <IPaymentCoupon> .Success(_mapper.Map <IPaymentCoupon>(coupon)));
            }
            catch (StripeException e)
            {
                return(PaymentGatewayResult <IPaymentCoupon> .Failed(e));
            }
        }