Completed
Push — master ( 330dad...b4ceb2 )
by
unknown
12s queued 10s
created

Transaction.encapsulation_character()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
module AuthorizeNet::AIM
2
  # The AIM transaction class. Handles building the transaction payload and
3
  # transmitting it to the gateway.
4
  class Transaction < AuthorizeNet::KeyValueTransaction
5
    # The default options for the constructor.
6
    @@option_defaults = {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using a class variable like @@option_defaults is generally not recommended; did you consider
using an class instance variable instead?
Loading history...
7
      transaction_type: Type::AUTHORIZE_AND_CAPTURE,
8
      gateway: :production,
9
      test: false,
10
      allow_split: false,
11
      delimiter: ',',
12
      encapsulation_character: nil,
13
      verify_ssl: true,
14
      device_type: DeviceType::UNKNOWN,
15
      market_type: MarketType::RETAIL
16
    }
17
18
    # Fields to convert to/from booleans.
19
    @@boolean_fields = %i[tax_exempt test_request recurring_billing allow_partial_auth delim_data email_customer relay_response]
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using a class variable like @@boolean_fields is generally not recommended; did you consider
using an class instance variable instead?
Loading history...
20
21
    # Fields to convert to/from BigDecimal.
22
    @@decimal_fields = [:amount]
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using a class variable like @@decimal_fields is generally not recommended; did you consider
using an class instance variable instead?
Loading history...
23
24
    # Constructs an AIM transaction. You can use the new AIM transaction object
25
    # to issue a request to the payment gateway and parse the response into a new
26
    # AuthorizeNet::AIM::Response object.
27
    #
28
    # +api_login_id+:: Your API login ID, as a string.
29
    # +api_transaction_key+:: Your API transaction key, as a string.
30
    # +options+:: A hash of options. See below for values.
31
    #
32
    # Options
33
    # +transaction_type+:: The type of transaction to perform. Defaults to AuthorizeNet::Type::AUTHORIZE_AND_CAPTURE. This value is only used if run is called directly.
34
    # +gateway+:: The gateway to submit the transaction to. Can be a URL string, an AuthorizeNet::AIM::Transaction::Gateway constant, or one of the convenience symbols :sandbox, :test, :card_present_test, :card_present_live, :card_present_sandbox, :card_present_production, :production, or :live (:test is an alias for :sandbox, :card_present_test is an alias for :card_present_sandbox, :card_present_production is an alias for :card_present_live, and :live is an alias for :production).
35
    # +test+:: A boolean indicating if the transaction should be run in test mode or not (defaults to false).
36
    # +allow_split+:: A boolean indicating if split transactions should be allowed (defaults to false).
37
    # +delimiter+:: A single character (as a string) that will be used to delimit the response from the gateway. Defaults to ','.
38
    # +encapsulation_character+:: A single character (as a string) that will be used to encapsulate each field in the response from the gateway. Defaults to nil.
39
    # +verify_ssl+:: A boolean indicating if the SSL certificate of the +gateway+ should be verified. Defaults to true.
40
    # +device_type+:: A constant from DeviceType indicating the type of POS device used in a card present transaction. Defaults to DeviceType::UNKNOWN.
41
    # +market_type+:: A constant from MarketType indicating your industry. Used for card present transactions. Defaults to MarketType::RETAIL.
42
    #
43
    def initialize(api_login_id, api_transaction_key, options = {})
44
      ActiveSupport::Deprecation.warn "use AuthorizeNet::API::Transaction"
45
      super()
46
      options = @@option_defaults.merge(options)
47
      @api_login_id = api_login_id
48
      @api_transaction_key = api_transaction_key
49
      @test_mode = options[:test]
50
      @response ||= nil
51
      @delimiter = options[:delimiter]
52
      @type = options[:transaction_type]
53
      @cp_version = nil
54
      case options[:gateway]
55
      when :sandbox, :test
56
        @gateway = Gateway::TEST
57
      when :production, :live
58
        @gateway = Gateway::LIVE
59
      when :card_present_live, :card_present_production
60
        @gateway = Gateway::CARD_PRESENT_LIVE
61
        @cp_version = '1.0'
62
      when :card_present_test, :card_present_sandbox
63
        @gateway = Gateway::CARD_PRESENT_TEST
64
        @cp_version = '1.0'
65
      else
66
        @gateway = options[:gateway]
67
      end
68
      @allow_split_transaction = options[:allow_split]
69
      @encapsulation_character = options[:encapsulation_character]
70
      @verify_ssl = options[:verify_ssl]
71
      @market_type = options[:market_type]
72
      @device_type = options[:device_type]
73
      @solution_id = options[:solution_id]
74
    end
75
76
    # Checks if the transaction has been configured for test mode or not. Return TRUE if the
77
    # transaction is a test transaction, FALSE otherwise. All transactions run against the sandbox
78
    # are considered test transactions.
79
    def test?
80
      super || @gateway == Gateway::TEST
81
    end
82
83
    # Returns TRUE if split transactions are allowed, FALSE otherwise.
84
    def split_transaction_allowed?
85
      !!@allow_split_transaction
86
    end
87
88
    # Returns the current encapsulation character unless there is none, in which case Nil is returned.
89
    attr_reader :encapsulation_character
90
91
    # Returns the gateway to be used for this transaction.
92
    attr_reader :gateway
93
94
    # Checks to see if the transaction has a response (meaning it has been submitted to the gateway).
95
    # Returns TRUE if a response is present, FALSE otherwise.
96
    def has_response?
97
      [email protected]?
98
    end
99
100
    # Retrieve the response object (or Nil if transaction hasn't been sent to the gateway).
101
    attr_reader :response
102
103
    # Returns the current delimiter we are using to parse the fields returned by the
104
    # gateway.
105
    attr_reader :delimiter
106
107
    # Sets the delimiter used to parse the response from the gateway.
108
    attr_writer :delimiter
109
110
    # Submits the transaction to the gateway for processing. Returns a response object. If the transaction
111
    # has already been run, it will return nil.
112
    def run
113
      make_request
114
    end
115
116
    # Returns the current card present API version that we are adhering to.
117
    attr_reader :cp_version
118
119
    attr_reader :solution_id
120
121
    #:enddoc:
122
    protected
123
124
    # An internal method that builds the POST body, submits it to the gateway, and constructs a Response object with the response.
125
    def make_request
126
      return nil if has_response?
127
      url = URI.parse(@gateway)
128
      fields = @fields.merge(type: @type, delim_char: @delimiter, delim_data: "TRUE", login: @api_login_id, tran_key: @api_transaction_key, relay_response: "FALSE")
129
130
      if @cp_version.nil?
131
        fields[:version] = @version
132
      else
133
        fields.merge!(cp_version: @cp_version, market_type: @market_type, device_type: @device_type, response_format: "1")
134
      end
135
      fields[:test_request] = boolean_to_value(@test_mode)
136
      fields[:allow_partial_auth] = 'TRUE' if @allow_split_transaction
137
      fields[:encap_char] = @encapsulation_character unless @encapsulation_character.nil?
138
      fields[:solution_id] = @solution_id unless @solution_id.nil?
139
      fields.each do |k, v|
140
        if @@boolean_fields.include?(k)
141
          fields[k] = boolean_to_value(v)
142
        elsif @@decimal_fields.include?(k)
143
          fields[k] = decimal_to_value(v)
144
        end
145
      end
146
      data = fields.collect do |key, val|
147
        to_param(key, val)
148
      end
149
      custom_field_keys = @custom_fields.keys.collect(&:to_s).sort.collect(&:to_sym)
150
      for key in custom_field_keys
151
        data += [to_param(key, @custom_fields[key.to_sym], '')]
152
      end
153
      data.flatten!
154
      request = Net::HTTP::Post.new(url.path)
155
      request.content_type = 'application/x-www-form-urlencoded'
156
      request.body = data.join("&")
157
      connection = Net::HTTP.new(url.host, url.port)
158
      connection.use_ssl = true
159
      if @verify_ssl
160
        connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
161
      else
162
        connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
163
      end
164
      begin
165
        @response = AuthorizeNet::AIM::Response.new((connection.start { |http| http.request(request) }), self)
166
      rescue StandardError
167
        @response = AuthorizeNet::AIM::Response.new($ERROR_INFO, self)
168
      end
169
    end
170
  end
171
end
172