diff --git a/lib/Account.php b/lib/Account.php index da3f5b5f2..41e83584c 100644 --- a/lib/Account.php +++ b/lib/Account.php @@ -37,6 +37,9 @@ */ class Account extends ApiResource { + const PATH_EXTERNAL_ACCOUNTS = '/external_accounts'; + const PATH_LOGIN_LINKS = '/login_links'; + public function instanceUrl() { if ($this['id'] === null) { @@ -131,6 +134,12 @@ public static function all($params = null, $opts = null) return self::_all($params, $opts); } + /** + * @param array|null $clientId + * @param array|string|null $opts + * + * @return StripeObject Object containing the response from the API. + */ public function deauthorize($clientId = null, $opts = null) { $params = array( @@ -139,4 +148,79 @@ public function deauthorize($clientId = null, $opts = null) ); OAuth::deauthorize($params, $opts); } + + /** + * @param array|null $id The ID of the account on which to create the external account. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function createExternalAccount($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $params, $opts); + } + + /** + * @param array|null $id The ID of the account to which the external account belongs. + * @param array|null $externalAccountId The ID of the external account to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function retrieveExternalAccount($id, $externalAccountId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $externalAccountId, $params, $opts); + } + + /** + * @param array|null $id The ID of the account to which the external account belongs. + * @param array|null $externalAccountId The ID of the external account to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function updateExternalAccount($id, $externalAccountId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $externalAccountId, $params, $opts); + } + + /** + * @param array|null $id The ID of the account to which the external account belongs. + * @param array|null $externalAccountId The ID of the external account to delete. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function deleteExternalAccount($id, $externalAccountId, $params = null, $opts = null) + { + return self::_deleteNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $externalAccountId, $params, $opts); + } + + /** + * @param array|null $id The ID of the account on which to retrieve the external accounts. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function allExternalAccounts($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_EXTERNAL_ACCOUNTS, $params, $opts); + } + + /** + * @param array|null $id The ID of the account on which to create the login link. + * @param array|null $params + * @param array|string|null $opts + * + * @return LoginLink + */ + public static function createLoginLink($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_LOGIN_LINKS, $params, $opts); + } } diff --git a/lib/ApiResource.php b/lib/ApiResource.php index 954807117..ee455c9b2 100644 --- a/lib/ApiResource.php +++ b/lib/ApiResource.php @@ -199,4 +199,108 @@ protected function _delete($params = null, $options = null) $this->refreshFrom($response, $opts); return $this; } + + /** + * @param string $method + * @param string $url + * @param array|null $params + * @param array|string|null $options + * + * @return StripeObject + */ + protected static function _nestedResourceOperation($method, $url, $params = null, $options = null) + { + self::_validateParams($params); + + list($response, $opts) = static::_staticRequest($method, $url, $params, $options); + $obj = Util\Util::convertToStripeObject($response->json, $opts); + $obj->setLastResponse($response); + return $obj; + } + + /** + * @param string $id + * @param string $nestedPath + * @param string|null $nestedId + * + * @return string + */ + protected static function _nestedResourceUrl($id, $nestedPath, $nestedId = null) + { + $url = static::resourceUrl($id) . $nestedPath; + if ($nestedId !== null) { + $url .= "/$nestedId"; + } + return $url; + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return StripeObject + */ + protected static function _createNestedResource($id, $nestedPath, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath); + return self::_nestedResourceOperation('post', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return StripeObject + */ + protected static function _retrieveNestedResource($id, $nestedPath, $nestedId, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath, $nestedId); + return self::_nestedResourceOperation('get', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return StripeObject + */ + protected static function _updateNestedResource($id, $nestedPath, $nestedId, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath, $nestedId); + return self::_nestedResourceOperation('post', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return StripeObject + */ + protected static function _deleteNestedResource($id, $nestedPath, $nestedId, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath, $nestedId); + return self::_nestedResourceOperation('delete', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return StripeObject + */ + protected static function _allNestedResources($id, $nestedPath, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath); + return self::_nestedResourceOperation('get', $url, $params, $options); + } } diff --git a/lib/ApplicationFee.php b/lib/ApplicationFee.php index fb5453203..3c9851990 100644 --- a/lib/ApplicationFee.php +++ b/lib/ApplicationFee.php @@ -9,6 +9,8 @@ */ class ApplicationFee extends ApiResource { + const PATH_REFUNDS = '/refunds'; + /** * This is a special case because the application fee endpoint has an * underscore in it. The parent `className` function strips underscores. @@ -67,4 +69,54 @@ public function refund($params = null, $opts = null) $this->refresh(); return $this; } + + /** + * @param array|null $id The ID of the application fee on which to create the refund. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function createRefund($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_REFUNDS, $params, $opts); + } + + /** + * @param array|null $id The ID of the application fee to which the refund belongs. + * @param array|null $refundId The ID of the refund to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function retrieveRefund($id, $refundId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_REFUNDS, $refundId, $params, $opts); + } + + /** + * @param array|null $id The ID of the application fee to which the refund belongs. + * @param array|null $refundId The ID of the refund to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function updateRefund($id, $refundId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_REFUNDS, $refundId, $params, $opts); + } + + /** + * @param array|null $id The ID of the application fee on which to retrieve the refunds. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function allRefunds($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_REFUNDS, $params, $opts); + } } diff --git a/lib/Customer.php b/lib/Customer.php index 9f928f2b8..d17c39ca8 100644 --- a/lib/Customer.php +++ b/lib/Customer.php @@ -26,6 +26,8 @@ */ class Customer extends ApiResource { + const PATH_SOURCES = '/sources'; + /** * @param array|string $id The ID of the customer to retrieve, or an * options array containing an `id` key. @@ -188,4 +190,67 @@ public function deleteDiscount() list($response, $opts) = $this->_request('delete', $url); $this->refreshFrom(array('discount' => null), $opts, true); } + + /** + * @param array|null $id The ID of the customer on which to create the source. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function createSource($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_SOURCES, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer to which the source belongs. + * @param array|null $sourceId The ID of the source to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function retrieveSource($id, $sourceId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_SOURCES, $sourceId, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer to which the source belongs. + * @param array|null $sourceId The ID of the source to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function updateSource($id, $sourceId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_SOURCES, $sourceId, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer to which the source belongs. + * @param array|null $sourceId The ID of the source to delete. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function deleteSource($id, $sourceId, $params = null, $opts = null) + { + return self::_deleteNestedResource($id, static::PATH_SOURCES, $sourceId, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer on which to retrieve the sources. + * @param array|null $params + * @param array|string|null $opts + * + * @return ExternalAccount + */ + public static function allSources($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_SOURCES, $params, $opts); + } } diff --git a/lib/Transfer.php b/lib/Transfer.php index 24a626ab9..a2184aade 100644 --- a/lib/Transfer.php +++ b/lib/Transfer.php @@ -25,6 +25,8 @@ */ class Transfer extends ApiResource { + const PATH_REVERSALS = '/reversals'; + /** * @param array|string $id The ID of the transfer to retrieve, or an * options array containing an `id` key. @@ -102,4 +104,54 @@ public function save($opts = null) { return $this->_save($opts); } + + /** + * @param array|null $id The ID of the transfer on which to create the reversal. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function createReversal($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_REVERSALS, $params, $opts); + } + + /** + * @param array|null $id The ID of the transfer to which the reversal belongs. + * @param array|null $reversalId The ID of the reversal to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function retrieveReversal($id, $reversalId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_REVERSALS, $reversalId, $params, $opts); + } + + /** + * @param array|null $id The ID of the transfer to which the reversal belongs. + * @param array|null $reversalId The ID of the reversal to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function updateReversal($id, $reversalId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_REVERSALS, $reversalId, $params, $opts); + } + + /** + * @param array|null $id The ID of the transfer on which to retrieve the reversals. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function allReversals($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_REVERSALS, $params, $opts); + } } diff --git a/tests/AccountTest.php b/tests/AccountTest.php index 5f8df5398..b313e53d4 100644 --- a/tests/AccountTest.php +++ b/tests/AccountTest.php @@ -360,4 +360,111 @@ public function testDeauthorize() Stripe::setClientId(null); } + + public function testStaticCreateExternalAccount() + { + $this->mockRequest( + 'POST', + '/v1/accounts/acct_123/external_accounts', + array('source' => 'btok_123'), + array('id' => 'ba_123', 'object' => 'bank_account') + ); + + $externalAccount = Account::createExternalAccount( + 'acct_123', + array('source' => 'btok_123') + ); + + $this->assertSame('ba_123', $externalAccount->id); + $this->assertSame('bank_account', $externalAccount->object); + } + + public function testStaticRetrieveExternalAccount() + { + $this->mockRequest( + 'GET', + '/v1/accounts/acct_123/external_accounts/ba_123', + array(), + array('id' => 'ba_123', 'object' => 'bank_account') + ); + + $externalAccount = Account::retrieveExternalAccount( + 'acct_123', + 'ba_123' + ); + + $this->assertSame('ba_123', $externalAccount->id); + $this->assertSame('bank_account', $externalAccount->object); + } + + public function testStaticUpdateExternalAccount() + { + $this->mockRequest( + 'POST', + '/v1/accounts/acct_123/external_accounts/ba_123', + array('metadata' => array('foo' => 'bar')), + array('id' => 'ba_123', 'object' => 'bank_account') + ); + + $externalAccount = Account::updateExternalAccount( + 'acct_123', + 'ba_123', + array('metadata' => array('foo' => 'bar')) + ); + + $this->assertSame('ba_123', $externalAccount->id); + $this->assertSame('bank_account', $externalAccount->object); + } + + public function testStaticDeleteExternalAccount() + { + $this->mockRequest( + 'DELETE', + '/v1/accounts/acct_123/external_accounts/ba_123', + array(), + array('id' => 'ba_123', 'deleted' => true) + ); + + $externalAccount = Account::deleteExternalAccount( + 'acct_123', + 'ba_123' + ); + + $this->assertSame('ba_123', $externalAccount->id); + $this->assertSame(true, $externalAccount->deleted); + } + + public function testStaticAllExternalAccounts() + { + $this->mockRequest( + 'GET', + '/v1/accounts/acct_123/external_accounts', + array(), + array('object' => 'list', 'data' => array()) + ); + + $externalAccounts = Account::allExternalAccounts( + 'acct_123' + ); + + $this->assertSame('list', $externalAccounts->object); + $this->assertEmpty($externalAccounts->data); + } + + public function testStaticCreateLoginLink() + { + $this->mockRequest( + 'POST', + '/v1/accounts/acct_123/login_links', + array(), + array('object' => 'login_link', 'url' => 'https://example.com') + ); + + $loginLink = Account::createLoginLink( + 'acct_123' + ); + + $this->assertSame('login_link', $loginLink->object); + $this->assertSame('https://example.com', $loginLink->url); + } } diff --git a/tests/ApplicationFeeTest.php b/tests/ApplicationFeeTest.php index fe6df9230..6894fa8c8 100644 --- a/tests/ApplicationFeeTest.php +++ b/tests/ApplicationFeeTest.php @@ -19,4 +19,75 @@ public function testList() $d = ApplicationFee::all(); $this->assertSame($d->url, '/v1/application_fees'); } + + public function testStaticCreateRefund() + { + $this->mockRequest( + 'POST', + '/v1/application_fees/fee_123/refunds', + array(), + array('id' => 'fr_123', 'object' => 'fee_refund') + ); + + $feeRefund = ApplicationFee::createRefund( + 'fee_123' + ); + + $this->assertSame('fr_123', $feeRefund->id); + $this->assertSame('fee_refund', $feeRefund->object); + } + + public function testStaticRetrieveRefund() + { + $this->mockRequest( + 'GET', + '/v1/application_fees/fee_123/refunds/fr_123', + array(), + array('id' => 'fr_123', 'object' => 'fee_refund') + ); + + $feeRefund = ApplicationFee::retrieveRefund( + 'fee_123', + 'fr_123' + ); + + $this->assertSame('fr_123', $feeRefund->id); + $this->assertSame('fee_refund', $feeRefund->object); + } + + public function testStaticUpdateRefund() + { + $this->mockRequest( + 'POST', + '/v1/application_fees/fee_123/refunds/fr_123', + array('metadata' => array('foo' => 'bar')), + array('id' => 'fr_123', 'object' => 'fee_refund') + ); + + $feeRefund = ApplicationFee::updateRefund( + 'fee_123', + 'fr_123', + array('metadata' => array('foo' => 'bar')) + ); + + $this->assertSame('fr_123', $feeRefund->id); + $this->assertSame('fee_refund', $feeRefund->object); + } + + public function testStaticAllRefunds() + { + $this->mockRequest( + 'GET', + '/v1/application_fees/fee_123/refunds', + array(), + array('object' => 'list', 'data' => array()) + ); + + $feeRefunds = ApplicationFee::allRefunds( + 'fee_123' + ); + + $this->assertSame('list', $feeRefunds->object); + $this->assertEmpty($feeRefunds->data); + } } diff --git a/tests/CustomerTest.php b/tests/CustomerTest.php index 1679853fb..bcee4e882 100644 --- a/tests/CustomerTest.php +++ b/tests/CustomerTest.php @@ -244,4 +244,95 @@ public function testCustomerDeleteSource() $postDeleteSources = $postDeleteCustomer->sources->all(); $this->assertSame(count($postDeleteSources["data"]), 1); } + + + public function testStaticCreateSource() + { + $this->mockRequest( + 'POST', + '/v1/customers/cus_123/sources', + array('source' => 'tok_123'), + array('id' => 'card_123', 'object' => 'card') + ); + + $source = Customer::createSource( + 'cus_123', + array('source' => 'tok_123') + ); + + $this->assertSame('card_123', $source->id); + $this->assertSame('card', $source->object); + } + + public function testStaticRetrieveSource() + { + $this->mockRequest( + 'GET', + '/v1/customers/cus_123/sources/card_123', + array(), + array('id' => 'card_123', 'object' => 'card') + ); + + $source = Customer::retrieveSource( + 'cus_123', + 'card_123' + ); + + $this->assertSame('card_123', $source->id); + $this->assertSame('card', $source->object); + } + + public function testStaticUpdateSource() + { + $this->mockRequest( + 'POST', + '/v1/customers/cus_123/sources/card_123', + array('metadata' => array('foo' => 'bar')), + array('id' => 'card_123', 'object' => 'card') + ); + + $source = Customer::updateSource( + 'cus_123', + 'card_123', + array('metadata' => array('foo' => 'bar')) + ); + + $this->assertSame('card_123', $source->id); + $this->assertSame('card', $source->object); + } + + public function testStaticDeleteSource() + { + $this->mockRequest( + 'DELETE', + '/v1/customers/cus_123/sources/card_123', + array(), + array('id' => 'card_123', 'deleted' => true) + ); + + $source = Customer::deleteSource( + 'cus_123', + 'card_123' + ); + + $this->assertSame('card_123', $source->id); + $this->assertSame(true, $source->deleted); + } + + public function testStaticAllSources() + { + $this->mockRequest( + 'GET', + '/v1/customers/cus_123/sources', + array(), + array('object' => 'list', 'data' => array()) + ); + + $sources = Customer::allsources( + 'cus_123' + ); + + $this->assertSame('list', $sources->object); + $this->assertEmpty($sources->data); + } } diff --git a/tests/TransferTest.php b/tests/TransferTest.php index f4fd347dc..298e3c293 100644 --- a/tests/TransferTest.php +++ b/tests/TransferTest.php @@ -43,4 +43,75 @@ public function testTransferUpdateMetadataAll() $updatedTransfer = Transfer::retrieve($transfer->id, $this->opts); $this->assertSame('foo bar', $updatedTransfer->metadata['test']); } + + public function testStaticCreateReversal() + { + $this->mockRequest( + 'POST', + '/v1/transfers/tr_123/reversals', + array(), + array('id' => 'trr_123', 'object' => 'transfer_reversal') + ); + + $reversal = Transfer::createReversal( + 'tr_123' + ); + + $this->assertSame('trr_123', $reversal->id); + $this->assertSame('transfer_reversal', $reversal->object); + } + + public function testStaticRetrieveReversal() + { + $this->mockRequest( + 'GET', + '/v1/transfers/tr_123/reversals/trr_123', + array(), + array('id' => 'trr_123', 'object' => 'transfer_reversal') + ); + + $reversal = Transfer::retrieveReversal( + 'tr_123', + 'trr_123' + ); + + $this->assertSame('trr_123', $reversal->id); + $this->assertSame('transfer_reversal', $reversal->object); + } + + public function testStaticUpdateReversal() + { + $this->mockRequest( + 'POST', + '/v1/transfers/tr_123/reversals/trr_123', + array('metadata' => array('foo' => 'bar')), + array('id' => 'trr_123', 'object' => 'transfer_reversal') + ); + + $reversal = Transfer::updateReversal( + 'tr_123', + 'trr_123', + array('metadata' => array('foo' => 'bar')) + ); + + $this->assertSame('trr_123', $reversal->id); + $this->assertSame('transfer_reversal', $reversal->object); + } + + public function testStaticAllReversals() + { + $this->mockRequest( + 'GET', + '/v1/transfers/tr_123/reversals', + array(), + array('object' => 'list', 'data' => array()) + ); + + $reversals = Transfer::allReversals( + 'tr_123' + ); + + $this->assertSame('list', $reversals->object); + $this->assertEmpty($reversals->data); + } }