def test_credit_card_limit(self): funding_card = balanced.Card(**CARD).save() debit = funding_card.debit(amount=250005) card = balanced.Card(**CREDITABLE_CARD).save() with self.assertRaises(requests.HTTPError) as exc: credit = card.credit(amount=250001) self.assertEqual(exc.exception.status_code, 409) self.assertEqual(exc.exception.category_code, 'amount-exceeds-limit')
def test_credit_existing_card(self): funding_card = balanced.Card(**CARD).save() card = balanced.Card(**CREDITABLE_CARD).save() debit = funding_card.debit(amount=250000) credit = card.credit(amount=250000) self.assertTrue(credit.id.startswith('CR')) self.assertEqual(credit.href, '/credits/{0}'.format(credit.id)) self.assertEqual(credit.status, 'succeeded') self.assertEqual(credit.amount, 250000)
def test_credit_card_require_name(self): funding_card = balanced.Card(**CARD).save() debit = funding_card.debit(amount=250005) card_payload = CREDITABLE_CARD.copy() card_payload.pop("name") card = balanced.Card(**card_payload).save() with self.assertRaises(requests.HTTPError) as exc: credit = card.credit(amount=250001) self.assertEqual(exc.exception.status_code, 400) self.assertEqual(exc.exception.category_code, 'name-required-to-credit')
def test_charge_on_balanced_handles_MultipleFoundError(self): card = balanced.Card(number='4242424242424242', expiration_year=2020, expiration_month=12).save() card.associate_to_customer(self.balanced_customer_href) card = balanced.Card(number='4242424242424242', expiration_year=2030, expiration_month=12).save() card.associate_to_customer(self.balanced_customer_href) actual = self.payday.charge_on_balanced('whatever username', self.balanced_customer_href, D('10.00')) assert actual == (D('10.61'), D('0.61'), 'MultipleResultsFound()')
def test_anonymous_listing_with_existing_buyer_account(self): email_address = email_generator.next() card = balanced.Card(card_number='4111111111111111', expiration_month=12, expiration_year=2020, security_code=123).save() ogaccount = balanced.Marketplace.my_marketplace.create_buyer( email_address, card.uri, ) payload = self._guest_listing_payload(email_address) resp = self.client.post('/list', data=payload) self.assertEqual(resp.status_code, 302) self.assertIn('/list/1/complete', resp.data) # check locally user = User.query.filter(User.email_address == email_address).one() # NOTE: guest passwords currently disabled self.assertIsNone(user.password_hash) # self.assertTrue(user.check_password('ab')) # check in balanced account = user.balanced_account self.assertTrue('merchant' in account.roles) self.assertTrue('buyer' in account.roles) self.assertEqual(account.email_address, email_address) self.assertEqual(ogaccount.uri, account.uri)
def setUp(self): Harness.setUp(self) self.alice = self.make_participant('alice', elsewhere='github') self.balanced_customer_href = unicode(balanced.Customer().save().href) self.card_href = unicode( balanced.Card( number='4111111111111111', expiration_month=10, expiration_year=2020, address={ 'line1': "123 Main Street", 'state': 'Confusion', 'postal_code': '90210', }, # gittip stores some of the address data in the meta fields, # continue using them to support backwards compatibility meta={ 'address_2': 'Box 2', 'city_town': '', 'region': 'Confusion', }).save().href ) # XXX Why don't we actually associate this with the customer? See XXX in # test_billing_payday.TestPaydayChargeOnBalanced. self.bank_account_href = unicode( balanced.BankAccount( name='Homer Jay', account_number='112233a', routing_number='121042882', ).save().href)
def test_dispute(self): card = balanced.Card(**DISPUTE_CARD).save() debit = card.debit(amount=100) # TODO: this is ugly, I think we should provide a more # reliable way to generate dispute, at least it should not # take this long print >> sys.stderr, ( 'It takes a while before the dispute record created, ' 'take and nap and wake up, then it should be done :/ ' '(last time I tried it took 10 minutes...)' ) timeout = 12 * 60 interval = 10 begin = time.time() while True: if balanced.Dispute.query.count(): break time.sleep(interval) elapsed = time.time() - begin print >> sys.stderr, 'Polling disputes..., elapsed', elapsed self.assertLess(elapsed, timeout, 'Ouch, timeout') dispute = balanced.Dispute.query.one() self.assertEqual(dispute.status, 'pending') self.assertEqual(dispute.reason, 'fraud') self.assertEqual(dispute.transaction.id, debit.id)
def test_merchant_no_bank_account(self): mp = balanced.Marketplace.query.one() merchant_payload = copy.deepcopy(merchants.BUSINESS_MERCHANT) merchant_payload['tax_id'] = '123456789' merchant = mp.create_merchant( '*****@*****.**', merchant=merchant_payload, ) # now try to credit amount = 10000 buyer_account = self._find_buyer_account() buyer_account.debit(amount=amount) with self.assertRaises(requests.HTTPError) as exc: merchant.credit(amount) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) # try to debit with self.assertRaises(requests.HTTPError) as exc: merchant.debit(600) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) # add a card, make sure we can use it card_payload = dict(self.us_card_payload) card = balanced.Card(**card_payload).save() card_uri = card.uri merchant.add_card(card_uri=card_uri) # try to debit again debit = merchant.debit(601) self.assertEqual(debit.source.id, card.id)
def test_transactions_invalid_funding_sources(self): mp = balanced.Marketplace.query.one() card_payload = dict(self.us_card_payload) card = balanced.Card(**card_payload).save() card_uri = card.uri buyer = mp.create_buyer( email_address='*****@*****.**', card_uri=card_uri, meta={'foo': 'bar'}, ) # invalidate card card.is_valid = False card.save() # Now use the card with self.assertRaises(requests.HTTPError) as exc: # ...implicitly buyer.debit(6000) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) self.assertEqual(the_exception.category_code, 'no-funding-source') with self.assertRaises(requests.HTTPError) as exc: # ... and explicitly buyer.debit(7000, source_uri=card.uri) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) self.assertEqual(the_exception.category_code, 'card-not-valid') with self.assertRaises(requests.HTTPError) as exc: buyer.credit(8000) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) self.assertEqual(the_exception.category_code, 'no-funding-destination')
def test_04_create_a_buyer(self): self.assertIsNotNone(balanced.config.api_key_secret) card_number = TEST_CARDS['visa'][0] buyer_name = 'khalkhalash onastick' card_payload = { 'street_address': '123 Fake Street', 'city': 'Jollywood', 'state': 'CA', 'postal_code': '90210', 'name': buyer_name, 'card_number': card_number, 'expiration_month': 12, 'expiration_year': 2013, } card = balanced.Card(**card_payload).save() card_uri = card.uri mp = self._find_marketplace() buyer = mp.create_buyer(email_address='*****@*****.**', card_uri=card_uri, meta={'test#': 'test_d'}) self.assertTrue(buyer.id.startswith('AC'), buyer.id) self.assertEqual(buyer.name, 'khalkhalash onastick') self.assertEqual(buyer.roles, ['buyer']) self.assertIsNotNone(buyer.created_at) self.assertDictEqual(buyer.meta, {'test#': 'test_d'}) self.assertIsNotNone(buyer.uri) self.assertTrue(buyer.uri.startswith(mp.uri + '/accounts'))
def test_settle_account_negative_balance(self): merchant = balanced.Customer().save() order = merchant.create_order() card = balanced.Card(**INTERNATIONAL_CARD).save() order.debit_from(source=card, amount=1234) payable_account = merchant.payable_account account_credit = payable_account.credit( amount=1234, order=order.href, appears_on_statement_as='Payout') bank_account = balanced.BankAccount( account_number='1234567890', routing_number='321174851', name='Someone', ).save() bank_account.associate_to_customer(merchant) payable_account.settle( funding_instrument=bank_account.href, appears_on_statement_as="Settlement Oct", description="Settlement for payouts from October") payable_account = merchant.payable_account self.assertEqual(payable_account.balance, 0) account_credit.reverse(amount=1234) payable_account = merchant.payable_account self.assertEqual(payable_account.balance, -1234) payable_account.settle( funding_instrument=bank_account.href, appears_on_statement_as="Settlement Oct", description="Settlement for payouts from October") payable_account = merchant.payable_account self.assertEqual(payable_account.balance, 0)
def test_anonymous_listing_with_existing_buyer_account(self): email = email_generator.next() card = balanced.Card(number='4111111111111111', expiration_month=12, expiration_year=2020, cvv=123).save() ogaccount = balanced.Customer( email=email, source=card.href, ).save() payload = self._guest_listing_payload(email) resp = self.client.post('/list', data=payload) self.assertEqual(resp.status_code, 302) self.assertIn('/list/1/complete', resp.data) # check locally user = User.query.filter(User.email == email).one() # NOTE: guest passwords currently disabled self.assertIsNone(user.password_hash) # self.assertTrue(user.check_password('ab')) # check in balanced account = user.balanced_customer self.assertEqual(account.email, email) self.assertEqual(ogaccount.href, account.href)
def test_invalid_funding_instrument(self): balanced.configure(self.processor_key) # create a card card = balanced.Card( name='BILLY_INTERGRATION_TESTER', number='5105105105105100', expiration_month='12', expiration_year='2020', security_code='123', ).save() card_uri = card.href + 'NOTEXIST' # create a company company = self.create_company() api_key = str(company['api_key']) # create a customer res = self.testapp.post('/v1/customers', headers=[self.make_auth(api_key)], status=200) customer = res.json self.assertEqual(customer['company_guid'], company['guid']) # create an invoice res = self.testapp.post('/v1/invoices', dict( customer_guid=customer['guid'], amount=5566, funding_instrument_uri=card_uri, ), headers=[self.make_auth(api_key)], status=400) self.assertEqual(res.json['error_class'], 'InvalidFundingInstrument')
def test_update_stupid_values(self): mp = balanced.Marketplace.query.one() card_payload = dict(self.us_card_payload) card = balanced.Card(**card_payload).save() card_uri = card.uri buyer = mp.create_buyer( email_address='*****@*****.**', card_uri=card_uri, meta={'foo': 'bar'}, ) # Add a bank account to test crediting bank_account_payload = dict(self.bank_account_payload) bank_account = balanced.BankAccount(**bank_account_payload).save() bank_account_uri = bank_account.uri buyer.add_bank_account(bank_account_uri=bank_account_uri) name = buyer.name buyer.name = 's' * 1000 with self.assertRaises(requests.HTTPError) as exc: buyer.save() the_exception = exc.exception self.assertIn('must have length <=', the_exception.description) buyer.name = name with self.assertRaises(requests.HTTPError) as exc: buyer.debit(100**100) the_exception = exc.exception self.assertEqual(the_exception.status_code, 400) self.assertIn('must be <=', the_exception.description) with self.assertRaises(requests.HTTPError) as exc: buyer.credit(100**100) the_exception = exc.exception self.assertEqual(the_exception.status_code, 400) self.assertIn('must be <=', the_exception.description)
def test_order(self): merchant = balanced.Customer().save() bank_account = balanced.BankAccount(**BANK_ACCOUNT).save() bank_account.associate_to_customer(merchant) order = merchant.create_order(description='foo order') card = balanced.Card(**INTERNATIONAL_CARD).save() # debit to increment escrow card.debit(amount=1000) # debit the card and associate with the order. card.debit(amount=100, order=order) order = balanced.Order.fetch(order.href) # the order captured the amount of the debit self.assertEqual(order.amount_escrowed, 100) # pay out half credit = bank_account.credit(amount=50, order=order) self.assertEqual(credit.order.href, order.href) order = balanced.Order.fetch(order.href) # half the money remains self.assertEqual(order.amount_escrowed, 50) # not enough money in the order to pay out with self.assertRaises(balanced.exc.BalancedError): bank_account.credit(amount=150, order=order)
def test_create_card_hold_multiple_cards(self): customer_href = self.make_balanced_customer() card = balanced.Card(number='4242424242424242', expiration_year=2020, expiration_month=12).save() card.associate_to_customer(customer_href) card = balanced.Card(number='4242424242424242', expiration_year=2030, expiration_month=12).save() card.associate_to_customer(customer_href) bob = self.make_participant('bob', balanced_customer_href=customer_href, is_suspicious=False) hold, error = create_card_hold(self.db, bob, D('10.00')) assert error == 'MultipleResultsFound()'
def test_get_none_for_none(self): card = balanced.Card(**CARD).save() customer = balanced.Customer().save() self.assertIsNone(card.customer) card.associate_to_customer(customer) card = balanced.Card.get(card.href) self.assertIsNotNone(card.customer) self.assertTrue(isinstance(card.customer, balanced.Customer))
def test_general_resources(self): card = balanced.Card(**CARD).save() customer = balanced.Customer().save() card.associate_to_customer(customer) debit = card.debit(amount=1000) self.assertIsNotNone(debit) self.assertIsNotNone(debit.source) self.assertTrue(isinstance(debit.source, balanced.Card))
def test_reverse_a_credit(self): card = balanced.Card(**INTERNATIONAL_CARD).save() card.debit(5000) bank_account = balanced.BankAccount(**BANK_ACCOUNT_W_TYPE).save() credit = bank_account.credit(amount=5000) reversal = credit.reverse() self.assertEqual(reversal.amount, 5000) self.assertIn(credit.id, reversal.credit.href)
def test_create_card_hold_multiple_cards(self): bob = self.make_participant('bob', balanced_customer_href='new', is_suspicious=False) card = balanced.Card(number='4242424242424242', expiration_year=2020, expiration_month=12).save() card.associate_to_customer(bob.balanced_customer_href) ExchangeRoute.insert(bob, 'balanced-cc', card.href) card = balanced.Card(number='4242424242424242', expiration_year=2030, expiration_month=12).save() card.associate_to_customer(bob.balanced_customer_href) ExchangeRoute.insert(bob, 'balanced-cc', card.href) hold, error = create_card_hold(self.db, bob, D('10.00')) assert error == ''
def handle(self, *args, **options): # sample charge card card = balanced.Card(cvv='123', expiration_month='12', number='5105105105105100', expiration_year='2020').save() cc = balanced.Card.fetch(card.href) clients = [ 'Dwayne Wade', 'Richard Hamilton', 'Leon Powe', 'Manute Bol', 'Spud Webb', 'Dennis Rodman', 'Nate Robinson', 'Manu Ginobili', 'David Robinson', 'Ray Allen' ] timezone = current_tz() data = [] for client in clients: back = randint(100, 500) # random # of days startdate = date.today() - timedelta(days=back) data.append({'name': client, 'start': startdate}) print "Test data for payments history (today is %s)" % date.today() for d in data: blitz = Blitz.objects.get(url_slug='3weeks') m = (len( list( rrule.rrule(rrule.MONTHLY, dtstart=d['start'], until=date.today())))) c = create_client( d['name'], "*****@*****.**" % d['name'].split(' ', 1)[0].lower(), "asdf", randint(22, 35), randint(180, 230), 6, randint(0, 11), 'M') c.balanced_account_uri = card.href c.save() add_client_to_blitz(blitz, c, None, blitz.price, d['start']) # charge a partial amount for each client meta = { "client_id": c.pk, "blitz_id": blitz.pk, 'email': c.user.email } payment = randint(1, 3) * blitz.price * 100 debit = cc.debit(appears_on_statement_as='Blitz.us test', amount=payment, description='Blitz.us test', meta=meta) print d['name'], "*****@*****.**" % d['name'].split( ' ', 1)[0].lower(), " Start:" + str( d['start']), " # months" + str(m), "Charge: (cents)" + str( payment)
def test_associate_bad_cards(self): mp = balanced.Marketplace.query.one() card_payload = dict(self.us_card_payload) card = balanced.Card(**card_payload).save() card_uri = card.uri buyer = mp.create_buyer( email_address='*****@*****.**', card_uri=card_uri, meta={'foo': 'bar'}, ) # Invalid card card_payload = dict(self.us_card_payload) card_payload['is_valid'] = False card = balanced.Card(**card_payload).save() card_uri = card.uri with self.assertRaises(requests.HTTPError) as exc: buyer.add_card(card_uri=card_uri) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) self.assertEqual(the_exception.category_code, 'card-not-valid') # Already-associated card card_payload = dict(self.us_card_payload) card = balanced.Card(**card_payload).save() card_uri = card.uri mp.create_buyer( email_address='*****@*****.**', card_uri=card_uri, meta={'foo': 'bar'}, ) with self.assertRaises(requests.HTTPError) as exc: buyer.add_card(card_uri=card_uri) the_exception = exc.exception self.assertEqual(the_exception.status_code, 409) self.assertEqual(the_exception.category_code, 'card-already-funding-src') # Completely fake card uri with self.assertRaises(requests.HTTPError) as exc: buyer.add_card(card_uri='/completely/fake') the_exception = exc.exception self.assertEqual(the_exception.status_code, 400)
def test_valid_non_us_address_no_postal_code(self): card_number = cards.TEST_CARDS['visa'][0] card_payload = { 'card_number': card_number, 'expiration_month': 12, 'expiration_year': 2013, } card_payload.update(self.valid_international_address) card_payload.update(self.person) balanced.Card(**card_payload).save()
def _create_buyer_account(self): mp = balanced.Marketplace.query.one() card_payload = dict(self.us_card_payload) card = balanced.Card(**card_payload).save() card_uri = card.uri buyer = mp.create_buyer( email_address='*****@*****.**', card_uri=card_uri, meta={'foo': 'bar'}, ) return buyer
def test_create_card_hold_bad_card(self): bob = self.make_participant('bob', balanced_customer_href='new', is_suspicious=False) card = balanced.Card(number='4444444444444448', expiration_year=2020, expiration_month=12).save() card.associate_to_customer(bob.balanced_customer_href) ExchangeRoute.insert(bob, 'balanced-cc', card.href) hold, error = create_card_hold(self.db, bob, D('10.00')) assert error.startswith('402 Payment Required, ')
def test_credit_a_bank_account(self): self.create_marketplace() # NOTE: fresh mp for escrow checks card = balanced.Card(**INTERNATIONAL_CARD).save() bank_account = balanced.BankAccount(**BANK_ACCOUNT).save() debit = card.debit(amount=10000) credit = bank_account.credit(amount=1000) self.assertTrue(credit.id.startswith('CR')) self.assertEqual(credit.amount, 1000) with self.assertRaises(requests.HTTPError) as exc: bank_account.credit(amount=(debit.amount - credit.amount) + 1) self.assertEqual(exc.exception.status_code, 409) self.assertEqual(exc.exception.category_code, 'insufficient-funds')
def test_debit(self): customer = balanced.Customer().save() card = balanced.Card(**CARD).save() card.associate_to_customer(customer) for uri in self._iter_card_uris( marketplace=self.marketplace, customer=customer, card=card, ): debit = balanced.Debit(amount=100, source=uri).save() self.assertEqual(debit.source.href, card.href) self.assertEqual(debit.amount, 100)
def test_charge_on_balanced_failure(self): customer_with_bad_card = unicode(balanced.Customer().save().href) card = balanced.Card(number='4444444444444448', expiration_year=2020, expiration_month=12).save() card.associate_to_customer(customer_with_bad_card) actual = self.payday.charge_on_balanced('whatever username', customer_with_bad_card, D('10.00')) assert actual == (D('10.61'), D('0.61'), '402 Client Error: PAYMENT REQUIRED')
def test_create_card_hold_bad_card(self): customer_href = self.make_balanced_customer() card = balanced.Card(number='4444444444444448', expiration_year=2020, expiration_month=12).save() card.associate_to_customer(customer_href) bob = self.make_participant('bob', balanced_customer_href=customer_href, is_suspicious=False) hold, error = create_card_hold(self.db, bob, D('10.00')) assert error.startswith('402 Payment Required, ')
def main(): init() request_bin = RequestBinClient() print 'let\'s create a callback' balanced.Callback(url=request_bin.callback_url, ).save() print "let's create a customer" balanced.Customer(name='Bob McTavish').save() print 'let\'s create a card and associate it with a new account' card = balanced.Card( expiration_month='12', csc='123', number='5105105105105100', expiration_year='2020', ).save() print 'generate a debit (which implicitly creates and captures a hold)' card.debit(100) print 'event creation is an async operation, let\'s wait until we have ' \ 'some events!' while not balanced.Event.query.count(): print 'Zzzz' time.sleep(0) print 'Woop, we got some events, let us see what there is to look at' for event in balanced.Event.query: print 'this was a {0} event, it occurred at {1}, the callback has a ' \ 'status of {2}'.format( event.type, event.occurred_at, event.callback_statuses ) print 'you can inspect each event to see the logs' event = balanced.Event.query.first() for callback in event.callbacks: print 'inspecting callback to {0} for event {1}'.format( callback.url, event.type, ) for log in callback.logs: print 'this attempt to the callback has a status "{0}"'.format( log.status) print 'ok, let\'s check with requestb.in to see if our callbacks fired' print 'we received {0} callbacks, you can view them at {1}'.format( len(request_bin.get_requests()), request_bin.view_url, )