public async Task <ActionResult> Notify([FromQuery] string customKey, [FromHeader] string HMAC, [FromForm] PaymentNotifyRequest model) { try { logger.LogTrace("Start processing callback {Notify} ", nameof(Notify), customKey); logger.LogTrace(JsonConvert.SerializeObject(Request.Form)); if (ModelState.IsValid) { var calculatedHMAC = CalculateHMACSHA512Hex(Request.Form); if (!string.Equals(HMAC, calculatedHMAC)) { logger.LogError($"Invalid HMAC {HMAC} {calculatedHMAC}"); logger.LogError(JsonConvert.SerializeObject(Request.Form)); return(Content("ER")); } var request = new ProcessPaymentTransaction() { TransactionHash = model.TransactionHash, Address = model.Address, Amount = model.Amount, AmountBigInt = model.AmountBigInt, Currency = Enum.Parse <Currency>(model.Currency), // TODO IsConfirmed = model.IsConfirmed, VerificationCode = model.VerificationCode // TODO check }; var rs = await paymentService.ProcessCallback(request); if (rs.IsValid) { logger.LogInformation("End processing Notify"); return(Content("OK")); } else { logger.LogError("End processing Notify with Error"); return(Content("ER")); } } else { logger.LogError("ModelState Error", JsonConvert.SerializeObject(ModelState)); } } catch (Exception e) { logger.LogError("paymentTransactionService.ProcessCallback Exception {error}", e.ToString()); } logger.LogInformation("Finish processing callback {Notify} {CustomKey}", nameof(Notify), customKey); return(Content("ER")); }
public void PaymentsCallbackTest1() { var wallet = context.Wallets.First(w => w.UserId == user.Id && w.Currency == Currency.GVT); Assert.IsNull(wallet.WalletTransactions); var payment = new ProcessPaymentTransaction { Amount = 100, Address = "0x00", Status = PaymentTransactionStatus.ConfirmedAndValidated, Currency = Currency.GVT }; paymentService.ProcessCallback(payment); Assert.AreEqual(100, context.Wallets.First(w => w.UserId == user.Id && w.Currency == Currency.GVT).Amount); }
public async Task <PaymentTransactionInfo> ProcessCallback(ProcessPaymentTransaction request) { var blockchainAddress = context.BlockchainAddresses.FirstOrDefault(addr => addr.Address == request.Address); if (blockchainAddress == null) { var msg = $"Eth address not found - {request.Address}"; logger.LogError(msg); throw new ApplicationException(msg); } if (request.Currency != blockchainAddress.Currency) { var msg = $"Wallet and Transaction currency should be the same {blockchainAddress.Id}"; logger.LogError(msg); throw new ApplicationException(msg); } var wallet = context.Wallets.First(w => w.UserId == blockchainAddress.UserId && w.Currency == blockchainAddress.Currency); PaymentTransactionInfo paymentTransactionInfo; using (var transaction = await context.Database.BeginTransactionAsync()) { var paymentTransaction = context.PaymentTransactions .FirstOrDefault(t => t.Hash == request.TransactionHash && t.BlockchainAddressId == blockchainAddress.Id); if (paymentTransaction != null) { if (paymentTransaction.Status == PaymentTransactionStatus.Pending || paymentTransaction.Status == PaymentTransactionStatus.New) { paymentTransaction.Status = request.Status; paymentTransaction.LastUpdated = DateTime.UtcNow; context.Update(paymentTransaction); await context.SaveChangesAsync(); } else { logger.LogError($"Can not override status from {paymentTransaction.Status} to {request.Status}"); } } else { var walletTransactions = new WalletTransactions() { Id = Guid.NewGuid(), WalletId = wallet.Id, Type = WalletTransactionsType.Deposit, Date = DateTime.UtcNow, Amount = request.Amount }; context.WalletTransactions.Add(walletTransactions); await context.SaveChangesAsync(); paymentTransaction = new PaymentTransactions { Id = Guid.NewGuid(), Hash = request.TransactionHash, Type = PaymentTransactionType.Deposit, BlockchainAddressId = blockchainAddress.Id, Amount = request.Amount, Fee = request.Fee, DateCreated = DateTime.UtcNow, Status = request.Status, PayoutTxHash = request.PayoutTxHash, PayoutServiceFee = request.PayoutServiceFee, PayoutMinerFee = request.PayoutMinerFee, WalletTransaction = walletTransactions }; context.PaymentTransactions.Add(paymentTransaction); if (paymentTransaction.Status == PaymentTransactionStatus.ConfirmedAndValidated) { wallet.Amount += paymentTransaction.Amount; await context.SaveChangesAsync(); } } transaction.Commit(); paymentTransactionInfo = new PaymentTransactionInfo { TransactionId = paymentTransaction.Id, TransactionHash = paymentTransaction.Hash, Amount = paymentTransaction.Amount, Currency = request.Currency.ToString(), GatewayCode = request.GatewayCode, Status = paymentTransaction.Status, IsValid = true }; } return(paymentTransactionInfo); }
public async Task <PaymentTransactionInfo> ProcessCallback(ProcessPaymentTransaction request) { var blockchainAddress = context.BlockchainAddresses.FirstOrDefault(addr => addr.Address == request.Address && addr.Currency == request.Currency); if (blockchainAddress == null) { var msg = $"{request.Currency} address not found - {request.Address}"; logger.LogError(msg); throw new ApplicationException(msg); } if (request.VerificationCode != blockchainAddress.VerificationCode) { var msg = $"Invalid VerificationCode {request.VerificationCode} for {request.Address}"; logger.LogError(msg); throw new ApplicationException(msg); } PaymentTransactionInfo transactionInfo; using (var transaction = await context.Database.BeginTransactionAsync()) { var wallet = context.Wallets.FirstOrDefault(w => w.UserId == blockchainAddress.UserId && w.Currency == blockchainAddress.Currency); if (wallet == null) { wallet = new Wallet() { UserId = blockchainAddress.UserId.Value, Amount = 0, Currency = blockchainAddress.Currency, }; context.Wallets.Add(wallet); context.SaveChanges(); } var blockchainTransaction = context.BlockchainTransactions .FirstOrDefault(t => t.Hash == request.TransactionHash && t.BlockchainAddressId == blockchainAddress.Id); if (blockchainTransaction != null) { if (blockchainTransaction.Status == BlockchainTransactionStatus.Pending || blockchainTransaction.Status == BlockchainTransactionStatus.New) { blockchainTransaction.Status = request.IsConfirmed ? BlockchainTransactionStatus.ConfirmedAndValidated : BlockchainTransactionStatus.Pending; blockchainTransaction.LastUpdated = DateTime.UtcNow; context.Update(blockchainTransaction); if (blockchainTransaction.Status == BlockchainTransactionStatus.ConfirmedAndValidated) { ProcessPayment(wallet, blockchainTransaction); } } else { logger.LogError($"Can not override status from {blockchainTransaction.Status} to {request.IsConfirmed}"); } } else { blockchainTransaction = new BlockchainTransaction { Id = Guid.NewGuid(), Hash = request.TransactionHash, Type = BlockchainTransactionType.Deposit, BlockchainAddressId = blockchainAddress.Id, Amount = request.Amount, //AmountBigInt = request.AmountBigInt,//TODO: Please add as string Currency = request.Currency, Fee = request.Fee, DateCreated = DateTime.UtcNow, Status = request.IsConfirmed ? BlockchainTransactionStatus.ConfirmedAndValidated : BlockchainTransactionStatus.Pending }; context.BlockchainTransactions.Add(blockchainTransaction); if (blockchainTransaction.Status == BlockchainTransactionStatus.ConfirmedAndValidated) { ProcessPayment(wallet, blockchainTransaction); } } await context.SaveChangesAsync(); transaction.Commit(); transactionInfo = new PaymentTransactionInfo { TransactionId = blockchainTransaction.Id, TransactionHash = blockchainTransaction.Hash, Amount = blockchainTransaction.Amount, Currency = request.Currency.ToString(), GatewayCode = request.GatewayCode, Status = blockchainTransaction.Status, IsValid = true }; } return(transactionInfo); }