Skip to content

Commit

Permalink
Quickpay: enable recurring payments
Browse files Browse the repository at this point in the history
Add failing test

Fixes activemerchant#2172

Move create_token call from store to purchase

The return value of store will now have the card id rather than a (single-use) token.

We will request a new token each time we do a purchase.

Only request a new token if purchase is called with the card id as a String.

In that case, replace the card id with the token before continuing.

Otherwise, complete the purchase using whatever was passed in, which should be the full card details.

Avoid Undefined method errors by making sure the id is always returned as a String.

This ensures the authorization_from method always returns the same type.

Retrieve the payment id from the response to use in the url for the next API call.

It is not getting passed correctly in r.authorization.

Tests now pass.

Add failing test for an authorization based on a token.

If authorize is called with a card id, then swap it for a single-use token before proceeding.

Simplify handling of the single-use token.
  • Loading branch information
wsmoak committed Jul 25, 2016
1 parent 114710b commit 47ae56a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 11 deletions.
27 changes: 16 additions & 11 deletions lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,33 @@ def initialize(options = {})

def purchase(money, credit_card_or_reference, options = {})
MultiResponse.run(true) do |r|
if credit_card_or_reference.is_a?(String)
r.process { create_token(credit_card_or_reference, options) }
credit_card_or_reference = r.authorization
end
r.process { create_payment(money, options) }
r.process {
post = authorization_params(money, credit_card_or_reference, options)
add_autocapture(post, false)
commit(synchronized_path("/payments/#{r.authorization}/authorize"), post)
commit(synchronized_path("/payments/#{r.responses.last.params["id"]}/authorize"), post)
}
r.process {
post = capture_params(money, credit_card_or_reference, options)
commit(synchronized_path("/payments/#{r.authorization}/capture"), post)
commit(synchronized_path("/payments/#{r.responses.last.params["id"]}/capture"), post)
}
end
end

def authorize(money, credit_card_or_reference, options = {})
MultiResponse.run(true) do |r|
if credit_card_or_reference.is_a?(String)
r.process { create_token(credit_card_or_reference, options) }
credit_card_or_reference = r.authorization
end
r.process { create_payment(money, options) }
r.process {
post = authorization_params(money, credit_card_or_reference, options)
commit(synchronized_path("/payments/#{r.authorization}/authorize"), post)
commit(synchronized_path("/payments/#{r.responses.last.params["id"]}/authorize"), post)
}
end
end
Expand Down Expand Up @@ -71,12 +79,10 @@ def store(credit_card, options = {})
MultiResponse.run do |r|
r.process { create_store(options) }
r.process { authorize_store(r.authorization, credit_card, options)}
r.process { create_token(r.authorization, options.merge({id: r.authorization}))}
end
end

def unstore(identification)
identification = identification.split(";").last
commit(synchronized_path "/cards/#{identification}/cancel")
end

Expand Down Expand Up @@ -150,15 +156,15 @@ def commit(action, params = {})

Response.new(success, message_from(success, response), response,
:test => test?,
:authorization => authorization_from(response, params[:id])
:authorization => authorization_from(response)
)
end

def authorization_from(response, auth_id)
def authorization_from(response)
if response["token"]
"#{response["token"]};#{auth_id}"
response["token"].to_s
else
response["id"]
response["id"].to_s
end
end

Expand Down Expand Up @@ -205,8 +211,7 @@ def add_additional_params(action, post, options = {})
def add_credit_card_or_reference(post, credit_card_or_reference, options = {})
post[:card] ||= {}
if credit_card_or_reference.is_a?(String)
reference = credit_card_or_reference.split(";").first
post[:card][:token] = reference
post[:card][:token] = credit_card_or_reference
else
post[:card][:number] = credit_card_or_reference.number
post[:card][:cvd] = credit_card_or_reference.verification_value
Expand Down
17 changes: 17 additions & 0 deletions test/remote/gateways/remote_quickpay_v10_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,23 @@ def test_successful_store_and_reference_purchase
assert_success purchase
end

def test_successful_store_and_reference_recurring_purchase
assert store = @gateway.store(@valid_card, @options)
assert_success store
assert signup = @gateway.purchase(@amount, store.authorization, @options)
assert_success signup
@options[:order_id] = generate_unique_id[0...10]
assert renewal = @gateway.purchase(@amount, store.authorization, @options)
assert_success renewal
end

def test_successful_store_and_reference_authorize
assert store = @gateway.store(@valid_card, @options)
assert_success store
assert authorization = @gateway.authorize(@amount, store.authorization, @options)
assert_success authorization
end

def test_successful_unstore
assert response = @gateway.store(@valid_card, @options)
assert_success response
Expand Down

0 comments on commit 47ae56a

Please sign in to comment.