Skip to content

Commit

Permalink
Merge pull request #705 from stripe/ob-error-object
Browse files Browse the repository at this point in the history
Add ErrorObject to Stripe exceptions
  • Loading branch information
ob-stripe authored Aug 22, 2019
2 parents 49ca276 + 8a1bb96 commit c757fa5
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 5 deletions.
2 changes: 2 additions & 0 deletions init.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
require(dirname(__FILE__) . '/lib/Discount.php');
require(dirname(__FILE__) . '/lib/Dispute.php');
require(dirname(__FILE__) . '/lib/EphemeralKey.php');
require(dirname(__FILE__) . '/lib/ErrorObject.php');
require(dirname(__FILE__) . '/lib/Event.php');
require(dirname(__FILE__) . '/lib/ExchangeRate.php');
require(dirname(__FILE__) . '/lib/File.php');
Expand Down Expand Up @@ -134,6 +135,7 @@

// OAuth
require(dirname(__FILE__) . '/lib/OAuth.php');
require(dirname(__FILE__) . '/lib/OAuthErrorObject.php');

// Webhooks
require(dirname(__FILE__) . '/lib/Webhook.php');
Expand Down
17 changes: 17 additions & 0 deletions lib/Error/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
abstract class Base extends Exception
{
protected $error;
protected $httpBody;
protected $httpHeaders;
protected $httpStatus;
Expand All @@ -37,6 +38,13 @@ public function __construct(
if ($httpHeaders && isset($httpHeaders['Request-Id'])) {
$this->requestId = $httpHeaders['Request-Id'];
}

$this->error = $this->constructErrorObject();
}

public function getError()
{
return $this->error;
}

public function getHttpBody()
Expand Down Expand Up @@ -75,4 +83,13 @@ public function __toString()
$idStr = ($this->getRequestId() == null) ? "" : "(Request {$this->getRequestId()}) ";
return "{$statusStr}{$idStr}{$this->getMessage()}";
}

protected function constructErrorObject()
{
if (is_null($this->jsonBody) || !array_key_exists('error', $this->jsonBody)) {
return null;
}

return \Stripe\ErrorObject::constructFrom($this->jsonBody['error']);
}
}
9 changes: 9 additions & 0 deletions lib/Error/OAuth/OAuthBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,13 @@ public function getErrorCode()
{
return $this->errorCode;
}

protected function constructErrorObject()
{
if (is_null($this->jsonBody)) {
return null;
}

return \Stripe\ErrorObject::constructFrom($this->jsonBody);
}
}
66 changes: 66 additions & 0 deletions lib/ErrorObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Stripe;

/**
* Class ErrorObject
*
* @property string $charge For card errors, the ID of the failed charge.
* @property string $code For some errors that could be handled
* programmatically, a short string indicating the error code reported.
* @property string $decline_code For card errors resulting from a card issuer
* decline, a short string indicating the card issuer's reason for the
* decline if they provide one.
* @property string $doc_url A URL to more information about the error code
* reported.
* @property string $message A human-readable message providing more details
* about the error. For card errors, these messages can be shown to your
* users.
* @property string $param If the error is parameter-specific, the parameter
* related to the error. For example, you can use this to display a message
* near the correct form field.
* @property PaymentIntent $payment_intent The PaymentIntent object for errors
* returned on a request involving a PaymentIntent.
* @property PaymentMethod $payment_method The PaymentMethod object for errors
* returned on a request involving a PaymentMethod.
* @property SetupIntent $setup_intent The SetupIntent object for errors
* returned on a request involving a SetupIntent.
* @property StripeObject $source The source object for errors returned on a
* request involving a source.
* @property string $type The type of error returned. One of
* `api_connection_error`, `api_error`, `authentication_error`,
* `card_error`, `idempotency_error`, `invalid_request_error`, or
* `rate_limit_error`.
*
* @package Stripe
*/
class ErrorObject extends StripeObject
{
/**
* Refreshes this object using the provided values.
*
* @param array $values
* @param null|string|array|Util\RequestOptions $opts
* @param boolean $partial Defaults to false.
*/
public function refreshFrom($values, $opts, $partial = false)
{
// Unlike most other API resources, the API will omit attributes in
// error objects when they have a null value. We manually set default
// values here to facilitate generic error handling.
$values = array_merge([
'charge' => null,
'code' => null,
'decline_code' => null,
'doc_url' => null,
'message' => null,
'param' => null,
'payment_intent' => null,
'payment_method' => null,
'setup_intent' => null,
'source' => null,
'type' => null,
], $values);
parent::refreshFrom($values, $opts, $partial);
}
}
33 changes: 33 additions & 0 deletions lib/OAuthErrorObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Stripe;

/**
* Class OAuthErrorObject
*
* @property string $error
* @property string $error_description
*
* @package Stripe
*/
class OAuthErrorObject extends StripeObject
{
/**
* Refreshes this object using the provided values.
*
* @param array $values
* @param null|string|array|Util\RequestOptions $opts
* @param boolean $partial Defaults to false.
*/
public function refreshFrom($values, $opts, $partial = false)
{
// Unlike most other API resources, the API will omit attributes in
// error objects when they have a null value. We manually set default
// values here to facilitate generic error handling.
$values = array_merge([
'error' => null,
'error_description' => null,
], $values);
parent::refreshFrom($values, $opts, $partial);
}
}
12 changes: 7 additions & 5 deletions tests/Stripe/Error/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

class BaseTest extends TestCase
{
public function createFixture($params = [])
public function createFixture()
{
return $this->getMockForAbstractClass(\Stripe\Error\Base::class, [
'message',
200,
'{"key": "value"}',
['key' => 'value'],
'{"error": {"code": "some_code"}}',
['error' => ['code' => 'some_code']],
[
'Some-Header' => 'Some Value',
'Request-Id' => 'req_test',
Expand All @@ -22,10 +22,12 @@ 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('{"error": {"code": "some_code"}}', $e->getHttpBody());
$this->assertSame(['error' => ['code' => 'some_code']], $e->getJsonBody());
$this->assertSame('Some Value', $e->getHttpHeaders()['Some-Header']);
$this->assertSame('req_test', $e->getRequestId());
$this->assertNotNull($e->getError());
$this->assertSame('some_code', $e->getError()->code);
}

public function testToString()
Expand Down
40 changes: 40 additions & 0 deletions tests/Stripe/Error/OAuth/OAuthBaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Stripe;

class OAuthBaseTest extends TestCase
{
public function createFixture()
{
return $this->getMockForAbstractClass(\Stripe\Error\OAuth\OAuthBase::class, [
'code',
'description',
200,
'{"error": "code", "error_description": "description"}',
['error' => 'code', 'error_description' => 'description'],
[
'Some-Header' => 'Some Value',
'Request-Id' => 'req_test',
],
]);
}

public function testGetters()
{
$e = $this->createFixture();
$this->assertSame(200, $e->getHttpStatus());
$this->assertSame('{"error": "code", "error_description": "description"}', $e->getHttpBody());
$this->assertSame(['error' => 'code', 'error_description' => 'description'], $e->getJsonBody());
$this->assertSame('Some Value', $e->getHttpHeaders()['Some-Header']);
$this->assertSame('req_test', $e->getRequestId());
$this->assertNotNull($e->getError());
$this->assertSame('code', $e->getError()->error);
$this->assertSame('description', $e->getError()->error_description);
}

public function testToString()
{
$e = $this->createFixture();
$this->assertContains("(Request req_test)", (string)$e);
}
}
23 changes: 23 additions & 0 deletions tests/Stripe/ErrorObjectTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Stripe;

class ErrorObjectTest extends TestCase
{
public function testDefaultValues()
{
$error = ErrorObject::constructFrom([]);

$this->assertNull($error->charge);
$this->assertNull($error->code);
$this->assertNull($error->decline_code);
$this->assertNull($error->doc_url);
$this->assertNull($error->message);
$this->assertNull($error->param);
$this->assertNull($error->payment_intent);
$this->assertNull($error->payment_method);
$this->assertNull($error->setup_intent);
$this->assertNull($error->source);
$this->assertNull($error->type);
}
}
14 changes: 14 additions & 0 deletions tests/Stripe/OAuthErrorObjectTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Stripe;

class OAuthErrorObjectTest extends TestCase
{
public function testDefaultValues()
{
$error = OAuthErrorObject::constructFrom([]);

$this->assertNull($error->error);
$this->assertNull($error->error_description);
}
}

0 comments on commit c757fa5

Please sign in to comment.