atomicpay

Handle AtomicPay’s webhook with Microsoft Azure (Part 2/3) – invoice verification with Azure KeyVault

Handle AtomicPay’s webhook with Microsoft Azure (Part 2/3) – invoice verification with Azure KeyVault

Series overview

  1. Handle the incoming notification with an Azure Function (first post)
  2. Verify the invoice state within the Azure Function, but store the API credentials in the most secure way (this post)
  3. Send a push notification via Azure Notificationhub to all devices that have linked a merchant’s account to it (third post [coming soon])

Storing credentials securely

When we consume web services, we need to authenticate our applications against them/their API. In the past, I always saw (and in fact, I also made) samples that do ignore the security of those credentials and provide them in code, leaving additional research (if you are new to that topic) and making the samples incomplete. As the goal of this post is to verify the state of a received invoice against the AtomicPay API, the first step is to provide a secure mechanism for storing our API credentials on Azure.

Get your AtomicPay API keys

If you haven’t signed up for an AtomicPay account, you should probably do it now. Once you have logged in, open the menu and select ‘API Integration‘:

AtomicPay menu select API Integration

On this page, you find your pre-generated API-Keys. Should your keys be compromised, you will be able to regenerate your keys here as well:

AtomicPay API Integration page

Introducing Azure KeyVault

According to the Azure KeyVault documentation, it is

a tool for securely storing and accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, or certificates. A Vault is logical group of secrets.

As we are dealing with a public/private key credential combo, Azure KeyVault fits our goal to securely store the credentials perfectly. Since November last year, Azure Functions are able to use the KeyVault via their AppSettings. This is what the first half of this post is about.

Creating a new KeyVault

Login to the Azure Portal and go to the Marketplace. Search for ‘Key Vault‘ there and select it from the results:

Azure Marketplace search for Key Vault

You will be prompted with the creation menu. Give it a unique name and select your existing resource group (which will make sure we are in the correct location automatically). Once done, click on the create button:

Azure create new key vault menu

It will take a minute or two until the deployment is done. From the notification, you’ll get a direct link to the resource:

In the overview menu, select ‘Secrets’, where we will store our credentials:

Azure KeyVault menu - select Secrets

If you are wondering why we are using the ‘Secrets‘ option over ‘Keys‘ – the keys are already generated by AtomicPay, and the import function wants a backup file. I did not have a deeper look into this option as the ‘Secrets‘ option offers all I need.

The next step is to add a secret entry for AtomicPay’s account id, public and private key:

Azure KeyVault add secret

Once you have added the Application ID and your keys into ‘Secrets‘, click on ‘Overview‘. On the right-hand side, you’ll see an entry called ‘DNS Name’. Hover with the mouse to reveal the copy button and copy it:

Azure KeyVault Url Copy

Now go to your Azure Function and select ‘Application settings‘. Scroll a bit down and add a new setting. You can name it whatever you want, I just used ‘KeyVaultUri‘. Paste the url you have copied earlier into the value field. Do not forget to hit the ‘Save‘-button after that:

Azure Function - Application settings

Now we are just one step away of being able to use the KeyVault in our code. Go back to ‘Overview‘ on your Function and click on the ‘Platform features‘ tab. Select ‘Identity‘ there:

Azure Function select Identity

We need to enable the ‘System assigned‘ managed identity feature to allow the Function to interact with the Azure KeyVault from our code. This will add our Function to an Azure AD instance that handles the access rights for us:

Azure function enable System assigned identity

Now we have everything in place to use the KeyVault to retrieve the API credentials we need for invoice verification.

Retrieving credentials in our code

Before we start to rewrite our function code, we need to install two NuGet-Packages into our Function project. Right click on the project and select ‘Manage NuGet Packages…‘. Search for these to packages and install them:

Refactoring the initial code

Whenever possible, we should take the chance to refactor our code. I have done so on adding the authentication layer for this sample. First, we will be moving the code to get the payload off the webhook into its own method:

        private static async Task<WebhookInvoiceInfo> GetPaymentPayload(HttpRequestMessage requestMessage)
        {
            _traceWriter.Info("trying to get payload object from request...");
            WebhookInvoiceInfo result = null;
            _jsonSerializerSettings = new JsonSerializerSettings()
            {
                MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                Converters ={

                        new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal },
                        StringToLongConverter.Instance,
                        StringToDecimalConverter.Instance,
                        StringToInvoiceStatusConverter.Instance,
                        StringToInvoiceStatusExceptionConverter.Instance
                }
            };

            _jsonSerializer = JsonSerializer.Create(_jsonSerializerSettings);

            using (var stream = await requestMessage.Content.ReadAsStreamAsync())
            {
                using (var reader = new StreamReader(stream))
                {
                    using (var jsonReader = new JsonTextReader(reader))
                    {
                        result = _jsonSerializer.Deserialize<WebhookInvoiceInfo>(jsonReader);
                    }
                }
            }

            return result;
        }

Next, we need are going to write another method to retrieve the credentials from the Azure KeyVault and initialize the AtomicPay SDK properly:

        private static async Task<bool> InitAtomicPay()
        {
            bool isAuthenticated = false;

            //initialize Azure Service Token Provider and authenticate this function against the KeyVault
            var serviceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(serviceTokenProvider.KeyVaultTokenCallback));

            //getting the key vault url
            var vaultBaseUrl = ConfigurationManager.AppSettings["KeyVaultUri"];

            //retrieving the appId and secrets
            var accId = await keyVaultClient.GetSecretAsync(vaultBaseUrl, "atomicpay-accId");
            var accPBK = await keyVaultClient.GetSecretAsync(vaultBaseUrl, "atomicpay-accPBK");
            var accPVK = await keyVaultClient.GetSecretAsync(vaultBaseUrl, "atomicpay-accPVK");

            //initialize AtomicPay SDK and return the result
            await AtomicPay.Config.Current.Init(accId.Value, accPBK.Value, accPVK.Value);

            if (!AtomicPay.Config.Current.IsInitialized)
            {
                isAuthenticated = false;
                _traceWriter.Info("failed to authenticate with AtomicPay");
            }
            else
            {
                isAuthenticated = true;
                _traceWriter.Info("successfully authenticated with AtomicPay.");
            }

            return isAuthenticated;
        }

Now that we authenticated against the API, we are finally able to verify the state of the invoice sent by the webhook. Let’s put everything together:

        //renamed this function (not particullary necessary)
        [FunctionName("InvoiceVerifier")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            //enable other methods to write to log
            _traceWriter = log;
            _traceWriter.Info($"arrived at function trigger for 'InvoiceVerifier'...");

            //retrieving the payload
            var payload = await GetPaymentPayload(req);

            //if payload is null, there is something wrong
            if (payload != null)
            {
                //authenticate the Function against AtomicPay
                var isAuthenticated = await InitAtomicPay();
                if (isAuthenticated)
                {
                    AtomicPay.Entity.InvoiceInfoDetails invoiceInfoDetails = null;

                    _traceWriter.Info($"trying to verify invoice id {payload.InvoiceId} ...");

                    //verifying the invoice 
                    using (var atomicPayClient = new AtomicPay.AtomicPayClient())
                    {
                        var invoiceObj = await atomicPayClient.GetInvoiceByIdAsync(payload?.InvoiceId);

                        if (invoiceObj == null)
                            return req.CreateResponse(HttpStatusCode.BadRequest, $"there was an error getting invoice with id {payload?.InvoiceId}. Response was null");

                        if (invoiceObj.IsError)
                            return req.CreateResponse(HttpStatusCode.BadRequest, $"there was an error getting invoice with id {payload?.InvoiceId}. Message from AtomicPay: {invoiceObj.Value.Message}");
                        else
                            invoiceInfoDetails = invoiceObj.Value?.Result?.FirstOrDefault();
                    }

                    //this will be the point where we will trigger the push notification in the last part
                    switch (invoiceInfoDetails.Status)
                    {
                        case AtomicPay.Entity.InvoiceStatus.Paid:
                        case AtomicPay.Entity.InvoiceStatus.PaidAfterExpiry:
                        case AtomicPay.Entity.InvoiceStatus.Overpaid:
                        case AtomicPay.Entity.InvoiceStatus.Complete:
                            log.Info($"invoice with id {invoiceInfoDetails.InvoiceId} is paid");
                            break;
                        default:
                            log.Info($"invoice with id {invoiceInfoDetails.InvoiceId} is not yet paid");
                            break;
                    }
                }
                else
                {
                    req.CreateResponse(HttpStatusCode.Unauthorized, "failed to authenticate with AtomicPay");
                }
            }
            else
                req.CreateResponse(HttpStatusCode.BadRequest, "there was an error getting the payload from request body");

            return req.CreateResponse(HttpStatusCode.OK, $"verified received invoice with id: '{payload?.InvoiceId}'");
        }

Save the changes to your code. After that, right click on the project and hit ‘Publish’ to update the function on Azure. Once you have published the updated code, you should be able to test your Function once again with Postman and receive a result like this:

Postman response from updated function

Conclusion

As you can see, Microsoft Azure provides a convenient way to store credentials and use them in your Azure Functions. This approach makes the whole process a whole lot more secure. This post also showed the ease of implementation of the AtomicPay .NET SDK.

In the third and last post of this series, we will connect our function to an Azure Notificationhub for sending push notifications to all devices that have registered with a certain merchant account. As always, I hope also this post was helpful for some of you.

Until the next post, happy coding, everyone!

Title image credit

Posted by msicc in Azure, Crypto&Blockchain, Dev Stories, Xamarin, 0 comments
Handle AtomicPay’s webhook with Microsoft Azure (Part 1/3)

Handle AtomicPay’s webhook with Microsoft Azure (Part 1/3)

In case you missed the announcement of the SDK, here is a quick way to read it now:

What is a webhook?

Webhooks are gaining popularity, and a lot of services and websites provide them for easier interactions with other websites and service. Most commonly, webhooks are triggered by an event, and send a request to subscribers of the webhook. AtomicPay provides such a webhook for invoices and their payment state.

Why Azure?

There are several reasons, with Azure being my personal choice of cloud service being the main one. Besides that, Azure provides two additional features I am a fan of, namely Azure KeyVault for credential handling and Azure Notificationhub for pushing notifications to a broad range of platforms. This new series will be split into three parts:

  1. Handle the incoming notification with an Azure Function (this post)
  2. Verify the invoice state within the Azure Function, but store the API credentials in the most secure way (second post)
  3. Send a push notification via Azure Notificationhub to all devices that have linked a merchant’s account to it (third post)

Getting started

First, login to your Azure account (or create a new one). On the left menu, select ‘Create a resource’ and search for ‘Serverless Function App’:

Azure Portal create new resource

In the next step, you’ll assign a name for your Function, create a new resource group and assign or create a storage account:

Azure new Function App settings

Once deployment is finished, click the ‘Go to resource’ button in the portal notification:

Azure notification deployment succeeded

Next step is to add the code for our function. Click on the ‘+’ sign besides ‘Functions’:

add new function

Now you have to decide how you want to move on in development. I chose Visual Studio, because we need some Nuget packages later and I enjoy having Intellisense while writing code. Just follow the instructions on screen to get your project up and running.

select ide for writing function code

Make sure you are selecting the v1 (.NET Framework) version of the project. This is needed because we want to connect to a Notificationhub later (in the third post), and as of now, v2 does not support this (according to the docs).

VS new project dialog for Azure Function

With a click on ‘OK’, Visual Studio creates the new project for you.

Seeing some code… finally!

If you look at the just generated code in the generated Function class, you may immediately be reminded at something. You’re right, as Azure functions are based on ASP.NET, so there are some similarities. Let’s have a look at the parameters of the Run method (you can change the method name as the FunctionName attribute declares the method already as such).

The first parameter is the HttpTriggerAttribute, which defines the AuthorizationLevel, the allowed methods and an optional route. The only change that I made to the default attribute parameters is to remove the “get” method, because AtomicPay’s Webhook sends a POST request.

The second parameter is the HttpRequestMessage that contains the request sent from AtomicPay. If you have been working with APIs or other web requests already, this should be familiar. We will work with this part as the sample continues.

Last but not least, we have a logging provider that enables us to write to the Azure Function’s log (which can be really useful if you’re searching an error). We will also use this as the sample continues.

AtomicPay webhook payload

In order to be able to handle the payload from AtomicPay, it is helpful to have a payload sample. Luckily, AtomicPay provides a detailed documentation for the webhook (as it does for the API). The payload looks like this:

 {
"invoice_id":"DBVZzHMxjjfdRZYeignEZC",
"order_id":"1235425",
"fiat_price":"1.00",
"fiat_currency":"USD",
"payment_currency":"BTC",
"payment_rate":"4,192.00",
"payment_address":"bc1qmtyax97phenvvs3sdg5r45kdcphd",
"payment_total":"0.00023855",
"payment_paid":"0.00023855",
"payment_due":"0.00000000",
"payment_txid":"14edecbf114f2b2e73cf7470916122286506de5",
"payment_confirmation":"3",
"status":"confirmed",
"statusException":"null"
} 

Depending on the cryptocurrency of the invoice, your function will be triggered multiple times – every time the status updates. As you probably want to have different actions for different states, it makes sense to create a class based on the JSON for deserialization and to further work with:

    public class WebhookInvoiceInfo
    {
        [JsonProperty("invoice_id")]
        public string InvoiceId { get; set; }

        [JsonProperty("order_id")]
        public string OrderId { get; set; }

        [JsonProperty("fiat_price")]
        [JsonConverter(typeof(StringToDecimalConverter))]
        public decimal FiatPrice { get; set; }

        [JsonProperty("fiat_currency")]
        public string FiatCurrency { get; set; }

        [JsonProperty("payment_currency")]
        public string PaymentCurrency { get; set; }

        [JsonProperty("payment_rate")]
        public string PaymentRate { get; set; }

        [JsonProperty("payment_address")]
        public string PaymentAddress { get; set; }

        [JsonProperty("payment_total")]
        [JsonConverter(typeof(StringToDecimalConverter))]
        public decimal PaymentTotal { get; set; }

        [JsonProperty("payment_paid")]
        [JsonConverter(typeof(StringToDecimalConverter))]
        public decimal PaymentPaid { get; set; }

        [JsonProperty("payment_due")]
        [JsonConverter(typeof(StringToDecimalConverter))]
        public decimal PaymentDue { get; set; }

        [JsonProperty("payment_txid")]
        public string PaymentTxid { get; set; }

        [JsonProperty("payment_confirmation")]
        [JsonConverter(typeof(StringToLongConverter))]
        public long PaymentConfirmation { get; set; }

        [JsonProperty("status")]
        [JsonConverter(typeof(StringToInvoiceStatusConverter))]
        public InvoiceStatus Status { get; set; }

        [JsonProperty("statusException")]
        [JsonConverter(typeof(StringToInvoiceStatusExceptionConverter))]
        public InvoiceStatusException StatusException { get; set; }
    }

You may have noticed that I have converters attached to some properties above. They are needed to convert the values into their correct types, as the API generally sends just strings. The class and its converters are part of the AtomicPay .NET SDK (find it on Nuget or Github), which we will use also in the second part of this blog series. Add the library in your prefered way to the project.

Working with the webhook’s payload

For this first part of the series, we are just going to write log entries based on the status of the incoming webhook. Just add these lines to the Run method of your function:

        [FunctionName("Function1")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            log.Info($"arrived at function trigger for AtomicPay webhook.");
            log.Info("trying to get payload object from request...");
            WebhookInvoiceInfo result = null;
            _jsonSerializerSettings = new JsonSerializerSettings()
            {
                MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                Converters ={

                        new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal },
                        StringToLongConverter.Instance,
                        StringToDecimalConverter.Instance,
                        StringToInvoiceStatusConverter.Instance,
                        StringToInvoiceStatusExceptionConverter.Instance
                }
            };

            _jsonSerializer = JsonSerializer.Create(_jsonSerializerSettings);

            using (var stream = await req.Content.ReadAsStreamAsync())
            {
                using (var reader = new StreamReader(stream))
                {
                    using (var jsonReader = new JsonTextReader(reader))
                    {
                        result = _jsonSerializer.Deserialize<WebhookInvoiceInfo>(jsonReader);
                    }
                }
            }

            if (result != null)
                log.Info($"received payload for invoice id: {result.InvoiceId} with status {result.Status.ToString()}");
            else
                log.Info("there was an error getting the payload from the request body");

            return result == null ?
                req.CreateResponse(HttpStatusCode.BadRequest, "there was an error getting the payload from the request body") :
                req.CreateResponse(HttpStatusCode.OK, "OK");
        }

We are reading the response content from the HttpRequestMessage and deserialize it. If there is no payload or something went wrong, our result will be null. We are writing a log entry that indicates if we have received a payload and the status of the invoice within it. In the end, we are returning the appropriate response to the POST request.

Testing the function locally

Another big advantage of using Visual Studio to write the Azure Function is the ability to debug locally. If you haven’t done so, you’ll need to install the
Azure Functions Core (CLI) tools – Visual Studio will prompt you to do so. Once that is done, we are able to debug locally:

Visual Studio debugging Azure function

Now that our local service is running, let’s test the function with Postman (this is one of my test invoices):

Postman request to local API test

As we can see, everything went smooth and our Function is working like expected:

API log local test

Now that we have verified our Function is able to run, we are ready to publish it.

Publishing the Function to Azure

To initiate the process, right click on the project name and select ‘Publish’. As we have already defined our project in the Azure Portal, we are using the ‘Select Existing’ option in the next step:

Publish to Azure Step 1

I am not selecting the ‘run from package file’ option here. Click ‘Publish’ to continue. You will be prompted with a selection window once again (you may have to login to your account first). Select your created project:

Publish to Azure Step 2

Confirm you selection with ‘OK’. After doing some additional preparation steps, Visual Studio will allow you to click the ‘Publish’ button:

Publish to Azure Step 3

Once you have published your function, visit the Azure Portal once again. Select your published function. The portal will show you the function.json declaration file. In the upper part of the website, you will find options to ‘Save‘, ‘Run‘ and ‘ </> Get function URL ‘. Click on the last one to view your function’s url:

Azure portal get function url

I am pretty sure you noticed the code parameter in the url. This parameter is needed with every call to your Azure function as authorization parameter. To test your function on Azure, copy the url and paste it into Postman (replacing the localhost url we used for local testing). You should get the same result in Postman – optimally, an OK-response.

Conclusion

If you followed along and your function is up and running – congratulations! You just created a basic “serverless” (aka running on someone else’s server) function. In the next post in this series, we will initialize the AtomicPay SDK properly, after we added our API credentials to another feature running on Azure – the KeyVault. As always, I hope this post is helpful for some of you.

Until the next post, happy coding, everyone!

Title image credit

Posted by msicc in Azure, Crypto&Blockchain, Dev Stories, Xamarin, 0 comments
Integrate crypto payments into your .Net applications with AtomicPay

Integrate crypto payments into your .Net applications with AtomicPay

If you have been following along, you may have noticed that I am discovering the cryptocurrency space lately. Today I want to introduce you to AtomicPay, a crypto payment processor that uses a different approach than traditional processors.

Why AtomicPay?

I have been thinking quite some time about how one can implement crypto payments into apps, be it desktop or mobile apps. Ever since then, it was clear for me that I need a solution where the payment happens between me and the customer directly, but all the infrastructure to handle invoicing etc. has to be handled from the outside.

Traditional payment processors often provide their service with a custodial wallet – you do not have control of the keys, so it is not really your wallet, just the grant to use it. Processing incoming transactions to this custodial wallet are routed through another wallet of the service, where those processors take their fees and process the reduced payment to your custodial wallet.

Security and Privacy

When it comes to crypto payments, there is always one problem: the balance between the ease of using and security/privacy. If you are looking at some other non-custodial services, they are providing payment processing by just using a single wallet address. Even if this is the easiest way to use crypto payments, it has some fundamental issues:

  • makes it way too easy to monitor transactions of a business/merchant entity
  • easy target for man-in-the-middle attacks
  • accountability issues (imagine 10 people paying the same amount, but for different products at nearly the same time)

Do you really want to put you and your customer/user at this risk? Surely not!

AtomicPay’s different approach

AtomicPay follows a different route. It provides an invoicing infrastructure that is easy to use, but payments are directly between merchant and customer.

It relies on the well established Electrum wallets. Never used any Electrum wallet before? No worries, AtomicPay helps you to initialize the wallet with step-by-step tutorials.

Electrum wallets are (optionally) SegWit-enabled, HD (hierarchical determistic) wallets. This means that for every incoming transcation, a new address is generated from your keys. Even though you could do multiple times, every address should be used only once. This makes attacks from the outside significantly harder and protects both you and your customer/user.

AtomicPay itself only has reading access – it can watch transactions, but never initialize any transfer out of the wallet of your funds. Atomicpay is able to calculate new valid receiver addresses for your Electrum wallet because of the BIP 0032 protocol by using your public key, which is the only thing you need to insert into their website.

AtomicPay features

AtomicPay provides quite a bunch of features:

  • on-the-fly PayUrl generation (QuickPay)
  • monitoring of incoming payments
  • notifications via Mail and Webhook
  • free-to-use REST API
  • very low fees
  • and more…

Introducing AtomicPay.Net SDK

As AtomicPay convinced me to be a valuable solution for crypto payments, I started to create a new library for their API. The SDK makes it very simple to call all endpoints and to integrate it into your .NET applications. The library is available on Github and as NuGet package. You’ll find informations on how to use the library on Github as well. My repo will also be forked into AtomicPay’s Github account soon and gain a bit more visibility this way.

What’s next?

The library is only the first step and lays the groundwork for more things to come, namely:

  • Webhook code sample with Azure Function and Notificationhub
  • Xamarin component for AtomicPay
  • Administration app for merchants (iOS and Android)

If you have ideas or questions on the library, feel free to ping me on the well known social accounts or leave a comment under this post. As always, I hope the library will be helpful.

Until the next post, happy coding, everyone!

Disclaimer: I am contributing to this project with code written by me under the MIT License. Future contributions may contain their own (and different) disclaimer. I am not getting paid for my contributions to the project.

Please note that none of my crypto related posts is an investment or financial advice. As crypto currencies are volatile and risky,  you should only invest as much as you can afford to lose. Always do your own research!

Posted by msicc in Crypto&Blockchain, Dev Stories, 0 comments