User Tools

Site Tools


en-233-api-ruby


API for Ruby Applications


# ========================================================================================
#
#   FOLLOWZUP PROJECT
#
# ========================================================================================
#
#   Copyright (C) 2016 Followzup.com
#
#   This program is free software: you can redistribute it and/or modify it under
#   the terms of the GNU General Public License as published by the Free Software
#   Foundation, either version 3 of the License, or any later version.
#
#   This program is distributed in the hope that it will be useful, but WITHOUT 
#   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
#   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>
#
# ========================================================================================

##
# Contributor: Dener Carmo
# E-mail:      dener.wilian at gmail.com
#              https://github.com/denerblack
##

require 'base64'
require 'openssl'
require 'uri'
require 'net/http'
require 'rexml/document'
require 'byebug'
require 'mcrypt'

################################################################################
# https://sourceforge.net/projects/mcrypt/files/Libmcrypt/                     #
# Install the gem:                                                             #
# gem install ruby-mcrypt --test -- --with-mcrypt-dir=/path/to/mcrypt/prefix   #
# More info:                                                                   #
# https://github.com/kingpong/ruby-mcrypt#mcrypt---libmcrypt-bindings-for-ruby #
################################################################################

class fzup_#idchannel#
  attr_accessor :fzup_channel
  attr_accessor :fzup_pubkey64
  attr_accessor :fzup_pubkey
  attr_accessor :fzup_lastseq
  attr_accessor :fzup_retcode
  attr_accessor :fzup_retframe

  FZUP_URI = URI("http://www.followzup.com/wschannel")
  INVALID_SEQUENCE = "6101"
  PSEUDO_KEY = OpenSSL::Random.pseudo_bytes(24)
  IV = 0.chr * 16;

  def initialize
    @fzup_channel = "#idchannel#"
    @fzup_lastseq = 0
    @fzup_pubkey64 = "#pubkey64#"
    @fzup_pubkey = Base64.decode64(fzup_pubkey64)

  end

  def decrypt(fzup_encrypted_url)
    puts fzup_encrypted_url
    url_decoded = URI.decode(fzup_encrypted_url)
    url_decoded_base64 = Base64.decode64(url_decoded)
    rsa_key = OpenSSL::PKey::RSA.new(fzup_pubkey)
    rsa_key.public_decrypt(url_decoded_base64)
  end

  def submit(fzup_tab = {})
    fzup_param = {
      "FZUP_COMMAND" => "",
      "FZUP_LASTSEQ" => "0",
      "FZUP_MESSAGEID" => "",
      "FZUP_SUBSCODE" => "",
      "FZUP_USER" => "",
      "FZUP_HOURS" => "0",
      "FZUP_MSGTEXT" => "",
      "FZUP_MSGURL" => ""
    }

    fzup_tab.each do |key, value|
      fzup_param[key] = value if fzup_param.has_key?(key)
    end

    seq = fzup_param["FZUP_LASTSEQ"].to_i
    fzup_lastseq = seq > 0 ? seq : 0

    cmd = fzup_param["FZUP_COMMAND"]

    return ["6103", fzup_lastseq.to_s, "<?xml version=\"1.0\" encoding=\"utf-8\"?><followzup></followzup>"] unless cmd.eql?("chck") || cmd.eql?("smsg")

    begin

      @fzup_lastseq += 1

      plain = build_xml(cmd, @fzup_lastseq,
      fzup_param["FZUP_USER"],
      fzup_param["FZUP_SUBSCODE"],
      fzup_param["FZUP_HOURS"],
      Base64::encode64(fzup_param["FZUP_MSGTEXT"]),
      Base64::encode64(fzup_param["FZUP_MSGURL"]))

      crypt_data = mcrypt(plain)

      rsa_key = OpenSSL::PKey::RSA.new(fzup_pubkey)
      key_2 = rsa_key.public_encrypt(PSEUDO_KEY)
      data = Base64.encode64(crypt_data)
      key_3 = Base64.encode64(key_2)

      response = send_data(key_3, data)
      response_xml = REXML::Document.new(response.body)
      unless response_xml.to_s.empty?
        @retframe = ""
        response_xml.elements.each('followzup/retcode') {|z| @fzup_retcode = z.text }
        response_xml.elements.each('followzup/retframe') {|z| @retframe = z.text }
        retframe_decoded = Base64.decode64(@retframe)
        retframe_mcrypt = mcrypt(retframe_decoded, :decrypt)
        fzup_retframe = REXML::Document.new(retframe_mcrypt)
        fzup_retframe.elements.each('followzup/seq') { |z| @fzup_lastseq = z.text.to_i } if fzup_retcode.eql?(INVALID_SEQUENCE)
      end

    end while fzup_retcode.eql?('6101')

    [fzup_retcode, fzup_lastseq, fzup_retframe.to_s]
  end


  private

  def mcrypt(data, type = :encrypt)
    enc = Mcrypt.new(:rijndael_128, :cbc, PSEUDO_KEY, IV, :zeros)
    encrypted = type.eql?(:encrypt) ? enc.encrypt(data) : enc.decrypt(data)
    encrypted
  end


  def send_data(key, data)
    request = Net::HTTP::Post.new(FZUP_URI)
    request.initialize_http_header({"User-Agent" => "wschannel: #{fzup_channel}"})
    request.set_form_data('id' => fzup_channel,
    'key' => key,
    'frame'=> data)
    response = Net::HTTP.start(FZUP_URI.hostname, FZUP_URI.port) do |http|
      http.request(request)
    end
    response
  end

  def build_xml(cmd, fzup_lastseq, user, subscode, hours, msgtext, msgurl)
    xml =  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
    xml << "<followzup>"
    xml << "<com>#{cmd}</com>"
    xml << "<seq>#{fzup_lastseq}</seq>"
    case cmd
    when "chck"
      xml << "<usr>#{user}</usr>"
      xml << "<sub>#{subscode}</sub>"
    when "smsg"
      xml << "<usr>#{user}</usr>"
      xml << "<hrs>#{hours}</hrs>"
      xml << "<msg>#{msgtext}</msg>"
      xml << "<url>#{msgurl}</url>"
    end
    xml << "</followzup>"
    xml
  end
end


en-233-api-ruby.txt ยท Last modified: 2017/06/19 17:46 by admin

Page Tools