< Back to blog

Crypto payments at checkout with MetaMask

Providing flexible payment options for customers at checkout is essential when running an online store. Some customers want to pay with their credit card, others with a digital wallet, while increasingly customers want to pay with cryptocurrency.

Cryptocurrency payments eliminate the hassle of accepting large sums, and provide a secure transaction between business and customer.

Commerce.js allows brands to sell anywhere with their powerful headless checkout, giving businesses freedom over where and how they convert customers, including what payment methods are available. Businesses can add cryptocurrency payment options at the checkout, and still rely on Commerce.js to handle the order confirmation, inventory management, and other post order functions.

What is MetaMask?

MetaMask is a popular cryptocurrency wallet that interacts with the Ethereum blockchain. As a browser extension or mobile app, it allows users to easily access their Ethereum to then exchange for goods and services.

Adding MetaMask into the checkout

To accept crypto payments in the browser, we will be using MetaMask to inject a Web 3.0 framework into the browser. MetaMask at checkout will allow the customer to confirm which wallet they would like the funds transferred from and then confirm payment.

Let’s take a look at what’s involved to add MetaMask as a payment option at checkout.

Configure Commerce.js

First, you will need a Commerce.js account. After signing up you’ll need to configure your settings to accept manual payments.

  • Go to Settings > Payment gateways
  • Add a card on file to access payment options other than the test gateway
  • Add a “Manual” payment gateway

Screen Shot 2021-11-22 at 3.55.15 PM

We’ve now set up our Manual payment gateway and have told Commerce.js to handle the payment flow at checkout. Read the docs on setting this up.

Frontend implementation

The frontend setup is super simple as we only need to connect a function to a single button.

For the purposes of this guide, I’ll be using one of Commerce.js’s open source starter kits, ChopChop. ChopChop is a React (Next.js) demo you can use to build projects or simply use as you explore the Commerce.js SDK and APIs.

In this guide we will only be implementing MetaMask as a payment option. ChopChop demo grab

Within the Chop Chop Next.js demo app we will be working under the file [components/Checkout/Checkout.js] inside the function “captureOrder”.

const captureOrder = async (values) => {
  setProcessing(true);

Implementing MetaMask

A brief lesson: everything on the blockchain is a hash “0x76t83t27827”, wallets, transactions etc. When a customer sends crypto to a merchant they use their wallet hash and signing keys.

Customer: 0x00001 -> send 0.01 eth -> Merchant: 0x00002 = transaction: 0x00023

Setting up MetaMask in your Commerce.js application takes one function with a few steps to create a transaction on the blockchain.

With MetaMask 9.0 and up, MetaMask injects an object called Ethereum that allows you to interface with it.

const accounts = await ethereum.request({
  method: "eth_requestAccounts",
});

The “eth_requestAccounts” method prompts the customer to select/confirm which account they would like to use in this transaction.

const fetchUSD = await fetch(
  "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD"
);
const usd2Eth = await fetchUSD.json();

We now need the current price of Ethereum so we can convert our transaction total to Ethereum. Feel free to use any API you trust here.

Crypto market API’s:

if (accounts?.length > 0 && usd2Eth) {
       let web3obj = new Web3();

To continue we need to know if the customer chose an account and if we have the current market price of Ethereum.

await ethereum
  .request({
    method: "eth_sendTransaction",
    params: [
      {
        to: "0xF087675e04F9e97E06497D578Baf904Ea1655F61",
        from: accounts[0],
        value: parseInt(
          web3obj.utils.toWei(
            (live.total.raw / usd2Eth.USD).toString(),
            "ether"
          )
        ).toString(16),
        gas: "0x2710",
        chainId: "0x3",
      },
    ],
  })

The “eth_sendTransaction” method accepts a few parameters.

  • to: Merchant wallet address
  • from: current customer’s wallet address (provided by “eth_requestAccounts”)
  • value: amount of ether to send ( checkout total converted to wei - the lowest unit of ether)
  • gas: placeholder of how much gas you’re willing to pay to confirm the transaction.

Gas is the fee attached to the transaction used to incentivise miners to confirm your transaction (higher the gas the faster the payment is processed).

“eth_sendTransaction” sends the transaction to the blockchain. And that's it!

try {

  const accounts = await ethereum.request({
    method: "eth_requestAccounts",
  });

  const fetchUSD = await fetch(
    "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD"
  );
  const usd2Eth = await fetchUSD.json();

  if (accounts?.length > 0 && usd2Eth) {
    let web3obj = new Web3();

    await ethereum
      .request({
        method: "eth_sendTransaction",
        params: [
          {
            to: "0xF087675e04F9e97E06497D578Baf904Ea1655F61",
            from: accounts[0],
            value: parseInt(
              web3obj.utils.toWei(
                (live.total.raw / usd2Eth.USD).toString(),
                "ether"
              )
            ).toString(16),
            gas: "0x2710",
            chainId: "0x3",
          },
        ],
      })
      .then(async (txHash) => {
        const newOrder = await capture({
          ...checkoutPayload,
          payment: {
            gateway: "manual",
            manual: {
              id: process.env.GATEWAY_ID,
            },
          },
        });
        handleOrderSuccess(newOrder);
        setProcessing(false);
      })
      .catch((error) => console.error);
  }
} catch (res) {
  setProcessing(false);
}

Following the transaction creation, proceed with the normal Commerce.js user flow by showing an order confirmation page. ChopChop confirmation

You will then see the order in your admin dashboard as per any other order.

Screen Shot 2021-11-22 at 3.22.20 PM

Additional resources

Resources and Community

Check out our documentation and community articles.

Join our community on Slack to connect with eCommerce developers from around the world. Share your projects with us, ask questions, or just hang out!

Join our community
Dev community image