Public Shopify Sinatra App

0

require 'shopify_api'
require 'sinatra'
require 'httparty'
require 'dotenv'
Dotenv.load

class App < Sinatra::Base
  attr_reader :tokens
  API_KEY    = ENV['API_KEY']
  API_SECRET = ENV['API_SECRET']
  APP_URL    = "xxxx.ngrok.io"

  def initialize
    @tokens = {}
    super
  end

  get '/shopify/install' do
    shop   = request.params['shop']
    scopes = "read_orders,read_products,write_products"
    redirect "http://#{shop}/admin/oauth/authorize?client_id=#{API_KEY}&scope=#{scopes}&redirect_uri=https://#{APP_URL}/shopify/auth"
  end

  get '/shopify/auth' do
    shop = request.params['shop']
    code = request.params['code']
    hmac = request.params['hmac']

    validate_hmac(hmac,request)
    get_shop_access_token(shop,API_KEY,API_SECRET,code)
    create_order_webhook
    redirect bulk_edit_url
  end

  get '/rest' do
    shop  = 'xxxx.myshopify.com'
    token = 'shpat_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    session = ShopifyAPI::Session.new(domain: shop, token: token, api_version: "2021-04")
    ShopifyAPI::Base.activate_session(session)

    # products = ShopifyAPI::Product.find(:all, params: { limit: 3 })
    # products.size

    shop = ShopifyAPI::Shop.current
    p1   = ShopifyAPI::Product.first
    p2   = ShopifyAPI::Product.last

    p1.title = "MMM"
    p1.save

    "#{shop.name} #{p1.title} #{p2.title} #{p2.variants.first.sku} #{p2.variants.first.inventory_quantity}"
  end

  get '/graphql' do
    shop  = 'xxxx.myshopify.com'
    token = 'shpat_xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    session = ShopifyAPI::Session.new(domain: shop, token: token, api_version: "2021-04")
    ShopifyAPI::Base.activate_session(session)

    ShopifyAPI::GraphQL.initialize_clients
    client = ShopifyAPI::GraphQL.client

    query = client.parse <<-'GRAPHQL'
    {
      shop {
        id
        name
        email
      }
      products(first:3) {
        edges {
          node {
            id
            variants(first:3) {
              edges {
                node {
                  id
                  displayName
                  sku
                }
              }
            }
          }
        }
      }
    }
    GRAPHQL

    result = client.query(query)
    s1 = result.data.products.edges.first.node.variants.edges.first.node.sku
    s2 = result.data.products.edges.last.node.variants.edges.first.node.sku
    "#{s1} #{s2}"
  end

  helpers do
    def get_shop_access_token(shop,client_id,client_secret,code)
      if @tokens[shop].nil?
        url = "https://#{shop}/admin/oauth/access_token"

        payload = {
          client_id: client_id,
          client_secret: client_secret,
          code: code}

        response = HTTParty.post(url, body: payload)

        if response.code == 200
          @tokens[shop] = response['access_token']
        else
          return [500, "Something went wrong."]
        end

        instantiate_session(shop)
      end
    end

    def instantiate_session(shop)
      session = ShopifyAPI::Session.new(domain: shop, token: @tokens[shop], api_version: "2021-04")
      ShopifyAPI::Base.activate_session(session)
    end

    def validate_hmac(hmac,request)
      h = request.params.reject{|k,_| k == 'hmac' || k == 'signature'}
      query = URI.escape(h.sort.collect{|k,v| "#{k}=#{v}"}.join('&'))
      digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), API_SECRET, query)

      unless (hmac == digest)
        return [403, "Authentication failed. Digest provided was: #{digest}"]
      end
    end

    def verify_webhook(hmac, data)
      digest = OpenSSL::Digest.new('sha256')
      calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, API_SECRET, data)).strip

      hmac == calculated_hmac
    end

    def bulk_edit_url
      bulk_edit_url = "https://www.shopify.com/admin/bulk"\
                    "?resource_name=ProductVariant"\
                    "&edit=metafields.test.ingredients:string"
      return bulk_edit_url
    end

    def create_order_webhook
      # create webhook for order creation if it doesn't exist
      unless ShopifyAPI::Webhook.find(:all).any?
        webhook = {
          topic: 'orders/create',
          address: "https://#{APP_URL}/shopify/webhook/order_create",
          format: 'json'}

        ShopifyAPI::Webhook.create(webhook)
      end
    end
  end
end

run App.run!

  • 0 posts
  • 0 subtopics
  • about 1 month ago by vince