Transaction.php in Commerce Braintree 7
File
braintree_php/lib/Braintree/Transaction.phpView source
<?php
/**
* Braintree Transaction processor
*
* @package Braintree
* @category Resources
* @copyright 2010 Braintree Payment Solutions
*/
/**
* Creates and manages transactions
*
* At minimum, an amount, credit card number, and
* credit card expiration date are required.
*
* <b>Minimalistic example:</b>
* <code>
* Braintree_Transaction::saleNoValidate(array(
* 'amount' => '100.00',
* 'creditCard' => array(
* 'number' => '5105105105105100',
* 'expirationDate' => '05/12',
* ),
* ));
* </code>
*
* <b>Full example:</b>
* <code>
* Braintree_Transaction::saleNoValidate(array(
* 'amount' => '100.00',
* 'orderId' => '123',
* 'creditCard' => array(
* // if token is omitted, the gateway will generate a token
* 'token' => 'credit_card_123',
* 'number' => '5105105105105100',
* 'expirationDate' => '05/2011',
* 'cvv' => '123',
* ),
* 'customer' => array(
* // if id is omitted, the gateway will generate an id
* 'id' => 'customer_123',
* 'firstName' => 'Dan',
* 'lastName' => 'Smith',
* 'company' => 'Braintree Payment Solutions',
* 'email' => 'dan@example.com',
* 'phone' => '419-555-1234',
* 'fax' => '419-555-1235',
* 'website' => 'http://braintreepayments.com'
* ),
* 'billing' => array(
* 'firstName' => 'Carl',
* 'lastName' => 'Jones',
* 'company' => 'Braintree',
* 'streetAddress' => '123 E Main St',
* 'extendedAddress' => 'Suite 403',
* 'locality' => 'Chicago',
* 'region' => 'IL',
* 'postalCode' => '60622',
* 'countryName' => 'United States of America'
* ),
* 'shipping' => array(
* 'firstName' => 'Andrew',
* 'lastName' => 'Mason',
* 'company' => 'Braintree',
* 'streetAddress' => '456 W Main St',
* 'extendedAddress' => 'Apt 2F',
* 'locality' => 'Bartlett',
* 'region' => 'IL',
* 'postalCode' => '60103',
* 'countryName' => 'United States of America'
* ),
* 'customFields' => array(
* 'birthdate' => '11/13/1954'
* )
* )
* </code>
*
* <b>== Storing in the Vault ==</b>
*
* The customer and credit card information used for
* a transaction can be stored in the vault by setting
* <i>transaction[options][storeInVault]</i> to true.
* <code>
* $transaction = Braintree_Transaction::saleNoValidate(array(
* 'customer' => array(
* 'firstName' => 'Adam',
* 'lastName' => 'Williams'
* ),
* 'creditCard' => array(
* 'number' => '5105105105105100',
* 'expirationDate' => '05/2012'
* ),
* 'options' => array(
* 'storeInVault' => true
* )
* ));
*
* echo $transaction->customerDetails->id
* // '865534'
* echo $transaction->creditCardDetails->token
* // '6b6m'
* </code>
*
* To also store the billing address in the vault, pass the
* <b>addBillingAddressToPaymentMethod</b> option.
* <code>
* Braintree_Transaction.saleNoValidate(array(
* ...
* 'options' => array(
* 'storeInVault' => true
* 'addBillingAddressToPaymentMethod' => true
* )
* ));
* </code>
*
* <b>== Submitting for Settlement==</b>
*
* This can only be done when the transction's
* status is <b>authorized</b>. If <b>amount</b> is not specified,
* the full authorized amount will be settled. If you would like to settle
* less than the full authorized amount, pass the desired amount.
* You cannot settle more than the authorized amount.
*
* A transaction can be submitted for settlement when created by setting
* $transaction[options][submitForSettlement] to true.
*
* <code>
* $transaction = Braintree_Transaction::saleNoValidate(array(
* 'amount' => '100.00',
* 'creditCard' => array(
* 'number' => '5105105105105100',
* 'expirationDate' => '05/2012'
* ),
* 'options' => array(
* 'submitForSettlement' => true
* )
* ));
* </code>
*
* <b>== More information ==</b>
*
* For more detailed information on Transactions, see {@link http://www.braintreepayments.com/gateway/transaction-api http://www.braintreepaymentsolutions.com/gateway/transaction-api}
*
* @package Braintree
* @category Resources
* @copyright 2010 Braintree Payment Solutions
*
*
* @property-read string $avsErrorResponseCode
* @property-read string $avsPostalCodeResponseCode
* @property-read string $avsStreetAddressResponseCode
* @property-read string $cvvResponseCode
* @property-read string $id transaction id
* @property-read string $amount transaction amount
* @property-read object $billingDetails transaction billing address
* @property-read string $createdAt transaction created timestamp
* @property-read object $creditCardDetails transaction credit card info
* @property-read object $customerDetails transaction customer info
* @property-read array $customFields custom fields passed with the request
* @property-read string $processorResponseCode gateway response code
* @property-read object $shippingDetails transaction shipping address
* @property-read string $status transaction status
* @property-read array $statusHistory array of StatusDetails objects
* @property-read string $type transaction type
* @property-read string $updatedAt transaction updated timestamp
*
*/
final class Braintree_Transaction extends Braintree {
// Transaction Status
const AUTHORIZATION_EXPIRED = 'authorization_expired';
const AUTHORIZING = 'authorizing';
const AUTHORIZED = 'authorized';
const GATEWAY_REJECTED = 'gateway_rejected';
const FAILED = 'failed';
const PROCESSOR_DECLINED = 'processor_declined';
const SETTLED = 'settled';
const SETTLING = 'settling';
const SUBMITTED_FOR_SETTLEMENT = 'submitted_for_settlement';
const VOIDED = 'voided';
// Transaction Types
const SALE = 'sale';
const CREDIT = 'credit';
// Transaction Created Using
const FULL_INFORMATION = 'full_information';
const TOKEN = 'token';
// Transaction Sources
const API = 'api';
const CONTROL_PANEL = 'control_panel';
const RECURRING = 'recurring';
// Gateway Rejection Reason
const AVS = 'avs';
const AVS_AND_CVV = 'avs_and_cvv';
const CVV = 'cvv';
const DUPLICATE = 'duplicate';
public static function cloneTransaction($transactionId, $attribs) {
Braintree_Util::verifyKeys(self::cloneSignature(), $attribs);
return self::_doCreate('/transactions/' . $transactionId . '/clone', array(
'transactionClone' => $attribs,
));
}
/**
* @ignore
* @access public
* @param array $attribs
* @return object
*/
private static function create($attribs) {
Braintree_Util::verifyKeys(self::createSignature(), $attribs);
return self::_doCreate('/transactions', array(
'transaction' => $attribs,
));
}
/**
*
* @ignore
* @access public
* @param array $attribs
* @return object
* @throws Braintree_Exception_ValidationError
*/
private static function createNoValidate($attribs) {
$result = self::create($attribs);
return self::returnObjectOrThrowException(__CLASS__, $result);
}
/**
*
* @access public
* @param array $attribs
* @return object
*/
public static function createFromTransparentRedirect($queryString) {
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::confirm", E_USER_NOTICE);
$params = Braintree_TransparentRedirect::parseAndValidateQueryString($queryString);
return self::_doCreate('/transactions/all/confirm_transparent_redirect_request', array(
'id' => $params['id'],
));
}
/**
*
* @access public
* @param none
* @return string
*/
public static function createTransactionUrl() {
trigger_error("DEPRECATED: Please use Braintree_TransparentRedirectRequest::url", E_USER_NOTICE);
return Braintree_Configuration::merchantUrl() . '/transactions/all/create_via_transparent_redirect_request';
}
public static function cloneSignature() {
return array(
'amount',
array(
'options' => array(
'submitForSettlement',
),
),
);
}
/**
* creates a full array signature of a valid gateway request
* @return array gateway request signature format
*/
public static function createSignature() {
return array(
'amount',
'customerId',
'merchantAccountId',
'orderId',
'paymentMethodToken',
'purchaseOrderNumber',
'recurring',
'shippingAddressId',
'taxAmount',
'taxExempt',
'type',
array(
'creditCard' => array(
'token',
'cardholderName',
'cvv',
'expirationDate',
'expirationMonth',
'expirationYear',
'number',
),
),
array(
'customer' => array(
'id',
'company',
'email',
'fax',
'firstName',
'lastName',
'phone',
'website',
),
),
array(
'billing' => array(
'firstName',
'lastName',
'company',
'countryName',
'countryCodeAlpha2',
'countryCodeAlpha3',
'countryCodeNumeric',
'extendedAddress',
'locality',
'postalCode',
'region',
'streetAddress',
),
),
array(
'shipping' => array(
'firstName',
'lastName',
'company',
'countryName',
'countryCodeAlpha2',
'countryCodeAlpha3',
'countryCodeNumeric',
'extendedAddress',
'locality',
'postalCode',
'region',
'streetAddress',
),
),
array(
'options' => array(
'storeInVault',
'storeInVaultOnSuccess',
'submitForSettlement',
'addBillingAddressToPaymentMethod',
'storeShippingAddressInVault',
),
),
array(
'customFields' => array(
'_anyKey_',
),
),
array(
'descriptor' => array(
'name',
'phone',
),
),
);
}
/**
*
* @access public
* @param array $attribs
* @return object
*/
public static function credit($attribs) {
return self::create(array_merge($attribs, array(
'type' => Braintree_Transaction::CREDIT,
)));
}
/**
*
* @access public
* @param array $attribs
* @return object
* @throws Braintree_Exception_ValidationError
*/
public static function creditNoValidate($attribs) {
$result = self::credit($attribs);
return self::returnObjectOrThrowException(__CLASS__, $result);
}
/**
* @access public
*
*/
public static function find($id) {
self::_validateId($id);
try {
$response = Braintree_Http::get('/transactions/' . $id);
return self::factory($response['transaction']);
} catch (Braintree_Exception_NotFound $e) {
throw new Braintree_Exception_NotFound('transaction with id ' . $id . ' not found');
}
}
/**
* new sale
* @param array $attribs
* @return array
*/
public static function sale($attribs) {
return self::create(array_merge(array(
'type' => Braintree_Transaction::SALE,
), $attribs));
}
/**
* roughly equivalent to the ruby bang method
* @access public
* @param array $attribs
* @return array
* @throws Braintree_Exception_ValidationsFailed
*/
public static function saleNoValidate($attribs) {
$result = self::sale($attribs);
return self::returnObjectOrThrowException(__CLASS__, $result);
}
/**
* Returns a ResourceCollection of transactions matching the search query.
*
* If <b>query</b> is a string, the search will be a basic search.
* If <b>query</b> is a hash, the search will be an advanced search.
* For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/transaction-api#searching http://www.braintreepaymentsolutions.com/gateway/transaction-api}
*
* @param mixed $query search query
* @param array $options options such as page number
* @return object Braintree_ResourceCollection
* @throws InvalidArgumentException
*/
public static function search($query) {
$criteria = array();
foreach ($query as $term) {
$criteria[$term->name] = $term
->toparam();
}
$response = braintree_http::post('/transactions/advanced_search_ids', array(
'search' => $criteria,
));
$pager = array(
'className' => __CLASS__,
'classMethod' => 'fetch',
'methodArgs' => array(
$query,
),
);
return new Braintree_ResourceCollection($response, $pager);
}
public static function fetch($query, $ids) {
$criteria = array();
foreach ($query as $term) {
$criteria[$term->name] = $term
->toparam();
}
$criteria["ids"] = Braintree_TransactionSearch::ids()
->in($ids)
->toparam();
$response = braintree_http::post('/transactions/advanced_search', array(
'search' => $criteria,
));
return braintree_util::extractattributeasarray($response['creditCardTransactions'], 'transaction');
}
/**
* void a transaction by id
*
* @param string $id transaction id
* @return object Braintree_Result_Successful|Braintree_Result_Error
*/
public static function void($transactionId) {
self::_validateId($transactionId);
$response = Braintree_Http::put('/transactions/' . $transactionId . '/void');
return self::_verifyGatewayResponse($response);
}
/**
*
*/
public static function voidNoValidate($transactionId) {
$result = self::void($transactionId);
return self::returnObjectOrThrowException(__CLASS__, $result);
}
public static function submitForSettlement($transactionId, $amount = null) {
self::_validateId($transactionId);
$response = Braintree_Http::put('/transactions/' . $transactionId . '/submit_for_settlement', array(
'transaction' => array(
'amount' => $amount,
),
));
return self::_verifyGatewayResponse($response);
}
public static function submitForSettlementNoValidate($transactionId, $amount = null) {
$result = self::submitForSettlement($transactionId, $amount);
return self::returnObjectOrThrowException(__CLASS__, $result);
}
/**
* sets instance properties from an array of values
*
* @ignore
* @access protected
* @param array $transactionAttribs array of transaction data
* @return none
*/
protected function _initialize($transactionAttribs) {
$this->_attributes = $transactionAttribs;
$this
->_set('creditCardDetails', new Braintree_Transaction_CreditCardDetails($transactionAttribs['creditCard']));
$this
->_set('customerDetails', new Braintree_Transaction_CustomerDetails($transactionAttribs['customer']));
$this
->_set('billingDetails', new Braintree_Transaction_AddressDetails($transactionAttribs['billing']));
$this
->_set('shippingDetails', new Braintree_Transaction_AddressDetails($transactionAttribs['shipping']));
$this
->_set('subscriptionDetails', new Braintree_Transaction_SubscriptionDetails($transactionAttribs['subscription']));
$this
->_set('descriptor', new Braintree_Descriptor($transactionAttribs['descriptor']));
$statusHistory = array();
foreach ($transactionAttribs['statusHistory'] as $history) {
$statusHistory[] = new Braintree_Transaction_StatusDetails($history);
}
$this
->_set('statusHistory', $statusHistory);
$addOnArray = array();
if (isset($transactionAttribs['addOns'])) {
foreach ($transactionAttribs['addOns'] as $addOn) {
$addOnArray[] = Braintree_AddOn::factory($addOn);
}
}
$this
->_set('addOns', $addOnArray);
$discountArray = array();
if (isset($transactionAttribs['discounts'])) {
foreach ($transactionAttribs['discounts'] as $discount) {
$discountArray[] = Braintree_Discount::factory($discount);
}
}
$this
->_set('discounts', $discountArray);
}
/**
* returns a string representation of the transaction
* @return string
*/
public function __toString() {
// array of attributes to print
$display = array(
'id',
'type',
'amount',
'status',
'createdAt',
'creditCardDetails',
'customerDetails',
);
$displayAttributes = array();
foreach ($display as $attrib) {
$displayAttributes[$attrib] = $this->{$attrib};
}
return __CLASS__ . '[' . Braintree_Util::attributesToString($displayAttributes) . ']';
}
public static function refund($transactionId, $amount = null) {
$params = array(
'transaction' => array(
'amount' => $amount,
),
);
$response = Braintree_Http::post('/transactions/' . $transactionId . '/refund', $params);
return self::_verifyGatewayResponse($response);
}
public function isEqual($otherTx) {
return $this->id === $otherTx->id;
}
public function vaultCreditCard() {
$token = $this->creditCardDetails->token;
if (empty($token)) {
return null;
}
else {
return Braintree_CreditCard::find($token);
}
}
public function vaultCustomer() {
$customerId = $this->customerDetails->id;
if (empty($customerId)) {
return null;
}
else {
return Braintree_Customer::find($customerId);
}
}
/**
* sends the create request to the gateway
*
* @ignore
* @param var $url
* @param array $params
* @return mixed
*/
public static function _doCreate($url, $params) {
$response = Braintree_Http::post($url, $params);
return self::_verifyGatewayResponse($response);
}
/**
* verifies that a valid transaction id is being used
* @ignore
* @param string transaction id
* @throws InvalidArgumentException
*/
private static function _validateId($id = null) {
if (empty($id)) {
throw new InvalidArgumentException('expected transaction id to be set');
}
if (!preg_match('/^[0-9a-z]+$/', $id)) {
throw new InvalidArgumentException($id . ' is an invalid transaction id.');
}
}
/* private class methods */
/**
* generic method for validating incoming gateway responses
*
* creates a new Braintree_Transaction object and encapsulates
* it inside a Braintree_Result_Successful object, or
* encapsulates a Braintree_Errors object inside a Result_Error
* alternatively, throws an Unexpected exception if the response is invalid.
*
* @ignore
* @param array $response gateway response values
* @return object Result_Successful or Result_Error
* @throws Braintree_Exception_Unexpected
*/
private static function _verifyGatewayResponse($response) {
if (isset($response['transaction'])) {
// return a populated instance of Braintree_Transaction
return new Braintree_Result_Successful(self::factory($response['transaction']));
}
else {
if (isset($response['apiErrorResponse'])) {
return new Braintree_Result_Error($response['apiErrorResponse']);
}
else {
throw new Braintree_Exception_Unexpected("Expected transaction or apiErrorResponse");
}
}
}
/**
* factory method: returns an instance of Braintree_Transaction
* to the requesting method, with populated properties
*
* @ignore
* @return object instance of Braintree_Transaction
*/
public static function factory($attributes) {
$instance = new self();
$instance
->_initialize($attributes);
return $instance;
}
}
Classes
Name![]() |
Description |
---|---|
Braintree_Transaction | Creates and manages transactions |