/// <inheritdoc /> public async Task OnMessageAsync(IAgentContext agentContext, UnpackedMessageContext messageContext) { var message = messageContext.GetMessage <AnyAgentMessage>(); var requestDecorator = message.FindDecorator <PaymentRequestDecorator>("payment_request"); if (requestDecorator != null) { var record = new PaymentRecord { ConnectionId = messageContext.Connection.Id, Details = requestDecorator.Details, ReferenceId = requestDecorator.Details.Id, Address = requestDecorator.Method.Data.PayeeId, Amount = requestDecorator.Details.Total.Amount.Value }; await record.TriggerAsync(PaymentTrigger.RequestReceived); await _recordService.AddAsync(agentContext.Wallet, record); if (messageContext.ContextRecord != null) { messageContext.ContextRecord.SetTag("PaymentRecordId", record.Id); await _recordService.UpdateAsync(agentContext.Wallet, messageContext.ContextRecord); } } var receiptDecorator = message.FindDecorator <PaymentReceiptDecorator>("payment_receipt"); if (receiptDecorator != null) { var search = await _recordService.SearchAsync <PaymentRecord>( wallet : agentContext.Wallet, query : SearchQuery.Equal(nameof(PaymentRecord.ReferenceId), receiptDecorator.RequestId), options : null, count : 5); var record = search.FirstOrDefault() ?? new PaymentRecord(); record.ReceiptId = receiptDecorator.TransactionId; await record.TriggerAsync(PaymentTrigger.ReceiptReceived); if (search.Any()) { await _recordService.UpdateAsync(agentContext.Wallet, record); } else { await _recordService.AddAsync(agentContext.Wallet, record); } } }
public async Task <PaymentRecord> AttachPaymentRequestAsync(IAgentContext context, AgentMessage agentMessage, PaymentDetails details, PaymentAddressRecord addressRecord = null) { // TODO: Add validation var paymentRecord = new PaymentRecord { Address = addressRecord.Address, Method = "sov", Amount = details.Total.Amount.Value, Details = details }; details.Id = details.Id ?? paymentRecord.Id; paymentRecord.ReferenceId = details.Id; await paymentRecord.TriggerAsync(PaymentTrigger.RequestSent); await recordService.AddAsync(context.Wallet, paymentRecord); agentMessage.AddDecorator(new PaymentRequestDecorator { Method = new PaymentMethod { SupportedMethods = "sov", Data = new PaymentMethodData { PayeeId = addressRecord.Address, SupportedNetworks = new[] { "Sovrin MainNet" } } }, Details = details }, "payment_request"); return(paymentRecord); }
/// <inheritdoc /> public async Task MakePaymentAsync(IAgentContext agentContext, PaymentRecord paymentRecord, PaymentAddressRecord addressFromRecord = null) { if (paymentRecord.Amount == 0) { throw new AgentFrameworkException(ErrorCode.InvalidRecordData, "Cannot make a payment with 0 amount"); } await paymentRecord.TriggerAsync(PaymentTrigger.ProcessPayment); if (paymentRecord.Address == null) { throw new AgentFrameworkException(ErrorCode.InvalidRecordData, "Payment record is missing an address"); } var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet); if (addressFromRecord == null) { addressFromRecord = await GetDefaultPaymentAddressAsync(agentContext); } await RefreshBalanceAsync(agentContext, addressFromRecord); if (addressFromRecord.Balance < paymentRecord.Amount) { throw new AgentFrameworkException(ErrorCode.PaymentInsufficientFunds, "Address doesn't have enough funds to make this payment"); } var txnFee = await GetTransactionFeeAsync(agentContext, TransactionTypes.XFER_PUBLIC); var paymentResult = await IndyPayments.BuildPaymentRequestAsync( wallet : agentContext.Wallet, submitterDid : null, inputsJson : addressFromRecord.Sources.Select(x => x.Source).ToJson(), outputsJson : new[] { new IndyPaymentOutputSource { Amount = paymentRecord.Amount, Recipient = paymentRecord.Address }, new IndyPaymentOutputSource { Recipient = addressFromRecord.Address, Amount = addressFromRecord.Balance - paymentRecord.Amount - txnFee } }.ToJson(), extra : null); var response = await Ledger.SignAndSubmitRequestAsync(await agentContext.Pool, agentContext.Wallet, provisioning.Endpoint.Did, paymentResult.Result); var paymentResponse = await IndyPayments.ParsePaymentResponseAsync(TokenConfiguration.MethodName, response); var paymentOutputs = paymentResponse.ToObject <IList <IndyPaymentOutputSource> >(); var paymentOutput = paymentOutputs.SingleOrDefault(x => x.Recipient == paymentRecord.Address); paymentRecord.ReceiptId = paymentOutput.Receipt; addressFromRecord.Sources = paymentOutputs .Where(x => x.Recipient == addressFromRecord.Address) .Select(x => new IndyPaymentInputSource { Amount = x.Amount, PaymentAddress = x.Recipient, Source = x.Receipt }) .ToList(); await recordService.UpdateAsync(agentContext.Wallet, paymentRecord); await recordService.UpdateAsync(agentContext.Wallet, addressFromRecord); }