NEW Upgrade of Stripe lib to 6.4.1

This commit is contained in:
Laurent Destailleur 2018-03-07 19:26:06 +01:00
parent b9f1695b34
commit 8c03fdd51f
69 changed files with 5502 additions and 0 deletions

View File

@ -0,0 +1,34 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for listable resources. Adds a `all()` static method to the class.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait All
{
/**
* @param array|null $params
* @param array|string|null $opts
*
* @return \Stripe\Collection of ApiResources
*/
public static function all($params = null, $opts = null)
{
self::_validateParams($params);
$url = static::classUrl();
list($response, $opts) = static::_staticRequest('get', $url, $params, $opts);
$obj = \Stripe\Util\Util::convertToStripeObject($response->json, $opts);
if (!is_a($obj, 'Stripe\\Collection')) {
$class = get_class($obj);
$message = "Expected type \"Stripe\\Collection\", got \"$class\" instead";
throw new Error\Api($message);
}
$obj->setLastResponse($response);
$obj->setRequestParams($params);
return $obj;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for creatable resources. Adds a `create()` static method to the class.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait Create
{
/**
* @param array|null $params
* @param array|string|null $options
*
* @return \Stripe\ApiResource The created resource.
*/
public static function create($params = null, $options = null)
{
self::_validateParams($params);
$url = static::classUrl();
list($response, $opts) = static::_staticRequest('post', $url, $params, $options);
$obj = \Stripe\Util\Util::convertToStripeObject($response->json, $opts);
$obj->setLastResponse($response);
return $obj;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for deletable resources. Adds a `delete()` method to the class.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait Delete
{
/**
* @param array|null $params
* @param array|string|null $opts
*
* @return \Stripe\ApiResource The deleted resource.
*/
public function delete($params = null, $opts = null)
{
self::_validateParams($params);
$url = $this->instanceUrl();
list($response, $opts) = $this->_request('delete', $url, $params, $opts);
$this->refreshFrom($response, $opts);
return $this;
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for resources that have nested resources.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait NestedResource
{
/**
* @param string $method
* @param string $url
* @param array|null $params
* @param array|string|null $options
*
* @return \Stripe\StripeObject
*/
protected static function _nestedResourceOperation($method, $url, $params = null, $options = null)
{
self::_validateParams($params);
list($response, $opts) = static::_staticRequest($method, $url, $params, $options);
$obj = \Stripe\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 \Stripe\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 \Stripe\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 \Stripe\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 \Stripe\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 \Stripe\StripeObject
*/
protected static function _allNestedResources($id, $nestedPath, $params = null, $options = null)
{
$url = static::_nestedResourceUrl($id, $nestedPath);
return self::_nestedResourceOperation('get', $url, $params, $options);
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for resources that need to make API requests.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait Request
{
/**
* @param array|null|mixed $params The list of parameters to validate
*
* @throws \Stripe\Error\Api if $params exists and is not an array
*/
protected static function _validateParams($params = null)
{
if ($params && !is_array($params)) {
$message = "You must pass an array as the first argument to Stripe API "
. "method calls. (HINT: an example call to create a charge "
. "would be: \"Stripe\\Charge::create(['amount' => 100, "
. "'currency' => 'usd', 'source' => 'tok_1234'])\")";
throw new \Stripe\Error\Api($message);
}
}
/**
* @param string $method HTTP method ('get', 'post', etc.)
* @param string $url URL for the request
* @param array $params list of parameters for the request
* @param array|string|null $options
*
* @return array tuple containing (the JSON response, $options)
*/
protected function _request($method, $url, $params = [], $options = null)
{
$opts = $this->_opts->merge($options);
list($resp, $options) = static::_staticRequest($method, $url, $params, $opts);
$this->setLastResponse($resp);
return [$resp->json, $options];
}
/**
* @param string $method HTTP method ('get', 'post', etc.)
* @param string $url URL for the request
* @param array $params list of parameters for the request
* @param array|string|null $options
*
* @return array tuple containing (the JSON response, $options)
*/
protected static function _staticRequest($method, $url, $params, $options)
{
$opts = \Stripe\Util\RequestOptions::parse($options);
$requestor = new \Stripe\ApiRequestor($opts->apiKey, static::baseUrl());
list($response, $opts->apiKey) = $requestor->request($method, $url, $params, $opts->headers);
$opts->discardNonPersistentHeaders();
return [$response, $opts];
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for retrievable resources. Adds a `retrieve()` static method to the
* class.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait Retrieve
{
/**
* @param array|string $id The ID of the API resource to retrieve,
* or an options array containing an `id` key.
* @param array|string|null $opts
*
* @return \Stripe\StripeObject
*/
public static function retrieve($id, $opts = null)
{
$opts = \Stripe\Util\RequestOptions::parse($opts);
$instance = new static($id, $opts);
$instance->refresh();
return $instance;
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Stripe\ApiOperations;
/**
* Trait for updatable resources. Adds an `update()` static method and a
* `save()` method to the class.
*
* This trait should only be applied to classes that derive from StripeObject.
*/
trait Update
{
/**
* @param string $id The ID of the resource to update.
* @param array|null $params
* @param array|string|null $opts
*
* @return \Stripe\ApiResource The updated resource.
*/
public static function update($id, $params = null, $opts = null)
{
self::_validateParams($params);
$url = static::resourceUrl($id);
list($response, $opts) = static::_staticRequest('post', $url, $params, $opts);
$obj = \Stripe\Util\Util::convertToStripeObject($response->json, $opts);
$obj->setLastResponse($response);
return $obj;
}
/**
* @param array|string|null $opts
*
* @return \Stripe\ApiResource The saved resource.
*/
public function save($opts = null)
{
$params = $this->serializeParameters();
if (count($params) > 0) {
$url = $this->instanceUrl();
list($response, $opts) = $this->_request('post', $url, $params, $opts);
$this->refreshFrom($response, $opts);
}
return $this;
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Stripe\Error;
class Idempotency extends Base
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace Stripe\Error\OAuth;
/**
* InvalidClient is raised when authentication fails.
*/
class InvalidClient extends OAuthBase
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace Stripe\Error\OAuth;
/**
* InvalidGrant is raised when a specified code doesn't exist, is
* expired, has been used, or doesn't belong to you; a refresh token doesn't
* exist, or doesn't belong to you; or if an API key's mode (live or test)
* doesn't match the mode of a code or refresh token.
*/
class InvalidGrant extends OAuthBase
{
}

View File

@ -0,0 +1,11 @@
<?php
namespace Stripe\Error\OAuth;
/**
* InvalidRequest is raised when a code, refresh token, or grant type
* parameter is not provided, but was required.
*/
class InvalidRequest extends OAuthBase
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace Stripe\Error\OAuth;
/**
* InvalidScope is raised when an invalid scope parameter is provided.
*/
class InvalidScope extends OAuthBase
{
}

View File

@ -0,0 +1,23 @@
<?php
namespace Stripe\Error\OAuth;
class OAuthBase extends \Stripe\Error\Base
{
public function __construct(
$code,
$description,
$httpStatus = null,
$httpBody = null,
$jsonBody = null,
$httpHeaders = null
) {
parent::__construct($description, $httpStatus, $httpBody, $jsonBody, $httpHeaders);
$this->code = $code;
}
public function getErrorCode()
{
return $this->code;
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Stripe\Error\OAuth;
/**
* UnsupportedGrantType is raised when an unuspported grant type
* parameter is specified.
*/
class UnsupportedGrantType extends OAuthBase
{
}

View File

@ -0,0 +1,11 @@
<?php
namespace Stripe\Error\OAuth;
/**
* UnsupportedResponseType is raised when an unsupported response type
* parameter is specified.
*/
class UnsupportedResponseType extends OAuthBase
{
}

View File

@ -0,0 +1,20 @@
<?php
namespace Stripe\Error;
class SignatureVerification extends Base
{
public function __construct(
$message,
$sigHeader,
$httpBody = null
) {
parent::__construct($message, null, $httpBody, null, null);
$this->sigHeader = $sigHeader;
}
public function getSigHeader()
{
return $this->sigHeader;
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Stripe\Util;
/**
* A very basic implementation of LoggerInterface that has just enough
* functionality that it can be the default for this library.
*/
class DefaultLogger implements LoggerInterface
{
public function error($message, array $context = [])
{
if (count($context) > 0) {
throw new \Exception('DefaultLogger does not currently implement context. Please implement if you need it.');
}
error_log($message);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Stripe\Util;
/**
* Describes a logger instance.
*
* This is a subset of the interface of the same name in the PSR-3 logger
* interface. We guarantee to keep it compatible, but we'd redefined it here so
* that we don't have to pull in the extra dependencies for users who don't want
* it.
*
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
* for the full interface specification.
*
* The message MUST be a string or object implementing __toString().
*
* The message MAY contain placeholders in the form: {foo} where foo
* will be replaced by the context data in key "foo".
*
* The context array can contain arbitrary data, the only assumption that
* can be made by implementors is that if an Exception instance is given
* to produce a stack trace, it MUST be in a key named "exception".
*/
interface LoggerInterface
{
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
* @param array $context
* @return null
*/
public function error($message, array $context = []);
}

View File

@ -0,0 +1,34 @@
<?php
namespace Stripe\Util;
/**
* A basic random generator. This is in a separate class so we the generator
* can be injected as a dependency and replaced with a mock in tests.
*/
class RandomGenerator
{
/**
* Returns a random value between 0 and $max.
*
* @param float $max (optional)
* @return float
*/
public function randFloat($max = 1.0)
{
return mt_rand() / mt_getrandmax() * $max;
}
/**
* Returns a v4 UUID.
*
* @return string
*/
public function uuid()
{
$arr = array_values(unpack('N1a/n4b/N1c', openssl_random_pseudo_bytes(16)));
$arr[2] = ($arr[2] & 0x0fff) | 0x4000;
$arr[3] = ($arr[3] & 0x3fff) | 0x8000;
return vsprintf('%08x-%04x-%04x-%04x-%04x%08x', $arr);
}
}

View File

@ -0,0 +1,365 @@
<?php
namespace Stripe;
class AccountTest extends TestCase
{
const TEST_RESOURCE_ID = 'acct_123';
const TEST_EXTERNALACCOUNT_ID = 'ba_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/accounts'
);
$resources = Account::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Account", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/accounts/' . self::TEST_RESOURCE_ID
);
$resource = Account::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Account", $resource);
}
public function testIsRetrievableWithoutId()
{
$this->expectsRequest(
'get',
'/v1/account'
);
$resource = Account::retrieve();
$this->assertInstanceOf("Stripe\\Account", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/accounts'
);
$resource = Account::create(["type" => "custom"]);
$this->assertInstanceOf("Stripe\\Account", $resource);
}
public function testIsSaveable()
{
$resource = Account::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/accounts/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Account", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/accounts/' . self::TEST_RESOURCE_ID
);
$resource = Account::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Account", $resource);
}
public function testIsDeletable()
{
$resource = Account::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/accounts/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Account", $resource);
}
public function testIsRejectable()
{
$account = Account::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/accounts/' . $account->id . '/reject'
);
$resource = $account->reject(["reason" => "fraud"]);
$this->assertInstanceOf("Stripe\\Account", $resource);
$this->assertSame($resource, $account);
}
public function testIsDeauthorizable()
{
$resource = Account::retrieve(self::TEST_RESOURCE_ID);
$this->stubRequest(
'post',
'/oauth/deauthorize',
[
'client_id' => Stripe::getClientId(),
'stripe_user_id' => $resource->id,
],
null,
false,
[
'stripe_user_id' => $resource->id,
],
200,
Stripe::$connectBase
);
$resource->deauthorize();
}
public function testCanCreateExternalAccount()
{
$this->expectsRequest(
'post',
'/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts'
);
$resource = Account::createExternalAccount(self::TEST_RESOURCE_ID, [
"external_account" => "btok_123",
]);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanRetrieveExternalAccount()
{
$this->expectsRequest(
'get',
'/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID
);
$resource = Account::retrieveExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanUpdateExternalAccount()
{
$this->expectsRequest(
'post',
'/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID
);
$resource = Account::updateExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID, [
"name" => "name",
]);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanDeleteExternalAccount()
{
$this->expectsRequest(
'delete',
'/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID
);
$resource = Account::deleteExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanListExternalAccounts()
{
$this->expectsRequest(
'get',
'/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts'
);
$resources = Account::allExternalAccounts(self::TEST_RESOURCE_ID);
$this->assertTrue(is_array($resources->data));
}
public function testCanCreateLoginLink()
{
$this->expectsRequest(
'post',
'/v1/accounts/' . self::TEST_RESOURCE_ID . '/login_links'
);
$resource = Account::createLoginLink(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\LoginLink", $resource);
}
public function testSerializeNewAdditionalOwners()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
'legal_entity' => StripeObject::constructFrom([]),
], null);
$obj->legal_entity->additional_owners = [
['first_name' => 'Joe'],
['first_name' => 'Jane'],
];
$expected = [
'legal_entity' => [
'additional_owners' => [
0 => ['first_name' => 'Joe'],
1 => ['first_name' => 'Jane'],
],
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializePartiallyChangedAdditionalOwners()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
'legal_entity' => [
'additional_owners' => [
StripeObject::constructFrom(['first_name' => 'Joe']),
StripeObject::constructFrom(['first_name' => 'Jane']),
],
],
], null);
$obj->legal_entity->additional_owners[1]->first_name = 'Stripe';
$expected = [
'legal_entity' => [
'additional_owners' => [
1 => ['first_name' => 'Stripe'],
],
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializeUnchangedAdditionalOwners()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
'legal_entity' => [
'additional_owners' => [
StripeObject::constructFrom(['first_name' => 'Joe']),
StripeObject::constructFrom(['first_name' => 'Jane']),
],
],
], null);
$expected = [
'legal_entity' => [
'additional_owners' => [],
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializeUnsetAdditionalOwners()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
'legal_entity' => [
'additional_owners' => [
StripeObject::constructFrom(['first_name' => 'Joe']),
StripeObject::constructFrom(['first_name' => 'Jane']),
],
],
], null);
$obj->legal_entity->additional_owners = null;
// Note that the empty string that we send for this one has a special
// meaning for the server, which interprets it as an array unset.
$expected = [
'legal_entity' => [
'additional_owners' => '',
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
/**
* @expectedException \InvalidArgumentException
*/
public function testSerializeAdditionalOwnersDeletedItem()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
'legal_entity' => [
'additional_owners' => [
StripeObject::constructFrom(['first_name' => 'Joe']),
StripeObject::constructFrom(['first_name' => 'Jane']),
],
],
], null);
unset($obj->legal_entity->additional_owners[0]);
$obj->serializeParameters();
}
public function testSerializeExternalAccountString()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
], null);
$obj->external_account = 'btok_123';
$expected = [
'external_account' => 'btok_123',
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializeExternalAccountHash()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
], null);
$obj->external_account = [
'object' => 'bank_account',
'routing_number' => '110000000',
'account_number' => '000123456789',
'country' => 'US',
'currency' => 'usd',
];
$expected = [
'external_account' => [
'object' => 'bank_account',
'routing_number' => '110000000',
'account_number' => '000123456789',
'country' => 'US',
'currency' => 'usd',
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializeBankAccountString()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
], null);
$obj->bank_account = 'btok_123';
$expected = [
'bank_account' => 'btok_123',
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializeBankAccountHash()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'account',
], null);
$obj->bank_account = [
'object' => 'bank_account',
'routing_number' => '110000000',
'account_number' => '000123456789',
'country' => 'US',
'currency' => 'usd',
];
$expected = [
'bank_account' => [
'object' => 'bank_account',
'routing_number' => '110000000',
'account_number' => '000123456789',
'country' => 'US',
'currency' => 'usd',
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace Stripe;
class AlipayAccountTest extends TestCase
{
const TEST_RESOURCE_ID = 'aliacc_123';
// Because of the wildcard nature of sources, stripe-mock cannot currently
// reliably return sources of a given type, so we create a fixture manually
public function createFixture($params = [])
{
if (empty($params)) {
$params['customer'] = 'cus_123';
}
$base = [
'id' => self::TEST_RESOURCE_ID,
'object' => 'card',
'metadata' => [],
];
return AlipayAccount::constructFrom(
array_merge($params, $base),
new Util\RequestOptions()
);
}
public function testHasCorrectUrlForCustomer()
{
$resource = $this->createFixture(['customer' => 'cus_123']);
$this->assertSame(
"/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
/**
* @expectedException \Stripe\Error\InvalidRequest
*/
public function testIsNotDirectlyRetrievable()
{
AlipayAccount::retrieve(self::TEST_RESOURCE_ID);
}
public function testIsSaveable()
{
$resource = $this->createFixture();
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID
);
$resource->save();
$this->assertSame("Stripe\\AlipayAccount", get_class($resource));
}
/**
* @expectedException \Stripe\Error\InvalidRequest
*/
public function testIsNotDirectlyUpdatable()
{
AlipayAccount::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
}
public function testIsDeletable()
{
$resource = $this->createFixture();
$this->expectsRequest(
'delete',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID
);
$resource->delete();
$this->assertSame("Stripe\\AlipayAccount", get_class($resource));
}
}

View File

@ -0,0 +1,572 @@
<?php
namespace Stripe;
use Stripe\HttpClient\CurlClient;
class ApiRequestorTest extends TestCase
{
public function testEncodeObjects()
{
$reflector = new \ReflectionClass('Stripe\\ApiRequestor');
$method = $reflector->getMethod('_encodeObjects');
$method->setAccessible(true);
$a = ['customer' => new Customer('abcd')];
$enc = $method->invoke(null, $a);
$this->assertSame($enc, ['customer' => 'abcd']);
// Preserves UTF-8
$v = ['customer' => ""];
$enc = $method->invoke(null, $v);
$this->assertSame($enc, $v);
// Encodes latin-1 -> UTF-8
$v = ['customer' => "\xe9"];
$enc = $method->invoke(null, $v);
$this->assertSame($enc, ['customer' => "\xc3\xa9"]);
// Encodes booleans
$v = true;
$enc = $method->invoke(null, $v);
$this->assertSame('true', $enc);
$v = false;
$enc = $method->invoke(null, $v);
$this->assertSame('false', $enc);
}
public function testHttpClientInjection()
{
$reflector = new \ReflectionClass('Stripe\\ApiRequestor');
$method = $reflector->getMethod('httpClient');
$method->setAccessible(true);
$curl = new CurlClient();
$curl->setTimeout(10);
ApiRequestor::setHttpClient($curl);
$injectedCurl = $method->invoke(new ApiRequestor());
$this->assertSame($injectedCurl, $curl);
}
public function testDefaultHeaders()
{
$reflector = new \ReflectionClass('Stripe\\ApiRequestor');
$method = $reflector->getMethod('_defaultHeaders');
$method->setAccessible(true);
// no way to stub static methods with PHPUnit 4.x :(
Stripe::setAppInfo('MyTestApp', '1.2.34', 'https://mytestapp.example');
$apiKey = 'sk_test_notarealkey';
$clientInfo = ['httplib' => 'testlib 0.1.2'];
$headers = $method->invoke(null, $apiKey, $clientInfo);
$ua = json_decode($headers['X-Stripe-Client-User-Agent']);
$this->assertSame($ua->application->name, 'MyTestApp');
$this->assertSame($ua->application->version, '1.2.34');
$this->assertSame($ua->application->url, 'https://mytestapp.example');
$this->assertSame($ua->httplib, 'testlib 0.1.2');
$this->assertSame(
$headers['User-Agent'],
'Stripe/v1 PhpBindings/' . Stripe::VERSION . ' MyTestApp/1.2.34 (https://mytestapp.example)'
);
$this->assertSame($headers['Authorization'], 'Bearer ' . $apiKey);
}
/**
* @expectedException \Stripe\Error\Authentication
* @expectedExceptionMessageRegExp #No API key provided#
*/
public function testRaisesAuthenticationErrorWhenNoApiKey()
{
Stripe::setApiKey(null);
Charge::create();
}
public function testRaisesInvalidRequestErrorOn400()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
null,
false,
[
'error' => [
'type' => 'invalid_request_error',
'message' => 'Missing id',
'param' => 'id',
],
],
400
);
try {
Charge::create();
$this->fail("Did not raise error");
} catch (Error\InvalidRequest $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame('Missing id', $e->getMessage());
$this->assertSame('id', $e->getStripeParam());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesIdempotencyErrorOn400AndTypeIdempotencyError()
{
$this->stubRequest(
'POST',
'/v1/charges',
array(),
null,
false,
array(
'error' => array(
'type' => 'idempotency_error',
'message' => "Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than 'abc' if you meant to execute a different request.",
),
),
400
);
try {
Charge::create();
$this->fail("Did not raise error");
} catch (Error\Idempotency $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame("Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than 'abc' if you meant to execute a different request.", $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesAuthenticationErrorOn401()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
null,
false,
[
'error' => [
'type' => 'invalid_request_error',
'message' => 'You did not provide an API key.',
],
],
401
);
try {
Charge::create();
$this->fail("Did not raise error");
} catch (Error\Authentication $e) {
$this->assertSame(401, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame('You did not provide an API key.', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesCardErrorOn402()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
null,
false,
[
'error' => [
'type' => 'card_error',
'message' => 'Your card was declined.',
'code' => 'card_declined',
'decline_code' => 'generic_decline',
'charge' => 'ch_declined_charge',
'param' => 'exp_month',
],
],
402
);
try {
Charge::create();
$this->fail("Did not raise error");
} catch (Error\Card $e) {
$this->assertSame(402, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame('Your card was declined.', $e->getMessage());
$this->assertSame('card_declined', $e->getStripeCode());
$this->assertSame('generic_decline', $e->getDeclineCode());
$this->assertSame('exp_month', $e->getStripeParam());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesPermissionErrorOn403()
{
$this->stubRequest(
'GET',
'/v1/accounts/foo',
[],
null,
false,
[
'error' => [
'type' => 'invalid_request_error',
'message' => "The provided key 'sk_test_********************1234' does not have access to account 'foo' (or that account does not exist). Application access may have been revoked.",
],
],
403
);
try {
Account::retrieve('foo');
$this->fail("Did not raise error");
} catch (Error\Permission $e) {
$this->assertSame(403, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame("The provided key 'sk_test_********************1234' does not have access to account 'foo' (or that account does not exist). Application access may have been revoked.", $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesInvalidRequestErrorOn404()
{
$this->stubRequest(
'GET',
'/v1/charges/foo',
[],
null,
false,
[
'error' => [
'type' => 'invalid_request_error',
'message' => 'No such charge: foo',
'param' => 'id',
],
],
404
);
try {
Charge::retrieve('foo');
$this->fail("Did not raise error");
} catch (Error\InvalidRequest $e) {
$this->assertSame(404, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame('No such charge: foo', $e->getMessage());
$this->assertSame('id', $e->getStripeParam());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesRateLimitErrorOn429()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
null,
false,
[
'error' => [
'message' => 'Too many requests',
],
],
429
);
try {
Charge::create();
$this->fail("Did not raise error");
} catch (Error\RateLimit $e) {
$this->assertSame(429, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame('Too many requests', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesRateLimitErrorOn400AndCodeRateLimit()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
null,
false,
[
'error' => [
'code' => 'rate_limit',
'message' => 'Too many requests',
],
],
400
);
try {
Charge::create();
$this->fail("Did not raise error");
} catch (Error\RateLimit $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertTrue(is_array($e->getJsonBody()));
$this->assertSame('Too many requests', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesOAuthInvalidRequestError()
{
$this->stubRequest(
'POST',
'/oauth/token',
[],
null,
false,
[
'error' => 'invalid_request',
'error_description' => 'No grant type specified',
],
400,
Stripe::$connectBase
);
try {
OAuth::token();
$this->fail("Did not raise error");
} catch (Error\OAuth\InvalidRequest $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertSame('invalid_request', $e->getErrorCode());
$this->assertSame('No grant type specified', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesOAuthInvalidClientError()
{
$this->stubRequest(
'POST',
'/oauth/token',
[],
null,
false,
[
'error' => 'invalid_client',
'error_description' => 'No authentication was provided. Send your secret API key using the Authorization header, or as a client_secret POST parameter.',
],
401,
Stripe::$connectBase
);
try {
OAuth::token();
$this->fail("Did not raise error");
} catch (Error\OAuth\InvalidClient $e) {
$this->assertSame(401, $e->getHttpStatus());
$this->assertSame('invalid_client', $e->getErrorCode());
$this->assertSame('No authentication was provided. Send your secret API key using the Authorization header, or as a client_secret POST parameter.', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesOAuthInvalidGrantError()
{
$this->stubRequest(
'POST',
'/oauth/token',
[],
null,
false,
[
'error' => 'invalid_grant',
'error_description' => 'This authorization code has already been used. All tokens issued with this code have been revoked.',
],
400,
Stripe::$connectBase
);
try {
OAuth::token();
$this->fail("Did not raise error");
} catch (Error\OAuth\InvalidGrant $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertSame('invalid_grant', $e->getErrorCode());
$this->assertSame('This authorization code has already been used. All tokens issued with this code have been revoked.', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesOAuthInvalidScopeError()
{
$this->stubRequest(
'POST',
'/oauth/token',
[],
null,
false,
[
'error' => 'invalid_scope',
'error_description' => 'Invalid scope provided: invalid_scope.',
],
400,
Stripe::$connectBase
);
try {
OAuth::token();
$this->fail("Did not raise error");
} catch (Error\OAuth\InvalidScope $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertSame('invalid_scope', $e->getErrorCode());
$this->assertSame('Invalid scope provided: invalid_scope.', $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesOAuthUnsupportedGrantTypeError()
{
$this->stubRequest(
'POST',
'/oauth/token',
[],
null,
false,
[
'error' => 'unsupported_grant_type',
],
400,
Stripe::$connectBase
);
try {
OAuth::token();
$this->fail("Did not raise error");
} catch (Error\OAuth\UnsupportedGrantType $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertSame('unsupported_grant_type', $e->getErrorCode());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testRaisesOAuthUnsupportedResponseTypeError()
{
$this->stubRequest(
'POST',
'/oauth/token',
[],
null,
false,
[
'error' => 'unsupported_response_type',
'error_description' => "Only 'code' response_type is supported, but 'unsupported_response_type' was provided",
],
400,
Stripe::$connectBase
);
try {
OAuth::token();
$this->fail("Did not raise error");
} catch (Error\OAuth\UnsupportedResponseType $e) {
$this->assertSame(400, $e->getHttpStatus());
$this->assertSame('unsupported_response_type', $e->getErrorCode());
$this->assertSame("Only 'code' response_type is supported, but 'unsupported_response_type' was provided", $e->getMessage());
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testHeaderStripeVersionGlobal()
{
Stripe::setApiVersion('2222-22-22');
$this->stubRequest(
'POST',
'/v1/charges',
[],
[
'Stripe-Version: 2222-22-22',
],
false,
[
'id' => 'ch_123',
'object' => 'charge',
]
);
Charge::create();
}
public function testHeaderStripeVersionRequestOptions()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
[
'Stripe-Version: 2222-22-22',
],
false,
[
'id' => 'ch_123',
'object' => 'charge',
]
);
Charge::create([], ['stripe_version' => '2222-22-22']);
}
public function testHeaderStripeAccountGlobal()
{
Stripe::setAccountId('acct_123');
$this->stubRequest(
'POST',
'/v1/charges',
[],
[
'Stripe-Account: acct_123',
],
false,
[
'id' => 'ch_123',
'object' => 'charge',
]
);
Charge::create();
}
public function testHeaderStripeAccountRequestOptions()
{
$this->stubRequest(
'POST',
'/v1/charges',
[],
[
'Stripe-Account: acct_123',
],
false,
[
'id' => 'ch_123',
'object' => 'charge',
]
);
Charge::create([], ['stripe_account' => 'acct_123']);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace Stripe;
class ApplePayDomainTest extends TestCase
{
const TEST_RESOURCE_ID = 'apwc_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/apple_pay/domains'
);
$resources = ApplePayDomain::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\ApplePayDomain", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/apple_pay/domains/' . self::TEST_RESOURCE_ID
);
$resource = ApplePayDomain::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\ApplePayDomain", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/apple_pay/domains'
);
$resource = ApplePayDomain::create([
"domain_name" => "domain",
]);
$this->assertInstanceOf("Stripe\\ApplePayDomain", $resource);
}
public function testIsDeletable()
{
$resource = ApplePayDomain::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/apple_pay/domains/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\ApplePayDomain", $resource);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Stripe;
class ApplicationFeeRefundTest extends TestCase
{
const TEST_RESOURCE_ID = 'fr_123';
const TEST_FEE_ID = 'fee_123';
public function testIsSaveable()
{
$resource = ApplicationFee::retrieveRefund(self::TEST_FEE_ID, self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/application_fees/' . $resource->fee . '/refunds/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource);
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Stripe;
class ApplicationFeeTest extends TestCase
{
const TEST_RESOURCE_ID = 'fee_123';
const TEST_FEEREFUND_ID = 'fr_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/application_fees'
);
$resources = ApplicationFee::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\ApplicationFee", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/application_fees/' . self::TEST_RESOURCE_ID
);
$resource = ApplicationFee::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\ApplicationFee", $resource);
}
public function testIsRefundable()
{
$fee = ApplicationFee::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/application_fees/' . $fee->id . '/refunds'
);
$resource = $fee->refund();
$this->assertInstanceOf("Stripe\\ApplicationFee", $resource);
$this->assertSame($resource, $fee);
}
public function testCanCreateRefund()
{
$this->expectsRequest(
'post',
'/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds'
);
$resource = ApplicationFee::createRefund(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource);
}
public function testCanRetrieveRefund()
{
$this->expectsRequest(
'get',
'/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds/' . self::TEST_FEEREFUND_ID
);
$resource = ApplicationFee::retrieveRefund(self::TEST_RESOURCE_ID, self::TEST_FEEREFUND_ID);
$this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource);
}
public function testCanUpdateRefund()
{
$this->expectsRequest(
'post',
'/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds/' . self::TEST_FEEREFUND_ID
);
$resource = ApplicationFee::updateRefund(self::TEST_RESOURCE_ID, self::TEST_FEEREFUND_ID);
$this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource);
}
public function testCanListRefunds()
{
$this->expectsRequest(
'get',
'/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds'
);
$resources = ApplicationFee::allRefunds(self::TEST_RESOURCE_ID);
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resources->data[0]);
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Stripe;
class BalanceTest extends TestCase
{
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/balance'
);
$resource = Balance::retrieve();
$this->assertInstanceOf("Stripe\\Balance", $resource);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Stripe;
class BalanceTransactionTest extends TestCase
{
const TEST_RESOURCE_ID = 'txn_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/balance/history'
);
$resources = BalanceTransaction::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\BalanceTransaction", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/balance/history/' . self::TEST_RESOURCE_ID
);
$resource = BalanceTransaction::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\BalanceTransaction", $resource);
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace Stripe;
class BankAccountTest extends TestCase
{
const TEST_RESOURCE_ID = 'ba_123';
// Because of the wildcard nature of sources, stripe-mock cannot currently
// reliably return sources of a given type, so we create a fixture manually
public function createFixture($params = [])
{
if (empty($params)) {
$params['customer'] = 'cus_123';
}
$base = [
'id' => self::TEST_RESOURCE_ID,
'object' => 'bank_account',
'metadata' => [],
];
return BankAccount::constructFrom(
array_merge($params, $base),
new Util\RequestOptions()
);
}
public function testHasCorrectUrlForCustomer()
{
$resource = $this->createFixture(['customer' => 'cus_123']);
$this->assertSame(
"/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
public function testHasCorrectUrlForAccount()
{
$resource = $this->createFixture(['account' => 'acct_123']);
$this->assertSame(
"/v1/accounts/acct_123/external_accounts/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
/**
* @expectedException \Stripe\Error\InvalidRequest
*/
public function testIsNotDirectlyRetrievable()
{
BankAccount::retrieve(self::TEST_RESOURCE_ID);
}
public function testIsSaveable()
{
$resource = $this->createFixture();
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID
);
$resource->save();
$this->assertSame("Stripe\\BankAccount", get_class($resource));
}
/**
* @expectedException \Stripe\Error\InvalidRequest
*/
public function testIsNotDirectlyUpdatable()
{
BankAccount::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
}
public function testIsDeletable()
{
$resource = $this->createFixture();
$this->expectsRequest(
'delete',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID
);
$resource->delete();
$this->assertSame("Stripe\\BankAccount", get_class($resource));
}
public function testIsVerifiable()
{
$resource = $this->createFixture();
$this->expectsRequest(
'post',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID . "/verify",
[
"amounts" => [1, 2]
]
);
$resource->verify(["amounts" => [1, 2]]);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Stripe;
class BitcoinReceiverTest extends TestCase
{
const TEST_RESOURCE_ID = 'btcrcv_123';
// Because of the wildcard nature of sources, stripe-mock cannot currently
// reliably return sources of a given type, so we create a fixture manually
public function createFixture($params = [])
{
$base = [
'id' => self::TEST_RESOURCE_ID,
'object' => 'bitcoin_receiver',
'metadata' => [],
];
return BitcoinReceiver::constructFrom(
array_merge($params, $base),
new Util\RequestOptions()
);
}
public function testHasCorrectStandaloneUrl()
{
$resource = $this->createFixture();
$this->assertSame(
"/v1/bitcoin/receivers/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
public function testHasCorrectUrlForCustomer()
{
$resource = $this->createFixture(['customer' => 'cus_123']);
$this->assertSame(
"/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/bitcoin/receivers'
);
$resources = BitcoinReceiver::all();
$this->assertTrue(is_array($resources->data));
$this->assertSame("Stripe\\BitcoinReceiver", get_class($resources->data[0]));
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/bitcoin/receivers/' . self::TEST_RESOURCE_ID
);
$resource = BitcoinReceiver::retrieve(self::TEST_RESOURCE_ID);
$this->assertSame("Stripe\\BitcoinReceiver", get_class($resource));
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace Stripe;
class CardTest extends TestCase
{
const TEST_RESOURCE_ID = 'card_123';
// Because of the wildcard nature of sources, stripe-mock cannot currently
// reliably return sources of a given type, so we create a fixture manually
public function createFixture($params = [])
{
if (empty($params)) {
$params['customer'] = 'cus_123';
}
$base = [
'id' => self::TEST_RESOURCE_ID,
'object' => 'card',
'metadata' => [],
];
return Card::constructFrom(
array_merge($params, $base),
new Util\RequestOptions()
);
}
public function testHasCorrectUrlForCustomer()
{
$resource = $this->createFixture(['customer' => 'cus_123']);
$this->assertSame(
"/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
public function testHasCorrectUrlForAccount()
{
$resource = $this->createFixture(['account' => 'acct_123']);
$this->assertSame(
"/v1/accounts/acct_123/external_accounts/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
public function testHasCorrectUrlForRecipient()
{
$resource = $this->createFixture(['recipient' => 'rp_123']);
$this->assertSame(
"/v1/recipients/rp_123/cards/" . self::TEST_RESOURCE_ID,
$resource->instanceUrl()
);
}
/**
* @expectedException \Stripe\Error\InvalidRequest
*/
public function testIsNotDirectlyRetrievable()
{
Card::retrieve(self::TEST_RESOURCE_ID);
}
public function testIsSaveable()
{
$resource = $this->createFixture();
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID
);
$resource->save();
$this->assertSame("Stripe\\Card", get_class($resource));
}
/**
* @expectedException \Stripe\Error\InvalidRequest
*/
public function testIsNotDirectlyUpdatable()
{
Card::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
}
public function testIsDeletable()
{
$resource = $this->createFixture();
$this->expectsRequest(
'delete',
'/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID
);
$resource->delete();
$this->assertSame("Stripe\\Card", get_class($resource));
}
}

View File

@ -0,0 +1,140 @@
<?php
namespace Stripe;
class ChargeTest extends TestCase
{
const TEST_RESOURCE_ID = 'ch_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/charges'
);
$resources = Charge::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Charge", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/charges/' . self::TEST_RESOURCE_ID
);
$resource = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Charge", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/charges'
);
$resource = Charge::create([
"amount" => 100,
"currency" => "usd",
"source" => "tok_123"
]);
$this->assertInstanceOf("Stripe\\Charge", $resource);
}
public function testIsSaveable()
{
$resource = Charge::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/charges/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Charge", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/charges/' . self::TEST_RESOURCE_ID
);
$resource = Charge::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Charge", $resource);
}
public function testCanRefund()
{
$charge = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/charges/' . $charge->id . '/refund'
);
$resource = $charge->refund();
$this->assertInstanceOf("Stripe\\Charge", $resource);
$this->assertSame($resource, $charge);
}
public function testCanCapture()
{
$charge = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/charges/' . $charge->id . '/capture'
);
$resource = $charge->capture();
$this->assertInstanceOf("Stripe\\Charge", $resource);
$this->assertSame($resource, $charge);
}
public function testCanUpdateDispute()
{
$charge = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/charges/' . $charge->id . '/dispute'
);
$resource = $charge->updateDispute();
$this->assertInstanceOf("Stripe\\Dispute", $resource);
}
public function testCanCloseDispute()
{
$charge = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/charges/' . $charge->id . '/dispute/close'
);
$resource = $charge->closeDispute();
$this->assertInstanceOf("Stripe\\Charge", $resource);
$this->assertSame($resource, $charge);
}
public function testCanMarkAsFraudulent()
{
$charge = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/charges/' . $charge->id,
['fraud_details' => ['user_report' => 'fraudulent']]
);
$resource = $charge->markAsFraudulent();
$this->assertInstanceOf("Stripe\\Charge", $resource);
$this->assertSame($resource, $charge);
}
public function testCanMarkAsSafe()
{
$charge = Charge::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/charges/' . $charge->id,
['fraud_details' => ['user_report' => 'safe']]
);
$resource = $charge->markAsSafe();
$this->assertInstanceOf("Stripe\\Charge", $resource);
$this->assertSame($resource, $charge);
}
}

View File

@ -0,0 +1,147 @@
<?php
namespace Stripe;
class CollectionTest extends TestCase
{
/**
* @before
*/
public function setUpFixture()
{
$this->fixture = Collection::constructFrom([
'data' => [['id' => 1]],
'has_more' => true,
'url' => '/things',
]);
}
public function testCanList()
{
$this->stubRequest(
'GET',
'/things',
[],
null,
false,
[
'data' => [['id' => 1]],
'has_more' => true,
'url' => '/things',
]
);
$resources = $this->fixture->all();
$this->assertTrue(is_array($resources->data));
}
public function testCanRetrieve()
{
$this->stubRequest(
'GET',
'/things/1',
[],
null,
false,
[
'id' => 1,
]
);
$this->fixture->retrieve(1);
}
public function testCanCreate()
{
$this->stubRequest(
'POST',
'/things',
[
'foo' => 'bar',
],
null,
false,
[
'id' => 2,
]
);
$this->fixture->create([
'foo' => 'bar',
]);
}
public function testProvidesAutoPagingIterator()
{
$this->stubRequest(
'GET',
'/things',
[
'starting_after' => 1,
],
null,
false,
[
'data' => [['id' => 2], ['id' => 3]],
'has_more' => false,
]
);
$seen = [];
foreach ($this->fixture->autoPagingIterator() as $item) {
array_push($seen, $item['id']);
}
$this->assertSame([1, 2, 3], $seen);
}
public function testSupportsIteratorToArray()
{
$this->stubRequest(
'GET',
'/things',
[
'starting_after' => 1,
],
null,
false,
[
'data' => [['id' => 2], ['id' => 3]],
'has_more' => false,
]
);
$seen = [];
foreach (iterator_to_array($this->fixture->autoPagingIterator()) as $item) {
array_push($seen, $item['id']);
}
$this->assertSame([1, 2, 3], $seen);
}
public function testHeaders()
{
$this->stubRequest(
'POST',
'/things',
[
'foo' => 'bar',
],
[
'Stripe-Account: acct_foo',
'Idempotency-Key: qwertyuiop',
],
false,
[
'id' => 2,
]
);
$this->fixture->create([
'foo' => 'bar',
], [
'stripe_account' => 'acct_foo',
'idempotency_key' => 'qwertyuiop',
]);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Stripe;
class CountrySpecTest extends TestCase
{
const TEST_RESOURCE_ID = 'US';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/country_specs'
);
$resources = CountrySpec::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\CountrySpec", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/country_specs/' . self::TEST_RESOURCE_ID
);
$resource = CountrySpec::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\CountrySpec", $resource);
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace Stripe;
class CouponTest extends TestCase
{
const TEST_RESOURCE_ID = '25OFF';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/coupons'
);
$resources = Coupon::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Coupon", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/coupons/' . self::TEST_RESOURCE_ID
);
$resource = Coupon::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Coupon", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/coupons'
);
$resource = Coupon::create([
"percent_off" => 25,
"duration" => "repeating",
"duration_in_months" => 3,
"id" => self::TEST_RESOURCE_ID,
]);
$this->assertInstanceOf("Stripe\\Coupon", $resource);
}
public function testIsSaveable()
{
$resource = Coupon::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/coupons/' . self::TEST_RESOURCE_ID
);
$resource->save();
$this->assertInstanceOf("Stripe\\Coupon", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/coupons/' . self::TEST_RESOURCE_ID
);
$resource = Coupon::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Coupon", $resource);
}
public function testIsDeletable()
{
$resource = Coupon::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/coupons/' . self::TEST_RESOURCE_ID
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Coupon", $resource);
}
}

View File

@ -0,0 +1,269 @@
<?php
namespace Stripe;
class CustomerTest extends TestCase
{
const TEST_RESOURCE_ID = 'cus_123';
const TEST_SOURCE_ID = 'ba_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/customers'
);
$resources = Customer::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Customer", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/customers/' . self::TEST_RESOURCE_ID
);
$resource = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Customer", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/customers'
);
$resource = Customer::create();
$this->assertInstanceOf("Stripe\\Customer", $resource);
}
public function testIsSaveable()
{
$resource = Customer::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/customers/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Customer", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/customers/' . self::TEST_RESOURCE_ID
);
$resource = Customer::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Customer", $resource);
}
public function testIsDeletable()
{
$resource = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/customers/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Customer", $resource);
}
public function testCanAddInvoiceItem()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/invoiceitems',
[
"amount" => 100,
"currency" => "usd",
"customer" => $customer->id
]
);
$resource = $customer->addInvoiceItem([
"amount" => 100,
"currency" => "usd"
]);
$this->assertInstanceOf("Stripe\\InvoiceItem", $resource);
}
public function testCanListInvoices()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'get',
'/v1/invoices',
["customer" => $customer->id]
);
$resources = $customer->invoices();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Invoice", $resources->data[0]);
}
public function testCanListInvoiceItems()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'get',
'/v1/invoiceitems',
["customer" => $customer->id]
);
$resources = $customer->invoiceItems();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\InvoiceItem", $resources->data[0]);
}
public function testCanListCharges()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'get',
'/v1/charges',
["customer" => $customer->id]
);
$resources = $customer->charges();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Charge", $resources->data[0]);
}
public function testCanUpdateSubscription()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->stubRequest(
'post',
'/v1/customers/' . $customer->id . '/subscription',
["plan" => "plan"],
null,
false,
[
"object" => "subscription",
"id" => "sub_foo"
]
);
$resource = $customer->updateSubscription(["plan" => "plan"]);
$this->assertInstanceOf("Stripe\\Subscription", $resource);
$this->assertSame("sub_foo", $customer->subscription->id);
}
public function testCanCancelSubscription()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->stubRequest(
'delete',
'/v1/customers/' . $customer->id . '/subscription',
[],
null,
false,
[
"object" => "subscription",
"id" => "sub_foo"
]
);
$resource = $customer->cancelSubscription();
$this->assertInstanceOf("Stripe\\Subscription", $resource);
$this->assertSame("sub_foo", $customer->subscription->id);
}
public function testCanDeleteDiscount()
{
$customer = Customer::retrieve(self::TEST_RESOURCE_ID);
$this->stubRequest(
'delete',
'/v1/customers/' . $customer->id . '/discount'
);
$customer->deleteDiscount();
$this->assertSame($customer->discount, null);
}
public function testCanCreateSource()
{
$this->expectsRequest(
'post',
'/v1/customers/' . self::TEST_RESOURCE_ID . '/sources'
);
$resource = Customer::createSource(self::TEST_RESOURCE_ID, ["source" => "btok_123"]);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanRetrieveSource()
{
$this->expectsRequest(
'get',
'/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID
);
$resource = Customer::retrieveSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanUpdateSource()
{
$this->expectsRequest(
'post',
'/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID
);
$resource = Customer::updateSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID, ["name" => "name"]);
// stripe-mock returns a Card on this method and not a bank account
$this->assertInstanceOf("Stripe\\Card", $resource);
}
public function testCanDeleteSource()
{
$this->expectsRequest(
'delete',
'/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID
);
$resource = Customer::deleteSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID);
$this->assertInstanceOf("Stripe\\BankAccount", $resource);
}
public function testCanListSources()
{
$this->expectsRequest(
'get',
'/v1/customers/' . self::TEST_RESOURCE_ID . '/sources'
);
$resources = Customer::allSources(self::TEST_RESOURCE_ID);
$this->assertTrue(is_array($resources->data));
}
public function testSerializeSourceString()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'customer',
], null);
$obj->source = 'tok_visa';
$expected = [
'source' => 'tok_visa',
];
$this->assertSame($expected, $obj->serializeParameters());
}
public function testSerializeSourceMap()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'customer',
], null);
$obj->source = [
'object' => 'card',
'number' => '4242424242424242',
'exp_month' => 12,
'exp_year' => 2032,
];
$expected = [
'source' => [
'object' => 'card',
'number' => '4242424242424242',
'exp_month' => 12,
'exp_year' => 2032,
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Stripe;
class DisputeTest extends TestCase
{
const TEST_RESOURCE_ID = 'dp_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/disputes'
);
$resources = Dispute::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Dispute", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/disputes/' . self::TEST_RESOURCE_ID
);
$resource = Dispute::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Dispute", $resource);
}
public function testIsSaveable()
{
$resource = Dispute::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/disputes/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Dispute", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/disputes/' . self::TEST_RESOURCE_ID
);
$resource = Dispute::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Dispute", $resource);
}
public function testIsClosable()
{
$dispute = Dispute::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/disputes/' . $dispute->id . '/close'
);
$resource = $dispute->close();
$this->assertInstanceOf("Stripe\\Dispute", $resource);
$this->assertSame($resource, $dispute);
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace Stripe;
class EphemeralKeyTest extends TestCase
{
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/ephemeral_keys',
null,
["Stripe-Version: 2017-05-25"]
);
$resource = EphemeralKey::create([
"customer" => "cus_123",
], ["stripe_version" => "2017-05-25"]);
$this->assertInstanceOf("Stripe\\EphemeralKey", $resource);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testIsNotCreatableWithoutAnExplicitApiVersion()
{
$resource = EphemeralKey::create([
"customer" => "cus_123",
]);
}
public function testIsDeletable()
{
$key = EphemeralKey::create([
"customer" => "cus_123",
], ["stripe_version" => "2017-05-25"]);
$this->expectsRequest(
'delete',
'/v1/ephemeral_keys/' . $key->id
);
$resource = $key->delete();
$this->assertInstanceOf("Stripe\\EphemeralKey", $resource);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Stripe;
class BaseTest extends TestCase
{
public function createFixture($params = [])
{
return $this->getMockForAbstractClass('Stripe\\Error\\Base', [
'message',
200,
'{"key": "value"}',
['key' => 'value'],
[
'Some-Header' => 'Some Value',
'Request-Id' => 'req_test',
],
]);
}
public function testGetters()
{
$e = $this->createFixture();
$this->assertSame(200, $e->getHttpStatus());
$this->assertSame('{"key": "value"}', $e->getHttpBody());
$this->assertSame(['key' => 'value'], $e->getJsonBody());
$this->assertSame('Some Value', $e->getHttpHeaders()['Some-Header']);
$this->assertSame('req_test', $e->getRequestId());
}
public function testToString()
{
$e = $this->createFixture();
$this->assertContains("from API request 'req_test'", (string)$e);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Stripe;
class SignatureVerificationTest extends TestCase
{
public function testGetters()
{
$e = new Error\SignatureVerification('message', 'sig_header');
$this->assertSame('sig_header', $e->getSigHeader());
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Stripe;
class EventTest extends TestCase
{
const TEST_RESOURCE_ID = 'evt_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/events'
);
$resources = Event::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Event", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/events/' . self::TEST_RESOURCE_ID
);
$resource = Event::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Event", $resource);
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace Stripe;
class ExchangeRateTest extends TestCase
{
public function testIsListable()
{
$this->stubRequest(
'get',
'/v1/exchange_rates',
[],
null,
false,
[
'object' => 'list',
'data' => [
[
'id' => 'eur',
'object' => 'exchange_rate',
'rates' => ['usd' => 1.18221],
],
[
'id' => 'usd',
'object' => 'exchange_rate',
'rates' => ['eur' => 0.845876],
],
],
]
);
$listRates = ExchangeRate::all();
$this->assertTrue(is_array($listRates->data));
$this->assertEquals('exchange_rate', $listRates->data[0]->object);
}
public function testIsRetrievable()
{
$this->stubRequest(
'get',
'/v1/exchange_rates/usd',
[],
null,
false,
[
'id' => 'usd',
'object' => 'exchange_rate',
'rates' => ['eur' => 0.845876],
]
);
$rates = ExchangeRate::retrieve("usd");
$this->assertEquals('exchange_rate', $rates->object);
}
}

View File

@ -0,0 +1,104 @@
<?php
namespace Stripe;
class FileUploadTest extends TestCase
{
const TEST_RESOURCE_ID = 'file_123';
/**
* @before
*/
public function setUpFixture()
{
// PHP <= 5.5 does not support arrays as class constants, so we set up
// the fixture as an instance variable.
$this->fixture = [
'id' => self::TEST_RESOURCE_ID,
'object' => 'file_upload',
];
}
public function testIsListable()
{
$this->stubRequest(
'get',
'/v1/files',
[],
null,
false,
[
'object' => 'list',
'data' => [$this->fixture],
'resource_url' => '/v1/files',
],
200,
Stripe::$apiUploadBase
);
$resources = FileUpload::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\FileUpload", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->stubRequest(
'get',
'/v1/files/' . self::TEST_RESOURCE_ID,
[],
null,
false,
$this->fixture,
200,
Stripe::$apiUploadBase
);
$resource = FileUpload::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\FileUpload", $resource);
}
public function testIsCreatableWithFileHandle()
{
$this->stubRequest(
'post',
'/v1/files',
null,
['Content-Type: multipart/form-data'],
true,
$this->fixture,
200,
Stripe::$apiUploadBase
);
$fp = fopen(dirname(__FILE__) . '/../data/test.png', 'r');
$resource = FileUpload::create([
"purpose" => "dispute_evidence",
"file" => $fp,
]);
$this->assertInstanceOf("Stripe\\FileUpload", $resource);
}
public function testIsCreatableWithCurlFile()
{
if (!class_exists('\CurlFile', false)) {
// Older PHP versions don't support this
return;
}
$this->stubRequest(
'post',
'/v1/files',
null,
['Content-Type: multipart/form-data'],
true,
$this->fixture,
200,
Stripe::$apiUploadBase
);
$curlFile = new \CurlFile(dirname(__FILE__) . '/../data/test.png');
$resource = FileUpload::create([
"purpose" => "dispute_evidence",
"file" => $curlFile,
]);
$this->assertInstanceOf("Stripe\\FileUpload", $resource);
}
}

View File

@ -0,0 +1,228 @@
<?php
namespace Stripe;
use Stripe\HttpClient\CurlClient;
class CurlClientTest extends TestCase
{
/**
* @before
*/
public function saveOriginalNetworkValues()
{
$this->origMaxNetworkRetries = Stripe::getMaxNetworkRetries();
$this->origMaxNetworkRetryDelay = Stripe::getMaxNetworkRetryDelay();
$this->origInitialNetworkRetryDelay = Stripe::getInitialNetworkRetryDelay();
}
/**
* @before
*/
public function setUpReflectors()
{
$stripeReflector = new \ReflectionClass('\Stripe\Stripe');
$this->maxNetworkRetryDelayProperty = $stripeReflector->getProperty('maxNetworkRetryDelay');
$this->maxNetworkRetryDelayProperty->setAccessible(true);
$this->initialNetworkRetryDelayProperty = $stripeReflector->getProperty('initialNetworkRetryDelay');
$this->initialNetworkRetryDelayProperty->setAccessible(true);
$curlClientReflector = new \ReflectionClass('Stripe\HttpClient\CurlClient');
$this->shouldRetryMethod = $curlClientReflector->getMethod('shouldRetry');
$this->shouldRetryMethod->setAccessible(true);
$this->sleepTimeMethod = $curlClientReflector->getMethod('sleepTime');
$this->sleepTimeMethod->setAccessible(true);
}
/**
* @after
*/
public function restoreOriginalNetworkValues()
{
Stripe::setMaxNetworkRetries($this->origMaxNetworkRetries);
$this->setMaxNetworkRetryDelay($this->origMaxNetworkRetryDelay);
$this->setInitialNetworkRetryDelay($this->origInitialNetworkRetryDelay);
}
private function setMaxNetworkRetryDelay($maxNetworkRetryDelay)
{
$this->maxNetworkRetryDelayProperty->setValue(null, $maxNetworkRetryDelay);
}
private function setInitialNetworkRetryDelay($initialNetworkRetryDelay)
{
$this->initialNetworkRetryDelayProperty->setValue(null, $initialNetworkRetryDelay);
}
private function createFakeRandomGenerator($returnValue = 1.0)
{
$fakeRandomGenerator = $this->getMock('Stripe\Util\RandomGenetator', ['randFloat']);
$fakeRandomGenerator->method('randFloat')->willReturn($returnValue);
return $fakeRandomGenerator;
}
public function testTimeout()
{
$curl = new CurlClient();
$this->assertSame(CurlClient::DEFAULT_TIMEOUT, $curl->getTimeout());
$this->assertSame(CurlClient::DEFAULT_CONNECT_TIMEOUT, $curl->getConnectTimeout());
// implicitly tests whether we're returning the CurlClient instance
$curl = $curl->setConnectTimeout(1)->setTimeout(10);
$this->assertSame(1, $curl->getConnectTimeout());
$this->assertSame(10, $curl->getTimeout());
$curl->setTimeout(-1);
$curl->setConnectTimeout(-999);
$this->assertSame(0, $curl->getTimeout());
$this->assertSame(0, $curl->getConnectTimeout());
}
public function testUserAgentInfo()
{
$curl = new CurlClient();
$uaInfo = $curl->getUserAgentInfo();
$this->assertNotNull($uaInfo);
$this->assertNotNull($uaInfo['httplib']);
$this->assertNotNull($uaInfo['ssllib']);
}
public function testDefaultOptions()
{
// make sure options array loads/saves properly
$optionsArray = [CURLOPT_PROXY => 'localhost:80'];
$withOptionsArray = new CurlClient($optionsArray);
$this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray);
// make sure closure-based options work properly, including argument passing
$ref = null;
$withClosure = new CurlClient(function ($method, $absUrl, $headers, $params, $hasFile) use (&$ref) {
$ref = func_get_args();
return [];
});
$withClosure->request('get', 'https://httpbin.org/status/200', [], [], false);
$this->assertSame($ref, ['get', 'https://httpbin.org/status/200', [], [], false]);
// this is the last test case that will run, since it'll throw an exception at the end
$withBadClosure = new CurlClient(function () {
return 'thisShouldNotWork';
});
$this->setExpectedException('Stripe\Error\Api', "Non-array value returned by defaultOptions CurlClient callback");
$withBadClosure->request('get', 'https://httpbin.org/status/200', [], [], false);
}
public function testSslOption()
{
// make sure options array loads/saves properly
$optionsArray = [CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1];
$withOptionsArray = new CurlClient($optionsArray);
$this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray);
}
public function testShouldRetryOnTimeout()
{
Stripe::setMaxNetworkRetries(2);
$curlClient = new CurlClient();
$this->assertTrue($this->shouldRetryMethod->invoke($curlClient, CURLE_OPERATION_TIMEOUTED, 0, 0));
}
public function testShouldRetryOnConnectionFailure()
{
Stripe::setMaxNetworkRetries(2);
$curlClient = new CurlClient();
$this->assertTrue($this->shouldRetryMethod->invoke($curlClient, CURLE_COULDNT_CONNECT, 0, 0));
}
public function testShouldRetryOnConflict()
{
Stripe::setMaxNetworkRetries(2);
$curlClient = new CurlClient();
$this->assertTrue($this->shouldRetryMethod->invoke($curlClient, 0, 409, 0));
}
public function testShouldNotRetryAtMaximumCount()
{
Stripe::setMaxNetworkRetries(2);
$curlClient = new CurlClient();
$this->assertFalse($this->shouldRetryMethod->invoke($curlClient, 0, 0, Stripe::getMaxNetworkRetries()));
}
public function testShouldNotRetryOnCertValidationError()
{
Stripe::setMaxNetworkRetries(2);
$curlClient = new CurlClient();
$this->assertFalse($this->shouldRetryMethod->invoke($curlClient, CURLE_SSL_PEER_CERTIFICATE, -1, 0));
}
public function testSleepTimeShouldGrowExponentially()
{
$this->setMaxNetworkRetryDelay(999);
$curlClient = new CurlClient(null, $this->createFakeRandomGenerator());
$this->assertEquals(
Stripe::getInitialNetworkRetryDelay() * 1,
$this->sleepTimeMethod->invoke($curlClient, 1)
);
$this->assertEquals(
Stripe::getInitialNetworkRetryDelay() * 2,
$this->sleepTimeMethod->invoke($curlClient, 2)
);
$this->assertEquals(
Stripe::getInitialNetworkRetryDelay() * 4,
$this->sleepTimeMethod->invoke($curlClient, 3)
);
$this->assertEquals(
Stripe::getInitialNetworkRetryDelay() * 8,
$this->sleepTimeMethod->invoke($curlClient, 4)
);
}
public function testSleepTimeShouldEnforceMaxNetworkRetryDelay()
{
$this->setInitialNetworkRetryDelay(1);
$this->setMaxNetworkRetryDelay(2);
$curlClient = new CurlClient(null, $this->createFakeRandomGenerator());
$this->assertEquals(1, $this->sleepTimeMethod->invoke($curlClient, 1));
$this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 2));
$this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 3));
$this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 4));
}
public function testSleepTimeShouldAddSomeRandomness()
{
$randomValue = 0.8;
$this->setInitialNetworkRetryDelay(1);
$this->setMaxNetworkRetryDelay(8);
$curlClient = new CurlClient(null, $this->createFakeRandomGenerator($randomValue));
$baseValue = Stripe::getInitialNetworkRetryDelay() * (0.5 * (1 + $randomValue));
// the initial value cannot be smaller than the base,
// so the randomness is ignored
$this->assertEquals(Stripe::getInitialNetworkRetryDelay(), $this->sleepTimeMethod->invoke($curlClient, 1));
// after the first one, the randomness is applied
$this->assertEquals($baseValue * 2, $this->sleepTimeMethod->invoke($curlClient, 2));
$this->assertEquals($baseValue * 4, $this->sleepTimeMethod->invoke($curlClient, 3));
$this->assertEquals($baseValue * 8, $this->sleepTimeMethod->invoke($curlClient, 4));
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace Stripe;
class InvoiceItemTest extends TestCase
{
const TEST_RESOURCE_ID = 'ii_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/invoiceitems'
);
$resources = InvoiceItem::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\InvoiceItem", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/invoiceitems/' . self::TEST_RESOURCE_ID
);
$resource = InvoiceItem::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\InvoiceItem", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/invoiceitems'
);
$resource = InvoiceItem::create([
"amount" => 100,
"currency" => "usd",
"customer" => "cus_123"
]);
$this->assertInstanceOf("Stripe\\InvoiceItem", $resource);
}
public function testIsSaveable()
{
$resource = InvoiceItem::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/invoiceitems/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\InvoiceItem", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/invoiceitems/' . self::TEST_RESOURCE_ID
);
$resource = InvoiceItem::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\InvoiceItem", $resource);
}
public function testIsDeletable()
{
$invoiceItem = InvoiceItem::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/invoiceitems/' . $invoiceItem->id
);
$resource = $invoiceItem->delete();
$this->assertInstanceOf("Stripe\\InvoiceItem", $resource);
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Stripe;
class InvoiceTest extends TestCase
{
const TEST_RESOURCE_ID = 'in_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/invoices'
);
$resources = Invoice::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Invoice", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/invoices/' . self::TEST_RESOURCE_ID
);
$resource = Invoice::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Invoice", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/invoices'
);
$resource = Invoice::create([
"customer" => "cus_123"
]);
$this->assertInstanceOf("Stripe\\Invoice", $resource);
}
public function testIsSaveable()
{
$resource = Invoice::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/invoices/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Invoice", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/invoices/' . self::TEST_RESOURCE_ID
);
$resource = Invoice::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Invoice", $resource);
}
public function testCanRetrieveUpcoming()
{
$this->expectsRequest(
'get',
'/v1/invoices/upcoming'
);
$resource = Invoice::upcoming(["customer" => "cus_123"]);
$this->assertInstanceOf("Stripe\\Invoice", $resource);
}
public function testIsPayable()
{
$invoice = Invoice::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/invoices/' . $invoice->id . '/pay'
);
$resource = $invoice->pay();
$this->assertInstanceOf("Stripe\\Invoice", $resource);
$this->assertSame($resource, $invoice);
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace Stripe;
class OAuthTest extends TestCase
{
public function testAuthorizeUrl()
{
$uriStr = OAuth::authorizeUrl([
'scope' => 'read_write',
'state' => 'csrf_token',
'stripe_user' => [
'email' => 'test@example.com',
'url' => 'https://example.com/profile/test',
'country' => 'US',
],
]);
$uri = parse_url($uriStr);
parse_str($uri['query'], $params);
$this->assertSame('https', $uri['scheme']);
$this->assertSame('connect.stripe.com', $uri['host']);
$this->assertSame('/oauth/authorize', $uri['path']);
$this->assertSame('ca_123', $params['client_id']);
$this->assertSame('read_write', $params['scope']);
$this->assertSame('test@example.com', $params['stripe_user']['email']);
$this->assertSame('https://example.com/profile/test', $params['stripe_user']['url']);
$this->assertSame('US', $params['stripe_user']['country']);
}
/**
* @expectedException \Stripe\Error\Authentication
* @expectedExceptionMessageRegExp #No client_id provided#
*/
public function testRaisesAuthenticationErrorWhenNoClientId()
{
Stripe::setClientId(null);
OAuth::authorizeUrl();
}
public function testToken()
{
$this->stubRequest(
'POST',
'/oauth/token',
[
'grant_type' => 'authorization_code',
'code' => 'this_is_an_authorization_code',
],
null,
false,
[
'access_token' => 'sk_access_token',
'scope' => 'read_only',
'livemode' => false,
'token_type' => 'bearer',
'refresh_token' => 'sk_refresh_token',
'stripe_user_id' => 'acct_test',
'stripe_publishable_key' => 'pk_test',
],
200,
Stripe::$connectBase
);
$resp = OAuth::token([
'grant_type' => 'authorization_code',
'code' => 'this_is_an_authorization_code',
]);
$this->assertSame('sk_access_token', $resp->access_token);
}
public function testDeauthorize()
{
$this->stubRequest(
'POST',
'/oauth/deauthorize',
[
'stripe_user_id' => 'acct_test_deauth',
'client_id' => 'ca_123',
],
null,
false,
[
'stripe_user_id' => 'acct_test_deauth',
],
200,
Stripe::$connectBase
);
$resp = OAuth::deauthorize([
'stripe_user_id' => 'acct_test_deauth',
]);
$this->assertSame('acct_test_deauth', $resp->stripe_user_id);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Stripe;
class OrderReturnTest extends TestCase
{
const TEST_RESOURCE_ID = 'orret_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/order_returns'
);
$resources = OrderReturn::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\OrderReturn", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/order_returns/' . self::TEST_RESOURCE_ID
);
$resource = OrderReturn::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\OrderReturn", $resource);
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Stripe;
class OrderTest extends TestCase
{
const TEST_RESOURCE_ID = 'or_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/orders'
);
$resources = Order::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Order", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/orders/' . self::TEST_RESOURCE_ID
);
$resource = Order::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Order", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/orders'
);
$resource = Order::create([
'currency' => 'usd'
]);
$this->assertInstanceOf("Stripe\\Order", $resource);
}
public function testIsSaveable()
{
$resource = Order::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/orders/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Order", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/orders/' . self::TEST_RESOURCE_ID
);
$resource = Order::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Order", $resource);
}
public function testIsPayable()
{
$resource = Order::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/orders/' . $resource->id . '/pay'
);
$resource->pay();
$this->assertInstanceOf("Stripe\\Order", $resource);
}
public function testIsReturnable()
{
$order = Order::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/orders/' . $order->id . '/returns'
);
$resource = $order->returnOrder();
$this->assertInstanceOf("Stripe\\OrderReturn", $resource);
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace Stripe;
class PayoutTest extends TestCase
{
const TEST_RESOURCE_ID = 'po_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/payouts'
);
$resources = Payout::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Payout", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/payouts/' . self::TEST_RESOURCE_ID
);
$resource = Payout::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Payout", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/payouts'
);
$resource = Payout::create([
"amount" => 100,
"currency" => "usd"
]);
$this->assertInstanceOf("Stripe\\Payout", $resource);
}
public function testIsSaveable()
{
$resource = Payout::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/payouts/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Payout", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/payouts/' . self::TEST_RESOURCE_ID
);
$resource = Payout::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Payout", $resource);
}
public function testIsCancelable()
{
$resource = Payout::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/payouts/' . $resource->id . '/cancel'
);
$resource->cancel();
$this->assertInstanceOf("Stripe\\Payout", $resource);
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace Stripe;
class PlanTest extends TestCase
{
const TEST_RESOURCE_ID = 'plan';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/plans'
);
$resources = Plan::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Plan", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/plans/' . self::TEST_RESOURCE_ID
);
$resource = Plan::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Plan", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/plans'
);
$resource = Plan::create([
'amount' => 100,
'interval' => 'month',
'currency' => 'usd',
'name' => self::TEST_RESOURCE_ID,
'id' => self::TEST_RESOURCE_ID
]);
$this->assertInstanceOf("Stripe\\Plan", $resource);
}
public function testIsSaveable()
{
$resource = Plan::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/plans/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Plan", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/plans/' . self::TEST_RESOURCE_ID
);
$resource = Plan::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Plan", $resource);
}
public function testIsDeletable()
{
$resource = Plan::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/plans/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Plan", $resource);
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace Stripe;
class ProductTest extends TestCase
{
const TEST_RESOURCE_ID = 'prod_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/products'
);
$resources = Product::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Product", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/products/' . self::TEST_RESOURCE_ID
);
$resource = Product::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Product", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/products'
);
$resource = Product::create([
'name' => 'name',
'type' => 'good'
]);
$this->assertInstanceOf("Stripe\\Product", $resource);
}
public function testIsSaveable()
{
$resource = Product::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/products/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Product", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/products/' . self::TEST_RESOURCE_ID
);
$resource = Product::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Product", $resource);
}
public function testIsDeletable()
{
$resource = Product::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/products/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Product", $resource);
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace Stripe;
class RecipientTest extends TestCase
{
const TEST_RESOURCE_ID = 'rp_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/recipients'
);
$resources = Recipient::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Recipient", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/recipients/' . self::TEST_RESOURCE_ID
);
$resource = Recipient::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Recipient", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/recipients'
);
$resource = Recipient::create([
"name" => "name",
"type" => "individual"
]);
$this->assertInstanceOf("Stripe\\Recipient", $resource);
}
public function testIsSaveable()
{
$resource = Recipient::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/recipients/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Recipient", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/recipients/' . self::TEST_RESOURCE_ID
);
$resource = Recipient::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Recipient", $resource);
}
public function testIsDeletable()
{
$resource = Recipient::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/recipients/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Recipient", $resource);
}
public function testCanListTransfers()
{
$recipient = Recipient::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'get',
'/v1/transfers',
["recipient" => $recipient->id]
);
$resources = $recipient->transfers();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Transfer", $resources->data[0]);
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Stripe;
class RefundTest extends TestCase
{
const TEST_RESOURCE_ID = 're_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/refunds'
);
$resources = Refund::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Refund", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/refunds/' . self::TEST_RESOURCE_ID
);
$resource = Refund::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Refund", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/refunds'
);
$resource = Refund::create([
"charge" => "ch_123"
]);
$this->assertInstanceOf("Stripe\\Refund", $resource);
}
public function testIsSaveable()
{
$resource = Refund::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/refunds/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Refund", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/refunds/' . self::TEST_RESOURCE_ID
);
$resource = Refund::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Refund", $resource);
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace Stripe;
class SKUTest extends TestCase
{
const TEST_RESOURCE_ID = 'sku_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/skus'
);
$resources = SKU::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\SKU", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/skus/' . self::TEST_RESOURCE_ID
);
$resource = SKU::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\SKU", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/skus'
);
$resource = SKU::create([
'currency' => 'usd',
'inventory' => [
'type' => 'finite',
'quantity' => 1
],
'price' => 100,
'product' => "prod_123"
]);
$this->assertInstanceOf("Stripe\\SKU", $resource);
}
public function testIsSaveable()
{
$resource = SKU::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/skus/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\SKU", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/skus/' . self::TEST_RESOURCE_ID
);
$resource = SKU::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\SKU", $resource);
}
public function testIsDeletable()
{
$resource = SKU::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/skus/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\SKU", $resource);
}
}

View File

@ -0,0 +1,134 @@
<?php
namespace Stripe;
class SourceTest extends TestCase
{
const TEST_RESOURCE_ID = 'src_123';
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/sources/' . self::TEST_RESOURCE_ID
);
$resource = Source::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Source", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/sources'
);
$resource = Source::create([
"type" => "card"
]);
$this->assertInstanceOf("Stripe\\Source", $resource);
}
public function testIsSaveable()
{
$resource = Source::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/sources/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Source", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/sources/' . self::TEST_RESOURCE_ID
);
$resource = Source::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Source", $resource);
}
public function testCanSaveCardExpiryDate()
{
$response = [
'id' => 'src_foo',
'object' => 'source',
'card' => [
'exp_month' => 8,
'exp_year' => 2019,
],
];
$source = Source::constructFrom($response);
$response['card']['exp_month'] = 12;
$response['card']['exp_year'] = 2022;
$this->stubRequest(
'POST',
'/v1/sources/src_foo',
[
'card' => [
'exp_month' => 12,
'exp_year' => 2022,
]
],
null,
false,
$response
);
$source->card->exp_month = 12;
$source->card->exp_year = 2022;
$source->save();
$this->assertSame(12, $source->card->exp_month);
$this->assertSame(2022, $source->card->exp_year);
}
public function testIsDetachableWhenAttached()
{
$resource = Source::retrieve(self::TEST_RESOURCE_ID);
$resource->customer = "cus_123";
$this->expectsRequest(
'delete',
'/v1/customers/cus_123/sources/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\Source", $resource);
}
/**
* @expectedException \Stripe\Error\Api
*/
public function testIsNotDetachableWhenUnattached()
{
$resource = Source::retrieve(self::TEST_RESOURCE_ID);
$resource->detach();
}
public function testCanListSourceTransactions()
{
$source = Source::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'get',
'/v1/sources/' . $source->id . "/source_transactions"
);
$resources = $source->sourceTransactions();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\SourceTransaction", $resources->data[0]);
}
public function testCanVerify()
{
$resource = Source::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/sources/' . $resource->id . "/verify"
);
$resource->verify(["values" => [32, 45]]);
$this->assertInstanceOf("Stripe\\Source", $resource);
}
}

View File

@ -0,0 +1,453 @@
<?php
namespace Stripe;
class StripeObjectTest extends TestCase
{
/**
* @before
*/
public function setUpReflectors()
{
// Sets up reflectors needed by some tests to access protected or
// private attributes.
// This is used to invoke the `deepCopy` protected function
$this->deepCopyReflector = new \ReflectionMethod('Stripe\\StripeObject', 'deepCopy');
$this->deepCopyReflector->setAccessible(true);
// This is used to access the `_opts` protected variable
$this->optsReflector = new \ReflectionProperty('Stripe\\StripeObject', '_opts');
$this->optsReflector->setAccessible(true);
}
public function testArrayAccessorsSemantics()
{
$s = new StripeObject();
$s['foo'] = 'a';
$this->assertSame($s['foo'], 'a');
$this->assertTrue(isset($s['foo']));
unset($s['foo']);
$this->assertFalse(isset($s['foo']));
}
public function testNormalAccessorsSemantics()
{
$s = new StripeObject();
$s->foo = 'a';
$this->assertSame($s->foo, 'a');
$this->assertTrue(isset($s->foo));
unset($s->foo);
$this->assertFalse(isset($s->foo));
}
public function testArrayAccessorsMatchNormalAccessors()
{
$s = new StripeObject();
$s->foo = 'a';
$this->assertSame($s['foo'], 'a');
$s['bar'] = 'b';
$this->assertSame($s->bar, 'b');
}
public function testCount()
{
$s = new StripeObject();
$this->assertSame(0, count($s));
$s['key1'] = 'value1';
$this->assertSame(1, count($s));
$s['key2'] = 'value2';
$this->assertSame(2, count($s));
unset($s['key1']);
$this->assertSame(1, count($s));
}
public function testKeys()
{
$s = new StripeObject();
$s->foo = 'bar';
$this->assertSame($s->keys(), ['foo']);
}
public function testValues()
{
$s = new StripeObject();
$s->foo = 'bar';
$this->assertSame($s->values(), ['bar']);
}
public function testToArray()
{
$s = new StripeObject();
$s->foo = 'a';
$converted = $s->__toArray();
$this->assertInternalType('array', $converted);
$this->assertArrayHasKey('foo', $converted);
$this->assertEquals('a', $converted['foo']);
}
public function testRecursiveToArray()
{
$s = new StripeObject();
$z = new StripeObject();
$s->child = $z;
$z->foo = 'a';
$converted = $s->__toArray(true);
$this->assertInternalType('array', $converted);
$this->assertArrayHasKey('child', $converted);
$this->assertInternalType('array', $converted['child']);
$this->assertArrayHasKey('foo', $converted['child']);
$this->assertEquals('a', $converted['child']['foo']);
}
public function testNonexistentProperty()
{
$s = new StripeObject();
$this->assertNull($s->nonexistent);
}
public function testPropertyDoesNotExists()
{
$s = new StripeObject();
$this->assertNull($s['nonexistent']);
}
public function testJsonEncode()
{
$s = new StripeObject();
$s->foo = 'a';
$this->assertEquals('{"foo":"a"}', json_encode($s));
}
public function testToString()
{
$s = new StripeObject();
$s->foo = 'a';
$string = $s->__toString();
$expected = <<<EOS
Stripe\StripeObject JSON: {
"foo": "a"
}
EOS;
$this->assertEquals($expected, $string);
}
public function testReplaceNewNestedUpdatable()
{
$s = new StripeObject();
$s->metadata = ['bar'];
$this->assertSame($s->metadata, ['bar']);
$s->metadata = ['baz', 'qux'];
$this->assertSame($s->metadata, ['baz', 'qux']);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testSetPermanentAttribute()
{
$s = new StripeObject();
$s->id = 'abc_123';
}
/**
* @expectedException \InvalidArgumentException
*/
public function testSetEmptyStringValue()
{
$s = new StripeObject();
$s->foo = '';
}
public function testSerializeParametersOnEmptyObject()
{
$obj = StripeObject::constructFrom([]);
$this->assertSame([], $obj->serializeParameters());
}
public function testSerializeParametersOnNewObjectWithSubObject()
{
$obj = new StripeObject();
$obj->metadata = ['foo' => 'bar'];
$this->assertSame(['metadata' => ['foo' => 'bar']], $obj->serializeParameters());
}
public function testSerializeParametersOnBasicObject()
{
$obj = StripeObject::constructFrom(['foo' => null]);
$obj->updateAttributes(['foo' => 'bar']);
$this->assertSame(['foo' => 'bar'], $obj->serializeParameters());
}
public function testSerializeParametersOnMoreComplexObject()
{
$obj = StripeObject::constructFrom([
'foo' => StripeObject::constructFrom([
'bar' => null,
'baz' => null,
]),
]);
$obj->foo->bar = 'newbar';
$this->assertSame(['foo' => ['bar' => 'newbar']], $obj->serializeParameters());
}
public function testSerializeParametersOnArray()
{
$obj = StripeObject::constructFrom([
'foo' => null,
]);
$obj->foo = ['new-value'];
$this->assertSame(['foo' => ['new-value']], $obj->serializeParameters());
}
public function testSerializeParametersOnArrayThatShortens()
{
$obj = StripeObject::constructFrom([
'foo' => ['0-index', '1-index', '2-index'],
]);
$obj->foo = ['new-value'];
$this->assertSame(['foo' => ['new-value']], $obj->serializeParameters());
}
public function testSerializeParametersOnArrayThatLengthens()
{
$obj = StripeObject::constructFrom([
'foo' => ['0-index', '1-index', '2-index'],
]);
$obj->foo = array_fill(0, 4, 'new-value');
$this->assertSame(['foo' => array_fill(0, 4, 'new-value')], $obj->serializeParameters());
}
public function testSerializeParametersOnArrayOfHashes()
{
$obj = StripeObject::constructFrom(['foo' => null]);
$obj->foo = [
StripeObject::constructFrom(['bar' => null]),
];
$obj->foo[0]->bar = 'baz';
$this->assertSame(['foo' => [['bar' => 'baz']]], $obj->serializeParameters());
}
public function testSerializeParametersDoesNotIncludeUnchangedValues()
{
$obj = StripeObject::constructFrom([
'foo' => null,
]);
$this->assertSame([], $obj->serializeParameters());
}
public function testSerializeParametersOnUnchangedArray()
{
$obj = StripeObject::constructFrom([
'foo' => ['0-index', '1-index', '2-index'],
]);
$obj->foo = ['0-index', '1-index', '2-index'];
$this->assertSame([], $obj->serializeParameters());
}
public function testSerializeParametersWithStripeObject()
{
$obj = StripeObject::constructFrom([]);
$obj->metadata = StripeObject::constructFrom(['foo' => 'bar']);
$serialized = $obj->serializeParameters();
$this->assertSame(['foo' => 'bar'], $serialized['metadata']);
}
public function testSerializeParametersOnReplacedStripeObject()
{
$obj = StripeObject::constructFrom([
'metadata' => StripeObject::constructFrom(['bar' => 'foo']),
]);
$obj->metadata = StripeObject::constructFrom(['baz' => 'foo']);
$serialized = $obj->serializeParameters();
$this->assertSame(['bar' => '', 'baz' => 'foo'], $serialized['metadata']);
}
public function testSerializeParametersOnArrayOfStripeObjects()
{
$obj = StripeObject::constructFrom([]);
$obj->metadata = [
StripeObject::constructFrom(['foo' => 'bar']),
];
$serialized = $obj->serializeParameters();
$this->assertSame([['foo' => 'bar']], $serialized['metadata']);
}
public function testSerializeParametersOnSetApiResource()
{
$customer = Customer::constructFrom(['id' => 'cus_123']);
$obj = StripeObject::constructFrom([]);
// the key here is that the property is set explicitly (and therefore
// marked as unsaved), which is why it gets included below
$obj->customer = $customer;
$serialized = $obj->serializeParameters();
$this->assertSame(['customer' => $customer], $serialized);
}
public function testSerializeParametersOnNotSetApiResource()
{
$customer = Customer::constructFrom(['id' => 'cus_123']);
$obj = StripeObject::constructFrom(['customer' => $customer]);
$serialized = $obj->serializeParameters();
$this->assertSame([], $serialized);
}
public function testSerializeParametersOnApiResourceFlaggedWithSaveWithParent()
{
$customer = Customer::constructFrom(['id' => 'cus_123']);
$customer->saveWithParent = true;
$obj = StripeObject::constructFrom(['customer' => $customer]);
$serialized = $obj->serializeParameters();
$this->assertSame(['customer' => []], $serialized);
}
public function testSerializeParametersRaisesExceotionOnOtherEmbeddedApiResources()
{
// This customer doesn't have an ID and therefore the library doesn't know
// what to do with it and throws an InvalidArgumentException because it's
// probably not what the user expected to happen.
$customer = Customer::constructFrom([]);
$obj = StripeObject::constructFrom([]);
$obj->customer = $customer;
try {
$serialized = $obj->serializeParameters();
$this->fail("Did not raise error");
} catch (\InvalidArgumentException $e) {
$this->assertSame(
"Cannot save property `customer` containing an API resource of type Stripe\Customer. " .
"It doesn't appear to be persisted and is not marked as `saveWithParent`.",
$e->getMessage()
);
} catch (\Exception $e) {
$this->fail("Unexpected exception: " . get_class($e));
}
}
public function testSerializeParametersForce()
{
$obj = StripeObject::constructFrom([
'id' => 'id',
'metadata' => StripeObject::constructFrom([
'bar' => 'foo',
]),
]);
$serialized = $obj->serializeParameters(true);
$this->assertSame(['id' => 'id', 'metadata' => ['bar' => 'foo']], $serialized);
}
public function testDirty()
{
$obj = StripeObject::constructFrom([
'id' => 'id',
'metadata' => StripeObject::constructFrom([
'bar' => 'foo',
]),
]);
// note that `$force` and `dirty()` are for different things, but are
// functionally equivalent
$obj->dirty();
$serialized = $obj->serializeParameters();
$this->assertSame(['id' => 'id', 'metadata' => ['bar' => 'foo']], $serialized);
}
public function testDeepCopy()
{
$opts = [
"api_base" => Stripe::$apiBase,
"api_key" => "apikey",
];
$values = [
"id" => 1,
"name" => "Stripe",
"arr" => [
StripeObject::constructFrom(["id" => "index0"], $opts),
"index1",
2,
],
"map" => [
"0" => StripeObject::constructFrom(["id" => "index0"], $opts),
"1" => "index1",
"2" => 2
],
];
$copyValues = $this->deepCopyReflector->invoke(null, $values);
// we can't compare the hashes directly because they have embedded
// objects which are different from each other
$this->assertEquals($values["id"], $copyValues["id"]);
$this->assertEquals($values["name"], $copyValues["name"]);
$this->assertEquals(count($values["arr"]), count($copyValues["arr"]));
// internal values of the copied StripeObject should be the same,
// but the object itself should be new (hence the assertNotSame)
$this->assertEquals($values["arr"][0]["id"], $copyValues["arr"][0]["id"]);
$this->assertNotSame($values["arr"][0], $copyValues["arr"][0]);
// likewise, the Util\RequestOptions instance in _opts should have
// copied values but be a new instance
$this->assertEquals(
$this->optsReflector->getValue($values["arr"][0]),
$this->optsReflector->getValue($copyValues["arr"][0])
);
$this->assertNotSame(
$this->optsReflector->getValue($values["arr"][0]),
$this->optsReflector->getValue($copyValues["arr"][0])
);
// scalars however, can be compared
$this->assertEquals($values["arr"][1], $copyValues["arr"][1]);
$this->assertEquals($values["arr"][2], $copyValues["arr"][2]);
// and a similar story with the hash
$this->assertEquals($values["map"]["0"]["id"], $copyValues["map"]["0"]["id"]);
$this->assertNotSame($values["map"]["0"], $copyValues["map"]["0"]);
$this->assertNotSame(
$this->optsReflector->getValue($values["arr"][0]),
$this->optsReflector->getValue($copyValues["arr"][0])
);
$this->assertEquals(
$this->optsReflector->getValue($values["map"]["0"]),
$this->optsReflector->getValue($copyValues["map"]["0"])
);
$this->assertNotSame(
$this->optsReflector->getValue($values["map"]["0"]),
$this->optsReflector->getValue($copyValues["map"]["0"])
);
$this->assertEquals($values["map"]["1"], $copyValues["map"]["1"]);
$this->assertEquals($values["map"]["2"], $copyValues["map"]["2"]);
}
public function testDeepCopyMaintainClass()
{
$charge = Charge::constructFrom(["id" => 1], null);
$copyCharge = $this->deepCopyReflector->invoke(null, $charge);
$this->assertEquals(get_class($charge), get_class($copyCharge));
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace Stripe;
class StripeTest extends TestCase
{
/**
* @before
*/
public function saveOriginalValues()
{
$this->orig = [
'caBundlePath' => Stripe::$caBundlePath,
];
}
/**
* @after
*/
public function restoreOriginalValues()
{
Stripe::$caBundlePath = $this->orig['caBundlePath'];
}
public function testCABundlePathAccessors()
{
Stripe::setCABundlePath('path/to/ca/bundle');
$this->assertEquals('path/to/ca/bundle', Stripe::getCABundlePath());
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace Stripe;
class SubscriptionItemTest extends TestCase
{
const TEST_RESOURCE_ID = 'si_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/subscription_items'
);
$resources = SubscriptionItem::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\SubscriptionItem", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/subscription_items/' . self::TEST_RESOURCE_ID
);
$resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\SubscriptionItem", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/subscription_items'
);
$resource = SubscriptionItem::create([
"plan" => "plan",
"subscription" => "sub_123"
]);
$this->assertInstanceOf("Stripe\\SubscriptionItem", $resource);
}
public function testIsSaveable()
{
$resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/subscription_items/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\SubscriptionItem", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/subscription_items/' . self::TEST_RESOURCE_ID
);
$resource = SubscriptionItem::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\SubscriptionItem", $resource);
}
public function testIsDeletable()
{
$resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/subscription_items/' . $resource->id
);
$resource->delete();
$this->assertInstanceOf("Stripe\\SubscriptionItem", $resource);
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace Stripe;
class SubscriptionTest extends TestCase
{
const TEST_RESOURCE_ID = 'sub_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/subscriptions'
);
$resources = Subscription::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Subscription", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/subscriptions/' . self::TEST_RESOURCE_ID
);
$resource = Subscription::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Subscription", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/subscriptions'
);
$resource = Subscription::create([
"customer" => "cus_123",
"plan" => "plan"
]);
$this->assertInstanceOf("Stripe\\Subscription", $resource);
}
public function testIsSaveable()
{
$resource = Subscription::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/subscriptions/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Subscription", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/subscriptions/' . self::TEST_RESOURCE_ID
);
$resource = Subscription::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Subscription", $resource);
}
public function testIsCancelable()
{
$resource = Subscription::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/subscriptions/' . $resource->id,
[
'at_period_end' => 'true',
]
);
$resource->cancel([
'at_period_end' => true,
]);
$this->assertInstanceOf("Stripe\\Subscription", $resource);
}
public function testCanDeleteDiscount()
{
$resource = Subscription::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'delete',
'/v1/subscriptions/' . $resource->id . '/discount'
);
$resource->deleteDiscount();
$this->assertInstanceOf("Stripe\\Subscription", $resource);
}
public function testSerializeParametersItems()
{
$obj = Util\Util::convertToStripeObject([
'object' => 'subscription',
'items' => Util\Util::convertToStripeObject([
'object' => 'list',
'data' => [],
], null),
], null);
$obj->items = [
['id' => 'si_foo', 'deleted' => true],
['plan' => 'plan_bar'],
];
$expected = [
'items' => [
0 => ['id' => 'si_foo', 'deleted' => true],
1 => ['plan' => 'plan_bar'],
],
];
$this->assertSame($expected, $obj->serializeParameters());
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Stripe;
class ThreeDSecureTest extends TestCase
{
const TEST_RESOURCE_ID = 'tdsrc_123';
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/3d_secure/' . self::TEST_RESOURCE_ID
);
$resource = ThreeDSecure::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\ThreeDSecure", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/3d_secure'
);
$resource = ThreeDSecure::create([
"amount" => 100,
"currency" => "usd",
"return_url" => "url"
]);
$this->assertInstanceOf("Stripe\\ThreeDSecure", $resource);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Stripe;
class TokenTest extends TestCase
{
const TEST_RESOURCE_ID = 'tok_123';
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/tokens/' . self::TEST_RESOURCE_ID
);
$resource = Token::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Token", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/tokens'
);
$resource = Token::create(["card" => "tok_visa"]);
$this->assertInstanceOf("Stripe\\Token", $resource);
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Stripe;
class TopupTest extends TestCase
{
const TEST_RESOURCE_ID = 'tu_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/topups'
);
$resources = Topup::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Topup", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/topups/' . self::TEST_RESOURCE_ID
);
$resource = Topup::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Topup", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/topups'
);
$resource = Topup::create([
"amount" => 100,
"currency" => "usd",
"source" => "tok_123",
"description" => "description",
"statement_descriptor" => "statement descriptor"
]);
$this->assertInstanceOf("Stripe\\Topup", $resource);
}
public function testIsSaveable()
{
$resource = Topup::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/topups/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Topup", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/topups/' . self::TEST_RESOURCE_ID
);
$resource = Topup::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Topup", $resource);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Stripe;
class TransferReversalTest extends TestCase
{
const TEST_RESOURCE_ID = 'trr_123';
const TEST_TRANSFER_ID = 'tr_123';
public function testIsSaveable()
{
$resource = Transfer::retrieveReversal(self::TEST_TRANSFER_ID, self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/transfers/' . $resource->transfer . '/reversals/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\TransferReversal", $resource);
}
}

View File

@ -0,0 +1,140 @@
<?php
namespace Stripe;
class TransferTest extends TestCase
{
const TEST_RESOURCE_ID = 'tr_123';
const TEST_REVERSAL_ID = 'trr_123';
public function testIsListable()
{
$this->expectsRequest(
'get',
'/v1/transfers'
);
$resources = Transfer::all();
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\Transfer", $resources->data[0]);
}
public function testIsRetrievable()
{
$this->expectsRequest(
'get',
'/v1/transfers/' . self::TEST_RESOURCE_ID
);
$resource = Transfer::retrieve(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\Transfer", $resource);
}
public function testIsCreatable()
{
$this->expectsRequest(
'post',
'/v1/transfers'
);
$resource = Transfer::create([
"amount" => 100,
"currency" => "usd",
"destination" => "acct_123"
]);
$this->assertInstanceOf("Stripe\\Transfer", $resource);
}
public function testIsSaveable()
{
$resource = Transfer::retrieve(self::TEST_RESOURCE_ID);
$resource->metadata["key"] = "value";
$this->expectsRequest(
'post',
'/v1/transfers/' . $resource->id
);
$resource->save();
$this->assertInstanceOf("Stripe\\Transfer", $resource);
}
public function testIsUpdatable()
{
$this->expectsRequest(
'post',
'/v1/transfers/' . self::TEST_RESOURCE_ID
);
$resource = Transfer::update(self::TEST_RESOURCE_ID, [
"metadata" => ["key" => "value"],
]);
$this->assertInstanceOf("Stripe\\Transfer", $resource);
}
public function testIsReversable()
{
$resource = Transfer::retrieve(self::TEST_RESOURCE_ID);
$this->expectsRequest(
'post',
'/v1/transfers/' . $resource->id . '/reversals'
);
$resource->reverse();
$this->assertInstanceOf("Stripe\\Transfer", $resource);
}
public function testIsCancelable()
{
$transfer = Transfer::retrieve(self::TEST_RESOURCE_ID);
// stripe-mock does not support this anymore so we stub it
$this->stubRequest(
'post',
'/v1/transfers/' . $transfer->id . '/cancel'
);
$resource = $transfer->cancel();
$this->assertInstanceOf("Stripe\\Transfer", $resource);
$this->assertSame($resource, $transfer);
}
public function testCanCreateReversal()
{
$this->expectsRequest(
'post',
'/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals'
);
$resource = Transfer::createReversal(self::TEST_RESOURCE_ID);
$this->assertInstanceOf("Stripe\\TransferReversal", $resource);
}
public function testCanRetrieveReversal()
{
$this->expectsRequest(
'get',
'/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals/' . self::TEST_REVERSAL_ID
);
$resource = Transfer::retrieveReversal(self::TEST_RESOURCE_ID, self::TEST_REVERSAL_ID);
$this->assertInstanceOf("Stripe\\TransferReversal", $resource);
}
public function testCanUpdateReversal()
{
$this->expectsRequest(
'post',
'/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals/' . self::TEST_REVERSAL_ID
);
$resource = Transfer::updateReversal(
self::TEST_RESOURCE_ID,
self::TEST_REVERSAL_ID,
[
"metadata" => ["key" => "value"],
]
);
$this->assertInstanceOf("Stripe\\TransferReversal", $resource);
}
public function testCanListReversal()
{
$this->expectsRequest(
'get',
'/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals'
);
$resources = Transfer::allReversals(self::TEST_RESOURCE_ID);
$this->assertTrue(is_array($resources->data));
$this->assertInstanceOf("Stripe\\TransferReversal", $resources->data[0]);
}
}

View File

@ -0,0 +1,28 @@
<?php
// Test in a slightly different namespace than usual. See comment on
// `error_log` below.
namespace Stripe\Util;
class UtilLoggerTest extends \Stripe\TestCase
{
public function testDefaultLogger()
{
$logger = new DefaultLogger();
$logger->error("message");
global $lastMessage;
$this->assertSame($lastMessage, "message");
}
}
// This is a little terrible, but unfortunately there's no clean way to stub a
// call to `error_log`. Here we overwrite it so that we can get the last arguments
// that went to it. This is obviously bad, but luckily it's constrained to
// being just in \Stripe\Util (i.e. won't interfere with PHPUnit for example)
// and _just_ present when tests are running.
function error_log($message)
{
global $lastMessage;
$lastMessage = $message;
}

View File

@ -0,0 +1,81 @@
<?php
namespace Stripe;
class RequestOptionsTest extends TestCase
{
public function testStringAPIKey()
{
$opts = Util\RequestOptions::parse("foo");
$this->assertSame("foo", $opts->apiKey);
$this->assertSame([], $opts->headers);
}
public function testNull()
{
$opts = Util\RequestOptions::parse(null);
$this->assertSame(null, $opts->apiKey);
$this->assertSame([], $opts->headers);
}
public function testEmptyArray()
{
$opts = Util\RequestOptions::parse([]);
$this->assertSame(null, $opts->apiKey);
$this->assertSame([], $opts->headers);
}
public function testAPIKeyArray()
{
$opts = Util\RequestOptions::parse(
[
'api_key' => 'foo',
]
);
$this->assertSame('foo', $opts->apiKey);
$this->assertSame([], $opts->headers);
}
public function testIdempotentKeyArray()
{
$opts = Util\RequestOptions::parse(
[
'idempotency_key' => 'foo',
]
);
$this->assertSame(null, $opts->apiKey);
$this->assertSame(['Idempotency-Key' => 'foo'], $opts->headers);
}
public function testKeyArray()
{
$opts = Util\RequestOptions::parse(
[
'idempotency_key' => 'foo',
'api_key' => 'foo'
]
);
$this->assertSame('foo', $opts->apiKey);
$this->assertSame(['Idempotency-Key' => 'foo'], $opts->headers);
}
/**
* @expectedException Stripe\Error\Api
*/
public function testWrongType()
{
$opts = Util\RequestOptions::parse(5);
}
public function testDiscardNonPersistentHeaders()
{
$opts = Util\RequestOptions::parse(
[
'stripe_account' => 'foo',
'idempotency_key' => 'foo',
]
);
$opts->discardNonPersistentHeaders();
$this->assertSame(['Stripe-Account' => 'foo'], $opts->headers);
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace Stripe;
class UtilTest extends TestCase
{
public function testIsList()
{
$list = [5, 'nstaoush', []];
$this->assertTrue(Util\Util::isList($list));
$notlist = [5, 'nstaoush', [], 'bar' => 'baz'];
$this->assertFalse(Util\Util::isList($notlist));
}
public function testThatPHPHasValueSemanticsForArrays()
{
$original = ['php-arrays' => 'value-semantics'];
$derived = $original;
$derived['php-arrays'] = 'reference-semantics';
$this->assertSame('value-semantics', $original['php-arrays']);
}
public function testConvertStripeObjectToArrayIncludesId()
{
$customer = Util\Util::convertToStripeObject([
'id' => 'cus_123',
'object' => 'customer',
], null);
$this->assertTrue(array_key_exists("id", $customer->__toArray(true)));
}
public function testUtf8()
{
// UTF-8 string
$x = "\xc3\xa9";
$this->assertSame(Util\Util::utf8($x), $x);
// Latin-1 string
$x = "\xe9";
$this->assertSame(Util\Util::utf8($x), "\xc3\xa9");
// Not a string
$x = true;
$this->assertSame(Util\Util::utf8($x), $x);
}
public function testUrlEncode()
{
$a = [
'my' => 'value',
'that' => ['your' => 'example'],
'bar' => 1,
'baz' => null
];
$enc = Util\Util::urlEncode($a);
$this->assertSame('my=value&that%5Byour%5D=example&bar=1', $enc);
$a = ['that' => ['your' => 'example', 'foo' => null]];
$enc = Util\Util::urlEncode($a);
$this->assertSame('that%5Byour%5D=example', $enc);
$a = ['that' => 'example', 'foo' => ['bar', 'baz']];
$enc = Util\Util::urlEncode($a);
$this->assertSame('that=example&foo%5B%5D=bar&foo%5B%5D=baz', $enc);
$a = [
'my' => 'value',
'that' => ['your' => ['cheese', 'whiz', null]],
'bar' => 1,
'baz' => null
];
$enc = Util\Util::urlEncode($a);
$expected = 'my=value&that%5Byour%5D%5B%5D=cheese'
. '&that%5Byour%5D%5B%5D=whiz&bar=1';
$this->assertSame($expected, $enc);
// Ignores an empty array
$enc = Util\Util::urlEncode(['foo' => [], 'bar' => 'baz']);
$expected = 'bar=baz';
$this->assertSame($expected, $enc);
$a = ['foo' => [['bar' => 'baz'], ['bar' => 'bin']]];
$enc = Util\Util::urlEncode($a);
$this->assertSame('foo%5B0%5D%5Bbar%5D=baz&foo%5B1%5D%5Bbar%5D=bin', $enc);
}
}

View File

@ -0,0 +1,110 @@
<?php
namespace Stripe;
class WebhookTest extends TestCase
{
const EVENT_PAYLOAD = "{
\"id\": \"evt_test_webhook\",
\"object\": \"event\"
}";
const SECRET = "whsec_test_secret";
private function generateHeader($opts = [])
{
$timestamp = array_key_exists('timestamp', $opts) ? $opts['timestamp'] : time();
$payload = array_key_exists('payload', $opts) ? $opts['payload'] : self::EVENT_PAYLOAD;
$secret = array_key_exists('secret', $opts) ? $opts['secret'] : self::SECRET;
$scheme = array_key_exists('scheme', $opts) ? $opts['scheme'] : WebhookSignature::EXPECTED_SCHEME;
$signature = array_key_exists('signature', $opts) ? $opts['signature'] : null;
if ($signature === null) {
$signedPayload = "$timestamp.$payload";
$signature = hash_hmac("sha256", $signedPayload, $secret);
}
return "t=$timestamp,$scheme=$signature";
}
public function testValidJsonAndHeader()
{
$sigHeader = $this->generateHeader();
$event = Webhook::constructEvent(self::EVENT_PAYLOAD, $sigHeader, self::SECRET);
$this->assertEquals("evt_test_webhook", $event->id);
}
/**
* @expectedException \UnexpectedValueException
*/
public function testInvalidJson()
{
$payload = "this is not valid JSON";
$sigHeader = $this->generateHeader(["payload" => $payload]);
Webhook::constructEvent($payload, $sigHeader, self::SECRET);
}
/**
* @expectedException \Stripe\Error\SignatureVerification
*/
public function testValidJsonAndInvalidHeader()
{
$sigHeader = "bad_header";
Webhook::constructEvent(self::EVENT_PAYLOAD, $sigHeader, self::SECRET);
}
/**
* @expectedException \Stripe\Error\SignatureVerification
* @expectedExceptionMessage Unable to extract timestamp and signatures from header
*/
public function testMalformedHeader()
{
$sigHeader = "i'm not even a real signature header";
WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET);
}
/**
* @expectedException \Stripe\Error\SignatureVerification
* @expectedExceptionMessage No signatures found with expected scheme
*/
public function testNoSignaturesWithExpectedScheme()
{
$sigHeader = $this->generateHeader(["scheme" => "v0"]);
WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET);
}
/**
* @expectedException \Stripe\Error\SignatureVerification
* @expectedExceptionMessage No signatures found matching the expected signature for payload
*/
public function testNoValidSignatureForPayload()
{
$sigHeader = $this->generateHeader(["signature" => "bad_signature"]);
WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET);
}
/**
* @expectedException \Stripe\Error\SignatureVerification
* @expectedExceptionMessage Timestamp outside the tolerance zone
*/
public function testTimestampOutsideTolerance()
{
$sigHeader = $this->generateHeader(["timestamp" => time() - 15]);
WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10);
}
public function testValidHeaderAndSignature()
{
$sigHeader = $this->generateHeader();
$this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10));
}
public function testHeaderContainsValidSignature()
{
$sigHeader = $this->generateHeader() . ",v1=bad_signature";
$this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10));
}
public function testTimestampOffButNoTolerance()
{
$sigHeader = $this->generateHeader(["timestamp" => 12345]);
$this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B