module ActiveMerchant #:nodoc: module Billing #:nodoc: module Integrations #:nodoc: module DirecPay class Helper < ActiveMerchant::Billing::Integrations::Helper mapping :account, 'MID' mapping :order, 'Merchant Order No' mapping :amount, 'Amount' mapping :currency, 'Currency' mapping :country, 'Country' mapping :billing_address, :city => 'custCity', :address1 => 'custAddress', :state => 'custState', :zip => 'custPinCode', :country => 'custCountry', :phone => 'custMobileNo' mapping :shipping_address, :name => 'deliveryName', :city => 'deliveryCity', :address1 => 'deliveryAddress', :state => 'deliveryState', :zip => 'deliveryPinCode', :country => 'deliveryCountry', :phone => 'deliveryMobileNo' mapping :customer, :name => 'custName', :email => 'custEmailId' mapping :description, 'otherNotes' mapping :edit_allowed, 'editAllowed' mapping :return_url, 'Success URL' mapping :failure_url, 'Failure URL' mapping :operating_mode, 'Operating Mode' mapping :other_details, 'Other Details' mapping :collaborator, 'Collaborator' OPERATING_MODE = 'DOM' COUNTRY = 'IND' CURRENCY = 'INR' OTHER_DETAILS = 'NULL' EDIT_ALLOWED = 'Y' PHONE_CODES = { 'IN' => '91', 'US' => '01', 'CA' => '01' } ENCODED_PARAMS = [ :account, :operating_mode, :country, :currency, :amount, :order, :other_details, :return_url, :failure_url, :collaborator ] def initialize(order, account, options = {}) super collaborator = ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] ? 'TOML' : 'DirecPay' add_field(mappings[:collaborator], collaborator) add_field(mappings[:country], 'IND') add_field(mappings[:operating_mode], OPERATING_MODE) add_field(mappings[:other_details], OTHER_DETAILS) add_field(mappings[:edit_allowed], EDIT_ALLOWED) end def customer(params = {}) add_field(mappings[:customer][:name], full_name(params)) add_field(mappings[:customer][:email], params[:email]) end # Need to format the amount to have 2 decimal places def amount=(money) cents = money.respond_to?(:cents) ? money.cents : money if money.is_a?(String) or cents.to_i <= 0 raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' end add_field(mappings[:amount], sprintf("%.2f", cents.to_f/100)) end def shipping_address(params = {}) super(update_address(:shipping_address, params)) end def billing_address(params = {}) super(update_address(:billing_address, params)) end def form_fields add_failure_url add_request_parameters unencoded_parameters end private def add_request_parameters params = ENCODED_PARAMS.map{ |param| fields[mappings[param]] } encoded = encode_value(params.join('|')) add_field('requestparameter', encoded) end def unencoded_parameters params = fields.dup # remove all encoded params from exported fields ENCODED_PARAMS.each{ |param| params.delete(mappings[param]) } # remove all special characters from each field value params = params.collect{|name, value| [name, remove_special_characters(value)] } Hash[params] end def add_failure_url if fields[mappings[:failure_url]].nil? add_field(mappings[:failure_url], fields[mappings[:return_url]]) end end def update_address(address_type, params) params = params.dup address = params[:address1] address = "#{address} #{params[:address2]}" if params[:address2].present? address = "#{params[:company]} #{address}" if params[:company].present? params[:address1] = address params[:phone] = normalize_phone_number(params[:phone]) add_land_line_phone_for(address_type, params) if address_type == :shipping_address shipping_name = full_name(params) || fields[mappings[:customer][:name]] add_field(mappings[:shipping_address][:name], shipping_name) end params end # Split a single phone number into the country code, area code and local number as best as possible def add_land_line_phone_for(address_type, params) address_field = address_type == :billing_address ? 'custPhoneNo' : 'deliveryPhNo' if params.has_key?(:phone2) phone = normalize_phone_number(params[:phone2]) phone_country_code, phone_area_code, phone_number = nil if params[:country] == 'IN' && phone =~ /(91)? *(\d{3}) *(\d{4,})$/ phone_country_code, phone_area_code, phone_number = $1, $2, $3 else numbers = phone.split(' ') case numbers.size when 3 phone_country_code, phone_area_code, phone_number = numbers when 2 phone_area_code, phone_number = numbers else phone =~ /(\d{3})(\d+)$/ phone_area_code, phone_number = $1, $2 end end add_field("#{address_field}1", phone_country_code || phone_code_for_country(params[:country]) || '91') add_field("#{address_field}2", phone_area_code) add_field("#{address_field}3", phone_number) end end def normalize_phone_number(phone) phone.gsub(/[^\d ]+/, '') if phone end # Special characters are NOT allowed while posting transaction parameters on DirecPay system def remove_special_characters(string) string.gsub(/[~"'&#%]/, '-') end def encode_value(value) encoded = ActiveSupport::Base64.encode64s(value) string_to_encode = encoded[0, 1] + "T" + encoded[1, encoded.length] ActiveSupport::Base64.encode64s(string_to_encode) end def decode_value(value) decoded = ActiveSupport::Base64.decode64(value) string_to_decode = decoded[0, 1] + decoded[2, decoded.length] ActiveSupport::Base64.decode64(string_to_decode) end def phone_code_for_country(country) PHONE_CODES[country] end def full_name(params) return if params[:name].blank? && params[:first_name].blank? && params[:last_name].blank? params[:name] || "#{params[:first_name]} #{params[:last_name]}" end end end end end end