ndimatteo / HULL

💀 Headless Shopify Starter – powered by Next.js + Sanity.io
https://hull.dev
MIT License
1.37k stars 169 forks source link

[feature-request] Multi-currency #45

Open dnlmzw opened 2 years ago

dnlmzw commented 2 years ago

Hi @ndimatteo,

Thanks again for this amazing repo. Using it for another project now. I like the features you've added since I last pulled the code. Awesome!

I implemented a multi currency feature on the last project, which I need on this project as well so I thought I'd bring it up as a feature request. I solved it by making all of my prices available through an API, to avoid having to update the records in Sanity every time the exchange rate changed

What I wrote is a quite handheld/hacky and is breakable with +250 products, but maybe you can use my code for inspiration.

I'm very happy to hear if this is something you've already thought about how you'd go about implement it, since I'd be happy to find a more future-proof solution. Also, detecting the IP and duplicating the checkout to create a new checkout on Shopify's side is something I've worked on but haven't yet found a good solution for.

Keep up the good work!

in /api/shopify/product-prices?currencyCode=DKK

import axios from 'axios'

export default async function send(req, res) {
  const {
    query: { currencyCode },
  } = req

  const hasShopify =
    process.env.SHOPIFY_STORE_ID && process.env.SHOPIFY_API_PASSWORD

  if (!currencyCode)
    return res.status(401).json({ error: 'Currency code is required' })

  if (!hasShopify)
    return res.status(401).json({ error: 'Shopify API not setup' })

  // Setup our Shopify connection
  const shopifyConfig = {
    'Content-Type': 'application/json',
    'X-Shopify-Storefront-Access-Token': process.env.SHOPIFY_API_TOKEN,
  }

  const countries = [
    { currencyCode: 'USD', countryCode: 'US' },
    {
      currencyCode: 'DKK',
      countryCode: 'DK',
    },
    {
      currencyCode: 'GBP',
      countryCode: 'GB',
    },
  ]
  const countryCode =
    countries.find((c) => c.currencyCode === currencyCode)?.countryCode || 'DE'

  // Fetch product prices for all products
  let data = {}
  await axios({
    url: `https://${process.env.SHOPIFY_STORE_ID}.myshopify.com/api/2021-07/graphql.json`,
    method: 'POST',
    headers: shopifyConfig,
    data: {
      query: `
        query allProducts($countryCode: CountryCode) @inContext(country: $countryCode) {
          products(first: 250) {
            edges {
              node {
                handle
                variants(first: 250) {
                  edges {
                    node {
                      id
                      priceV2 {
                        amount
                        currencyCode
                      }
                    }
                  }
                }
              }
            }
          }
        }
        `,
      variables: {
        countryCode,
      },
    },
  }).then((result) => {
    data = result.data?.data
      ? (data = {
          data: {
            products: result.data.data.products.edges.map(({ node }) => ({
              handle: node.handle,
              ...node.variants.edges[0].node.priceV2,
            })),
          },
        })
      : result.data
  })

  res.statusCode = 200
  res.json(data)
}
ndimatteo commented 2 years ago

Thanks for this @dnlmzw!

Multi-currency is something I've been looking into, lots of moving parts with that, not only with displaying correct prices, but also taking a customer to the shopify checkout flow.

I don't have any immediate plans to add this just yet, but it is on the roadmap 😉

If you have any other insights from your experience let me know!