Nicolas Cognaux - Tech entrepreneur & engineer

I share about development, productivity, open source and entrepreneurship.

Accept cryptocurrencies as easily as with Stripe

2021-09-15 Nicolas Cognaux 8 min readDevelopment

Some days ago, my company, Seety, was in the press because we are the first parking payment app to allow Crypto payments. This feature was super easily implemented, so I thought it would be a good idea to share how we implemented it in less than 24h (from idea to production).

Why do we allow crypto payment for parking?

I cofounded Seety, a parking assistant app that helps you along your parking journey. We provide the exact parking rules, prices, and mapping of the different parking zones. On our natural development plan, we wanted to also provide parking payment as you’ll often need to pay your parking.

The parking payment market is really crowded: Only in Belgium, we have more than six parking payment apps. All those apps are on the market for years and don’t really innovate a lot.

On our side, we are the small new challenger and wanted to stand out by being the easiest and most tech savvy solution. For example, we are the only one to only use geolocation to identify parking zones, we integrate with Android Auto & Apple CarPlay, we use machine learning to predict parking controls,… The next step for us was to add crypto payment in our app.

We are sure that crypto payments and the blockchain in general is a great technology and we wanted to embrace it, at our scale. Today, too few places and services allow for payment in crypto. We are convinced that in order to drive its adoption, we have to create practical use cases for the users.

Accepting crypto payments allows us to touch a very bound and enthusiastic community. Those will eventually become customers. It also highlighted our tech image in the market and generated a lot of PR.

How to add crypto payment in an app?

With Seety, our “classic payment” platform is Adyen. We use their platform to handle credit-card payments and are super satisfied. They handle all the certifications, security, banking aspects etc for us. However, they don’t allow crypto payments. As stated by their CEO, the volatility of the cryptocurrencies is an issue and will block its adoptions as a payment method so they don’t want to handle it currently.

We searched for a similar platform for our MVP, something that can handle crypto payments the same way as Adyen. And we turned to Coinbase Commerce. There are also other providers, like Crypto.com. We wanted an easy and fast implementation for our MVP so we took Coinbase Commerce.

Coinbase Commerce provides three types of integrations:

  1. Link to pay: A payment link redirects the user to Coinbase, allowing her to pay directly on a webpage
  2. SDK for in app integration: Direct integration in your website or app via a javascript package
  3. Shopify & Woocommerce integration: No-code solution for e-commerce

We use the “Link to pay” integration. It allows us to generate payment pages to display directly in our app. That was both the easiest and the most convenient solution for our users.

How does it work?

In our app, the user can buy “Seety credits” to pay for parking sessions. Each time a user asks for credits, we generate a payment link and redirect him to. When the transaction is detected in the blockchain, Coinbase Commerce calls a webhook to notify our server. The webhook is triggered when the transaction has been detected and is processed. When it’s confirmed, we credit our user with the corresponding amount.

The following diagram shows the states of transactions. All those changes are notified in webhook requests: Transaction statuses, from the Coinbase Commerce doc

We only care about the “Completed” and “Resolved” states. The Unresolved states are handled manually by our team as those cases are anecdotical.

Configure your API key and webhook endpoint

First of all, if you don’t have a Coinbase account, create one.

When your Coinbase account is ready, you can link it to a Coinbase Commerce account. It’ll take you less than 5 minutes. After that, you’ll be able to configure the API keys and webhooks.

Go to Settings and configure your API key and webhook URL handler. It’s also important to note down the shared secret:

  • API key is needed when you send a request to the Coinbase Commerce API
  • Webhook URL is the URL where Coinbase will send the transaction states & updates
  • The shared secret is used to authenticate requests made to your webhook endpoint

The setting screens of Coinbase Commerce

On the Settings page, you can also enable or disable specific crypto-currencies, edit the colors of the payment pages, etc.

Coding time!

The best part of that process is the coding. It’s super easy: Coinbase Commerce handles all the difficult bits (temporary wallet, rates conversions, blockchain monitoring, etc.) for you.

You only need to code two things: The charge creation (you ask a payment), and the payment handling.

Generate a payment link

When a user wants to buy something, you can use a code as simple as below to generate a charge (and a payment link).

This code sends a request to Coinbase Commerce, to create a new charge. The charge is sent with the metadata corresponding to the item bought. You can add any key/values you need in the metadata, those will also be sent with the webhook request.

In our case, we send a credit transaction’s ID in the metadata. The credit transaction’s state is “unverified” until the charge is confirmed in the webhook logic.

// Your variables
const REDIRECT_URL_END = '...'; // URL to redirect the user after payment
const REDIRECT_URL_CANCEL = '...'; // URL to redirect user when payment is cancelled
const COINBASE_API_KEY = '...'; // Your coinbase API key (available in Coinbase commerce settings)


const body = {
  name: 'My super product', // Change those as you want
  description: 'Description of the product', // Change those as you want
  local_price: {
    amount: 100, // Price of the product (in currency, here 100€)
    currency: 'EUR', // Define thecurrency of the price (EUR, USD,...)
  },
  pricing_type: 'fixed_price',
  metadata: {
    // Define your metadata here, for example, userID, productID
  },
  redirect_url: REDIRECT_URL_END,
  cancel_url: REDIRECT_URL_CANCEL,
};

const { data } = await fetch('https://api.commerce.coinbase.com/charges', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CC-Version': '2018-03-22',
    'X-CC-Api-Key': COINBASE_API_KEY,
  },
  body: JSON.stringify(body),
}).then((r) => r.json());
// Link to the payment page is in data.hosted_url, you can redirect your user there

Webhook handler (Listen for payment updates)

When a payment (charge) is updated, Coinbase Commerce will send a request to your webhook URL. This request will contain the status of the charge, with the metadata associated.

The request is signed using a SHA256 HMAC (available in the X-CC-Webhook-Signature header). It’s highly recommended to check the signature to be sure that the request wasn’t forged by someone else than Coinbase Commerce. The code below checks the signature and reacts to the state of the charge.

// Your inputs
const headers = XXX; // Headers sent in the webhooks (request.headers in express)
const rawBody = XXX; // Raw body of the request (Exact string received by your server)

// Your variables
const API_SHARED_SECRET = '...'; // Coinbase commerce shared secret (Available in the Settings section) 

// We verify that the webhook was requested by Coinbase commerce
const hash = headers['X-CC-Webhook-Signature'];
const hashVerif = createHmac('sha256', API_SHARED_SECRET)
  .update(rawBody)
  .digest('hex');

if (hash !== hashVerif) {
  // Error: The payload has been altered or is not sent by Coinbase Stop the execution here !
  return;
}

// The request is authenticated, we can now check its status and unlock the product for the user
const event = JSON.parse(rawBody)
if (event.type === 'charge:confirmed' || event.type === 'charge:resolved') {
  const { metadata } = event.data;
  // Your charge has been paid, you can now unlock the product for the user
}

With those two bits of code, you can generate payment pages and handle payments. Everything is secured by Coinbase and the money will be available in your Commerce account directly.

When you want to withdraw your money, you can either convert it to Fiat (EUR, USD,…) or transfer it to your Coinbase account to use it later.

Conclusion

As you can see, it’s super easy to add crypto payments in an app or a website. Everyone knows Stripe for online payment. Crypto payments are as easy as Stripe to implement with Coinbase Commerce.

For us, this implementation is only an MVP. We will measure the adoption. If there is a demand, we will develop something cleaner and maybe an in-house integration, allowing us to handle more tokens and reduce costs.

For now, this feature is boosting our brand image, we participate in the crypto-payment adoption, and it gives us a lot of press exposure. So we are convinced it was really worth it!

So now, why don’t you add crypto payments to your app?


I hope you learned something reading my article. If you want to continue the discussion, I’m always available on Twitter: @Gp2mv3

Don't miss an episode!

Nicolas Cognaux (Gp2mv3) - Tech entrepreneur & engineer

About Nicolas Cognaux

Entrepreneur and CTO. I’m an electrical engineer and passionate about software development. I post about technologies, entrepreneurship, projects, and geeky stuff. Follow me on social media to stay updated.

Don't miss an episode!

  • Made with ❤️ in Belgium 🇧🇪 by @Gp2mv3