|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
*@author nicolaas [at] sunny side up. co . nz |
|
5
|
|
|
* |
|
6
|
|
|
* |
|
7
|
|
|
**/ |
|
8
|
|
|
|
|
9
|
|
|
|
|
10
|
|
|
class DpsPxPayStoredPayment extends DpsPxPayPayment |
|
|
|
|
|
|
11
|
|
|
{ |
|
12
|
|
|
private static $pxaccess_url = 'https://sec.paymentexpress.com/pxpay/pxaccess.aspx'; |
|
|
|
|
|
|
13
|
|
|
|
|
14
|
|
|
private static $pxpost_url = 'https://sec.paymentexpress.com/pxpost.aspx'; |
|
|
|
|
|
|
15
|
|
|
|
|
16
|
|
|
private static $username = ''; |
|
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
private static $password = ''; |
|
|
|
|
|
|
19
|
|
|
|
|
20
|
|
|
private static $add_card_explanation = "Storing a Card means your Credit Card will be kept on file for your next purchase. "; |
|
|
|
|
|
|
21
|
|
|
|
|
22
|
|
|
public function getPaymentFormFields() |
|
23
|
|
|
{ |
|
24
|
|
|
$logo = '<img src="' . self::$logo . '" alt="Credit Card Payments Powered by DPS"/>'; |
|
|
|
|
|
|
25
|
|
|
$privacyLink = '<a href="' . self::$privacy_link . '" target="_blank" title="Read DPS\'s privacy policy">' . $logo . '</a><br/>'; |
|
|
|
|
|
|
26
|
|
|
$paymentsList = ''; |
|
27
|
|
|
foreach (self::$credit_cards as $name => $image) { |
|
|
|
|
|
|
28
|
|
|
$paymentsList .= '<img src="' . $image . '" alt="' . $name . '"/>'; |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
|
|
$fields = new FieldList(); |
|
32
|
|
|
$storedCards = null; |
|
33
|
|
|
if ($m = Member::currentUser()) { |
|
34
|
|
|
$storedCards = DpsPxPayStoredCard::get()->filter(array("MemberID" => $m->ID)); |
|
35
|
|
|
} |
|
36
|
|
|
|
|
37
|
|
|
$cardsDropdown = array('' => ' --- Select Stored Card ---'); |
|
38
|
|
|
|
|
39
|
|
|
if ($storedCards->count()) { |
|
40
|
|
|
foreach ($storedCards as $card) { |
|
|
|
|
|
|
41
|
|
|
$cardsDropdown[$card->BillingID] = $card->CardHolder.' - '.$card->CardNumber.' ('.$card->CardName.')'; |
|
42
|
|
|
} |
|
43
|
|
|
$s = ""; |
|
44
|
|
|
if ($storedCards->count()>1) { |
|
45
|
|
|
$s = "s"; |
|
46
|
|
|
} |
|
47
|
|
|
$cardsDropdown["deletecards"] = " --- Delete Stored Card$s --- "; |
|
48
|
|
|
$fields->push(new DropdownField('DPSUseStoredCard', 'Use a stored card?', $cardsDropdown, $value = $card->BillingID, $form = null, $emptyString = "--- use new Credit Card ---")); |
|
|
|
|
|
|
49
|
|
|
} else { |
|
50
|
|
|
$fields->push(new DropdownField('DPSStoreCard', '', array(1 => 'Store Credit Card', 0 => 'Do NOT Store Credit Card'))); |
|
51
|
|
|
$fields->push(new LiteralField("AddCardExplanation", "<p>".Config::inst()->get('DpsPxPayStoredPayment', 'add_card_explanation')."</p>")); |
|
52
|
|
|
} |
|
53
|
|
|
$fields->push(new LiteralField('DPSInfo', $privacyLink)); |
|
54
|
|
|
$fields->push(new LiteralField('DPSPaymentsList', $paymentsList)); |
|
55
|
|
|
Requirements::javascript(THIRDPARTY_DIR."/jquery/jquery.js"); |
|
56
|
|
|
//Requirements::block(THIRDPARTY_DIR."/jquery/jquery.js"); |
|
|
|
|
|
|
57
|
|
|
//Requirements::javascript(Director::protocol()."ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"); |
|
|
|
|
|
|
58
|
|
|
Requirements::javascript("payment_dps/javascript/DpxPxPayStoredPayment.js"); |
|
59
|
|
|
return $fields; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
public function autoProcessPayment($amount, $ref) |
|
63
|
|
|
{ |
|
64
|
|
|
$DPSUrl = $this->buildURL($amount, $ref, false); |
|
|
|
|
|
|
65
|
|
|
/* |
|
|
|
|
|
|
66
|
|
|
add CURL HERE |
|
67
|
|
|
$data = array('page' => $page); |
|
68
|
|
|
// create our curl object |
|
69
|
|
|
$ch = curl_init(); |
|
70
|
|
|
$lurl = 'http://www.test.com'; |
|
71
|
|
|
curl_setopt( $ch, CURLOPT_POST, true ); |
|
72
|
|
|
curl_setopt( $ch, CURLOPT_POSTFIELDS,$data); |
|
73
|
|
|
curl_setopt($ch, CURLOPT_URL, $lurl); |
|
74
|
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,1); |
|
75
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 0); |
|
76
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
|
77
|
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); |
|
78
|
|
|
curl_setopt($ch, CURLOPT_FAILONERROR, 0); |
|
79
|
|
|
$content = curl_exec($ch); |
|
80
|
|
|
curl_close($ch); |
|
81
|
|
|
return $content; |
|
82
|
|
|
*/ |
|
83
|
|
|
} |
|
84
|
|
|
|
|
85
|
|
|
/** |
|
86
|
|
|
* @param array $data The form request data - see OrderForm |
|
87
|
|
|
* @param OrderForm $form The form object submitted on |
|
88
|
|
|
* |
|
89
|
|
|
* @return EcommercePayment_Result |
|
90
|
|
|
*/ |
|
91
|
|
|
public function processPayment($data, $form) |
|
92
|
|
|
{ |
|
93
|
|
|
if (!isset($data["DPSUseStoredCard"])) { |
|
94
|
|
|
$data["DPSUseStoredCard"] = null; |
|
95
|
|
|
} |
|
96
|
|
|
if (!isset($data["DPSStoreCard"])) { |
|
97
|
|
|
$data["DPSStoreCard"] = null; |
|
98
|
|
|
} |
|
99
|
|
|
if (!isset($data["Amount"])) { |
|
100
|
|
|
USER_ERROR("There was no amount information for processing the payment.", E_USER_WARNING); |
|
101
|
|
|
} |
|
102
|
|
|
if ($data["DPSUseStoredCard"] == "deletecards") { |
|
103
|
|
|
//important!!! |
|
104
|
|
|
$data["DPSUseStoredCard"] = null; |
|
105
|
|
|
if ($m = Member::currentUser()) { |
|
106
|
|
|
$storedCards = DpsPxPayStoredCard::get()->filter(array("MemberID" => $m->ID)); |
|
107
|
|
|
if ($storedCards->count()) { |
|
108
|
|
|
foreach ($storedCards as $card) { |
|
109
|
|
|
$card->delete(); |
|
110
|
|
|
} |
|
111
|
|
|
if ($storedCards = DpsPxPayStoredCard::get()->filter(array("MemberID" => $m->ID))) { |
|
|
|
|
|
|
112
|
|
|
DB::query("DELETE FROM DpsPxPayStoredCard WHERE MemberID = ".$m->ID); |
|
113
|
|
|
} |
|
114
|
|
|
} |
|
115
|
|
|
} |
|
116
|
|
|
} elseif ($data["DPSUseStoredCard"]) { |
|
117
|
|
|
return $this->processViaPostRatherThanPxPay($data, $form, $data["DPSUseStoredCard"]); |
|
118
|
|
|
} |
|
119
|
|
|
$url = $this->buildURL($data["Amount"], $data["DPSUseStoredCard"], $data["DPSStoreCard"]); |
|
120
|
|
|
return $this->executeURL($url); |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
|
|
124
|
|
|
|
|
125
|
|
|
|
|
126
|
|
|
public function processViaPostRatherThanPxPay($data, $form, $cardToUse) |
|
|
|
|
|
|
127
|
|
|
{ |
|
128
|
|
|
|
|
129
|
|
|
// 1) Main Settings |
|
130
|
|
|
|
|
131
|
|
|
$inputs['PostUsername'] = $this->config->get("username"); |
|
|
|
|
|
|
132
|
|
|
$inputs['PostPassword'] = $this->config->get("password"); |
|
|
|
|
|
|
133
|
|
|
|
|
134
|
|
|
// 2) Payment Informations |
|
135
|
|
|
|
|
136
|
|
|
$inputs['Amount'] = $this->Amount->Amount; |
|
|
|
|
|
|
137
|
|
|
$inputs['InputCurrency'] = $this->Amount->Currency; |
|
|
|
|
|
|
138
|
|
|
$inputs['TxnId'] = $this->ID; |
|
139
|
|
|
$inputs['TxnType'] = DpsPxPayComs::get_txn_type(); |
|
140
|
|
|
$inputs["MerchantReference"] = $this->ID; |
|
141
|
|
|
|
|
142
|
|
|
// 3) Credit Card Informations |
|
143
|
|
|
$inputs["DpsBillingId"] = $cardToUse; |
|
144
|
|
|
|
|
145
|
|
|
|
|
146
|
|
|
// 4) DPS Transaction Sending |
|
147
|
|
|
|
|
148
|
|
|
$responseFields = $this->doPayment($inputs); |
|
149
|
|
|
// 5) DPS Response Management |
|
150
|
|
|
|
|
151
|
|
|
if (isset($responseFields['SUCCESS']) && $responseFields['SUCCESS']) { |
|
152
|
|
|
$this->Status = 'Success'; |
|
|
|
|
|
|
153
|
|
|
$result = EcommercePayment_Success::create(); |
|
154
|
|
|
} else { |
|
155
|
|
|
$this->Status = 'Failure'; |
|
|
|
|
|
|
156
|
|
|
$result = EcommercePayment_Failure::create(); |
|
157
|
|
|
} |
|
158
|
|
|
if (isset($responseFields['DPSTXNREF'])) { |
|
159
|
|
|
if ($transactionRef = $responseFields['DPSTXNREF']) { |
|
160
|
|
|
$this->TxnRef = $transactionRef; |
|
|
|
|
|
|
161
|
|
|
} |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
if (isset($responseFields['HELPTEXT'])) { |
|
165
|
|
|
if ($helpText = $responseFields['HELPTEXT']) { |
|
166
|
|
|
$this->Message = $helpText; |
|
|
|
|
|
|
167
|
|
|
} |
|
168
|
|
|
} |
|
169
|
|
|
if (isset($responseFields['RESPONSETEXT'])) { |
|
170
|
|
|
if ($responseText = $responseFields['RESPONSETEXT']) { |
|
171
|
|
|
$this->Message .= $responseText; |
|
|
|
|
|
|
172
|
|
|
} |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
$this->write(); |
|
176
|
|
|
return $result; |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
public function doPayment(array $inputs) |
|
|
|
|
|
|
180
|
|
|
{ |
|
181
|
|
|
|
|
182
|
|
|
// 1) Transaction Creation |
|
183
|
|
|
$transaction = "<Txn>"; |
|
184
|
|
|
foreach ($inputs as $name => $value) { |
|
185
|
|
|
if ($name == "Amount") { |
|
186
|
|
|
$value = number_format($value, 2, '.', ''); |
|
187
|
|
|
} |
|
188
|
|
|
$transaction .= "<$name>$value</$name>"; |
|
189
|
|
|
} |
|
190
|
|
|
$transaction .= "</Txn>"; |
|
191
|
|
|
|
|
192
|
|
|
// 2) CURL Creation |
|
193
|
|
|
$clientURL = curl_init(); |
|
194
|
|
|
curl_setopt($clientURL, CURLOPT_URL, $this->config()-get("pxpost_url")); |
|
195
|
|
|
curl_setopt($clientURL, CURLOPT_POST, 1); |
|
196
|
|
|
curl_setopt($clientURL, CURLOPT_POSTFIELDS, $transaction); |
|
197
|
|
|
curl_setopt($clientURL, CURLOPT_RETURNTRANSFER, 1); |
|
198
|
|
|
//curl_setopt($clientURL, CURLOPT_SSLVERSION, 3); |
|
|
|
|
|
|
199
|
|
|
|
|
200
|
|
|
// 3) CURL Execution |
|
201
|
|
|
|
|
202
|
|
|
$resultXml = curl_exec($clientURL); |
|
203
|
|
|
|
|
204
|
|
|
// 4) CURL Closing |
|
205
|
|
|
|
|
206
|
|
|
curl_close($clientURL); |
|
207
|
|
|
|
|
208
|
|
|
// 5) XML Parser Creation |
|
209
|
|
|
|
|
210
|
|
|
$xmlParser = xml_parser_create(); |
|
211
|
|
|
$values = null; |
|
212
|
|
|
$indexes = null; |
|
213
|
|
|
xml_parse_into_struct($xmlParser, $resultXml, $values, $indexes); |
|
214
|
|
|
xml_parser_free($xmlParser); |
|
215
|
|
|
|
|
216
|
|
|
// 6) XML Result Parsed In A PHP Array |
|
217
|
|
|
|
|
218
|
|
|
$resultPhp = array(); |
|
219
|
|
|
$level = array(); |
|
220
|
|
|
foreach ($values as $xmlElement) { |
|
221
|
|
|
if ($xmlElement['type'] == 'open') { |
|
222
|
|
|
if (array_key_exists('attributes', $xmlElement)) { |
|
223
|
|
|
$arrayValues = array_values($xmlElement['attributes']); |
|
224
|
|
|
list($level[$xmlElement['level']], $extra) = $arrayValues; |
|
|
|
|
|
|
225
|
|
|
} else { |
|
226
|
|
|
$level[$xmlElement['level']] = $xmlElement['tag']; |
|
227
|
|
|
} |
|
228
|
|
|
} elseif ($xmlElement['type'] == 'complete') { |
|
229
|
|
|
$startLevel = 1; |
|
230
|
|
|
$phpArray = '$resultPhp'; |
|
231
|
|
|
while ($startLevel < $xmlElement['level']) { |
|
232
|
|
|
$phpArray .= '[$level['. $startLevel++ .']]'; |
|
233
|
|
|
} |
|
234
|
|
|
$phpArray .= '[$xmlElement[\'tag\']] = array_key_exists(\'value\', $xmlElement)? $xmlElement[\'value\'] : null;'; |
|
235
|
|
|
eval($phpArray); |
|
|
|
|
|
|
236
|
|
|
} |
|
237
|
|
|
} |
|
238
|
|
|
if (!isset($resultPhp['TXN'])) { |
|
239
|
|
|
return false; |
|
240
|
|
|
} |
|
241
|
|
|
$result = $resultPhp['TXN']; |
|
242
|
|
|
return $result; |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
|
|
246
|
|
|
|
|
247
|
|
|
protected function buildURL($amount, $cardToUse = '', $storeCard = false) |
|
|
|
|
|
|
248
|
|
|
{ |
|
249
|
|
|
$commsObject = new DpsPxPayComs(); |
|
250
|
|
|
|
|
251
|
|
|
/** |
|
252
|
|
|
* order details |
|
253
|
|
|
**/ |
|
254
|
|
|
$commsObject->setTxnType(DpsPxPayComs::get_txn_type()); |
|
255
|
|
|
$commsObject->setMerchantReference($this->ID); |
|
256
|
|
|
//replace any character that is NOT [0-9] or dot (.) |
|
257
|
|
|
$commsObject->setAmountInput(floatval(preg_replace("/[^0-9\.]/", "", $amount))); |
|
258
|
|
|
|
|
259
|
|
|
if (isset($cardToUse)) { |
|
260
|
|
|
$commsObject->setBillingId($cardToUse); |
|
261
|
|
|
} elseif ($storeCard) { |
|
262
|
|
|
$commsObject->setEnableAddBillCard(1); |
|
263
|
|
|
} |
|
264
|
|
|
|
|
265
|
|
|
/** |
|
266
|
|
|
* details of the redirection |
|
267
|
|
|
**/ |
|
268
|
|
|
$link = DpsPxPayStoredPayment_Handler::absolute_complete_link(); |
|
269
|
|
|
$commsObject->setUrlFail($link); |
|
270
|
|
|
$commsObject->setUrlSuccess($link); |
|
271
|
|
|
|
|
272
|
|
|
/** |
|
273
|
|
|
* process payment data (check if it is OK and go forward if it is... |
|
274
|
|
|
**/ |
|
275
|
|
|
$url = $commsObject->startPaymentProcess(); |
|
276
|
|
|
|
|
277
|
|
|
return $url; |
|
278
|
|
|
} |
|
279
|
|
|
} |
|
280
|
|
|
|
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.