BraintreeCustomerGateway

Braintree CustomerGateway module Creates and manages Customers.

Defined (1)

The class is defined in the following location(s).

/includes/lib/Braintree/lib/Braintree/CustomerGateway.php  
  1. class CustomerGateway 
  2. private $_gateway; 
  3. private $_config; 
  4. private $_http; 
  5.  
  6. public function __construct($gateway) 
  7. $this->_gateway = $gateway; 
  8. $this->_config = $gateway->config; 
  9. $this->_config->assertHasAccessTokenOrKeys(); 
  10. $this->_http = new Http($gateway->config); 
  11.  
  12. public function all() 
  13. $path = $this->_config->merchantPath() . '/customers/advanced_search_ids'; 
  14. $response = $this->_http->post($path); 
  15. $pager = [ 
  16. 'object' => $this,  
  17. 'method' => 'fetch',  
  18. 'methodArgs' => [[]] 
  19. ]; 
  20.  
  21. return new ResourceCollection($response, $pager); 
  22.  
  23. public function fetch($query, $ids) 
  24. $criteria = []; 
  25. foreach ($query as $term) { 
  26. $criteria[$term->name] = $term->toparam(); 
  27. $criteria["ids"] = CustomerSearch::ids()->in($ids)->toparam(); 
  28. $path = $this->_config->merchantPath() . '/customers/advanced_search'; 
  29. $response = $this->_http->post($path, ['search' => $criteria]); 
  30.  
  31. return Util::extractattributeasarray( 
  32. $response['customers'],  
  33. 'customer' 
  34. ); 
  35.  
  36. /** 
  37. * Creates a customer using the given +attributes+. If <tt>:id</tt> is not passed,  
  38. * the gateway will generate it. 
  39. * <code> 
  40. * $result = Customer::create(array( 
  41. * 'first_name' => 'John',  
  42. * 'last_name' => 'Smith',  
  43. * 'company' => 'Smith Co.',  
  44. * 'email' => 'john@smith.com',  
  45. * 'website' => 'www.smithco.com',  
  46. * 'fax' => '419-555-1234',  
  47. * 'phone' => '614-555-1234' 
  48. * )); 
  49. * if($result->success) { 
  50. * echo 'Created customer ' . $result->customer->id; 
  51. * } else { 
  52. * echo 'Could not create customer, see result->errors'; 
  53. * } 
  54. * </code> 
  55. * @access public 
  56. * @param array $attribs 
  57. * @return Braintree_Result_Successful|Braintree_Result_Error 
  58. */ 
  59. public function create($attribs = []) 
  60. Util::verifyKeys(self::createSignature(), $attribs); 
  61. return $this->_doCreate('/customers', ['customer' => $attribs]); 
  62.  
  63. /** 
  64. * attempts the create operation assuming all data will validate 
  65. * returns a Customer object instead of a Result 
  66. * @access public 
  67. * @param array $attribs 
  68. * @return Customer 
  69. * @throws Exception\ValidationError 
  70. */ 
  71. public function createNoValidate($attribs = []) 
  72. $result = $this->create($attribs); 
  73. return Util::returnObjectOrThrowException(__CLASS__, $result); 
  74. /** 
  75. * create a customer from a TransparentRedirect operation 
  76. * @deprecated since version 2.3.0 
  77. * @access public 
  78. * @param array $attribs 
  79. * @return Customer 
  80. */ 
  81. public function createFromTransparentRedirect($queryString) 
  82. trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); 
  83. $params = TransparentRedirect::parseAndValidateQueryString( 
  84. $queryString 
  85. ); 
  86. return $this->_doCreate( 
  87. '/customers/all/confirm_transparent_redirect_request',  
  88. ['id' => $params['id']] 
  89. ); 
  90.  
  91. /** 
  92. * @deprecated since version 2.3.0 
  93. * @access public 
  94. * @param none 
  95. * @return string 
  96. */ 
  97. public function createCustomerUrl() 
  98. trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); 
  99. return $this->_config->baseUrl() . $this->_config->merchantPath() . 
  100. '/customers/all/create_via_transparent_redirect_request'; 
  101.  
  102.  
  103. /** 
  104. * creates a full array signature of a valid create request 
  105. * @return array gateway create request format 
  106. */ 
  107. public static function createSignature() 
  108.  
  109. $creditCardSignature = CreditCardGateway::createSignature(); 
  110. unset($creditCardSignature[array_search('customerId', $creditCardSignature)]); 
  111. $signature = [ 
  112. 'id', 'company', 'email', 'fax', 'firstName',  
  113. 'lastName', 'phone', 'website', 'deviceData',  
  114. 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce',  
  115. ['riskData' => 
  116. ['customerBrowser', 'customerIp', 'customer_browser', 'customer_ip'] 
  117. ],  
  118. ['creditCard' => $creditCardSignature],  
  119. ['customFields' => ['_anyKey_']],  
  120. ]; 
  121. return $signature; 
  122.  
  123. /** 
  124. * creates a full array signature of a valid update request 
  125. * @return array update request format 
  126. */ 
  127. public static function updateSignature() 
  128. $creditCardSignature = CreditCardGateway::updateSignature(); 
  129.  
  130. foreach($creditCardSignature AS $key => $value) { 
  131. if(is_array($value) and array_key_exists('options', $value)) { 
  132. array_push($creditCardSignature[$key]['options'], 'updateExistingToken'); 
  133.  
  134. $signature = [ 
  135. 'id', 'company', 'email', 'fax', 'firstName',  
  136. 'lastName', 'phone', 'website', 'deviceData',  
  137. 'deviceSessionId', 'fraudMerchantId', 'paymentMethodNonce', 'defaultPaymentMethodToken',  
  138. ['creditCard' => $creditCardSignature],  
  139. ['customFields' => ['_anyKey_']],  
  140. ]; 
  141. return $signature; 
  142.  
  143.  
  144. /** 
  145. * find a customer by id 
  146. * @access public 
  147. * @param string id customer Id 
  148. * @return Customer|boolean The customer object or false if the request fails. 
  149. * @throws Exception\NotFound 
  150. */ 
  151. public function find($id) 
  152. $this->_validateId($id); 
  153. try { 
  154. $path = $this->_config->merchantPath() . '/customers/' . $id; 
  155. $response = $this->_http->get($path); 
  156. return Customer::factory($response['customer']); 
  157. } catch (Exception\NotFound $e) { 
  158. throw new Exception\NotFound( 
  159. 'customer with id ' . $id . ' not found' 
  160. ); 
  161.  
  162. /** 
  163. * credit a customer for the passed transaction 
  164. * @access public 
  165. * @param int $customerId 
  166. * @param array $transactionAttribs 
  167. * @return Result\Successful|Result\Error 
  168. */ 
  169. public function credit($customerId, $transactionAttribs) 
  170. $this->_validateId($customerId); 
  171. return Transaction::credit( 
  172. array_merge($transactionAttribs,  
  173. ['customerId' => $customerId] 
  174. ); 
  175.  
  176. /** 
  177. * credit a customer, assuming validations will pass 
  178. * returns a Transaction object on success 
  179. * @access public 
  180. * @param int $customerId 
  181. * @param array $transactionAttribs 
  182. * @return Transaction 
  183. * @throws Exception\ValidationError 
  184. */ 
  185. public function creditNoValidate($customerId, $transactionAttribs) 
  186. $result = $this->credit($customerId, $transactionAttribs); 
  187. return Util::returnObjectOrThrowException('Braintree\Transaction', $result); 
  188.  
  189. /** 
  190. * delete a customer by id 
  191. * @param string $customerId 
  192. */ 
  193. public function delete($customerId) 
  194. $this->_validateId($customerId); 
  195. $path = $this->_config->merchantPath() . '/customers/' . $customerId; 
  196. $this->_http->delete($path); 
  197. return new Result\Successful(); 
  198.  
  199. /** 
  200. * create a new sale for a customer 
  201. * @param string $customerId 
  202. * @param array $transactionAttribs 
  203. * @return Result\Successful|Result\Error 
  204. * @see Transaction::sale() 
  205. */ 
  206. public function sale($customerId, $transactionAttribs) 
  207. $this->_validateId($customerId); 
  208. return Transaction::sale( 
  209. array_merge($transactionAttribs,  
  210. ['customerId' => $customerId] 
  211. ); 
  212.  
  213. /** 
  214. * create a new sale for a customer, assuming validations will pass 
  215. * returns a Transaction object on success 
  216. * @access public 
  217. * @param string $customerId 
  218. * @param array $transactionAttribs 
  219. * @return Transaction 
  220. * @throws Exception\ValidationsFailed 
  221. * @see Transaction::sale() 
  222. */ 
  223. public function saleNoValidate($customerId, $transactionAttribs) 
  224. $result = $this->sale($customerId, $transactionAttribs); 
  225. return Util::returnObjectOrThrowException('Braintree\Transaction', $result); 
  226.  
  227. /** 
  228. * Returns a ResourceCollection of customers matching the search query. 
  229. * If <b>query</b> is a string, the search will be a basic search. 
  230. * If <b>query</b> is a hash, the search will be an advanced search. 
  231. * For more detailed information and examples, see {@link http://www.braintreepayments.com/gateway/customer-api#searching http://www.braintreepaymentsolutions.com/gateway/customer-api} 
  232. * @param mixed $query search query 
  233. * @return ResourceCollection 
  234. * @throws InvalidArgumentException 
  235. */ 
  236. public function search($query) 
  237. $criteria = []; 
  238. foreach ($query as $term) { 
  239. $result = $term->toparam(); 
  240. if(is_null($result) || empty($result)) { 
  241. throw new InvalidArgumentException('Operator must be provided'); 
  242.  
  243. $criteria[$term->name] = $term->toparam(); 
  244.  
  245. $path = $this->_config->merchantPath() . '/customers/advanced_search_ids'; 
  246. $response = $this->_http->post($path, ['search' => $criteria]); 
  247. $pager = [ 
  248. 'object' => $this,  
  249. 'method' => 'fetch',  
  250. 'methodArgs' => [$query] 
  251. ]; 
  252.  
  253. return new ResourceCollection($response, $pager); 
  254.  
  255. /** 
  256. * updates the customer record 
  257. * if calling this method in static context, customerId 
  258. * is the 2nd attribute. customerId is not sent in object context. 
  259. * @access public 
  260. * @param string $customerId (optional) 
  261. * @param array $attributes 
  262. * @return Result\Successful|Result\Error 
  263. */ 
  264. public function update($customerId, $attributes) 
  265. Util::verifyKeys(self::updateSignature(), $attributes); 
  266. $this->_validateId($customerId); 
  267. return $this->_doUpdate( 
  268. 'put',  
  269. '/customers/' . $customerId,  
  270. ['customer' => $attributes] 
  271. ); 
  272.  
  273. /** 
  274. * update a customer record, assuming validations will pass 
  275. * if calling this method in static context, customerId 
  276. * is the 2nd attribute. customerId is not sent in object context. 
  277. * returns a Customer object on success 
  278. * @access public 
  279. * @param string $customerId 
  280. * @param array $attributes 
  281. * @return Customer 
  282. * @throws Exception\ValidationsFailed 
  283. */ 
  284. public function updateNoValidate($customerId, $attributes) 
  285. $result = $this->update($customerId, $attributes); 
  286. return Util::returnObjectOrThrowException(__CLASS__, $result); 
  287. /** 
  288. * @deprecated since version 2.3.0 
  289. * @access public 
  290. * @return string 
  291. */ 
  292. public function updateCustomerUrl() 
  293. trigger_error("DEPRECATED: Please use TransparentRedirectRequest::url", E_USER_NOTICE); 
  294. return $this->_config->baseUrl() . $this->_config->merchantPath() . 
  295. '/customers/all/update_via_transparent_redirect_request'; 
  296.  
  297. /** 
  298. * update a customer from a TransparentRedirect operation 
  299. * @deprecated since version 2.3.0 
  300. * @access public 
  301. * @param string $queryString 
  302. * @return object 
  303. */ 
  304. public function updateFromTransparentRedirect($queryString) 
  305. trigger_error("DEPRECATED: Please use TransparentRedirectRequest::confirm", E_USER_NOTICE); 
  306. $params = TransparentRedirect::parseAndValidateQueryString( 
  307. $queryString 
  308. ); 
  309. return $this->_doUpdate( 
  310. 'post',  
  311. '/customers/all/confirm_transparent_redirect_request',  
  312. ['id' => $params['id']] 
  313. ); 
  314.  
  315. /** instance methods */ 
  316.  
  317. /** 
  318. * sets instance properties from an array of values 
  319. * @ignore 
  320. * @access protected 
  321. * @param array $customerAttribs array of customer data 
  322. * @return void 
  323. */ 
  324. protected function _initialize($customerAttribs) 
  325. // set the attributes 
  326. $this->_attributes = $customerAttribs; 
  327.  
  328. // map each address into its own object 
  329. $addressArray = []; 
  330. if (isset($customerAttribs['addresses'])) { 
  331.  
  332. foreach ($customerAttribs['addresses'] AS $address) { 
  333. $addressArray[] = Address::factory($address); 
  334. $this->_set('addresses', $addressArray); 
  335.  
  336. // map each creditCard into its own object 
  337. $creditCardArray = []; 
  338. if (isset($customerAttribs['creditCards'])) { 
  339. foreach ($customerAttribs['creditCards'] AS $creditCard) { 
  340. $creditCardArray[] = CreditCard::factory($creditCard); 
  341. $this->_set('creditCards', $creditCardArray); 
  342.  
  343. // map each coinbaseAccount into its own object 
  344. $coinbaseAccountArray = []; 
  345. if (isset($customerAttribs['coinbaseAccounts'])) { 
  346. foreach ($customerAttribs['coinbaseAccounts'] AS $coinbaseAccount) { 
  347. $coinbaseAccountArray[] = CoinbaseAccount::factory($coinbaseAccount); 
  348. $this->_set('coinbaseAccounts', $coinbaseAccountArray); 
  349.  
  350. // map each paypalAccount into its own object 
  351. $paypalAccountArray = []; 
  352. if (isset($customerAttribs['paypalAccounts'])) { 
  353. foreach ($customerAttribs['paypalAccounts'] AS $paypalAccount) { 
  354. $paypalAccountArray[] = PayPalAccount::factory($paypalAccount); 
  355. $this->_set('paypalAccounts', $paypalAccountArray); 
  356.  
  357. // map each applePayCard into its own object 
  358. $applePayCardArray = []; 
  359. if (isset($customerAttribs['applePayCards'])) { 
  360. foreach ($customerAttribs['applePayCards'] AS $applePayCard) { 
  361. $applePayCardArray[] = ApplePayCard::factory($applePayCard); 
  362. $this->_set('applePayCards', $applePayCardArray); 
  363.  
  364. // map each androidPayCard into its own object 
  365. $androidPayCardArray = []; 
  366. if (isset($customerAttribs['androidPayCards'])) { 
  367. foreach ($customerAttribs['androidPayCards'] AS $androidPayCard) { 
  368. $androidPayCardArray[] = AndroidPayCard::factory($androidPayCard); 
  369. $this->_set('androidPayCards', $androidPayCardArray); 
  370.  
  371. $this->_set('paymentMethods', array_merge($this->creditCards, $this->paypalAccounts, $this->applePayCards, $this->coinbaseAccounts, $this->androidPayCards)); 
  372.  
  373. /** 
  374. * returns a string representation of the customer 
  375. * @return string 
  376. */ 
  377. public function __toString() 
  378. return __CLASS__ . '[' . 
  379. Util::attributesToString($this->_attributes) .']'; 
  380.  
  381. /** 
  382. * returns false if comparing object is not a Customer,  
  383. * or is a Customer with a different id 
  384. * @param object $otherCust customer to compare against 
  385. * @return boolean 
  386. */ 
  387. public function isEqual($otherCust) 
  388. return !($otherCust instanceof Customer) ? false : $this->id === $otherCust->id; 
  389.  
  390. /** 
  391. * returns an array containt all of the customer's payment methods 
  392. * @return array 
  393. */ 
  394. public function paymentMethods() 
  395. return $this->paymentMethods; 
  396.  
  397. /** 
  398. * returns the customer's default payment method 
  399. * @return CreditCard|PayPalAccount|ApplePayCard|AndroidPayCard 
  400. */ 
  401. public function defaultPaymentMethod() 
  402. $defaultPaymentMethods = array_filter($this->paymentMethods, 'Braintree\\Customer::_defaultPaymentMethodFilter'); 
  403. return current($defaultPaymentMethods); 
  404.  
  405. public static function _defaultPaymentMethodFilter($paymentMethod) 
  406. return $paymentMethod->isDefault(); 
  407.  
  408. /** private class properties */ 
  409.  
  410. /** 
  411. * @access protected 
  412. * @var array registry of customer data 
  413. */ 
  414. protected $_attributes = [ 
  415. 'addresses' => '',  
  416. 'company' => '',  
  417. 'creditCards' => '',  
  418. 'email' => '',  
  419. 'fax' => '',  
  420. 'firstName' => '',  
  421. 'id' => '',  
  422. 'lastName' => '',  
  423. 'phone' => '',  
  424. 'createdAt' => '',  
  425. 'updatedAt' => '',  
  426. 'website' => '',  
  427. ]; 
  428.  
  429. /** 
  430. * sends the create request to the gateway 
  431. * @ignore 
  432. * @param string $subPath 
  433. * @param array $params 
  434. * @return mixed 
  435. */ 
  436. public function _doCreate($subPath, $params) 
  437. $fullPath = $this->_config->merchantPath() . $subPath; 
  438. $response = $this->_http->post($fullPath, $params); 
  439.  
  440. return $this->_verifyGatewayResponse($response); 
  441.  
  442. /** 
  443. * verifies that a valid customer id is being used 
  444. * @ignore 
  445. * @param string customer id 
  446. * @throws InvalidArgumentException 
  447. */ 
  448. private function _validateId($id = null) { 
  449. if (is_null($id)) { 
  450. throw new InvalidArgumentException( 
  451. 'expected customer id to be set' 
  452. ); 
  453. if (!preg_match('/^[0-9A-Za-z_-]+$/', $id)) { 
  454. throw new InvalidArgumentException( 
  455. $id . ' is an invalid customer id.' 
  456. ); 
  457.  
  458.  
  459. /** private class methods */ 
  460.  
  461. /** 
  462. * sends the update request to the gateway 
  463. * @ignore 
  464. * @param string $subPath 
  465. * @param array $params 
  466. * @return mixed 
  467. */ 
  468. private function _doUpdate($httpVerb, $subPath, $params) 
  469. $fullPath = $this->_config->merchantPath() . $subPath; 
  470. $response = $this->_http->$httpVerb($fullPath, $params); 
  471.  
  472. return $this->_verifyGatewayResponse($response); 
  473.  
  474. /** 
  475. * generic method for validating incoming gateway responses 
  476. * creates a new Customer object and encapsulates 
  477. * it inside a Result\Successful object, or 
  478. * encapsulates a Errors object inside a Result\Error 
  479. * alternatively, throws an Unexpected exception if the response is invalid. 
  480. * @ignore 
  481. * @param array $response gateway response values 
  482. * @return Result\Successful|Result\Error 
  483. * @throws Exception\Unexpected 
  484. */ 
  485. private function _verifyGatewayResponse($response) 
  486. if (isset($response['customer'])) { 
  487. // return a populated instance of Customer 
  488. return new Result\Successful( 
  489. Customer::factory($response['customer']) 
  490. ); 
  491. } else if (isset($response['apiErrorResponse'])) { 
  492. return new Result\Error($response['apiErrorResponse']); 
  493. } else { 
  494. throw new Exception\Unexpected( 
  495. "Expected customer or apiErrorResponse" 
  496. );