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); }