1
|
|
|
<?php |
2
|
|
|
namespace Braintree; |
3
|
|
|
|
4
|
|
|
use InvalidArgumentException; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Braintree PaymentMethodGateway module |
8
|
|
|
* |
9
|
|
|
* @package Braintree |
10
|
|
|
* @category Resources |
11
|
|
|
* @copyright 2015 Braintree, a division of PayPal, Inc. |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Creates and manages Braintree PaymentMethods |
16
|
|
|
* |
17
|
|
|
* <b>== More information ==</b> |
18
|
|
|
* |
19
|
|
|
* |
20
|
|
|
* @package Braintree |
21
|
|
|
* @category Resources |
22
|
|
|
* @copyright 2015 Braintree, a division of PayPal, Inc. |
23
|
|
|
* |
24
|
|
|
*/ |
25
|
|
|
class PaymentMethodGateway |
26
|
|
|
{ |
27
|
|
|
private $_gateway; |
28
|
|
|
private $_config; |
29
|
|
|
private $_http; |
30
|
|
|
|
31
|
|
|
public function __construct($gateway) |
32
|
|
|
{ |
33
|
|
|
$this->_gateway = $gateway; |
34
|
|
|
$this->_config = $gateway->config; |
35
|
|
|
$this->_config->assertHasAccessTokenOrKeys(); |
36
|
|
|
$this->_http = new Http($gateway->config); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
|
40
|
|
|
public function create($attribs) |
41
|
|
|
{ |
42
|
|
|
Util::verifyKeys(self::createSignature(), $attribs); |
43
|
|
|
return $this->_doCreate('/payment_methods', ['payment_method' => $attribs]); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* find a PaymentMethod by token |
48
|
|
|
* |
49
|
|
|
* @param string $token payment method unique id |
50
|
|
|
* @return CreditCard|PayPalAccount |
51
|
|
|
* @throws Exception\NotFound |
52
|
|
|
*/ |
53
|
|
|
public function find($token) |
54
|
|
|
{ |
55
|
|
|
$this->_validateId($token); |
56
|
|
|
try { |
57
|
|
|
$path = $this->_config->merchantPath() . '/payment_methods/any/' . $token; |
58
|
|
|
$response = $this->_http->get($path); |
59
|
|
|
if (isset($response['creditCard'])) { |
60
|
|
|
return CreditCard::factory($response['creditCard']); |
61
|
|
|
} else if (isset($response['paypalAccount'])) { |
62
|
|
|
return PayPalAccount::factory($response['paypalAccount']); |
63
|
|
|
} else if (isset($response['coinbaseAccount'])) { |
64
|
|
|
return CoinbaseAccount::factory($response['coinbaseAccount']); |
65
|
|
|
} else if (isset($response['applePayCard'])) { |
66
|
|
|
return ApplePayCard::factory($response['applePayCard']); |
67
|
|
|
} else if (isset($response['androidPayCard'])) { |
68
|
|
|
return AndroidPayCard::factory($response['androidPayCard']); |
69
|
|
|
} else if (isset($response['amexExpressCheckoutCard'])) { |
70
|
|
|
return AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']); |
71
|
|
|
} else if (isset($response['europeBankAccount'])) { |
72
|
|
|
return EuropeBankAccount::factory($response['europeBankAccount']); |
73
|
|
|
} else if (isset($response['usBankAccount'])) { |
74
|
|
|
return UsBankAccount::factory($response['usBankAccount']); |
75
|
|
|
} else if (isset($response['venmoAccount'])) { |
76
|
|
|
return VenmoAccount::factory($response['venmoAccount']); |
77
|
|
|
} else if (is_array($response)) { |
78
|
|
|
return UnknownPaymentMethod::factory($response); |
79
|
|
|
} |
80
|
|
|
} catch (Exception\NotFound $e) { |
81
|
|
|
throw new Exception\NotFound( |
82
|
|
|
'payment method with token ' . $token . ' not found' |
83
|
|
|
); |
84
|
|
|
} |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
public function update($token, $attribs) |
88
|
|
|
{ |
89
|
|
|
Util::verifyKeys(self::updateSignature(), $attribs); |
90
|
|
|
return $this->_doUpdate('/payment_methods/any/' . $token, ['payment_method' => $attribs]); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
View Code Duplication |
public function delete($token) |
|
|
|
|
94
|
|
|
{ |
95
|
|
|
$this->_validateId($token); |
96
|
|
|
$path = $this->_config->merchantPath() . '/payment_methods/any/' . $token; |
97
|
|
|
$this->_http->delete($path); |
98
|
|
|
return new Result\Successful(); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function grant($sharedPaymentMethodToken, $allowVaulting) |
102
|
|
|
{ |
103
|
|
|
return $this->_doCreate( |
104
|
|
|
'/payment_methods/grant', |
105
|
|
|
[ |
106
|
|
|
'payment_method' => [ |
107
|
|
|
'shared_payment_method_token' => $sharedPaymentMethodToken, |
108
|
|
|
'allow_vaulting' => $allowVaulting |
109
|
|
|
] |
110
|
|
|
] |
111
|
|
|
); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
public function revoke($sharedPaymentMethodToken) |
115
|
|
|
{ |
116
|
|
|
return $this->_doCreate( |
117
|
|
|
'/payment_methods/revoke', |
118
|
|
|
[ |
119
|
|
|
'payment_method' => [ |
120
|
|
|
'shared_payment_method_token' => $sharedPaymentMethodToken |
121
|
|
|
] |
122
|
|
|
] |
123
|
|
|
); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
private static function baseSignature() |
127
|
|
|
{ |
128
|
|
|
$billingAddressSignature = AddressGateway::createSignature(); |
129
|
|
|
$optionsSignature = [ |
130
|
|
|
'failOnDuplicatePaymentMethod', |
131
|
|
|
'makeDefault', |
132
|
|
|
'verificationMerchantAccountId', |
133
|
|
|
'verifyCard', |
134
|
|
|
'verificationAmount' |
135
|
|
|
]; |
136
|
|
|
return [ |
137
|
|
|
'billingAddressId', |
138
|
|
|
'cardholderName', |
139
|
|
|
'cvv', |
140
|
|
|
'deviceData', |
141
|
|
|
'expirationDate', |
142
|
|
|
'expirationMonth', |
143
|
|
|
'expirationYear', |
144
|
|
|
'number', |
145
|
|
|
'paymentMethodNonce', |
146
|
|
|
'token', |
147
|
|
|
['options' => $optionsSignature], |
148
|
|
|
['billingAddress' => $billingAddressSignature] |
149
|
|
|
]; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
public static function createSignature() |
153
|
|
|
{ |
154
|
|
|
$signature = array_merge(self::baseSignature(), ['customerId']); |
155
|
|
|
return $signature; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public static function updateSignature() |
159
|
|
|
{ |
160
|
|
|
$billingAddressSignature = AddressGateway::updateSignature(); |
161
|
|
|
array_push($billingAddressSignature, [ |
162
|
|
|
'options' => [ |
163
|
|
|
'updateExisting' |
164
|
|
|
] |
165
|
|
|
]); |
166
|
|
|
$signature = array_merge(self::baseSignature(), [ |
167
|
|
|
'deviceSessionId', |
168
|
|
|
'venmoSdkPaymentMethodCode', |
169
|
|
|
'fraudMerchantId', |
170
|
|
|
['billingAddress' => $billingAddressSignature] |
171
|
|
|
]); |
172
|
|
|
return $signature; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* sends the create request to the gateway |
177
|
|
|
* |
178
|
|
|
* @ignore |
179
|
|
|
* @param string $subPath |
180
|
|
|
* @param array $params |
181
|
|
|
* @return mixed |
182
|
|
|
*/ |
183
|
|
View Code Duplication |
public function _doCreate($subPath, $params) |
|
|
|
|
184
|
|
|
{ |
185
|
|
|
$fullPath = $this->_config->merchantPath() . $subPath; |
186
|
|
|
$response = $this->_http->post($fullPath, $params); |
187
|
|
|
|
188
|
|
|
return $this->_verifyGatewayResponse($response); |
|
|
|
|
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* sends the update request to the gateway |
193
|
|
|
* |
194
|
|
|
* @ignore |
195
|
|
|
* @param string $subPath |
196
|
|
|
* @param array $params |
197
|
|
|
* @return mixed |
198
|
|
|
*/ |
199
|
|
View Code Duplication |
public function _doUpdate($subPath, $params) |
|
|
|
|
200
|
|
|
{ |
201
|
|
|
$fullPath = $this->_config->merchantPath() . $subPath; |
202
|
|
|
$response = $this->_http->put($fullPath, $params); |
203
|
|
|
|
204
|
|
|
return $this->_verifyGatewayResponse($response); |
|
|
|
|
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* generic method for validating incoming gateway responses |
209
|
|
|
* |
210
|
|
|
* creates a new CreditCard or PayPalAccount object |
211
|
|
|
* and encapsulates it inside a Result\Successful object, or |
212
|
|
|
* encapsulates a Errors object inside a Result\Error |
213
|
|
|
* alternatively, throws an Unexpected exception if the response is invalid. |
214
|
|
|
* |
215
|
|
|
* @ignore |
216
|
|
|
* @param array $response gateway response values |
217
|
|
|
* @return Result\Successful|Result\Error |
218
|
|
|
* @throws Exception\Unexpected |
219
|
|
|
*/ |
220
|
|
|
private function _verifyGatewayResponse($response) |
221
|
|
|
{ |
222
|
|
|
if (isset($response['creditCard'])) { |
223
|
|
|
return new Result\Successful( |
224
|
|
|
CreditCard::factory($response['creditCard']), |
|
|
|
|
225
|
|
|
'paymentMethod' |
|
|
|
|
226
|
|
|
); |
227
|
|
|
} else if (isset($response['paypalAccount'])) { |
228
|
|
|
return new Result\Successful( |
229
|
|
|
PayPalAccount::factory($response['paypalAccount']), |
|
|
|
|
230
|
|
|
"paymentMethod" |
|
|
|
|
231
|
|
|
); |
232
|
|
|
} else if (isset($response['coinbaseAccount'])) { |
233
|
|
|
return new Result\Successful( |
234
|
|
|
CoinbaseAccount::factory($response['coinbaseAccount']), |
|
|
|
|
235
|
|
|
"paymentMethod" |
|
|
|
|
236
|
|
|
); |
237
|
|
|
} else if (isset($response['applePayCard'])) { |
238
|
|
|
return new Result\Successful( |
239
|
|
|
ApplePayCard::factory($response['applePayCard']), |
|
|
|
|
240
|
|
|
"paymentMethod" |
|
|
|
|
241
|
|
|
); |
242
|
|
|
} else if (isset($response['androidPayCard'])) { |
243
|
|
|
return new Result\Successful( |
244
|
|
|
AndroidPayCard::factory($response['androidPayCard']), |
|
|
|
|
245
|
|
|
"paymentMethod" |
|
|
|
|
246
|
|
|
); |
247
|
|
|
} else if (isset($response['amexExpressCheckoutCard'])) { |
248
|
|
|
return new Result\Successful( |
249
|
|
|
AmexExpressCheckoutCard::factory($response['amexExpressCheckoutCard']), |
|
|
|
|
250
|
|
|
"paymentMethod" |
|
|
|
|
251
|
|
|
); |
252
|
|
|
} else if (isset($response['europeBankAccount'])) { |
253
|
|
|
return new Result\Successful( |
254
|
|
|
EuropeBankAccount::factory($response['europeBankAccount']), |
|
|
|
|
255
|
|
|
"paymentMethod" |
|
|
|
|
256
|
|
|
); |
257
|
|
|
} else if (isset($response['usBankAccount'])) { |
258
|
|
|
return new Result\Successful( |
259
|
|
|
UsBankAccount::factory($response['usBankAccount']), |
|
|
|
|
260
|
|
|
"paymentMethod" |
|
|
|
|
261
|
|
|
); |
262
|
|
|
} else if (isset($response['venmoAccount'])) { |
263
|
|
|
return new Result\Successful( |
264
|
|
|
VenmoAccount::factory($response['venmoAccount']), |
|
|
|
|
265
|
|
|
"paymentMethod" |
|
|
|
|
266
|
|
|
); |
267
|
|
View Code Duplication |
} else if (isset($response['paymentMethodNonce'])) { |
|
|
|
|
268
|
|
|
return new Result\Successful( |
269
|
|
|
PaymentMethodNonce::factory($response['paymentMethodNonce']), |
|
|
|
|
270
|
|
|
"paymentMethodNonce" |
|
|
|
|
271
|
|
|
); |
272
|
|
|
} else if (isset($response['apiErrorResponse'])) { |
273
|
|
|
return new Result\Error($response['apiErrorResponse']); |
274
|
|
|
} else if (is_array($response)) { |
275
|
|
|
return new Result\Successful( |
276
|
|
|
UnknownPaymentMethod::factory($response), |
|
|
|
|
277
|
|
|
"paymentMethod" |
|
|
|
|
278
|
|
|
); |
279
|
|
|
} else { |
280
|
|
|
throw new Exception\Unexpected( |
281
|
|
|
'Expected payment method or apiErrorResponse' |
282
|
|
|
); |
283
|
|
|
} |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* verifies that a valid payment method identifier is being used |
288
|
|
|
* @ignore |
289
|
|
|
* @param string $identifier |
290
|
|
|
* @param Optional $string $identifierType type of identifier supplied, default 'token' |
|
|
|
|
291
|
|
|
* @throws InvalidArgumentException |
292
|
|
|
*/ |
293
|
|
View Code Duplication |
private function _validateId($identifier = null, $identifierType = 'token') |
|
|
|
|
294
|
|
|
{ |
295
|
|
|
if (empty($identifier)) { |
296
|
|
|
throw new InvalidArgumentException( |
297
|
|
|
'expected payment method id to be set' |
298
|
|
|
); |
299
|
|
|
} |
300
|
|
|
if (!preg_match('/^[0-9A-Za-z_-]+$/', $identifier)) { |
301
|
|
|
throw new InvalidArgumentException( |
302
|
|
|
$identifier . ' is an invalid payment method ' . $identifierType . '.' |
303
|
|
|
); |
304
|
|
|
} |
305
|
|
|
} |
306
|
|
|
} |
307
|
|
|
class_alias('Braintree\PaymentMethodGateway', 'Braintree_PaymentMethodGateway'); |
308
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.