1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* This file is part of the Marlon Ogone package. |
4
|
|
|
* |
5
|
|
|
* (c) Marlon BVBA <[email protected]> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Ogone; |
12
|
|
|
|
13
|
|
|
use InvalidArgumentException; |
14
|
|
|
use RuntimeException; |
15
|
|
|
use BadMethodCallException; |
16
|
|
|
use Ogone\ShaComposer\ShaComposer; |
17
|
|
|
|
18
|
|
|
abstract class AbstractRequest implements Request |
19
|
|
|
{ |
20
|
|
|
/** @var ShaComposer */ |
21
|
|
|
protected $shaComposer; |
22
|
|
|
|
23
|
|
|
protected $ogoneUri; |
24
|
|
|
|
25
|
|
|
protected $parameters = array(); |
26
|
|
|
|
27
|
|
|
/** Note this is public to allow easy modification, if need be. */ |
28
|
|
|
public $allowedlanguages = array( |
29
|
|
|
'en_US' => 'English', 'cs_CZ' => 'Czech', 'de_DE' => 'German', |
30
|
|
|
'dk_DK' => 'Danish', 'el_GR' => 'Greek', 'es_ES' => 'Spanish', |
31
|
|
|
'fr_FR' => 'French', 'it_IT' => 'Italian', 'ja_JP' => 'Japanese', |
32
|
|
|
'nl_BE' => 'Flemish', 'nl_NL' => 'Dutch', 'no_NO' => 'Norwegian', |
33
|
|
|
'pl_PL' => 'Polish', 'pt_PT' => 'Portugese', 'ru_RU' => 'Russian', |
34
|
|
|
'se_SE' => 'Swedish', 'sk_SK' => 'Slovak', 'tr_TR' => 'Turkish' |
35
|
|
|
); |
36
|
|
|
|
37
|
|
|
protected $ogoneFields = array( |
38
|
|
|
'pspid', 'orderid', 'com', 'amount', 'currency', 'language', 'cn', 'email', |
39
|
|
|
'cardno', 'cvc', 'ed', 'ownerzip', 'owneraddress', 'ownercty', 'ownertown', 'ownertelno', |
40
|
|
|
'homeurl', 'catalogurl', 'accepturl', 'declineurl', 'exceptionurl', 'cancelurl', 'backurl', |
41
|
|
|
'complus', 'paramplus', 'pm', 'brand', 'title', 'bgcolor', 'txtcolor', 'tblbgcolor', |
42
|
|
|
'tbltxtcolor', 'buttonbgcolor', 'buttontxtcolor', 'logo', 'fonttype', 'tp', 'paramvar', |
43
|
|
|
'alias', 'aliasoperation', 'aliasusage', 'aliaspersistedafteruse', 'device', 'pmlisttype', |
44
|
|
|
'ecom_payment_card_verification', 'operation', 'withroot', 'remote_addr', 'rtimeout', |
45
|
|
|
'pmlist', 'exclpmlist', 'creditdebit', 'userid', |
46
|
|
|
// DirectLink with 3-D Secure: Extra request parameters. |
47
|
|
|
// https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/directlink-3-d/3-d-transaction-flow-via-directlink#extrarequestparameters |
48
|
|
|
'flag3d', 'http_accept', 'http_user_agent', 'win3ds', |
49
|
|
|
// Optional integration data: Delivery and Invoicing data. |
50
|
|
|
// https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/additional-data/delivery-and-invoicing-data |
51
|
|
|
'civility', 'cuid', 'ecom_billto_postal_city', 'ecom_billto_postal_countrycode', |
52
|
|
|
'ecom_billto_postal_name_first', 'ecom_billto_postal_name_last', 'ecom_billto_postal_postalcode', |
53
|
|
|
'ecom_billto_postal_street_line1', 'ecom_billto_postal_street_number', 'ecom_shipto_dob', |
54
|
|
|
'ecom_shipto_online_email', 'ecom_shipto_postal_city', 'ecom_shipto_postal_countrycode', |
55
|
|
|
'ecom_shipto_postal_name_first', 'ecom_shipto_postal_name_last', 'ecom_shipto_postal_name_prefix', |
56
|
|
|
'ecom_shipto_postal_postalcode', 'ecom_shipto_postal_state', 'ecom_shipto_postal_street_line1', |
57
|
|
|
'ecom_shipto_postal_street_number', 'ordershipcost', 'ordershipmeth', 'ordershiptaxcode', |
58
|
|
|
// Optional integration data: Order data ("ITEM" parameters). |
59
|
|
|
// https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/additional-data/order-data |
60
|
|
|
'itemattributes*', 'itemcategory*', 'itemcomments*', 'itemdesc*', 'itemdiscount*', |
61
|
|
|
'itemid*', 'itemname*', 'itemprice*', 'itemquant*', 'itemquantorig*', |
62
|
|
|
'itemunitofmeasure*', 'itemvat*', 'itemvatcode*', 'itemweight*', |
63
|
|
|
// Optional integration data: Travel data. |
64
|
|
|
// https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/additional-data/travel-data |
65
|
|
|
'datatype', 'aiairname', 'aitinum', 'aitidate', 'aiconjti', 'aipasname', |
66
|
|
|
'aiextrapasname*', 'aichdet', 'aiairtax', 'aivatamnt', 'aivatappl', 'aitypch', |
67
|
|
|
'aieycd', 'aiirst', 'aiorcity*', 'aiorcityl*', 'aidestcity*', 'aidestcityl*', |
68
|
|
|
'aistopov*', 'aicarrier*', 'aibookind*', 'aiflnum*', 'aifldate*', 'aiclass*', |
69
|
|
|
// Subscription Manager. |
70
|
|
|
// https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/subscription-manager/via-e-commerce-and-directlink#input |
71
|
|
|
'subscription_id', 'sub_amount', 'sub_com', 'sub_orderid', 'sub_period_unit', |
72
|
|
|
'sub_period_number', 'sub_period_moment', 'sub_startdate', 'sub_enddate', |
73
|
|
|
'sub_status', 'sub_comment', |
74
|
|
|
); |
75
|
|
|
|
76
|
|
|
/** @return string */ |
77
|
4 |
|
public function getShaSign() |
78
|
|
|
{ |
79
|
4 |
|
return $this->shaComposer->compose($this->toArray()); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** @return string */ |
83
|
4 |
|
public function getOgoneUri() |
84
|
|
|
{ |
85
|
4 |
|
return $this->ogoneUri; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** Ogone uri to send the customer to. Usually PaymentRequest::TEST or PaymentRequest::PRODUCTION */ |
89
|
15 |
|
public function setOgoneUri($ogoneUri) |
90
|
|
|
{ |
91
|
15 |
|
$this->validateOgoneUri($ogoneUri); |
92
|
10 |
|
$this->ogoneUri = $ogoneUri; |
93
|
10 |
|
} |
94
|
|
|
|
95
|
25 |
View Code Duplication |
public function setPspid($pspid) |
|
|
|
|
96
|
|
|
{ |
97
|
25 |
|
if (strlen($pspid) > 30) { |
98
|
1 |
|
throw new InvalidArgumentException("PSPId is too long"); |
99
|
|
|
} |
100
|
24 |
|
$this->parameters['pspid'] = $pspid; |
101
|
24 |
|
} |
102
|
|
|
|
103
|
6 |
|
public function setSecure() |
104
|
|
|
{ |
105
|
6 |
|
$this->parameters['win3ds'] = 'MAINW'; |
106
|
6 |
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* ISO code eg nl_BE |
110
|
|
|
*/ |
111
|
2 |
|
public function setLanguage($language) |
112
|
|
|
{ |
113
|
2 |
|
if (!array_key_exists($language, $this->allowedlanguages)) { |
114
|
1 |
|
throw new InvalidArgumentException("Invalid language ISO code"); |
115
|
|
|
} |
116
|
1 |
|
$this->parameters['language'] = $language; |
117
|
1 |
|
} |
118
|
|
|
|
119
|
|
|
/** Alias for setCn */ |
120
|
6 |
|
public function setCustomername($customername) |
121
|
|
|
{ |
122
|
6 |
|
$this->setCn($customername); |
123
|
6 |
|
} |
124
|
|
|
|
125
|
6 |
|
public function setCn($cn) |
126
|
|
|
{ |
127
|
6 |
|
$this->parameters['cn'] = str_replace(array("'", '"'), '', $cn); // replace quotes |
128
|
6 |
|
} |
129
|
|
|
|
130
|
|
|
public function setHomeurl($homeurl) |
131
|
|
|
{ |
132
|
|
|
if (!empty($homeurl)) { |
133
|
|
|
$this->validateUri($homeurl); |
134
|
|
|
} |
135
|
|
|
$this->parameters['homeurl'] = $homeurl; |
136
|
|
|
} |
137
|
|
|
|
138
|
6 |
|
public function setAccepturl($accepturl) |
139
|
|
|
{ |
140
|
6 |
|
$this->validateUri($accepturl); |
141
|
5 |
|
$this->parameters['accepturl'] = $accepturl; |
142
|
5 |
|
} |
143
|
|
|
|
144
|
2 |
|
public function setDeclineurl($declineurl) |
145
|
|
|
{ |
146
|
2 |
|
$this->validateUri($declineurl); |
147
|
1 |
|
$this->parameters['declineurl'] = $declineurl; |
148
|
1 |
|
} |
149
|
|
|
|
150
|
6 |
|
public function setExceptionurl($exceptionurl) |
151
|
|
|
{ |
152
|
6 |
|
$this->validateUri($exceptionurl); |
153
|
5 |
|
$this->parameters['exceptionurl'] = $exceptionurl; |
154
|
5 |
|
} |
155
|
|
|
|
156
|
3 |
|
public function setCancelurl($cancelurl) |
157
|
|
|
{ |
158
|
3 |
|
$this->validateUri($cancelurl); |
159
|
1 |
|
$this->parameters['cancelurl'] = $cancelurl; |
160
|
1 |
|
} |
161
|
|
|
|
162
|
1 |
|
public function setBackurl($backurl) |
163
|
|
|
{ |
164
|
1 |
|
$this->validateUri($backurl); |
165
|
1 |
|
$this->parameters['backurl'] = $backurl; |
166
|
1 |
|
} |
167
|
|
|
|
168
|
|
|
/** Alias for setParamplus */ |
169
|
1 |
|
public function setFeedbackParams(array $feedbackParams) |
170
|
|
|
{ |
171
|
1 |
|
$this->setParamplus($feedbackParams); |
172
|
1 |
|
} |
173
|
|
|
|
174
|
1 |
|
public function setParamplus(array $paramplus) |
175
|
|
|
{ |
176
|
1 |
|
$this->parameters['paramplus'] = http_build_query($paramplus); |
177
|
1 |
|
} |
178
|
|
|
|
179
|
25 |
|
public function validate() |
180
|
|
|
{ |
181
|
25 |
|
foreach ($this->getRequiredFields() as $field) { |
182
|
25 |
|
if (empty($this->parameters[$field])) { |
183
|
6 |
|
throw new RuntimeException("$field can not be empty"); |
184
|
|
|
} |
185
|
|
|
} |
186
|
19 |
|
} |
187
|
|
|
|
188
|
23 |
View Code Duplication |
protected function validateUri($uri) |
|
|
|
|
189
|
|
|
{ |
190
|
23 |
|
if (!filter_var($uri, FILTER_VALIDATE_URL)) { |
191
|
6 |
|
throw new InvalidArgumentException("Uri is not valid"); |
192
|
|
|
} |
193
|
17 |
|
if (strlen($uri) > 200) { |
194
|
1 |
|
throw new InvalidArgumentException("Uri is too long"); |
195
|
|
|
} |
196
|
16 |
|
} |
197
|
|
|
|
198
|
15 |
|
protected function validateOgoneUri($uri) |
199
|
|
|
{ |
200
|
15 |
|
$this->validateUri($uri); |
201
|
|
|
|
202
|
14 |
|
if (!in_array($uri, $this->getValidOgoneUris())) { |
203
|
4 |
|
throw new InvalidArgumentException('No valid Ogone url'); |
204
|
|
|
} |
205
|
10 |
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Allows setting ogone parameters that don't have a setter -- usually only |
209
|
|
|
* the unimportant ones like bgcolor, which you'd call with setBgcolor() |
210
|
|
|
* |
211
|
|
|
* @param $method |
212
|
|
|
* @param $args |
213
|
|
|
*/ |
214
|
3 |
|
public function __call($method, $args) |
215
|
|
|
{ |
216
|
3 |
|
if (substr($method, 0, 3) == 'set') { |
217
|
1 |
|
$field = strtolower(substr($method, 3)); |
218
|
|
|
// Also search for numbered fields, like ITEMID1, ITEMID2 etc. |
219
|
1 |
|
$numbered_field = preg_replace('/\d+$/', '*', $field); |
220
|
1 |
|
if (in_array($field, $this->ogoneFields) || in_array($numbered_field, $this->ogoneFields)) { |
221
|
1 |
|
$this->parameters[$field] = $args[0]; |
222
|
1 |
|
return; |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
226
|
3 |
|
if (substr($method, 0, 3) == 'get') { |
227
|
3 |
|
$field = strtolower(substr($method, 3)); |
228
|
3 |
|
if (array_key_exists($field, $this->parameters)) { |
229
|
2 |
|
return $this->parameters[$field]; |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
|
233
|
1 |
|
throw new BadMethodCallException("Unknown method $method"); |
234
|
|
|
} |
235
|
|
|
|
236
|
4 |
|
public function toArray() |
237
|
|
|
{ |
238
|
4 |
|
$this->validate(); |
239
|
4 |
|
return array_change_key_case($this->parameters, CASE_UPPER); |
240
|
|
|
} |
241
|
|
|
} |
242
|
|
|
|
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.