Example #1
0
        public async Task<DonationResponse> DonateAsync(DonationRequest request)
        {
            var currentUser = HttpContext.Current.User;
            try
            {
                var chance = _dbContext.Chances.FirstOrDefault(c => c.Id == request.ChanceId);

                if (chance == null || chance.Status != ChanceStatus.Open)
                {
                    return new DonationResponse()
                    {
                        Amount = 0,
                        Confirmation = null,
                        Message = "This Chance has either expired, or has been deleted and can no longer accept donations.",
                        Status = DonationStatus.Error
                    };
                }

                if (chance.ExpirationType == ExpirationType.Expiring
                    && DateTime.Now > chance.Expires)
                {
                    return new DonationResponse()
                    {
                        Amount = 0,
                        Confirmation = null,
                        Message = "This Chance has expired, and can no longer accept donations.",
                        Status = DonationStatus.Error
                    };
                }
                else
                {
                    var charge = new StripeChargeCreateOptions()
                    {
                        Amount = (int)(request.Amount * 100M), // amount is in cents usd
                        Currency = "usd",
                        Description = "SavingChance.com " + request.DonationType.ToString() + " for '" + chance.Title + "'",
                        Source = new StripeSourceOptions()
                        {
                            TokenId = request.StripeToken
                        },
                        Capture = true
                    };

                    if (currentUser.Identity.IsAuthenticated)
                    {
                        charge.ReceiptEmail = currentUser.Identity.Name;
                    }
                    else if (!string.IsNullOrEmpty(request.Email))
                    {
                        charge.ReceiptEmail = request.Email;
                    }

                    if (chance.SaveType == SaveType.Adoption 
                        && request.DonationType == DonationType.Adoption)
                    {
                        charge.Amount = (int)((chance.Goal - chance.Total) * 100M);  // adjust amount to remainder, in case other donations came in
                        chance.Status = ChanceStatus.PendingAdoption;
                    }

                    var options = new StripeRequestOptions()
                    {
                        ApiKey = ConfigurationManager.AppSettings["StripeApiKey"]
                    };

                    if (chance.SaveType == SaveType.Donation
                        || request.DonationType == DonationType.Donation)
                    {
                        // non-tipping point fee, goes straight to provider, we take a fee
                        charge.ApplicationFee = (int)(request.Amount * 100M * STANDARD_FEE); // fee is in cents usd
                        options.StripeConnectAccountId = chance.Sponsor.StripeAccountId;
                    }
                    else
                    {
                        var metaData = new Dictionary<string, string>
                        {
                            { "PaymentType", request.DonationType.ToString() },
                            { "ChanceId", chance.Id.ToString() },
                        };
                        charge.Metadata = metaData;
                    }

                    var chargeService = new StripeChargeService();
                    var chargeReceipt = chargeService.Create(charge, options);

                    if (request.IsPersonalized)
                    {
                        var message = string.IsNullOrEmpty(request.Message)
                            ? request.DonationType == DonationType.Adoption ? "I'd like to adopt '" + chance.Title + "'" : "I hope my donation will help '" + chance.Title + "'"
                            : request.Message;
                        message += "\r\n\r\n";
                        message += request.DonationType.ToString() + ": " + request.Amount.ToString("C0") + "\r\n";
                        message += "Payment: " + chargeReceipt.Source.Brand + ", Last Four: " + chargeReceipt.Source.Last4 + "\r\n";
                        message += "Created: " + chargeReceipt.Created.ToString() + "\r\n";
                        message += "Charge Id: " + chargeReceipt.Id + "\r\n";
                        string from = null;
                        if (!request.IsAnonymous)
                        {
                            if (currentUser.Identity.IsAuthenticated)
                                from = currentUser.Identity.Name;
                            else
                                from = request.Email;
                        }
                        // i want this to run async
                        await _emailService.SendAsync(chance.Sponsor.Email,
                                request.DonationType == DonationType.Adoption ? "Adoption Request For " + chance.Title : "Donation For " + chance.Title,
                                message,
                                null,
                                from);
                    }

                    var amount = (decimal)charge.Amount / 100M;
                    chance.Total += amount;
                    chance.Payments.Add(new Payment()
                    {
                        Amount = amount,
                        Created = chargeReceipt.Created,
                        Payor = currentUser.Identity.IsAuthenticated ? _dbContext.Users.Single(u => u.UserName.Equals(currentUser.Identity.Name)) : null,
                        PaymentType = request.DonationType,
                        StripeId = chargeReceipt.Id
                    });

                    await _dbContext.SaveChangesAsync();

                    return new DonationResponse()
                    {
                        Amount = (decimal)chargeReceipt.Amount / 100M,
                        Confirmation = chargeReceipt.Id.Replace("ch_", ""),
                        Message = chargeReceipt.FailureMessage,
                        Status = chargeReceipt.Status == "succeeded" ? DonationStatus.Success : DonationStatus.Error
                    };
                }
            }
            catch (Exception ex)
            {
                return new DonationResponse()
                {
                    Amount = 0,
                    Confirmation = "n/a",
                    Message = ex.Message + (!string.IsNullOrEmpty(((StripeException)ex).StripeError.DeclineCode) 
                        ? "<br />Reason: " + ((StripeException)ex).StripeError.DeclineCode 
                        : ""),
                    Status = DonationStatus.Error
                };
            }
        }
 public async Task<HttpResponseMessage> Post(DonationRequest request)
 {
     var result = await _paymentService.DonateAsync(request);
     return Request.CreateResponse<DonationResponse>(result.Status == DonationStatus.Success ? HttpStatusCode.OK : HttpStatusCode.InternalServerError, result);
 }