| 1 |  |  | module AuthorizeNet::SIM | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |   # The SIM response class. Handles parsing the response from the gateway. Also | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |   # provides a few relay response helpers used to implement Direct Post Method. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |   class Response < AuthorizeNet::KeyValueResponse | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |     # Our MD5 digest generator. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |     @@digest = OpenSSL::Digest.new('md5') | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |     include AuthorizeNet::SIM::Fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |     # Constructs a new response object from a +raw_response+. Provides utility methods | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |     # for validating the response as authentic, and for handling the Direct Post Method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |     # relay response. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |     # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |     # +raw_response+:: The raw response, either a string in POST body or GET query string format, or a hash of key/value pairs. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |     # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |     # Typical usage: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |     #   response = AuthorizeNet::SIM::Response("x_first_name=John&x_last_name=Doe") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |     def initialize(raw_response) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |       @raw_response = raw_response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |       @custom_fields = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |       @fields = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |       parse_response(@raw_response) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |     # Returns True if the MD5 hash found in the response payload validates using | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |     # the supplied api_login and secret merchant_value (THIS IS NOT YOUR API KEY). | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 27 |  | View Code Duplication |     def valid_md5?(api_login, merchant_value) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |       return false if @fields[:MD5_Hash].nil? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |       @@digest.hexdigest("#{merchant_value}#{api_login}#{@fields[:trans_id]}#{@fields[:amount]}").casecmp(@fields[:MD5_Hash]).zero? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |     # Returns an HTML string that can be returned to the gateway during the Relay Response, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |     # and will send the user on to URL you specify. Takes a hash of options, currently the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |     # only option is :include, which can be True to include all fields returned in the response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |     # as query string parameters, or it can be an array of fields to include. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |     def direct_post_reply(url, options = {}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |       url = direct_post_url(url, options[:include]) if options.key?(:include) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |       js_url = url.tr("'", '\'') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |       html_url = url.gsub('&', '&').tr('"', "\"") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |       html = <<-HTML | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  | <html><head><script type="text/javascript" charset="utf-8">window.location='#{js_url}';</script><noscript><meta http-equiv="refresh" content="1;url=#{html_url}"></noscript></head><body></body></html> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | HTML | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     # Returns an URL with the fields found in the response and specified in include_fields attached as | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     # part of the URL's query string. If you pass true instead of an array of fields, all fields will be | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |     # attached. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     def direct_post_url(base_url, include_fields = true) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |       url = base_url | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |       if include_fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |         fields = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |         case include_fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         when TrueClass | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |           fields = FIELDS.collect do |k| | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |             k_str = k.to_s | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |             k_str[2..k_str.length].to_sym | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |           end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |         when Array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |           fields = include_fields | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |         else | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |           fields = include_fields.to_a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |         end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |         parsed_url = URI.parse(url) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |         if parsed_url.query.nil? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |           parsed_url.query = '' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |         elsif !parsed_url.query.empty? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |           parsed_url.query = parsed_url.query.chomp('&') + '&' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |         parsed_url.query += ((fields.select { |k| @fields.key?(k) }).collect { |k| to_param(k, @fields[k]) }).join('&') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |         parsed_url.query.chomp('&') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |         url = parsed_url.to_s | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |       end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |       url | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |     # Check to see if the response indicated success. Success is defined as a valid MD5 hash | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |     # and an response code of AuthorizeNet::Response::ResponseCode::APPROVED. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |     def success?(api_login, merchant_value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |       valid_md5?(api_login, merchant_value) && approved? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |     # Returns the transaction's authorization code. This should be shown to the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |     # end user. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     def authorization_code | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |       @fields[:auth_code] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |     # Returns the transaction's authorization id. You will need this for future void, refund | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |     # and prior authorization capture requests. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |     def transaction_id | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |       @fields[:trans_id] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |     # Returns the customer id from the response. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |     def customer_id | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |       @fields[:cust_id] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |     # Returns a response code (from AVSResponseCode) indicating the result of any Address Verification | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |     # Service checks. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |     def avs_response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |       @fields[:avs_code] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |     #:enddoc: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |     protected | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |     # Internal helper to parse the raw response object. It handles both raw POST bodies and | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 109 |  |  |     # hashes. | 
            
                                                                        
                            
            
                                    
            
            
                | 110 |  |  |     def parse_response(raw_response) | 
            
                                                                        
                            
            
                                    
            
            
                | 111 |  |  |       case raw_response | 
            
                                                                        
                            
            
                                    
            
            
                | 112 |  |  |       when Hash | 
            
                                                                        
                            
            
                                    
            
            
                | 113 |  |  |         raw_response.each do |k, v| | 
            
                                                                        
                            
            
                                    
            
            
                | 114 |  |  |           k = k.to_sym | 
            
                                                                        
                            
            
                                    
            
            
                | 115 |  |  |           if FIELDS.include?(k) | 
            
                                                                        
                            
            
                                    
            
            
                | 116 |  |  |             @fields[to_internal_field(k)] = v # remove x_ from sym and stick in @fields | 
            
                                                                        
                            
            
                                    
            
            
                | 117 |  |  |           else | 
            
                                                                        
                            
            
                                    
            
            
                | 118 |  |  |             @custom_fields[k] = v | 
            
                                                                        
                            
            
                                    
            
            
                | 119 |  |  |           end | 
            
                                                                        
                            
            
                                    
            
            
                | 120 |  |  |         end | 
            
                                                                        
                            
            
                                    
            
            
                | 121 |  |  |       when String | 
            
                                                                        
                            
            
                                    
            
            
                | 122 |  |  |         # convert to hash and re-parse | 
            
                                                                        
                            
            
                                    
            
            
                | 123 |  |  |         hash = CGI.parse(raw_response) | 
            
                                                                        
                            
            
                                    
            
            
                | 124 |  |  |         hash.each do |k, v| | 
            
                                                                        
                            
            
                                    
            
            
                | 125 |  |  |           hash[k] = v[0] if v.is_a?(Array) && v.length == 1 | 
            
                                                                        
                            
            
                                    
            
            
                | 126 |  |  |         end | 
            
                                                                        
                            
            
                                    
            
            
                | 127 |  |  |         parse_response(hash) | 
            
                                                                        
                            
            
                                    
            
            
                | 128 |  |  |       else | 
            
                                                                        
                            
            
                                    
            
            
                | 129 |  |  |         parse_response(@raw_response.to_s) | 
            
                                                                        
                            
            
                                    
            
            
                | 130 |  |  |       end | 
            
                                                                        
                            
            
                                    
            
            
                | 131 |  |  |     end | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |   end | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 133 |  |  | end | 
            
                                                        
            
                                    
            
            
                | 134 |  |  |  |