*
  • $BALANCED_URL_ROOT If set applies to \Balanced\Settings::$url_root. *
  • $BALANCED_API_KEY If set applies to \Balanced\Settings::$api_key. * */ class SuiteTest extends \PHPUnit_Framework_TestCase { static $key, $marketplace, $email_counter = 0; static function _createBuyer($email_address = null, $card = null) { if ($email_address == null) $email_address = sprintf('m+%d@poundpay.com', self::$email_counter++); if ($card == null) $card = self::_createCard(); return self::$marketplace->createBuyer( $email_address, $card->uri, array('test#' => 'test_d'), 'Hobo Joe' ); } static function _createCard($account = null) { $card = self::$marketplace->createCard( '123 Fake Street', 'Jollywood', null, '90210', 'khalkhalash', '4112344112344113', null, 12, 2013); if ($account != null) { $account->addCard($card); $card = Card::get($card->uri); } return $card; } static function _createBankAccount($account = null) { $bank_account = self::$marketplace->createBankAccount( 'Homer Jay', '112233a', '121042882', 'checking' ); if ($account != null) { $account->addBankAccount($bank_account); $bank_account = $account->bank_accounts[0]; } return $bank_account; } public static function _createPersonMerchant($email_address = null, $bank_account = null) { if ($email_address == null) $email_address = sprintf('m+%d@poundpay.com', self::$email_counter++); if ($bank_account == null) $bank_account = self::_createBankAccount(); $merchant = array( 'type' => 'person', 'name' => 'William James', 'tax_id' => '393-48-3992', 'street_address' => '167 West 74th Street', 'postal_code' => '10023', 'dob' => '1842-01-01', 'phone_number' => '+16505551234', 'country_code' => 'USA' ); return self::$marketplace->createMerchant( $email_address, $merchant, $bank_account->uri ); } public static function _createBusinessMerchant($email_address = null, $bank_account = null) { if ($email_address == null) $email_address = sprintf('m+%d@poundpay.com', self::$email_counter++); if ($bank_account == null) $bank_account = self::_createBankAccount(); $merchant = array( 'type' => 'business', 'name' => 'Levain Bakery', 'tax_id' => '253912384', 'street_address' => '167 West 74th Street', 'postal_code' => '10023', 'phone_number' => '+16505551234', 'country_code' => 'USA', 'person' => array( 'name' => 'William James', 'tax_id' => '393483992', 'street_address' => '167 West 74th Street', 'postal_code' => '10023', 'dob' => '1842-01-01', 'phone_number' => '+16505551234', 'country_code' => 'USA', ), ); return self::$marketplace->createMerchant( $email_address, $merchant, $bank_account->uri ); } public static function setUpBeforeClass() { // url root $url_root = getenv('BALANCED_URL_ROOT'); if ($url_root != '') { Settings::$url_root = $url_root; } else Settings::$url_root = 'https://api.balancedpayments.com'; // api key $api_key = getenv('BALANCED_API_KEY'); if ($api_key != '') { Settings::$api_key = $api_key; } else { self::$key = new APIKey(); self::$key->save(); Settings::$api_key = self::$key->secret; } // marketplace try { self::$marketplace = Marketplace::mine(); } catch(\RESTful\Exceptions\NoResultFound $e) { self::$marketplace = new Marketplace(); self::$marketplace->save(); } } function testMarketplaceMine() { $marketplace = Marketplace::mine(); $this->assertEquals($this::$marketplace->id, $marketplace->id); } /** * @expectedException \RESTful\Exceptions\HTTPError */ function testAnotherMarketplace() { $marketplace = new Marketplace(); $marketplace->save(); } /** * @expectedException \RESTful\Exceptions\HTTPError */ function testDuplicateEmailAddress() { self::_createBuyer('dupe@poundpay.com'); self::_createBuyer('dupe@poundpay.com'); } function testIndexMarketplace() { $marketplaces = Marketplace::query()->all(); $this->assertEquals(count($marketplaces), 1); } function testCreateBuyer() { self::_createBuyer(); } function testCreateAccountWithoutEmailAddress() { self::$marketplace->createAccount(); } function testFindOrCreateAccountByEmailAddress() { $account1 = self::$marketplace->createAccount('foc@example.com'); $account2 = self::$marketplace->findOrCreateAccountByEmailAddress('foc@example.com'); $this->assertEquals($account2->id, $account2->id); $account3 = self::$marketplace->findOrCreateAccountByEmailAddress('foc2@example.com'); $this->assertNotEquals($account3->id, $account1->id); } function testGetBuyer() { $buyer1 = self::_createBuyer(); $buyer2 = Account::get($buyer1->uri); $this->assertEquals($buyer1->id, $buyer2->id); } function testMe() { $marketplace = Marketplace::mine(); $merchant = Merchant::me(); $this->assertEquals($marketplace->id, $merchant->marketplace->id); } function testDebitAndRefundBuyer() { $buyer = self::_createBuyer(); $debit = $buyer->debit( 1000, 'Softie', 'something i bought', array('hi' => 'bye') ); $refund = $debit->refund(100); } /** * @expectedException \RESTful\Exceptions\HTTPError */ function testDebitZero() { $buyer = self::_createBuyer(); $debit = $buyer->debit( 0, 'Softie', 'something i bought' ); } function testMultipleRefunds() { $buyer = self::_createBuyer(); $debit = $buyer->debit( 1500, 'Softie', 'something tart', array('hi' => 'bye')); $refunds = array( $debit->refund(100), $debit->refund(100), $debit->refund(100), $debit->refund(100)); $expected_refund_ids = array_map( function($x) { return $x->id; }, $refunds); sort($expected_refund_ids); $this->assertEquals($debit->refunds->total(), 4); // itemization $total = 0; $refund_ids = array(); foreach ($debit->refunds as $refund) { $total += $refund->amount; array_push($refund_ids, $refund->id); } sort($refund_ids); $this->assertEquals($total, 400); $this->assertEquals($expected_refund_ids, $refund_ids); // pagination $total = 0; $refund_ids = array(); foreach ($debit->refunds->paginate() as $page) { foreach ($page->items as $refund) { $total += $refund->amount; array_push($refund_ids, $refund->id); } } sort($refund_ids); $this->assertEquals($total, 400); $this->assertEquals($expected_refund_ids, $refund_ids); } function testDebitSource() { $buyer = self::_createBuyer(); $card1 = self::_createCard($buyer); $card2 = self::_createCard($buyer); $credit = $buyer->debit( 1000, 'Softie', 'something i bought' ); $this->assertEquals($credit->source->id, $card2->id); $credit = $buyer->debit( 1000, 'Softie', 'something i bought', null, $card1 ); $this->assertEquals($credit->source->id, $card1->id); } function testDebitOnBehalfOf() { $buyer = self::_createBuyer(); $merchant = self::$marketplace->createAccount(null); $card1 = self::_createCard($buyer); $debit = $buyer->debit(1000, null, null, null, null, $merchant); $this->assertEquals($debit->amount, 1000); // for now just test the debit succeeds. // TODO: once the on_behalf_of actually shows up on the response, test it. } /** * @expectedException \InvalidArgumentException */ function testDebitOnBehalfOfFailsForBuyer() { $buyer = self::_createBuyer(); $card1 = self::_createCard($buyer); $debit = $buyer->debit(1000, null, null, null, null, $buyer); } function testCreateAndVoidHold() { $buyer = self::_createBuyer(); $hold = $buyer->hold(1000); $this->assertEquals($hold->is_void, false); $hold->void(); $this->assertEquals($hold->is_void, true); } function testCreateAndCaptureHold() { $buyer = self::_createBuyer(); $hold = $buyer->hold(1000); $debit = $hold->capture(909); $this->assertEquals($debit->account->id, $buyer->id); $this->assertEquals($debit->hold->id, $hold->id); $this->assertEquals($hold->debit->id, $debit->id); } function testCreatePersonMerchant() { $merchant = self::_createPersonMerchant(); } function testCreateBusinessMerchant() { $merchant = self::_createBusinessMerchant(); } /** * @expectedException \RESTful\Exceptions\HTTPError */ function testCreditRequiresNonZeroAmount() { $buyer = self::_createBuyer(); $buyer->debit( 1000, 'Softie', 'something i bought' ); $merchant = self::_createBusinessMerchant(); $merchant->credit(0); } /** * @expectedException \RESTful\Exceptions\HTTPError */ function testCreditMoreThanEscrowBalanceFails() { $buyer = self::_createBuyer(); $buyer->credit( 1000, 'something i bought', null, null, 'Softie' ); $merchant = self::_createBusinessMerchant(); $merchant->credit(self::$marketplace->in_escrow + 1); } function testCreditDestiation() { $buyer = self::_createBuyer(); $buyer->debit(3000); # NOTE: build up escrow balance to credit $merchant = self::_createPersonMerchant(); $bank_account1 = self::_createBankAccount($merchant); $bank_account2 = self::_createBankAccount($merchant); $credit = $merchant->credit( 1000, 'something i sold', null, null, 'Softie' ); $this->assertEquals($credit->destination->id, $bank_account2->id); $credit = $merchant->credit( 1000, 'something i sold', null, $bank_account1, 'Softie' ); $this->assertEquals($credit->destination->id, $bank_account1->id); } function testAssociateCard() { $merchant = self::_createPersonMerchant(); $card = self::_createCard(); $merchant->addCard($card->uri); } function testAssociateBankAccount() { $merchant = self::_createPersonMerchant(); $bank_account = self::_createBankAccount(); $merchant->addBankAccount($bank_account->uri); } function testCardMasking() { $card = self::$marketplace->createCard( '123 Fake Street', 'Jollywood', null, '90210', 'khalkhalash', '4112344112344113', '123', 12, 2013); $this->assertEquals($card->last_four, '4113'); $this->assertFalse(property_exists($card, 'number')); } function testBankAccountMasking() { $bank_account = self::$marketplace->createBankAccount( 'Homer Jay', '112233a', '121042882', 'checking' ); $this->assertEquals($bank_account->last_four, '233a'); $this->assertEquals($bank_account->account_number, 'xxx233a'); } function testFilteringAndSorting() { $buyer = self::_createBuyer(); $debit1 = $buyer->debit(1122, null, null, array('tag' => '1')); $debit2 = $buyer->debit(3322, null, null, array('tag' => '1')); $debit3 = $buyer->debit(2211, null, null, array('tag' => '2')); $getId = function($o) { return $o->id; }; $debits = ( self::$marketplace->debits->query() ->filter(Debit::$f->meta->tag->eq('1')) ->sort(Debit::$f->created_at->asc()) ->all()); $debit_ids = array_map($getId, $debits); $this->assertEquals($debit_ids, array($debit1->id, $debit2->id)); $debits = ( self::$marketplace->debits->query() ->filter(Debit::$f->meta->tag->eq('2')) ->all()); $debit_ids = array_map($getId, $debits); $this->assertEquals($debit_ids, array($debit3->id)); $debits = ( self::$marketplace->debits->query() ->filter(Debit::$f->meta->contains('tag')) ->sort(Debit::$f->created_at->asc()) ->all()); $debit_ids = array_map($getId, $debits); $this->assertEquals($debit_ids, array($debit1->id, $debit2->id, $debit3->id)); $debits = ( self::$marketplace->debits->query() ->filter(Debit::$f->meta->contains('tag')) ->sort(Debit::$f->amount->desc()) ->all()); $debit_ids = array_map($getId, $debits); $this->assertEquals($debit_ids, array($debit2->id, $debit3->id, $debit1->id)); } function testMerchantIdentityFailure() { // NOTE: postal_code == '99999' && region == 'EX' triggers identity failure $identity = array( 'type' => 'business', 'name' => 'Levain Bakery', 'tax_id' => '253912384', 'street_address' => '167 West 74th Street', 'postal_code' => '99999', 'region' => 'EX', 'phone_number' => '+16505551234', 'country_code' => 'USA', 'person' => array( 'name' => 'William James', 'tax_id' => '393483992', 'street_address' => '167 West 74th Street', 'postal_code' => '99999', 'region' => 'EX', 'dob' => '1842-01-01', 'phone_number' => '+16505551234', 'country_code' => 'USA', ), ); try { self::$marketplace->createMerchant( sprintf('m+%d@poundpay.com', self::$email_counter++), $identity); } catch(\RESTful\Exceptions\HTTPError $e) { $this->assertEquals($e->response->code, 300); $expected = sprintf('https://www.balancedpayments.com/marketplaces/%s/kyc', self::$marketplace->id); $this->assertEquals($e->redirect_uri, $expected); $this->assertEquals($e->response->headers['Location'], $expected); return; } $this->fail('Expected exception HTTPError not raised.'); } function testInternationalCard() { $payload = array( 'card_number' => '4111111111111111', 'city' => '\xe9\x83\xbd\xe7\x95\x99\xe5\xb8\x82', 'country_code' => 'JPN', 'expiration_month' => 12, 'expiration_year' => 2014, 'name' => 'Johnny Fresh', 'postal_code' => '4020054', 'street_address' => '\xe7\x94\xb0\xe5\x8e\x9f\xef\xbc\x93\xe3\x83\xbc\xef\xbc\x98\xe3\x83\xbc\xef\xbc\x91' ); $card = self::$marketplace->cards->create($payload); $this->assertEquals($card->street_address, $payload['street_address']); } /** * @expectedException \RESTful\Exceptions\NoResultFound */ function testAccountWithEmailAddressNotFound() { self::$marketplace->accounts->query() ->filter(Account::$f->email_address->eq('unlikely@address.com')) ->one(); } function testDebitACard() { $buyer = self::_createBuyer(); $card = self::_createCard($buyer); $debit = $card->debit( 1000, 'Softie', 'something i bought', array('hi' => 'bye')); $this->assertEquals($debit->source->uri, $card->uri); } /** * @expectedException \UnexpectedValueException */ function testDebitAnUnassociatedCard() { $card = self::_createCard(); $card->debit(1000, 'Softie'); } function testCreditABankAccount() { $buyer = self::_createBuyer(); $buyer->debit(101); # NOTE: build up escrow balance to credit $merchant = self::_createPersonMerchant(); $bank_account = self::_createBankAccount($merchant); $credit = $bank_account->credit(55, 'something sour'); $this->assertEquals($credit->destination->uri, $bank_account->uri); } function testQuery() { $buyer = self::_createBuyer(); $tag = '123123123123'; $debit1 = $buyer->debit(1122, null, null, array('tag' => $tag)); $debit2 = $buyer->debit(3322, null, null, array('tag' => $tag)); $debit3 = $buyer->debit(2211, null, null, array('tag' => $tag)); $expected_debit_ids = array($debit1->id, $debit2->id, $debit3->id); $query = ( self::$marketplace->debits->query() ->filter(Debit::$f->meta->tag->eq($tag)) ->sort(Debit::$f->created_at->asc()) ->limit(1)); $this->assertEquals($query->total(), 3); $debit_ids = array(); foreach ($query as $debits) { array_push($debit_ids, $debits->id); } $this->assertEquals($debit_ids, $expected_debit_ids); $debit_ids = array($query[0]->id, $query[1]->id, $query[2]->id); $this->assertEquals($debit_ids, $expected_debit_ids); } function testBuyerPromoteToMerchant() { $merchant = array( 'type' => 'person', 'name' => 'William James', 'tax_id' => '393-48-3992', 'street_address' => '167 West 74th Street', 'postal_code' => '10023', 'dob' => '1842-01-01', 'phone_number' => '+16505551234', 'country_code' => 'USA' ); $buyer = self::_createBuyer(); $buyer->promoteToMerchant($merchant); } function testCreditAccountlessBankAccount() { $buyer = self::_createBuyer(); $buyer->debit(101); # NOTE: build up escrow balance to credit $bank_account = self::_createBankAccount(); $credit = $bank_account->credit(55, 'something sour'); $this->assertEquals($credit->bank_account->id, $bank_account->id); $bank_account = $bank_account->get($bank_account->id); $this->assertEquals($bank_account->credits->total(), 1); } function testCreditUnstoredBankAccount() { $buyer = self::_createBuyer(); $buyer->debit(101); # NOTE: build up escrow balance to credit $credit = Credit::bankAccount( 55, array( 'name' => 'Homer Jay', 'account_number' => '112233a', 'routing_number' => '121042882', 'type' => 'checking', ), 'something sour'); $this->assertFalse(property_exists($credit->bank_account, 'uri')); $this->assertFalse(property_exists($credit->bank_account, 'id')); $this->assertEquals($credit->bank_account->name, 'Homer Jay'); $this->assertEquals($credit->bank_account->account_number, 'xxx233a'); $this->assertEquals($credit->bank_account->type, 'checking'); } function testDeleteBankAccount() { $buyer = self::_createBuyer(); $buyer->debit(101); # NOTE: build up escrow balance to credit $bank_account = self::_createBankAccount(); $credit = $bank_account->credit(55, 'something sour'); $this->assertTrue(property_exists($credit->bank_account, 'uri')); $this->assertTrue(property_exists($credit->bank_account, 'id')); $bank_account = BankAccount::get($bank_account->id); $bank_account->delete(); $credit = Credit::get($credit->uri); $this->assertFalse(property_exists($credit->bank_account, 'uri')); $this->assertFalse(property_exists($credit->bank_account, 'id')); } function testGetBankAccounById() { $bank_account = self::_createBankAccount(); $bank_account_2 = BankAccount::get($bank_account->id); $this->assertEquals($bank_account_2->id, $bank_account->id); } /** * @expectedException \Balanced\Errors\InsufficientFunds */ function testInsufficientFunds() { $marketplace = Marketplace::get(self::$marketplace->uri); $amount = $marketplace->in_escrow + 100; $credit = Credit::bankAccount( $amount, array( 'name' => 'Homer Jay', 'account_number' => '112233a', 'routing_number' => '121042882', 'type' => 'checking', ), 'something sour'); } function testCreateCallback() { $callback = self::$marketplace->createCallback( 'http://example.com/php' ); $this->assertEquals($callback->url, 'http://example.com/php'); } /** * @expectedException \Balanced\Errors\BankAccountVerificationFailure */ function testBankAccountVerificationFailure() { $bank_account = self::_createBankAccount(); $buyer = self::_createBuyer(); $buyer->addBankAccount($bank_account); $verification = $bank_account->verify(); $verification->confirm(1, 2); } /** * @expectedException \Balanced\Errors\BankAccountVerificationFailure */ function testBankAccountVerificationDuplicate() { $bank_account = self::_createBankAccount(); $buyer = self::_createBuyer(); $buyer->addBankAccount($bank_account); $bank_account->verify(); $bank_account->verify(); } function testBankAccountVerificationSuccess() { $bank_account = self::_createBankAccount(); $buyer = self::_createBuyer(); $buyer->addBankAccount($bank_account); $verification = $bank_account->verify(); $verification->confirm(1, 1); // this will fail if the bank account is not verified $debit = $buyer->debit( 1000, 'Softie', 'something i bought', array('hi' => 'bye'), $bank_account ); $this->assertTrue(strpos($debit->source->uri, 'bank_account') > 0); } function testEvents() { $prev_num_events = Marketplace::mine()->events->total(); $account = self::_createBuyer(); $account->debit(123); $cur_num_events = Marketplace::mine()->events->total(); $count = 0; while ($cur_num_events == $prev_num_events && $count < 10) { printf("waiting for events - %d, %d == %d\n", $count + 1, $cur_num_events, $prev_num_events); sleep(2); // 2 seconds $cur_num_events = Marketplace::mine()->events->total(); $count += 1; } $this->assertTrue($cur_num_events > $prev_num_events); } }