require 'soap/wsdlDriver' require 'soap/header/simplehandler' require 'stringio' require File.dirname(__FILE__) + '/base' module ActiveMerchant #:nodoc: module Billing #:nodoc: module EwayRebill class ProxyBase < EwayBase::Proxy def wdsl "https://www.eway.com.au/gateway/rebill/test/managerebill_test.asmx?WSDL" end def header(eway_customer_id, username, password) EwayRebillHeader.new(eway_customer_id, username, password) end end # Add recurring billing - based on the Payflow API # See the EWay Managed reBILL Web Servicee for more details: # # Several options are available to customize the recurring profile: # # * profile_id - is only required for editing a recurring profile # * starting_at - takes a Date, Time, or string in mmddyyyy format. The date must be in the future. # * ending_at - takes a Date, Time, or string in mmddyyyy format. The date must be in the future, after the starting_at date # * name - The name of the customer to be billed. If not specified, the name from the credit card is used. # * periodicity - The frequency that the recurring payments will occur at. Can be one of # :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly # * payments - The term, or number of payments that will be made # * comment - A comment associated with the profile def recurring(money, credit_card, options = {}) # Step 1: Create a customer unless a customer_id is set unless options[:customer_id] customer_attributes = {} add_rebill_customer_data(customer_attributes, options) add_rebill_address_data(customer_attributes, options) customer = create_customer(customer_attributes) return customer if customer.error? options[:customer_id] = customer.customer.id end # Step 2: Create the Event event_attributes = {} event_attributes[:init_amt] = amount(money) event_attributes[:recur_amt] = amount(money) add_rebill_credit_card_data(event_attributes, credit_card) add_rebill_invoice_data(event_attributes, options) event = Event.new(event_attributes) event.create(@options[:login], @options[:username], @options[:password]) end def change_recurring(money, credit_card, options = {}) # Step 2: Create the Event event_attributes = {} event_attributes[:recur_amt] = amount(money) add_rebill_credit_card_data(event_attributes, credit_card) add_rebill_invoice_data(event_attributes, options) event = Event.new(event_attributes) event.update(@options[:login], @options[:username], @options[:password]) end def cancel_recurring(profile_id, customer_id) Event.delete(profile_id, customer_id) end def recurring_inquiry(profile_id, customer_id) Event.query(profile_id, customer_id) end def query_customer(id) Customer.query(@options[:login], @options[:username], @options[:password], id) end def create_customer(options = {}) customer = Customer.new(options) customer.create(@options[:login], @options[:username], @options[:password]) end def update_customer(id, options = {}) customer = Customer.new(options) customer.id = id customer.update(@options[:login], @options[:username], @options[:password]) end def delete_customer(id) Customer.delete(@options[:login], @options[:username], @options[:password], id) end def create_event(options = {}) event = Event.new(options) event.create(@options[:login], @options[:username], @options[:password]) end def query_event(customer_id, id) Event.query(@options[:login], @options[:username], @options[:password], customer_id, id) end def update_event(id, options = {}) event = Event.new(options) event.id = id event.update(@options[:login], @options[:username], @options[:password]) end def delete_event(customer_id, id) Event.delete(@options[:login], @options[:username], @options[:password], customer_id, id) end class EwayRebillHeader < SOAP::Header::SimpleHandler def initialize(eway_customer_id, username, password) super(XSD::QName.new('http://www.eway.com.au/gateway/rebill/manageRebill', 'eWAYHeader')) @item = { :eWAYCustomerID => eway_customer_id, :Username => username, :Password => password } end def on_simple_outbound @item if @item end end class Customer < ProxyBase def initialize(attributes = {}) self.fields = [ :id, :ref, :title, :first_name, :last_name, :company, :job_desc, :email, :address, :suburb, :state, :post_code, :country, :phone_1, :phone_2, :fax, :comments, :url ] super end def create(eway_customer_id, username, password) CustomerResponse.new(driver(eway_customer_id, username, password).CreateRebillCustomer(prepared_attributes).createRebillCustomerResult) end def update(eway_customer_id, username, password) CustomerResponse.new(driver(eway_customer_id, username, password).UpdateRebillCustomer(prepared_attributes).updateRebillCustomerResult) end def delete(eway_customer_id, username, password) CustomerResponse.new(driver(eway_customer_id, username, password).DeleteRebillCustomer(:RebillCustomerID => self.id).deleteRebillCustomerResult) end def self.delete(eway_customer_id, username, password, id) proxy = ProxyBase.new CustomerResponse.new(proxy.driver(eway_customer_id, username, password).DeleteRebillCustomer(:RebillCustomerID => id).deleteRebillCustomerResult) end def self.query(eway_customer_id, username, password, id) proxy = ProxyBase.new CustomerResponse.new(proxy.driver(eway_customer_id, username, password).QueryRebillCustomer(:RebillCustomerID => id).queryRebillCustomerResult) end def prepared_attributes(attributes = nil) attributes ||= @attributes tmp = {} self.fields.each do |key| case(key) when :url camel_key = "customerURL" when :id camel_key = "RebillCustomerID" else camel_key = "customer" + ProxyBase.camelize(key) end tmp[camel_key] = attributes.has_key?(key) && attributes[key] ? attributes[key] : "" end tmp end end class Event < ProxyBase def initialize(attributes = {}) self.fields = [ :id, :customer_id, :inv_ref, :inv_des, :cc_name, :cc_number, :cc_exp_month, :cc_exp_year, :init_amt, :init_date, :recur_amt, :start_date, :interval, :interval_type, :end_date ] super end def create(eway_customer_id, username, password) EventResponse.new(driver(eway_customer_id, username, password).CreateRebillEvent(prepared_attributes).createRebillEventResult) end def update(eway_customer_id, username, password) EventResponse.new(driver(eway_customer_id, username, password).UpdateRebillEvent(prepared_attributes).updateRebillEventResult) end def delete(eway_customer_id, username, password) EventResponse.new(driver(eway_customer_id, username, password).DeleteRebillEvent(:RebillID => self.id).deleteRebillEventResult) end def self.delete(eway_customer_id, username, password, customer_id, id) proxy = ProxyBase.new EventResponse.new(proxy.driver(eway_customer_id, username, password).DeleteRebillEvent(:RebillCustomerID => customer_id, :RebillID => id).deleteRebillEventResult) end def self.query(eway_customer_id, username, password, customer_id, id) proxy = ProxyBase.new EventResponse.new(proxy.driver(eway_customer_id, username, password).queryRebillEvent(:RebillCustomerID => customer_id, :RebillID => id).queryRebillEventResult) end def prepared_attributes(attributes = nil) attributes ||= @attributes tmp = {} self.fields.each do |key| case(key) when :id camel_key = "RebillID" when :customer_id camel_key = "RebillCustomerID" when :cc_name camel_key = "RebillCCName" when :cc_number camel_key = "RebillCCNumber" when :cc_exp_month camel_key = "RebillCCExpMonth" when :cc_exp_year camel_key = "RebillCCExpYear" when :init_date camel_key = "RebillInitDate" attributes[key] = attributes[key].strftime("%d/%m/%Y") unless attributes[key] == nil when :start_date camel_key = "RebillStartDate" attributes[key] = attributes[key].strftime("%d/%m/%Y") unless attributes[key] == nil when :end_date camel_key = "RebillEndDate" attributes[key] = attributes[key].strftime("%d/%m/%Y") unless attributes[key] == nil when :interval_type camel_key = "RebillIntervalType" unless attributes[key] == nil case(attributes[key].to_sym) when(:daily) attributes[key] = 1 when(:weekly) attributes[key] = 2 when(:monthly) attributes[key] = 3 when(:yearly) attributes[key] = 4 end end else camel_key = "Rebill" + ProxyBase.camelize(key) end tmp[camel_key] = attributes.has_key?(key) && attributes[key] ? attributes[key] : "" end tmp end end class CustomerResponse < EwayBase::Response attr_accessor :customer_id, :customer def initialize(soap_obj) super self.customer_id = soap_obj.rebillCustomerID == "0" ? nil : soap_obj.rebillCustomerID # Try to fill the customer object self.customer = Customer.new self.customer.id = self.customer_id self.customer.fields.each do |key| case(key) when(:url) method = "customerURL" else method = "customer" + ProxyBase.camelize(key) end self.customer.send("#{key}=", soap_obj.send(method)) if soap_obj.respond_to?(method) end end end class EventResponse < EwayBase::Response attr_accessor :rebill_id, :customer_id, :event def initialize(soap_obj) super self.rebill_id = soap_obj.rebillID if soap_obj.respond_to?(:rebillID) self.customer_id = soap_obj.rebillCustomerID if soap_obj.respond_to?(:rebillCustomerID) # Try to fill the event object self.event = Event.new self.event.id = self.rebill_id self.event.fields.each do |key| case(key) when(:id) method = "rebillID" when(:customer_id) method = "rebillCustomerID" when(:inv_des) method = "rebillInvDesc" when(:cc_name) method = "rebillCCName" when(:cc_number) method = "rebillCCNumber" when(:cc_exp_month) method = "rebillCCExpMonth" when(:cc_exp_year) method = "rebillCCExpYear" else method = "rebill" + ProxyBase.camelize(key) end case(key) when(:start_date) self.event.start_date = DateTime.strptime(soap_obj.rebillStartDate, "%d/%m/%Y") if soap_obj.respond_to?(:rebillStartDate) when(:init_date) self.event.init_date = DateTime.strptime(soap_obj.rebillInitDate, "%d/%m/%Y") if soap_obj.respond_to?(:rebillInitDate) when(:end_date) self.event.end_date = DateTime.strptime(soap_obj.rebillEndDate, "%d/%m/%Y") if soap_obj.respond_to?(:rebillEndDate) when(:interval_type) if soap_obj.respond_to?(:rebillIntervalType) case(soap_obj.rebillIntervalType) when('1') self.event.interval_type = :daily when('2') self.event.interval_type = :weekly when('3') self.event.interval_type = :monthly when('4') self.event.interval_type = :yearly end end else self.event.send("#{key}=", soap_obj.send(method)) if soap_obj.respond_to?(method) end end end end def interval(interval) case(interval) when :daily return 1 when :weekly return 1 when :biweekly return 2 when :quadweekly return 4 when :monthly return 1 when :bimonthly return 2 when :quarterly return 3 when :yearly return 1 when :biyearly return 2 end end def interval_type(interval) case(interval) when :daily return 1 when :weekly, :biweekly, :quadweekly return 2 when :monthly, :bimonthly, :quarterly return 3 when :yearly, :biyearly return 4 end end def add_rebill_credit_card_data(attributes, credit_card) attributes[:cc_number] = credit_card.number attributes[:cc_name] = credit_card.first_name + " " + credit_card.last_name attributes[:cc_exp_month] = credit_card.month attributes[:cc_exp_year] = credit_card.year end def add_rebill_customer_data(attributes, options) attributes[:first_name] = options[:first_name] attributes[:last_name] = options[:last_name] attributes[:email] = options[:email] if options[:customer] attributes[:ref] = options[:customer][:ref] attributes[:title] = options[:customer][:title] attributes[:company] = options[:customer][:company] attributes[:job_desc] = options[:customer][:job_desc] attributes[:phone_1] = options[:customer][:phone_1] attributes[:phone_2] = options[:customer][:phone_2] attributes[:fax] = options[:customer][:fax] attributes[:url] = options[:customer][:url] attributes[:comments] = options[:customer][:comments] end end def add_rebill_invoice_data(attributes, options) attributes[:customer_id] = options[:customer_id] attributes[:interval] = interval(options[:periodicity]) attributes[:interval_type] = interval_type(options[:periodicity]) attributes[:start_date] = options[:starting_at] attributes[:end_date] = options[:ending_at] end def add_rebill_address_data(attributes, options) attributes[:address] = options[:billing_address][:address1] attributes[:suburb] = options[:billing_address][:suburb] attributes[:state] = options[:billing_address][:state] attributes[:country] = options[:billing_address][:country] attributes[:post_code] = options[:billing_address][:zip] end end end end