123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- <?php
- namespace Braintree;
- use InvalidArgumentException;
- /**
- * Braintree CreditCardGateway module
- * Creates and manages Braintree CreditCards
- *
- * <b>== More information ==</b>
- *
- * For more detailed information on CreditCards, see {@link https://developers.braintreepayments.com/reference/response/credit-card/php https://developers.braintreepayments.com/reference/response/credit-card/php}<br />
- * For more detailed information on CreditCard verifications, see {@link https://developers.braintreepayments.com/reference/response/credit-card-verification/php https://developers.braintreepayments.com/reference/response/credit-card-verification/php}
- *
- * @package Braintree
- * @category Resources
- */
- class CreditCardGateway
- {
- 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 create($attribs)
- {
- Util::verifyKeys(self::createSignature(), $attribs);
- return $this->_doCreate('/payment_methods', ['credit_card' => $attribs]);
- }
- /**
- * attempts the create operation assuming all data will validate
- * returns a CreditCard object instead of a Result
- *
- * @access public
- * @param array $attribs
- * @return CreditCard
- * @throws Exception\ValidationError
- */
- public function createNoValidate($attribs)
- {
- $result = $this->create($attribs);
- return Util::returnObjectOrThrowException(__CLASS__, $result);
- }
- /**
- * create a customer from a TransparentRedirect operation
- *
- * @deprecated since version 2.3.0
- * @access public
- * @param array $attribs
- * @return Result\Successful|Result\Error
- */
- public function createFromTransparentRedirect($queryString)
- {
- trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE);
- $params = TransparentRedirect::parseAndValidateQueryString(
- $queryString
- );
- return $this->_doCreate(
- '/payment_methods/all/confirm_transparent_redirect_request',
- ['id' => $params['id']]
- );
- }
- /**
- *
- * @deprecated since version 2.3.0
- * @access public
- * @param none
- * @return string
- */
- public function createCreditCardUrl()
- {
- trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE);
- return $this->_config->baseUrl() . $this->_config->merchantPath().
- '/payment_methods/all/create_via_transparent_redirect_request';
- }
- /**
- * returns a ResourceCollection of expired credit cards
- * @return ResourceCollection
- */
- public function expired()
- {
- $path = $this->_config->merchantPath() . '/payment_methods/all/expired_ids';
- $response = $this->_http->post($path);
- $pager = [
- 'object' => $this,
- 'method' => 'fetchExpired',
- 'methodArgs' => []
- ];
- return new ResourceCollection($response, $pager);
- }
- public function fetchExpired($ids)
- {
- $path = $this->_config->merchantPath() . "/payment_methods/all/expired";
- $response = $this->_http->post($path, ['search' => ['ids' => $ids]]);
- return Util::extractattributeasarray(
- $response['paymentMethods'],
- 'creditCard'
- );
- }
- /**
- * returns a ResourceCollection of credit cards expiring between start/end
- *
- * @return ResourceCollection
- */
- public function expiringBetween($startDate, $endDate)
- {
- $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring_ids?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate);
- $response = $this->_http->post($queryPath);
- $pager = [
- 'object' => $this,
- 'method' => 'fetchExpiring',
- 'methodArgs' => [$startDate, $endDate]
- ];
- return new ResourceCollection($response, $pager);
- }
- public function fetchExpiring($startDate, $endDate, $ids)
- {
- $queryPath = $this->_config->merchantPath() . '/payment_methods/all/expiring?start=' . date('mY', $startDate) . '&end=' . date('mY', $endDate);
- $response = $this->_http->post($queryPath, ['search' => ['ids' => $ids]]);
- return Util::extractAttributeAsArray(
- $response['paymentMethods'],
- 'creditCard'
- );
- }
- /**
- * find a creditcard by token
- *
- * @access public
- * @param string $token credit card unique id
- * @return CreditCard
- * @throws Exception\NotFound
- */
- public function find($token)
- {
- $this->_validateId($token);
- try {
- $path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token;
- $response = $this->_http->get($path);
- return CreditCard::factory($response['creditCard']);
- } catch (Exception\NotFound $e) {
- throw new Exception\NotFound(
- 'credit card with token ' . $token . ' not found'
- );
- }
- }
- /**
- * Convert a payment method nonce to a credit card
- *
- * @access public
- * @param string $nonce payment method nonce
- * @return CreditCard
- * @throws Exception\NotFound
- */
- public function fromNonce($nonce)
- {
- $this->_validateId($nonce, "nonce");
- try {
- $path = $this->_config->merchantPath() . '/payment_methods/from_nonce/' . $nonce;
- $response = $this->_http->get($path);
- return CreditCard::factory($response['creditCard']);
- } catch (Exception\NotFound $e) {
- throw new Exception\NotFound(
- 'credit card with nonce ' . $nonce . ' locked, consumed or not found'
- );
- }
- }
- /**
- * create a credit on the card for the passed transaction
- *
- * @access public
- * @param array $attribs
- * @return Result\Successful|Result\Error
- */
- public function credit($token, $transactionAttribs)
- {
- $this->_validateId($token);
- return Transaction::credit(
- array_merge(
- $transactionAttribs,
- ['paymentMethodToken' => $token]
- )
- );
- }
- /**
- * create a credit on this card, assuming validations will pass
- *
- * returns a Transaction object on success
- *
- * @access public
- * @param array $attribs
- * @return Transaction
- * @throws Exception\ValidationError
- */
- public function creditNoValidate($token, $transactionAttribs)
- {
- $result = $this->credit($token, $transactionAttribs);
- return Util::returnObjectOrThrowException('Braintree\Transaction', $result);
- }
- /**
- * create a new sale for the current card
- *
- * @param string $token
- * @param array $transactionAttribs
- * @return Result\Successful|Result\Error
- * @see Transaction::sale()
- */
- public function sale($token, $transactionAttribs)
- {
- $this->_validateId($token);
- return Transaction::sale(
- array_merge(
- $transactionAttribs,
- ['paymentMethodToken' => $token]
- )
- );
- }
- /**
- * create a new sale using this card, assuming validations will pass
- *
- * returns a Transaction object on success
- *
- * @access public
- * @param array $transactionAttribs
- * @param string $token
- * @return Transaction
- * @throws Exception\ValidationsFailed
- * @see Transaction::sale()
- */
- public function saleNoValidate($token, $transactionAttribs)
- {
- $result = $this->sale($token, $transactionAttribs);
- return Util::returnObjectOrThrowException('Braintree\Transaction', $result);
- }
- /**
- * updates the creditcard record
- *
- * if calling this method in context, $token
- * is the 2nd attribute. $token is not sent in object context.
- *
- * @access public
- * @param array $attributes
- * @param string $token (optional)
- * @return Result\Successful|Result\Error
- */
- public function update($token, $attributes)
- {
- Util::verifyKeys(self::updateSignature(), $attributes);
- $this->_validateId($token);
- return $this->_doUpdate('put', '/payment_methods/credit_card/' . $token, ['creditCard' => $attributes]);
- }
- /**
- * update a creditcard record, assuming validations will pass
- *
- * if calling this method in context, $token
- * is the 2nd attribute. $token is not sent in object context.
- * returns a CreditCard object on success
- *
- * @access public
- * @param array $attributes
- * @param string $token
- * @return CreditCard
- * @throws Exception\ValidationsFailed
- */
- public function updateNoValidate($token, $attributes)
- {
- $result = $this->update($token, $attributes);
- return Util::returnObjectOrThrowException(__CLASS__, $result);
- }
- /**
- *
- * @access public
- * @param none
- * @return string
- */
- public function updateCreditCardUrl()
- {
- trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE);
- return $this->_config->baseUrl() . $this->_config->merchantPath() .
- '/payment_methods/all/update_via_transparent_redirect_request';
- }
- /**
- * update a customer from a TransparentRedirect operation
- *
- * @deprecated since version 2.3.0
- * @access public
- * @param array $attribs
- * @return object
- */
- public function updateFromTransparentRedirect($queryString)
- {
- trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE);
- $params = TransparentRedirect::parseAndValidateQueryString(
- $queryString
- );
- return $this->_doUpdate(
- 'post',
- '/payment_methods/all/confirm_transparent_redirect_request',
- ['id' => $params['id']]
- );
- }
- public function delete($token)
- {
- $this->_validateId($token);
- $path = $this->_config->merchantPath() . '/payment_methods/credit_card/' . $token;
- $this->_http->delete($path);
- return new Result\Successful();
- }
- private static function baseOptions()
- {
- return ['makeDefault', 'verificationMerchantAccountId', 'verifyCard', 'verificationAmount', 'venmoSdkSession'];
- }
- private static function baseSignature($options)
- {
- return [
- 'billingAddressId', 'cardholderName', 'cvv', 'number', 'deviceSessionId',
- 'expirationDate', 'expirationMonth', 'expirationYear', 'token', 'venmoSdkPaymentMethodCode',
- 'deviceData', 'fraudMerchantId', 'paymentMethodNonce',
- ['options' => $options],
- [
- 'billingAddress' => self::billingAddressSignature()
- ],
- ];
- }
- public static function billingAddressSignature()
- {
- return [
- 'firstName',
- 'lastName',
- 'company',
- 'countryCodeAlpha2',
- 'countryCodeAlpha3',
- 'countryCodeNumeric',
- 'countryName',
- 'extendedAddress',
- 'locality',
- 'region',
- 'postalCode',
- 'streetAddress'
- ];
- }
- public static function createSignature()
- {
- $options = self::baseOptions();
- $options[] = "failOnDuplicatePaymentMethod";
- $signature = self::baseSignature($options);
- $signature[] = 'customerId';
- return $signature;
- }
- public static function updateSignature()
- {
- $options = self::baseOptions();
- $options[] = "failOnDuplicatePaymentMethod";
- $signature = self::baseSignature($options);
- $updateExistingBillingSignature = [
- [
- 'options' => [
- 'updateExisting'
- ]
- ]
- ];
- foreach($signature AS $key => $value) {
- if(is_array($value) and array_key_exists('billingAddress', $value)) {
- $signature[$key]['billingAddress'] = array_merge_recursive($value['billingAddress'], $updateExistingBillingSignature);
- }
- }
- return $signature;
- }
- /**
- * sends the create request to the gateway
- *
- * @ignore
- * @param string $subPath
- * @param array $params
- * @return mixed
- */
- public function _doCreate($subPath, $params)
- {
- $fullPath = $this->_config->merchantPath() . $subPath;
- $response = $this->_http->post($fullPath, $params);
- return $this->_verifyGatewayResponse($response);
- }
- /**
- * verifies that a valid credit card identifier is being used
- * @ignore
- * @param string $identifier
- * @param Optional $string $identifierType type of identifier supplied, default "token"
- * @throws InvalidArgumentException
- */
- private function _validateId($identifier = null, $identifierType = "token")
- {
- if (empty($identifier)) {
- throw new InvalidArgumentException(
- 'expected credit card id to be set'
- );
- }
- if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) {
- throw new InvalidArgumentException(
- $identifier . ' is an invalid credit card ' . $identifierType . '.'
- );
- }
- }
- /**
- * sends the update request to the gateway
- *
- * @ignore
- * @param string $url
- * @param array $params
- * @return mixed
- */
- private function _doUpdate($httpVerb, $subPath, $params)
- {
- $fullPath = $this->_config->merchantPath() . $subPath;
- $response = $this->_http->$httpVerb($fullPath, $params);
- return $this->_verifyGatewayResponse($response);
- }
- /**
- * generic method for validating incoming gateway responses
- *
- * creates a new CreditCard object and encapsulates
- * it inside a Result\Successful object, or
- * encapsulates a Errors object inside a Result\Error
- * alternatively, throws an Unexpected exception if the response is invalid
- *
- * @ignore
- * @param array $response gateway response values
- * @return Result\Successful|Result\Error
- * @throws Exception\Unexpected
- */
- private function _verifyGatewayResponse($response)
- {
- if (isset($response['creditCard'])) {
- // return a populated instance of Address
- return new Result\Successful(
- CreditCard::factory($response['creditCard'])
- );
- } elseif (isset($response['apiErrorResponse'])) {
- return new Result\Error($response['apiErrorResponse']);
- } else {
- throw new Exception\Unexpected(
- "Expected address or apiErrorResponse"
- );
- }
- }
- }
- class_alias('Braintree\CreditCardGateway', 'Braintree_CreditCardGateway');
|