Class: Docdata::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/docdata/response.rb

Overview

Object representing a "response" with attributes provided by Docdata

Examples:

:create_success=>{
  :success=>"Operation successful.", 
  :key=>"A7B623A3A7DB5949316F82049450C3F3"
}

Constant Summary collapse

@@success =
false

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = nil) ⇒ Response

Initializer to transform a +Hash+ into an Response object

Parameters:

  • args (Hash) (defaults to: nil)


53
54
55
56
57
58
59
# File 'lib/docdata/response.rb', line 53

def initialize(args=nil)
  @report = {}
  return if args.nil?
  args.each do |k,v|
    instance_variable_set("@#{k}", v) unless v.nil?
  end
end

Instance Attribute Details

#amountInteger

Returns the captured amount in cents.

Returns:

  • (Integer)

    the captured amount in cents



35
36
37
# File 'lib/docdata/response.rb', line 35

def amount
  @amount
end

#currencyString

Returns Currency ("EUR", "GBP", "USD", etc.).

Returns:

  • (String)

    Currency ("EUR", "GBP", "USD", etc.)



41
42
43
# File 'lib/docdata/response.rb', line 41

def currency
  @currency
end

#keyString

Returns Payment key for future correspondence about this transaction.

Returns:

  • (String)

    Payment key for future correspondence about this transaction



14
15
16
# File 'lib/docdata/response.rb', line 14

def key
  @key
end

#messageString

Returns Response message from DocData.

Returns:

  • (String)

    Response message from DocData



23
24
25
# File 'lib/docdata/response.rb', line 23

def message
  @message
end

Returns:

  • (Boolean)


32
33
34
# File 'lib/docdata/response.rb', line 32

def paid
  @paid
end

#paymentDocdata::Payment

Returns object.

Returns:



44
45
46
# File 'lib/docdata/response.rb', line 44

def payment
  @payment
end

#reportHash

Returns The parsed report node of the reponse-xml.

Returns:

  • (Hash)

    The parsed report node of the reponse-xml



26
27
28
# File 'lib/docdata/response.rb', line 26

def report
  @report
end

#statusString

Returns the status of this response (capture response).

Returns:

  • (String)

    the status of this response (capture response)



38
39
40
# File 'lib/docdata/response.rb', line 38

def status
  @status
end

#successBoolean Also known as: success?

Returns true/false, depending of the API response.

Returns:

  • (Boolean)

    true/false, depending of the API response



16
17
18
# File 'lib/docdata/response.rb', line 16

def success
  @success
end

#urlString

Returns the return URL.

Returns:

  • (String)

    the return URL



47
48
49
# File 'lib/docdata/response.rb', line 47

def url
  @url
end

#xmlString

Returns The raw XML returned by the API.

Returns:

  • (String)

    The raw XML returned by the API



29
30
31
# File 'lib/docdata/response.rb', line 29

def xml
  @xml
end

Class Method Details

.parse(method_name, response) ⇒ Object

Parses the returned response hash and turns it into a new Docdata::Response object

Parameters:

  • method_name (String)

    (name of the method: create, start, cancel, etc.)

  • response (Hash)


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/docdata/response.rb', line 75

def self.parse(method_name, response)
  body, xml = self.response_body(response)
  if body["#{method_name}_response".to_sym] && body["#{method_name}_response".to_sym]["#{method_name}_error".to_sym]
    raise DocdataError.new(response), body["#{method_name}_response".to_sym]["#{method_name}_error".to_sym][:error]
  else
    m = body["#{method_name}_response".to_sym]["#{method_name}_success".to_sym]
    r = self.new(key: m[:key], message: m[:success], success: true)
    r.xml    = xml #save the raw xml
    # puts m[:report]
    if m[:report]
      r.report = m[:report]
    end
    r.set_attributes
    return r
  end
end

.response_body(response) ⇒ Hash

plain XML files, in normal use, it uses a Savon::Response

Returns:

  • (Hash)

    the body of the response. In the test environment, this uses



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/docdata/response.rb', line 94

def self.response_body(response)
  if response.is_a?(File)
    parser = Nori.new(:convert_tags_to => lambda { |tag| tag.snakecase.to_sym })
    xml = response.read 
    body = parser.parse(xml).first.last.first.last
  else
    body = response.body.to_hash
    xml = response.xml
  end
  return body, xml
end

Instance Method Details

#authorizedBoolean Also known as: authorized?

Returns:

  • (Boolean)


198
199
200
# File 'lib/docdata/response.rb', line 198

def authorized
  payment_status == "AUTHORIZED"
end

#canceledBoolean Also known as: canceled?

Returns:

  • (Boolean)


204
205
206
207
# File 'lib/docdata/response.rb', line 204

def canceled
  (payment_status && payment_status == "CANCELED") || 
    (capture_status && capture_status == "CANCELED")
end

#capture_statusString

Returns the status of the capture, if exists.

Returns:

  • (String)

    the status of the capture, if exists



211
212
213
214
215
216
217
# File 'lib/docdata/response.rb', line 211

def capture_status
  if report && Response.payment_node(report) && Response.payment_node(report)[:authorization] && Response.payment_node(report)[:authorization][:capture]
    Response.payment_node(report)[:authorization][:capture][:status]
  else
    nil
  end
end

#currency_to_setString

Returns the currency if this transaction.

Returns:

  • (String)

    the currency if this transaction



221
222
223
224
225
226
227
# File 'lib/docdata/response.rb', line 221

def currency_to_set
  if status_xml &&  status_xml.xpath("//amount").any?
    status_xml.xpath("//amount").first.attributes["currency"].value
  else
    nil
  end
end

#docNokogiri::XML::Document

Returns object.

Returns:

  • (Nokogiri::XML::Document)

    object



230
231
232
233
234
235
# File 'lib/docdata/response.rb', line 230

def doc
  # remove returns and whitespaces between tags
  xml_string = xml.gsub("\n", "").gsub(/>\s+</, "><")
  # return Nokogiri::XML::Document
  @doc ||= Nokogiri.XML(xml_string)
end

#is_paid?Boolean

Note:

Docdata doesn't explicitly say 'paid' or 'not paid', this is a little bit a gray area.

Note:

This method is never 100% reliable. If you need to finetune this, please implement your own method, using

There are several approaches to determine if a payment is paid, some slow and safe, other quick and unreliable. The reason for this is that some payment methods have a much longer processing time. For each payment method a different 'paid'. the available data (total_captured, total_registered, etc.) from the Docs: Safe route: The safest route to check whether all payments were made is for the merchants to refer to the “Total captured” amount to see whether this equals the “Total registered amount”. While this may be the safest indicator, the downside is that it can sometimes take a long time for acquirers or shoppers to actually have the money transferred and it can be captured. Quick route: Another option is to see whether the sum of “total shopper pending”, “total acquirer pending” and “total acquirer authorized” matches the “total registered sum”. This implies that everyone responsible has indicated that they are going to make the payment and that the merchant is trusting that everyone will indeed make this. While this route will be faster, it does also have the risk that some payments will actually not have been made. Balanced route: Depending on the merchant's situation, it can be a good option to only refer to certain totals. For instance, if the merchant only makes use of credit card payments it could be a good route to only look at “Total acquirer approved”, since this will be rather safe but quicker than looking at the captures.

Returns:

  • (Boolean)

    true/false, depending wether this payment is considered paid.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/docdata/response.rb', line 170

def is_paid?

  if payment_method
    case payment_method
    # ideal (dutch)
    when "IDEAL" 
      (total_registered == total_captured) ## && (capture_status == "CAPTURED")
    # creditcard
    when "MASTERCARD", "VISA", "AMEX"
      (total_registered == total_acquirer_approved)
    # sofort überweisung (german)
    when "SOFORT_UEBERWEISUNG"
      (total_registered == total_acquirer_approved)
    # podium giftcard (dutch)
    when "PODIUM_GIFTCARD"
      (total_registered == total_captured)
    # fallback: if total_registered equals total_caputured,
    # we can assume that this order is paid. No 100% guarantee.
    else
      total_registered == total_acquirer_approved
    end
  else
    false
  end
end

#payment_methodString

Returns the payment method of this transaction.

Returns:

  • (String)

    the payment method of this transaction



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/docdata/response.rb', line 114

def payment_method
  begin
    if report && Response.payment_node(report).present? && Response.payment_node(report)[:payment_method].present?
      Response.payment_node(report)[:payment_method].to_s
    else
      nil
    end
  rescue
    nil
  end
end

#payment_statusString

Returns the status string provided by the API. One of [AUTHORIZED, CANCELED].

Returns:

  • (String)

    the status string provided by the API. One of [AUTHORIZED, CANCELED]



128
129
130
131
132
133
134
# File 'lib/docdata/response.rb', line 128

def payment_status
  if report && Response.payment_node(report) && Response.payment_node(report)[:authorization]
    Response.payment_node(report)[:authorization][:status]
  else
    nil
  end
end

#pidString

Returns the PID of the transaction.

Returns:

  • (String)

    the PID of the transaction



137
138
139
140
141
142
143
# File 'lib/docdata/response.rb', line 137

def pid
  if report && Response.payment_node(report) && Response.payment_node(report)[:id]
    Response.payment_node(report)[:id]
  else
    nil
  end      
end

#set_attributesObject

Set the attributes based on the API response



62
63
64
65
66
67
# File 'lib/docdata/response.rb', line 62

def set_attributes
  self.paid     = is_paid?
  self.amount   = Response.payment_node(report)[:authorization][:amount].to_i if (report && Response.payment_node(report) && Response.payment_node(report)[:authorization] && Response.payment_node(report)[:authorization][:amount].present?)
  self.status   = capture_status if capture_status
  self.currency = currency_to_set
end

#status_xmlNokogiri::XML::Document

Note:

This is a fix for Nokogiri's trouble finding xpath elements after 'xlmns' attribute in a node.

Returns object, containing only the status section.

Returns:

  • (Nokogiri::XML::Document)

    object, containing only the status section



239
240
241
# File 'lib/docdata/response.rb', line 239

def status_xml
  @status_xml ||= Nokogiri.XML(doc.xpath("//S:Body").first.children.first.children.first.to_xml)
end