lib/phaxio/client.rb in phaxio-0.4.1 vs lib/phaxio/client.rb in phaxio-0.5.0
- old
+ new
@@ -1,31 +1,27 @@
module Phaxio
include HTTMultiParty
base_uri 'https://api.phaxio.com/v1'
module Config
- attr_accessor :api_key, :api_secret
+ attr_accessor :api_key, :api_secret, :callback_token
end
module Client
+ DIGEST = OpenSSL::Digest.new('sha1')
+
# Public: Send a fax.
#
# options - The Hash options used to refine the selection (default: {}):
# :to - The Phone Number (i.e. [country
# code][number] or just a 10 digit
# number in the US or Canada). Put
# square brackets after parameter
# name to send to multiple
# recipients (e.g. to[]) (required).
- # :filename - The Binary Stream name of the file
- # you want to fax. This is optional
- # if you specify string_data. Must
- # have file name in the filename
- # field of the body-part header. Put
- # square brackets after parameter
- # name to send multiple files (e.g.
- # filename[]) (required).
+ # :filename - A Ruby File of a document to fax
+ # (supported file types: https://www.phaxio.com/faq#faq10)
# :string_data - A String of html, plain text, or a
# URL. If additional files are
# specified as well, this data will
# be included first in the fax
# (optional).
@@ -58,18 +54,33 @@
# completed. Must be between 1 and 60
# (optional).
#
# Examples
#
- # Phaxio.send_fax(to: "0123456789", filename: "test.pdf")
+ # Phaxio.send_fax(to: "0123456789", filename: File.new("docToSend.pdf"))
#
# Returns a HTTParty::Response object containing a success bool,
# a String message, and an in faxID.
def send_fax(options)
send_post("/send", options)
end
+ # Public: Resend a fax.
+ #
+ # options - The Hash options used to refine the selection (default: {}):
+ # :id - The int id of the fax you want to resend (required).
+ #
+ # Examples
+ #
+ # Phaxio.resend_fax(id: "123456")
+ #
+ # Returns a HTTParty::Response object containing a success bool,
+ # a message string, and data containing the fax ID int.
+ def resend_fax(options)
+ send_post("/resendFax", options)
+ end
+
# Public: Test receiving a fax.
#
# options - The Hash options used to refine the selection (default: {}):
# from_number - The Phone Number of the simulated sender
# (optional).
@@ -129,11 +140,11 @@
# Public: Get a detailed list of the phone numbers you current own on
# Phaxio.
#
# options - The Hash options used to refne th selection (default: {}):
- # area_code - An integer area code you'd like to filter by
+ # area_code - An integer area code you'd like to filter by
# (optional).
# number - A String phone number you'd like to retrieve
# (optional).
#
# Examples
@@ -221,10 +232,28 @@
# and a String message.
def cancel_fax(options)
send_post("/faxCancel", options)
end
+ # Public: Delete a specific fax.
+ #
+ # options - The hash options used to refine the selection (defaults: {}):
+ # :id - The int ID of the fax you want to cancel
+ # (required).
+ # :files_only - The bool used to determine whether only the files
+ # are deleted. If not specified, default is false
+ # (optional).
+ #
+ # Examples
+ #
+ # Phaxio.delete_fax(id: 1234, files_only: true)
+ #
+ # Returns a HTTParty::Response object with success bool and message string.
+ def delete_fax(options)
+ send_post("/deleteFax", options)
+ end
+
# Public: Get the status of Client's account.
#
# Examples
#
# Phaxio.get_account_status
@@ -233,21 +262,235 @@
# (containing faxes_sent_this_month, faxes_sent_today, and balance).
def get_account_status
send_post("/accountStatus", {})
end
+ # Public: Attach a PhaxCode to a PDF you provide.
+ #
+ # options - Type: hash. Options used to refine the action (default: {}):
+ # x - Type: float. The x-coordinate (in PDF points*)
+ # where the PhaxCode should be drawn. x=0 is at the
+ # left-most point on the page. (required)
+ # y - Type: float. The y-coordinate (in PDF points*)
+ # where the PhaxCode should be drawn. Y=0 is the
+ # bottom-most point on the page. (required)
+ # filename - A Ruby File in PDF format (required)
+ # metadata - Type: string. Custom metadata to be associated
+ # with the created barcode. If not present, the
+ # basic PhaxCode for your account will be used.
+ # page_number - Type: integer. The page where the PhaxCode should
+ # be drawn. 1-based.
+ # *PDF points definition: A "point" is 1/72 of an inch. An
+ # 8.5"x11" document is therefore 612 pt x 792 pt.
+ #
+ # Examples
+ #
+ # Phaxio.attach_phaxcode_to_pdf(
+ # x: "0", y: "100", filename: File.new("input.pdf")
+ # )
+ #
+ # Response: A PDF file containing a PhaxCode at the location specified.
+ def attach_phaxcode_to_pdf(options)
+ if options[:filename].nil?
+ raise StandardError, 'You must include a PDF file.'
+ end
+
+ if options[:x] < 0 || options[:y] < 0
+ raise StandardError, 'Coordinates must be greater than or equal to 0.'
+ end
+
+ send_post('/attachPhaxCodeToPdf', options)
+ end
+
+ # Public: Create a custom PhaxCode.
+ #
+ # options - Type: hash. Options used to refine the action (default: {}):
+ # metadata - Type: string. Custom metadata to be associated with
+ # this barcode. If not present, the basic PhaxCode for
+ # your account will be used. (optional)
+ # redirect - Type: boolean. If present and true, the PhaxCode
+ # barcode image will be dumped in the response.
+ # (optional)
+ #
+ # Example:
+ # Phaxio.create_phaxcode(metadata: "sale_id=44")
+ #
+ # Response: If the redirect parameter is not provided, a JSON object with
+ # success, message, and data attributes is returned. The data
+ # attribute contains a url where the PhaxCode barcode image can be
+ # accessed. Otherwise, the image data is dumped in the response.
+ def create_phaxcode(options = {})
+ send_post('/createPhaxCode', options)
+ end
+
+ # Public: Get a Hosted Document with PhaxCode included
+ #
+ # Note: You will have to set up the hosted document with Phaxio (along with
+ # the relevant PhaxCode) before calling this method.
+ #
+ # options - Type: hash. Options used to refine the action (default: {}):
+ # name - Type: string. The name of a hosted document.
+ # (required)
+ # metadata - Type: string. Custom metadata to be associated with
+ # the PhaxCode that will be attached to the hosted
+ # document. If not present, the basic PhaxCode for your
+ # account will be used.
+ # (optional)
+ #
+ # Example:
+ # Phaxio.get_hosted_document(name:"business_fax")
+ #
+ # Response: A PDF copy of the hosted document with a PhaxCode included at
+ # the pre-specified location.
+ def get_hosted_document(options)
+ if options[:name].nil?
+ raise StandardError, 'You must include the name of the hosted document.'
+ end
+
+ send_post('/getHostedDocument', options)
+ end
+
+ # Public: Get a list of supported countries for sending faxes
+ #
+ # Note: This method doesn't require API keys and is included for the sake of
+ # completion.
+ #
+ # Example:
+ # Phaxio.supported_countries
+ #
+ # Response: A JSON object with success, message, and data attributes. The
+ # data attribute contains a hash, where the key contains the name
+ # of the country, and the value is a hash of attributes for the
+ # country (currently only pricing information).
+ #
+ # Example Response:
+ # {
+ # "success": true,
+ # "message": "Data contains supported countries.",
+ # "data": {
+ # "United States": {
+ # "price_per_page": 7
+ # },
+ # "Canada": {
+ # "price_per_page": 7
+ # },
+ # "United Kingdom": {
+ # "price_per_page": 10
+ # },
+ # ...
+ # }
+ # }
+ def supported_countries
+ post('/supportedCountries')
+ end
+
+ # Public: List area codes available for purchasing numbers
+ #
+ # Note: This method doesn't require API keys and is included for the sake of
+ # completion.
+ #
+ # options - Type: hash. Options used to refine the query (default: {}):
+ # is_toll_free - Type: boolean. Will only return toll free area
+ # codes. (optional)
+ # state - Type: string. A two character state or province
+ # abbreviation (e.g. IL or YT). Will only return
+ # area codes for this state. (optional)
+ #
+ # Response: A JSON object with success, message, and data attributes. The
+ # data attribute contains a map of area codes to city and state.
+ #
+ # Example response:
+ # {
+ # "success": true,
+ # "message": "295 area codes available.",
+ # "data": {
+ # "201": {
+ # "city": "Bayonne, Jersey City, Union City",
+ # "state": "New Jersey"
+ # },
+ # "202": {
+ # "city": "Washington",
+ # "state": "District Of Columbia"
+ # },
+ # ... a lot more area codes here...
+ # }
+ # }
+ def area_codes(options = {})
+ post('/areaCodes', options)
+ end
+
def send_post(path, options)
- post(path, query: options.merge!({api_key: api_key, api_secret: api_secret}))
+ post(
+ path, query: options.merge!(api_key: api_key, api_secret: api_secret)
+ )
end
+
+ # Public: Check the signature of the signed request.
+ #
+ # signature - Type: string. The X-Phaxio-Signature HTTP header value.
+ # url - Type: string. The full URL that was called by Phaxio,
+ # including the query. (required)
+ # params - Type: hash. The POSTed form data (required)
+ # files - Type: array. Submitted files (required - "received" fax
+ # callback only)
+ #
+ # Returns true if the signature matches the signed request, otherwise false
+ def valid_callback_signature?(signature, url, params, files = [])
+ check_signature = generate_check_signature(url, params, files)
+ check_signature == signature
+ end
+
+ # Public: Generate a signature using the request data and callback token
+ #
+ # url - Type: string. The full URL that was called by Phaxio,
+ # including the query. (required)
+ # params - Type: hash. The POSTed form data (required)
+ # files - Type: array. Submitted files (required - "received" fax
+ # callback only)
+ #
+ # Retuns a signature based on the request data and configured callback
+ # token, which can then be compared with the request signature.
+ def generate_check_signature(url, params, files = [])
+ params_string = generate_params_string(params)
+ file_string = generate_files_string(files)
+ callback_data = "#{url}#{params_string}#{file_string}"
+ OpenSSL::HMAC.hexdigest(DIGEST, callback_token, callback_data)
+ end
+
+ private
+
+ def generate_params_string(params)
+ sorted_params = params.sort_by { |key, _value| key }
+ params_strings = sorted_params.map { |key, value| "#{key}#{value}" }
+ params_strings.join
+ end
+
+ def generate_files_string(files)
+ files_array = files_to_array(files).reject(&:nil?)
+ sorted_files = files_array.sort_by { |file| file[:name] }
+ files_strings = sorted_files.map { |file| generate_file_string(file) }
+ files_strings.join
+ end
+
+ def files_to_array(files)
+ files.is_a?(Array) ? files : [files]
+ end
+
+ def generate_file_string(file)
+ file[:name] + DIGEST.hexdigest(file[:tempfile].read)
+ end
end
- # Public: Configure Phaxio with your api_key and api_secret
+ # Public: Configure Phaxio with your api_key, api_secret, and the callback
+ # token provided in your Phaxio account (to verify that requests are
+ # coming from Phaxio).
#
# Examples
#
# Phaxio.config do |config|
- # config.api_key = "12345678910"
- # config.api_secret = "10987654321"
+ # config.api_key = '12345678910'
+ # config.api_secret = '10987654321'
+ # config.callback_token = '32935829'
# end
#
# Returns nothing.
def self.config
yield(self)