Skip to content

Commit

Permalink
3.24.0
Browse files Browse the repository at this point in the history
  • Loading branch information
braintreeps committed Aug 10, 2017
1 parent 529c7f4 commit c0e8561
Show file tree
Hide file tree
Showing 23 changed files with 492 additions and 80 deletions.
6 changes: 6 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,6 @@
# Summary

# Checklist

- [ ] Added changelog entry
- [ ] Ran unit tests (Check the README for instructions)
13 changes: 13 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,16 @@
## 3.24.0
* Add AuthorizationAdjustment class and `authorizationAdjustments` to Transaction
* Add iDEAL webhook support
* Add `IDEAL_PAYMENT` to `PaymentInstrumentType`
* Create Braintree class to be PSR compliant
* Coinbase is no longer a supported payment method. `PAYMENT_METHOD_NO_LONGER_SUPPORTED` will be returned for Coinbase operations.
* Add `ApplePay` for web domain registration.
* Add facilitated details to Transaction if present
* Update link to transaction api documentation (thanks @qoheleth-tech!).
* Fix TransactionGateway return types (thanks @jjok!).
* Update return type for client token (thanks @jlaswell!).


## 3.23.1
* Fix token generator return type - thanks @jjok!
* Improve error reporting for connection issues - thanks @montymxb!
Expand Down
14 changes: 8 additions & 6 deletions lib/Braintree.php
Expand Up @@ -10,14 +10,16 @@
throw new Braintree_Exception('PHP version >= 5.4.0 required');
}

class Braintree {

function requireDependencies() {
$requiredExtensions = ['xmlwriter', 'openssl', 'dom', 'hash', 'curl'];
foreach ($requiredExtensions AS $ext) {
if (!extension_loaded($ext)) {
throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.');
public static function requireDependencies() {
$requiredExtensions = ['xmlwriter', 'openssl', 'dom', 'hash', 'curl'];
foreach ($requiredExtensions AS $ext) {
if (!extension_loaded($ext)) {
throw new Braintree_Exception('The Braintree library requires the ' . $ext . ' extension.');
}
}
}
}

requireDependencies();
Braintree::requireDependencies();
1 change: 0 additions & 1 deletion lib/Braintree/AccountUpdaterDailyReport.php
Expand Up @@ -9,7 +9,6 @@
*
* @property-read string $reportUrl
* @property-read date $reportDate
* @property-read date $receivedDate
*/
class AccountUpdaterDailyReport extends Base
{
Expand Down
65 changes: 65 additions & 0 deletions lib/Braintree/ApplePayGateway.php
@@ -0,0 +1,65 @@
<?php
namespace Braintree;

/**
* Braintree ApplePayGateway module
* Manages Apple Pay for Web
*
* @package Braintree
* @category Resources
*/
class ApplePayGateway
{
private $_gateway;
private $_config;
private $_http;

public function __construct($gateway)
{
$this->_gateway = $gateway;
$this->_config = $gateway->config;
$this->_config->assertHasAccessTokenOrKeys();
$this->_http = new Http($gateway->config);
}

public function registerDomain($domain)
{
$path = $this->_config->merchantPath() . '/processing/apple_pay/validate_domains';
$response = $this->_http->post($path, ['url' => $domain]);
if (array_key_exists('response', $response) && $response['response']['success'])
{
return new Result\Successful;
}
else if (array_key_exists('apiErrorResponse', $response))
{
return new Result\Error($response['apiErrorResponse']);
}
}

public function unregisterDomain($domain)
{
$path = $this->_config->merchantPath() . '/processing/apple_pay/unregister_domain';
$this->_http->delete($path, ['url' => $domain]);
return new Result\Successful;
}

public function registeredDomains()
{
$path = $this->_config->merchantPath() . '/processing/apple_pay/registered_domains';
$response = $this->_http->get($path);
if (array_key_exists('response', $response) && array_key_exists('domains', $response['response']))
{
$options = ApplePayOptions::factory($response['response']);
return new Result\Successful($options, 'applePayOptions');
}
else if (array_key_exists('apiErrorResponse', $response))
{
return new Result\Error($response['apiErrorResponse']);
}
else
{
throw new Exception\Unexpected('expected response or apiErrorResponse');
}
}
}
class_alias('Braintree\ApplePayGateway', 'Braintree_ApplePayGateway');
28 changes: 28 additions & 0 deletions lib/Braintree/ApplePayOptions.php
@@ -0,0 +1,28 @@
<?php
namespace Braintree;

/**
* Braintree ApplePayOptions module
* Manages configuration and options for Apple Pay
*
* @package Braintree
* @category Resources
*
* @property-read array $domains
*/

class ApplePayOptions extends Base
{
public static function factory($attributes)
{
$instance = new self();
$instance->_initialize($attributes);
return $instance;
}

protected function _initialize($attributes)
{
$this->_attributes = $attributes;
}
}
class_alias('Braintree\ApplePayOptions', 'Braintree_ApplePayOptions');
35 changes: 35 additions & 0 deletions lib/Braintree/AuthorizationAdjustment.php
@@ -0,0 +1,35 @@
<?php
namespace Braintree;

/**
* Creates an instance of AuthorizationAdjustment as returned from a transaction
*
* @package Braintree
*
* @property-read string $amount
* @property-read DateTime $timestamp
* @property-read boolean $success
*
*/

class AuthorizationAdjustment extends Base
{
public static function factory($attributes)
{
$instance = new self();
$instance->_initialize($attributes);

return $instance;
}

protected function _initialize($authorizationAdjustmentAttribs)
{
$this->_attributes = $authorizationAdjustmentAttribs;
}

public function __toString()
{
return __CLASS__ . '[' . Util::attributesToString($this->_attributes) . ']';
}
}
class_alias('Braintree\AuthorizationAdjustment', 'Braintree_Authorization_Adjustment');
2 changes: 2 additions & 0 deletions lib/Braintree/Error/Codes.php
Expand Up @@ -309,6 +309,7 @@ class Codes
const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_UNKNOWN = '93108';
const PAYMENT_METHOD_PAYMENT_METHOD_NONCE_LOCKED = '93109';
const PAYMENT_METHOD_PAYMENT_METHOD_PARAMS_ARE_REQUIRED = '93101';
const PAYMENT_METHOD_NO_LONGER_SUPPORTED = '93117';

const PAYPAL_ACCOUNT_AUTH_EXPIRED = '92911';
const PAYPAL_ACCOUNT_CANNOT_HAVE_BOTH_ACCESS_TOKEN_AND_CONSENT_CODE = '82903';
Expand Down Expand Up @@ -449,6 +450,7 @@ class Codes
const TRANSACTION_CUSTOM_FIELD_IS_TOO_LONG = '81527';
const TRANSACTION_HAS_ALREADY_BEEN_REFUNDED = '91512';
const TRANSACTION_IDEAL_PAYMENT_NOT_COMPLETE = '815141';
const TRANSACTION_IDEAL_PAYMENTS_CANNOT_BE_VAULTED = '915150';
const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_MATCH3_D_SECURE_MERCHANT_ACCOUNT = '91584';
const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_MATCH_IDEAL_PAYMENT_MERCHANT_ACCOUNT = '915143';
const TRANSACTION_MERCHANT_ACCOUNT_DOES_NOT_SUPPORT_MOTO = '91558';
Expand Down
29 changes: 29 additions & 0 deletions lib/Braintree/FacilitatedDetails.php
@@ -0,0 +1,29 @@
<?php
namespace Braintree;

class FacilitatedDetails extends Base
{
public static function factory($attributes)
{
$instance = new self();
$instance->_initialize($attributes);
return $instance;
}

protected function _initialize($attributes)
{
$this->_attributes = $attributes;
}

/**
* returns a string representation of the facilitated details
* @return string
*/
public function __toString()
{
return __CLASS__ . '[' .
Util::attributesToString($this->_attributes) .']';
}

}
class_alias('Braintree\FacilitatedDetails', 'Braintree_FacilitatedDetails');
2 changes: 1 addition & 1 deletion lib/Braintree/FacilitatorDetails.php
Expand Up @@ -17,7 +17,7 @@ protected function _initialize($attributes)
}

/**
* returns a string representation of the three d secure info
* returns a string representation of the facilitator details
* @return string
*/
public function __toString()
Expand Down
9 changes: 9 additions & 0 deletions lib/Braintree/Gateway.php
Expand Up @@ -41,6 +41,15 @@ public function address()
return new AddressGateway($this);
}

/**
*
* @return ApplePayGateway
*/
public function applePay()
{
return new ApplePayGateway($this);
}

/**
*
* @return ClientTokenGateway
Expand Down
7 changes: 4 additions & 3 deletions lib/Braintree/Http.php
Expand Up @@ -15,10 +15,11 @@ public function __construct($config)
$this->_config = $config;
}

public function delete($path)
public function delete($path, $params = null)
{
$response = $this->_doRequest('DELETE', $path);
if ($response['status'] === 200) {
$response = $this->_doRequest('DELETE', $path, $this->_buildXml($params));
$responseCode = $response['status'];
if ($responseCode === 200 || $responseCode === 204) {
return true;
} else {
Util::throwStatusCodeException($response['status']);
Expand Down
1 change: 1 addition & 0 deletions lib/Braintree/PaymentInstrumentType.php
Expand Up @@ -13,5 +13,6 @@ class PaymentInstrumentType
const ANDROID_PAY_CARD = 'android_pay_card';
const VENMO_ACCOUNT = 'venmo_account';
const US_BANK_ACCOUNT = 'us_bank_account';
const IDEAL_PAYMENT = 'ideal_payment';
}
class_alias('Braintree\PaymentInstrumentType', 'Braintree_PaymentInstrumentType');
13 changes: 13 additions & 0 deletions lib/Braintree/Transaction.php
Expand Up @@ -170,6 +170,7 @@
* @property-read \DateTime $updatedAt transaction updated DateTime
* @property-read Braintree\Disbursement $disbursementDetails populated when transaction is disbursed
* @property-read Braintree\Dispute $disputes populated when transaction is disputed
* @property-read Braintree\AuthorizationAdjustment $authorizationAdjustments populated when a transaction has authorization adjustments created when submitted for settlement
*
*/

Expand Down Expand Up @@ -412,12 +413,24 @@ protected function _initialize($transactionAttribs)
}
$this->_set('discounts', $discountArray);

$authorizationAdjustments = [];
if (isset($transactionAttribs['authorizationAdjustments'])) {
foreach ($transactionAttribs['authorizationAdjustments'] AS $authorizationAdjustment) {
$authorizationAdjustments[] = AuthorizationAdjustment::factory($authorizationAdjustment);
}
}

$this->_set('authorizationAdjustments', $authorizationAdjustments);

if(isset($transactionAttribs['riskData'])) {
$this->_set('riskData', RiskData::factory($transactionAttribs['riskData']));
}
if(isset($transactionAttribs['threeDSecureInfo'])) {
$this->_set('threeDSecureInfo', ThreeDSecureInfo::factory($transactionAttribs['threeDSecureInfo']));
}
if(isset($transactionAttribs['facilitatedDetails'])) {
$this->_set('facilitatedDetails', FacilitatedDetails::factory($transactionAttribs['facilitatedDetails']));
}
if(isset($transactionAttribs['facilitatorDetails'])) {
$this->_set('facilitatorDetails', FacilitatorDetails::factory($transactionAttribs['facilitatorDetails']));
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Braintree/Version.php
Expand Up @@ -11,8 +11,8 @@ class Version
* class constants
*/
const MAJOR = 3;
const MINOR = 23;
const TINY = 1;
const MINOR = 24;
const TINY = 0;

/**
* @ignore
Expand Down
6 changes: 6 additions & 0 deletions lib/Braintree/WebhookNotification.php
Expand Up @@ -27,6 +27,8 @@ class WebhookNotification extends Base
const ACCOUNT_UPDATER_DAILY_REPORT = 'account_updater_daily_report';
const CONNECTED_MERCHANT_STATUS_TRANSITIONED = 'connected_merchant_status_transitioned';
const CONNECTED_MERCHANT_PAYPAL_STATUS_CHANGED = 'connected_merchant_paypal_status_changed';
const IDEAL_PAYMENT_COMPLETE = 'ideal_payment_complete';
const IDEAL_PAYMENT_FAILED = 'ideal_payment_failed';

public static function parse($signature, $payload) {
return Configuration::gateway()->webhookNotification()->parse($signature, $payload);
Expand Down Expand Up @@ -89,6 +91,10 @@ protected function _initialize($attributes)
$this->_set('accountUpdaterDailyReport', AccountUpdaterDailyReport::factory($wrapperNode['accountUpdaterDailyReport']));
}

if (isset($wrapperNode['idealPayment'])) {
$this->_set('idealPayment', IdealPayment::factory($wrapperNode['idealPayment']));
}

if (isset($wrapperNode['errors'])) {
$this->_set('errors', new Error\ValidationErrorCollection($wrapperNode['errors']));
$this->_set('message', $wrapperNode['message']);
Expand Down
40 changes: 40 additions & 0 deletions lib/Braintree/WebhookTesting.php
Expand Up @@ -71,6 +71,12 @@ private static function _sampleXml($kind, $id)
case WebhookNotification::ACCOUNT_UPDATER_DAILY_REPORT:
$subjectXml = self::_accountUpdaterDailyReportSampleXml($id);
break;
case WebhookNotification::IDEAL_PAYMENT_COMPLETE:
$subjectXml = self::_idealPaymentCompleteSampleXml($id);
break;
case WebhookNotification::IDEAL_PAYMENT_FAILED:
$subjectXml = self::_idealPaymentFailedSampleXml($id);
break;
default:
$subjectXml = self::_subscriptionSampleXml($id);
break;
Expand Down Expand Up @@ -404,6 +410,40 @@ private static function _connectedMerchantPayPalStatusChangedSampleXml($id)
";
}

private static function _idealPaymentCompleteSampleXml($id)
{
return "
<ideal-payment>
<id>{$id}</id>
<status>COMPLETE</status>
<issuer>ABCISSUER</issuer>
<order-id>ORDERABC</order-id>
<currency>EUR</currency>
<amount>10.00</amount>
<created-at>2016-11-29T23:27:34.547Z</created-at>
<approval-url>https://example.com</approval-url>
<ideal-transaction-id>1234567890</ideal-transaction-id>
</ideal-payment>
";
}

private static function _idealPaymentFailedSampleXml($id)
{
return "
<ideal-payment>
<id>{$id}</id>
<status>FAILED</status>
<issuer>ABCISSUER</issuer>
<order-id>ORDERABC</order-id>
<currency>EUR</currency>
<amount>10.00</amount>
<created-at>2016-11-29T23:27:34.547Z</created-at>
<approval-url>https://example.com</approval-url>
<ideal-transaction-id>1234567890</ideal-transaction-id>
</ideal-payment>
";
}

private static function _timestamp()
{
$originalZone = date_default_timezone_get();
Expand Down

0 comments on commit c0e8561

Please sign in to comment.