Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Balanced::Customer Debit method charging incorrect cards #136

Open
adambarthelson opened this issue Jan 13, 2014 · 4 comments
Open

Balanced::Customer Debit method charging incorrect cards #136

adambarthelson opened this issue Jan 13, 2014 · 4 comments

Comments

@adambarthelson
Copy link

The 'debit' method for Balanced::Customer is charging cards that were previously added to the list of customer's cards, instead of charging the 'active card'.

customer.active_card            # Card 1
newCard = Balanced::Card.new    # Card 2
customer.add_card(newCard)
customer.active_card            # Card 2
customer.debit(amount)  # Charges Card 1 instead of Card 2
@adambarthelson
Copy link
Author

I assume this has to do with the bug where the default card is being set to something other than the newest when source_uri isn't explicitly set?

@mjallday
Copy link
Contributor

It should use the most recently added card when no explicitly set funding instrument is used.

Let me write a script to confirm that this is reproducible locally.

In the meantime I recommend that you debit the funding instrument you want to use explicitly. e.g. bank_account.debit(:amount => amount). This pattern is where we're moving in the next revision of the documentation, we're de-emphasising the ability to blindly charge a customer.

@mjallday
Copy link
Contributor

Here's the test script I wrote

require 'balanced'

key = Balanced::ApiKey.new.save
Balanced.configure(key.secret)
marketplace = Balanced::Marketplace.new.save
customer = Balanced::Customer.new.save
card1 = Balanced::Card.new(
  :card_number => '5105105105105100',
  :expiration_month => '12',
  :expiration_year => '2020',
  :security_code => '123'
).save
card2 = Balanced::Card.new(
  :card_number => '5105105105105100',
  :expiration_month => '12',
  :expiration_year => '2020',
  :security_code => '123'
).save
customer.add_card(card1.uri)
customer.add_card(card2.uri)
puts customer.active_card.uri
debit = customer.debit(:amount => 100)
puts debit.source.uri
puts card1.uri
puts card2.uri

And it does indeed seem to not work as expected (code snipped for brevity):

vagrant@rump-omnibus-build-lab:~$ sudo gem install balanced
Fetching: multipart-post-1.2.0.gem (100%)
Fetching: faraday-0.8.9.gem (100%)
Fetching: faraday_middleware-0.9.0.gem (100%)
Fetching: balanced-0.7.4.gem (100%)
Successfully installed multipart-post-1.2.0
Successfully installed faraday-0.8.9
Successfully installed faraday_middleware-0.9.0
Successfully installed balanced-0.7.4
4 gems installed
Installing ri documentation for multipart-post-1.2.0...
Installing ri documentation for faraday-0.8.9...
Installing ri documentation for faraday_middleware-0.9.0...
Installing ri documentation for balanced-0.7.4...
Installing RDoc documentation for multipart-post-1.2.0...
Installing RDoc documentation for faraday-0.8.9...
Installing RDoc documentation for faraday_middleware-0.9.0...
Installing RDoc documentation for balanced-0.7.4...
vagrant@rump-omnibus-build-lab:~$ irb
irb(main):001:0> require 'balanced'
=> true
irb(main):002:0> 
irb(main):003:0* key = Balanced::ApiKey.new.save
irb(main):004:0> Balanced.configure(key.secret)
irb(main):005:0> marketplace = Balanced::Marketplace.new.save
irb(main):006:0> customer = Balanced::Customer.new.save
irb(main):007:0> card1 = Balanced::Card.new(
irb(main):008:1*   :card_number => '5105105105105100',
irb(main):009:1*   :expiration_month => '12',
irb(main):010:1*   :expiration_year => '2020',
irb(main):011:1*   :security_code => '123'
irb(main):012:1> ).save
irb(main):013:0> card2 = Balanced::Card.new(
irb(main):014:1*   :card_number => '5105105105105100',
irb(main):015:1*   :expiration_month => '12',
irb(main):016:1*   :expiration_year => '2020',
irb(main):017:1*   :security_code => '123'
irb(main):018:1> ).save
irb(main):019:0> customer.add_card(card1.uri)
irb(main):020:0> customer.add_card(card2.uri)
irb(main):021:0> puts customer.active_card.uri
/v1/customers/CUO9Twe5nrJXIxikjgHec2K/cards/CCQlhYIrfZaHyiQVJ8x8Ufm
=> nil
irb(main):022:0> debit = customer.debit(:amount => 100)
irb(main):023:0> puts debit.source.uri
/v1/customers/CUO9Twe5nrJXIxikjgHec2K/cards/CCPfw0ycU00azJymC2xmuMo
=> nil
irb(main):024:0> puts card1.uri
/v1/marketplaces/TEST-MPN48LnSlLjuCWkeaS1b9lE/cards/CCPfw0ycU00azJymC2xmuMo
=> nil
irb(main):025:0> puts card2.uri
/v1/marketplaces/TEST-MPN48LnSlLjuCWkeaS1b9lE/cards/CCQlhYIrfZaHyiQVJ8x8Ufm
=> nil

@mjallday
Copy link
Contributor

One of our engineers, @victorlin, diagnosed the issue. What's happening is we are setting the first card_uri as the source when we add the second card and then is causing the first card to be set as the primary funding source.

The API is behaving as intended, this is something to do with the way our ruby and python client's are written.

To quote Victor:

    def add_card(self, card_uri):
        """
        Associates the `Card` represented by `card_uri` with this `Account`.
        """
        self.card_uri = card_uri
        self.save()

When the save() is called, it uses PUT to the update customer with card_uri, and receives the new customer response then update the local Customer instance with the the latest customer data returned from the server. Here comes the point, source of customer view in revision 1.0. So, the local instance's source_uri will be updated to the card1 like this

customer.source_uri = card1.uri

When the second add_card for card2 is called, the card1's uri will be passed as source_uri parameter. And as this actually updates the default_funding_source of the customer.

def update_customer(customer, **kwargs):
    # ...
    if 'source' in kwargs:
        customer.default_funding_source = kwargs['source']

So, in this way, primary_funding_source will always be the card1 as it looks the default_funding_source first then funding_sources. This is the story why the default funding source is not the latest one.

The correct solution to fix this is mentioned in #99, the client libraries should keep track of values that are changed on the resource and only send that changed data to the server.

@remear remear added the 1.0 label Apr 18, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants