Skip to content

Instantly share code, notes, and snippets.

@cyberhobo
Created December 19, 2016 23:09
Show Gist options
  • Select an option

  • Save cyberhobo/12ec1fb84595c74494258a80f531846b to your computer and use it in GitHub Desktop.

Select an option

Save cyberhobo/12ec1fb84595c74494258a80f531846b to your computer and use it in GitHub Desktop.

Revisions

  1. cyberhobo created this gist Dec 19, 2016.
    83 changes: 83 additions & 0 deletions freemius-api-client.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,83 @@
    module Freemius
    API_HOST = 'api.freemius.com'
    SANDBOX_HOST = 'sandbox-api.freemius.com'

    class Base
    # Options taken from http://docs.freemius.apiary.io/#introduction/the-authentication-header
    # * host Default is api.freemius.com
    # * api_version Default is v1
    # * scope_entity Default is 'plugin'. Could also be 'developer', 'install', 'site', 'user'
    # * scope_entity_id Required.
    # * public_key Required.
    # * secret_key Required.
    def initialize(options)
    Freemius.host = options.fetch(:host) { API_HOST }
    Freemius.api_version = options.fetch(:api_version) { 'v1' }
    Freemius.scope_entity = options.fetch(:scope_entity) { 'plugin' }
    Freemius.scope_entity_id = options.fetch(:scope_entity_id) do
    raise ArgumentError.new('Scope entity ID is required to initialize Freemius') if Freemius.scope_entity_id.nil?
    end
    Freemius.public_key = options.fetch(:public_key) do
    raise ArgumentError.new('Public key is required to initialize Freemius') if Freemius.public_key.nil?
    end
    Freemius.secret_key = options.fetch(:secret_key) do
    raise ArgumentError.new('Secret key is required to initialize Freemius') if Freemius.secret_key.nil?
    end
    end

    def base_url
    "https://#{Freemius.host}#{base_path}"
    end

    def base_path
    "/#{Freemius.api_version}/#{Freemius.scope_entity.pluralize}/#{Freemius.scope_entity_id}"
    end

    def submit(method, path, data = {})
    body = [:put, :post].include?(method) ? data.to_json : ''
    headers = headers(method, "#{base_path}/#{path.split('?').first}", body)
    response = http_client.run_request(method, path, body, headers)
    JSON.parse(response.body)
    end

    private

    def http_client
    @http_client ||= Faraday.new(base_url, :ssl => { :ca_file => ENV['CERT_PATH'], :version => :TLSv1 })
    end

    def headers(method, path, body)
    formatted_date = Time.now.strftime('%a, %e %b %Y %H:%M:%S %z')
    content_type = 'application/json'
    md5 = body.empty? ? '' : Digest::MD5.hexdigest(body)
    signature_content = "#{method.to_s.upcase}\n#{md5}\n#{content_type}\n#{formatted_date}\n#{path}"
    digest = OpenSSL::Digest.new('sha256')
    signature = base64_url_encode(OpenSSL::HMAC.hexdigest(digest, Freemius.secret_key, signature_content))
    {
    'Authorization' => "FS #{Freemius.scope_entity_id}:#{Freemius.public_key}:#{signature}",
    'Content-Type' => content_type,
    'Date' => formatted_date
    }
    end

    def base64_url_encode(data)
    Base64::encode64( data ).tr('+/', '-_').gsub('=', '').gsub("\n", '')
    end

    end

    class << self
    attr_accessor :host,
    :scope_entity,
    :scope_entity_id,
    :public_key,
    :secret_key,
    :api_version

    def configure
    yield self
    true
    end
    alias :config :configure
    end
    end