예제 #1
0
        public async Task <Result <PaymentResponse> > Charge(string referenceCode, ApiCaller apiCaller, IPaymentCallbackService paymentCallbackService)
        {
            return(await GetChargingAccountId()
                   .Bind(GetChargingAccount)
                   .Bind(GetChargingAmount)
                   .Check(ChargeMoney)
                   .Tap(SendNotificationIfRequired)
                   .Bind(StorePayment)
                   .Bind(ProcessPaymentResults)
                   .Map(CreateResult));


            Task <Result <int> > GetChargingAccountId()
            => paymentCallbackService.GetChargingAccountId(referenceCode);


            async Task <Result <AgencyAccount> > GetChargingAccount(int accountId)
            => await _context.AgencyAccounts.SingleOrDefaultAsync(a => a.Id == accountId)
            ?? Result.Failure <AgencyAccount>("Could not find agency account");


            async Task <Result <(AgencyAccount, MoneyAmount)> > GetChargingAmount(AgencyAccount account)
            {
                var(_, isFailure, amount, error) = await paymentCallbackService.GetChargingAmount(referenceCode);

                if (isFailure)
                {
                    return(Result.Failure <(AgencyAccount, MoneyAmount)>(error));
                }

                return(account, amount);
            }

            Task <Result> ChargeMoney((AgencyAccount account, MoneyAmount amount) chargeInfo)
            {
                var(account, amount) = chargeInfo;
                return(_accountPaymentProcessingService.ChargeMoney(account.Id, new ChargedMoneyData(
                                                                        currency: amount.Currency,
                                                                        amount: amount.Amount,
                                                                        reason: $"Charge money for service '{referenceCode}'",
                                                                        referenceCode: referenceCode),
                                                                    apiCaller));
            }

            async Task <Result <Payment> > StorePayment((AgencyAccount account, MoneyAmount amount) chargeInfo)
            {
                var(account, amount) = chargeInfo;
                var(paymentExistsForBooking, _, _, _) = await GetPayment(referenceCode);

                if (paymentExistsForBooking)
                {
                    return(Result.Failure <Payment>("Payment for current booking already exists"));
                }

                var now     = _dateTimeProvider.UtcNow();
                var info    = new AccountPaymentInfo(string.Empty);
                var payment = new Payment
                {
                    Amount        = amount.Amount,
                    AccountNumber = account.Id.ToString(),
                    Currency      = amount.Currency,
                    Created       = now,
                    Modified      = now,
                    Status        = PaymentStatuses.Captured,
                    Data          = JsonConvert.SerializeObject(info),
                    AccountId     = account.Id,
                    PaymentMethod = PaymentTypes.VirtualAccount,
                    ReferenceCode = referenceCode
                };

                _context.Payments.Add(payment);
                await _context.SaveChangesAsync();

                _context.Detach(payment);

                return(payment);
            }

            Task <Result> ProcessPaymentResults(Payment payment)
            => paymentCallbackService.ProcessPaymentChanges(payment);


            Task SendNotificationIfRequired((AgencyAccount account, MoneyAmount amount) chargeInfo)
            => _balanceManagementNotificationsService.SendNotificationIfRequired(chargeInfo.account, chargeInfo.amount);


            PaymentResponse CreateResult()
            => new(string.Empty, CreditCardPaymentStatuses.Success, string.Empty);
        }
        public ActionResult Profile(Account account)
        {
            try
            {
                var loginedAccount = (Account)SessionPersister.account;

                var currentAccount = ocmde.Accounts.SingleOrDefault(a => a.Id == account.Id);

                if (account.Username != null && account.Username.Length > 0 && loginedAccount.Username != account.Username)
                {
                    if (Exists(account.Username))
                    {
                        ModelState.AddModelError("username", Resources.Customer.Username_exists);
                    }
                }

                if (account.Password != null && account.Password.Length != 0 && !PasswordHelper.IsValidPassword(account.Password))
                {
                    ModelState.AddModelError("Password", Resources.Vendor.Password_validate_message);
                }

                if (ModelState.IsValid)
                {
                    if (account.Password != null && account.Password.Length != 0)
                    {
                        currentAccount.Password = BCrypt.Net.BCrypt.HashPassword(account.Password);
                    }
                    currentAccount.Email    = account.Email;
                    currentAccount.FullName = account.FullName;
                    currentAccount.Phone    = account.Phone;
                    currentAccount.Username = account.Username;

                    if (currentAccount.AccountAddresses.Count <= 0)
                    {
                        AccountAddress acctAddress = account.defaultAddress;
                        acctAddress.Id = Guid.NewGuid();
                        currentAccount.AccountAddresses.Add(acctAddress);
                    }
                    else
                    {
                        AccountAddress acctAddressOriginal = currentAccount.AccountAddresses.FirstOrDefault();
                        AccountAddress forUpdate           = ocmde.AccountAddresses.Find(acctAddressOriginal.Id);
                        forUpdate.City         = account.defaultAddress.City;
                        forUpdate.LineAddress1 = account.defaultAddress.LineAddress1;
                        forUpdate.LineAddress2 = account.defaultAddress.LineAddress2;
                        forUpdate.ZipCode      = account.defaultAddress.ZipCode;
                    }
                    if (currentAccount.AccountPaymentInfoes.Count <= 0)
                    {
                        AccountPaymentInfo paymentInfo = new AccountPaymentInfo();
                        paymentInfo.CreditCardNo = account.accountPaymentInfo.CreditCardNo;
                        paymentInfo.ExpiryDate   = account.accountPaymentInfo.ExpiryDate;
                        paymentInfo.FullName     = account.accountPaymentInfo.FullName;
                        //paymentInfo.Id = Guid.NewGuid();
                        currentAccount.AccountPaymentInfoes.Add(paymentInfo);
                    }
                    else
                    {
                        AccountPaymentInfo acctPaymentOriginal = currentAccount.AccountPaymentInfoes.FirstOrDefault();
                        acctPaymentOriginal.CreditCardNo = account.accountPaymentInfo.CreditCardNo;
                        acctPaymentOriginal.ExpiryDate   = account.accountPaymentInfo.ExpiryDate;
                        acctPaymentOriginal.FullName     = account.accountPaymentInfo.FullName;
                    }
                    ocmde.SaveChanges();
                    SessionPersister.account = ocmde.Accounts.Find(account.Id);
                    return(RedirectToAction("Profile", "Login"));
                }
                else
                {
                    return(View("Profile", account));
                }
            }
            catch (Exception e)
            {
                return(View("Error", new HandleErrorInfo(e, "Login", "Profile")));
            }
        }
예제 #3
0
        public Task <Result <PaymentResponse> > Charge(Booking booking, UserInfo user, int agencyId, string clientIp)
        {
            return(Result.Success()
                   .BindWithTransaction(_context, () =>
                                        Charge()
                                        .Tap(_ => ChangePaymentStatusToCaptured())));


            async Task <Result <PaymentResponse> > Charge()
            {
                var(_, isAmountFailure, amount, amountError) = await GetAmount();

                if (isAmountFailure)
                {
                    return(Result.Failure <PaymentResponse>(amountError));
                }

                var(_, isAccountFailure, account, accountError) = await _accountManagementService.Get(agencyId, booking.Currency);

                if (isAccountFailure)
                {
                    return(Result.Failure <PaymentResponse>(accountError));
                }

                return(await Result.Success()
                       .BindWithLock(_locker, typeof(Booking), booking.Id.ToString(), () => Result.Success()
                                     .Ensure(IsNotPayed, $"The booking '{booking.ReferenceCode}' is already paid")
                                     .Ensure(CanCharge, $"Could not charge money for the booking '{booking.ReferenceCode}'")
                                     .Bind(ChargeMoney)
                                     .Bind(StorePayment)
                                     .Map(CreateResult)));

                Task <Result <decimal> > GetAmount() => GetPendingAmount(booking).Map(p => p.Amount);

                bool IsNotPayed() => booking.PaymentStatus != BookingPaymentStatuses.Captured;

                bool CanCharge() =>
                booking.PaymentMethod == PaymentMethods.BankTransfer &&
                ChargeableStatuses.Contains(booking.Status);

                Task <Result> ChargeMoney()
                => _accountPaymentProcessingService.ChargeMoney(account.Id, new ChargedMoneyData(
                                                                    currency: account.Currency,
                                                                    amount: amount,
                                                                    reason: $"Charge money after booking '{booking.ReferenceCode}'",
                                                                    referenceCode: booking.ReferenceCode),
                                                                user);

                async Task <Result> StorePayment()
                {
                    var(paymentExistsForBooking, _, _, _) = await GetPayment(booking.Id);

                    if (paymentExistsForBooking)
                    {
                        return(Result.Failure("Payment for current booking already exists"));
                    }

                    var now     = _dateTimeProvider.UtcNow();
                    var info    = new AccountPaymentInfo(clientIp);
                    var payment = new Payment
                    {
                        Amount        = amount,
                        BookingId     = booking.Id,
                        AccountNumber = account.Id.ToString(),
                        Currency      = booking.Currency.ToString(),
                        Created       = now,
                        Modified      = now,
                        Status        = PaymentStatuses.Captured,
                        Data          = JsonConvert.SerializeObject(info),
                        AccountId     = account.Id,
                        PaymentMethod = PaymentMethods.BankTransfer
                    };

                    _context.Payments.Add(payment);
                    await _context.SaveChangesAsync();

                    return(Result.Success());
                }

                PaymentResponse CreateResult() => new PaymentResponse(string.Empty, CreditCardPaymentStatuses.Success, string.Empty);
            }

            async Task ChangePaymentStatusToCaptured()
            {
                if (booking.PaymentStatus == BookingPaymentStatuses.Captured)
                {
                    return;
                }

                booking.PaymentStatus = BookingPaymentStatuses.Captured;
                _context.Update(booking);
                await _context.SaveChangesAsync();
            }
        }