Class: Cardia::CreditCardTransaction

Inherits:
Object
  • Object
show all
Defined in:
lib/cardia/credit_card_transaction.rb

Overview

This class represents a credit card transaction against Cardia These are created at Cardia using one of the register methods:

  • register, which keeps the control with us (we dont redirect the user away), but gives the merchant full responsibility

  • register_3d, which forces our user into foreign territory, hopefully returning to us afterwards; but limits the merchants liabilities

Minimal usage example

require 'cardia'

customer = Cardia::Customer.new("John","Doe")
amount = 1000
order = Cardia::Order.new(amount, "My test order")
order.customer = customer
merchant = Cardia::Merchant.test_merchant
transaction = Cardia::CreditCardTransaction.with_http_connection(order)
transaction.merchant = merchant

card = Cardia::CreditCard.valid_card_for_testing

For regular transactions, use:

status = transaction.register(card)

For 3d secure, use:

status = transaction.register_3d(card, "http://my.success.url/", "http://my.failure.url/")

This will return a URL that the user should be redirected to. When the user is sent to this address he will either be redirected to

either the success or failure URL, depending on whether the payment was successful.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(an_order, http_connection) ⇒ CreditCardTransaction

:nodoc:



33
34
35
36
# File 'lib/cardia/credit_card_transaction.rb', line 33

def initialize(an_order, http_connection) #:nodoc:
  @order= an_order
  @http = http_connection
end

Instance Attribute Details

#merchantObject

Returns the value of attribute merchant.



31
32
33
# File 'lib/cardia/credit_card_transaction.rb', line 31

def merchant
  @merchant
end

#orderObject (readonly)

Returns the value of attribute order.



30
31
32
# File 'lib/cardia/credit_card_transaction.rb', line 30

def order
  @order
end

#verification_addressObject (readonly)

Returns the value of attribute verification_address.



30
31
32
# File 'lib/cardia/credit_card_transaction.rb', line 30

def verification_address
  @verification_address
end

Class Method Details

.server_nameObject

:nodoc:



210
211
212
# File 'lib/cardia/credit_card_transaction.rb', line 210

def self.server_name #:nodoc:
  "secure.cardia.no"
end

.with_http_connection(an_order) ⇒ Object

Creates a new instance. Send along your Order as the parameter, see Cardia::Order for methods that should be implemented in your order

  • an_order The order



40
41
42
43
44
# File 'lib/cardia/credit_card_transaction.rb', line 40

def self.with_http_connection(an_order)
  http = Net::HTTP.new(self.server_name,"443")
  http.use_ssl = true
  return self.new(an_order, http)
end

Instance Method Details

#change_amount(new_amount) ⇒ Object

This method changes the amount on a transaction You should probably investigate about the terms around this before actually using it



185
186
187
# File 'lib/cardia/credit_card_transaction.rb', line 185

def change_amount(new_amount)
  return invoke("ChangeAmount", "merchantToken=#{@merchant.token}&amount=#{new_amount}&merchantReference=#{@order.reference}")
end

#check_statusObject

Returns the transaction status as a Cardia::TransactionStatus instance



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/cardia/credit_card_transaction.rb', line 190

def check_status
  status, doc = invoke_transaction_web_service("ReturnTransactionStatus", "merchantToken=#{@merchant.token}&merchantReference=#{@order.reference}")
  response_code = doc.root.elements["ResponseCode"].text
  currency_code = doc.root.elements["CurrencyCode"].text
  recurring_code = doc.root.elements["RecurringCode"].text
  amt = doc.root.elements["Amount"]
  s = TransactionStatus.new(status)
  unless amt.nil?
    s.amount = Money.kroner(amt.text.to_i)
  end
  s.response_code = response_code.to_i
  s.currency_code = currency_code
  s.recurring_code = recurring_code
  return s
end

#confirm!Object

This method confirms payments that are “on hold”. Cardia calls this RevertOnHold



179
180
181
# File 'lib/cardia/credit_card_transaction.rb', line 179

def confirm!
  return invoke_transaction_web_service("RevertOnHoldTransaction", "merchantToken=#{@merchant.token}&merchantReference=#{@order.reference}")
end

#credit(amount = nil) ⇒ Object Also known as: refund

Credits the transaction. This is bank-speak for reversing it; giving the customer a full refund If you want to, you can supply the amount manually



172
173
174
175
# File 'lib/cardia/credit_card_transaction.rb', line 172

def credit(amount=nil)
  amount = @order.amount if amount.nil?
  return invoke("CreditTransaction", "merchantToken=#{@merchant.token}&amount=#{amount}&merchantReference=#{@order.reference}")
end

#do_invoke_web_service(base_url, method, values) ⇒ Object

:nodoc:



124
125
126
127
128
129
130
# File 'lib/cardia/credit_card_transaction.rb', line 124

def do_invoke_web_service(base_url, method, values) #:nodoc:
  http = http_connection
  url = base_url + method
  response, body = http.post(url, values, {"Content-Type" => "application/x-www-form-urlencoded"})
  response.value
  return REXML::Document.new(response.body)
end

#http_connectionObject



120
121
122
# File 'lib/cardia/credit_card_transaction.rb', line 120

def http_connection
  @http
end

#invoke(method, values) ⇒ Object

Implements the vanilla plain calls to Cardia



67
68
69
70
# File 'lib/cardia/credit_card_transaction.rb', line 67

def invoke(method, values) #:nodoc:
  status, doc = invoke_transaction_web_service(method, values)
  return status
end

#invoke_teller_web_service(method, values) ⇒ Object

:nodoc:



60
61
62
63
64
# File 'lib/cardia/credit_card_transaction.rb', line 60

def invoke_teller_web_service(method, values) #:nodoc:
  doc = do_invoke_web_service("/Service/Card/Mpi/TellerMpi/1.2/TellerMpi.asmx/", method, values)
  status_code = doc.root.elements["ResponseCode"].text.to_i
  return status_code, doc
end

#invoke_transaction_web_service(method, values) ⇒ Object

:nodoc:



52
53
54
55
56
57
58
# File 'lib/cardia/credit_card_transaction.rb', line 52

def invoke_transaction_web_service(method, values) #:nodoc:
  doc = do_invoke_web_service("/Service/Card/Transaction/1.2/Transaction.asmx/",
                              method,
                              values)
  status_code = doc.root.elements["StatusCode"].text.to_i
  return status_code, doc
end

#register(a_credit_card) ⇒ Object

Register the transaction with Cardia. Once this has been done, the amount is reserved on the users credit card, given that the the returned status says so…



102
103
104
105
# File 'lib/cardia/credit_card_transaction.rb', line 102

def register(a_credit_card)
  status, doc = register_with_doc(a_credit_card)
  return status
end

#register_3d(a_credit_card, success_url, failure_url) ⇒ Object

Register using 3DSecure. Send along a card, a URL for redirection after successful payments and a URL to redirect to when the payment was unsuccessful.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/cardia/credit_card_transaction.rb', line 133

def register_3d(a_credit_card, success_url, failure_url)
  raise "No verification code supplied" if a_credit_card.verification_value.nil?
  params = {
    :merchantToken                      => @merchant.token,
    :applicationIdentifier              => "", # not in use
    :cardNumber                         => a_credit_card.number,
    :expiryDate                         => a_credit_card.expires,
    :cv2Code                            => a_credit_card.verification_value,
    :merchantReference                  => @order.reference,
    :successfulTransactionUrl           => CGI::escape(success_url),
    :unsuccessfulTransactionUrl         => CGI::escape(failure_url),
    :authorizedNotAuthenticatedUrl      => "", # not in use
    :currencyCode                       => "NOK",
    :amount                             => @order.amount.to_i,
    :isOnHold                           => "true",
    :paymentType                        => a_credit_card.payment_type
  }
  opts = []
  params.each{|k,v| opts << "#{k}=#{v}"}
  values = opts.join("&")
  status, doc = invoke_teller_web_service("PrepareTransaction", values)
  unless status == 1
    raise doc.root.elements["Error"].text
  end
  address = doc.root.elements["Address"].text
  guid = doc.root.elements["ReferenceGuid"].text
  @verification_address = "#{address}?preparationGuid=#{guid}"
  return @verification_address
end

#register_with_doc(a_credit_card) ⇒ Object

Register the payment, keeping our user with us



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/cardia/credit_card_transaction.rb', line 73

def register_with_doc(a_credit_card) #:nodoc:
  raise "Invalid credit card" unless a_credit_card.valid?
  params =
    {
    :merchantToken                  => @merchant.token,
    :userToken                                      => @order.customer.token,
    :merchantReference      => @order.reference,
    :store                                                  => store_name,
    :orderDescription               => @order.description,
    :cardNumber                                     => a_credit_card.number,
    :expiryDate                                     => a_credit_card.expires,
    :cvc2Code                                               => a_credit_card.verification_value,
    :currencyCode                           => "NOK",
    :instanceId                                     => "",
    :amount                                                 => @order.amount.to_i, # croaks on floating point
    :purchaseDate                           => Date.today.strftime("%Y-%m-%d"),
    :isOnHold                                               => "true",
    :isPreRegistered                => "false"
  }
  opts = []
  params.each{|k,v| opts<<"#{k}=#{v}"}

  values = opts.join("&")
  method = "RegisterCardTransaction"
  status, doc = invoke_transaction_web_service(method, values)
  return status, doc
end

#store_nameObject

:nodoc:



206
207
208
# File 'lib/cardia/credit_card_transaction.rb', line 206

def store_name #:nodoc:
  "AS Juks og Bedrag"
end

#voidObject

Cancels a transaction. A good practice is probably to have a before_destroy filter in your order that does this



165
166
167
# File 'lib/cardia/credit_card_transaction.rb', line 165

def void
  return invoke("VoidTransaction", "merchantToken=#{@merchant.token}&userToken=#{@order.customer.token}&merchantReference=#{@order.reference}")
end

#wait_until_approvedObject

:nodoc:



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/cardia/credit_card_transaction.rb', line 107

def wait_until_approved #:nodoc:
  (1..10).each do |n|
    status = check_status
    if status == TransactionStatus.approved
      yield
      return
    end
    puts n
    sleep(2)
  end
  raise "Out of retries, Order not approved"
end