1 <?php
2
3 class SberbankPayment extends PaymentMethod {
4 static $db = array(
5 'TestMode' => 'Boolean',
6 'BaseURL' => 'Varchar(150)',
7
8 'Login' => 'Varchar(150)',
9 'Password' => 'Varchar(150)',
10
11 'TestLogin' => 'Varchar(150)',
12 'TestPassword' => 'Varchar(150)',
13
14 'TaxSystem' => "Enum('0, 1, 2, 3, 4, 5')",
15 );
16
17 static $defaults = array(
18 'BaseURL' => 'https://3dsec.sberbank.ru/payment/rest/',
19 );
20
21 static $paymentMethodIcons = array(
22 'cart_payment/img/SberbankPayment.png',
23 );
24
25 26 27 28 29
30 static function getPaymentMethod() {
31 return DataObject::get_one('SberbankPayment', 'Active = 1');
32 }
33
34 static $errorCodes = array(
35 1 => 'Заказ с таким номером уже зарегистрирован в системе',
36 3 => 'Неизвестная (запрещенная) валюта',
37 4 => 'Отсутствует обязательный параметр запроса',
38 5 => 'Ошибка значение параметра запроса',
39 7 => 'Системная ошибка',
40 );
41
42 static $orderStatuses = array(
43 0 => 'Заказ зарегистрирован, но не оплачен',
44 1 => 'Предавторизованная сумма захолдирована',
45 2 => 'Проведена полная авторизация суммы заказа',
46 3 => 'Авторизация отменена',
47 4 => 'По транзакции была проведена операция возврата',
48 5 => 'Инициирована авторизация через ACS банка-эмитента',
49 6 => 'Авторизация отклонена',
50 );
51
52 function onBeforeWrite() {
53 parent::onBeforeWrite();
54 }
55
56 function getTaxSystems() {
57 $rs = array();
58 foreach($this->dbObject('TaxSystem')->enumValues() as $type) {
59 $rs[$type] = _t('SberbankPayment.TaxSystem_' . $type, $type);
60 }
61 return $rs;
62 }
63
64 function getPaymentHandler() {
65 return 'SberbankPayment_Handler';
66 }
67
68 function getCMSFields() {
69 $fields = parent::getCMSFields();
70 $fields->findOrMakeTab('Root.Settings', _t('PaymentMethod.tab_Settings','Settings'));
71
72 $fields->addFieldToTab('Root.Settings', new DropdownField('TaxSystem', $this->fieldLabel('TaxSystem'), $this->getTaxSystems()));
73
74 $fields->addFieldToTab('Root.Settings', new HeaderField('WorkSettings', _t('PaymentMethod.WorkSettings', 'Work Settings')));
75 $fields->addFieldToTab('Root.Settings', $fields->dataFieldByName('BaseURL'));
76
77 $fields->addFieldToTab('Root.Settings', $fields->dataFieldByName('Login'));
78 $fields->addFieldToTab('Root.Settings', $fields->dataFieldByName('Password'));
79
80 $fields->addFieldToTab('Root.Settings', new HeaderField('TestSettings', _t('PaymentMethod.TestSettings', 'Test Settings')));
81
82 $fields->addFieldToTab('Root.Settings', $fields->dataFieldByName('TestLogin'));
83 $fields->addFieldToTab('Root.Settings', $fields->dataFieldByName('TestPassword'));
84
85 return $fields;
86 }
87
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
117
118 function Login() {
119 return ($this->TestMode) ? $this->TestLogin : $this->Login;
120 }
121
122 function Password() {
123 return ($this->TestMode) ? urlencode($this->TestPassword) : urlencode($this->Password);
124 }
125
126
127 function processPayment($payment) {
128 return new Payment_Processing($this->paymentLink($payment->ID));
129
130 131 132 133 134 135 136
137 }
138
139 function getOrderBundleData($payment) {
140 $order = $payment->PaidObject();
141 if (!$order) {
142 return false;
143 }
144 $bundleData = array();
145 $bundleData['orderCreationDate'] = strtotime($order->Created);
146
147
148 if ($order->Email || $order->Phone) {
149 $customerDetails = array();
150 if ($order->Email) {
151 $customerDetails['email'] = $order->Email;
152 }
153 if ($order->Phone) {
154 $customerDetails['phone'] = str_replace('+7', '8', $order->Phone);
155 }
156 if ($order->ClientName) {
157 $customerDetails['contact'] = $order->ClientName;
158 }
159 if ($order->ShippingMethodID && ($method = $order->ShippingMethod())) {
160 if ($order->Country && $order->City && $order->Address) {
161 $deliveryInfo = array();
162 $deliveryInfo['deliveryType'] = $method->Name;
163 $deliveryInfo['country'] = $order->Country;
164 $deliveryInfo['city'] = $order->City;
165 $deliveryInfo['postAddress'] = $order->Address;
166 $customerDetails['deliveryInfo'] = $deliveryInfo;
167 }
168 }
169 $bundleData['customerDetails'] = $customerDetails;
170 }
171
172
173 $items = array();
174 $i = 1;
175 foreach($order->Items() as $item) {
176 $itm = array();
177 $itm['positionId'] = $i;
178 $itm['name'] = $item->Title;
179
180
181
182
183
184
185 $itm['quantity'] = array(
186 'value' => $item->Quantity,
187 'measure' => _t('SberbankPayment.OrderItemMeasure'),
188 );
189
190 $itm['itemPrice'] = $item->ItemPrice * 100;
191 $itm['itemAmount'] = $item->getItemsPrice() * 100;
192 $itm['itemCode'] = $item->LinkedID;
193
194
195
196
197
198 if (singleton('Product')->hasMethod('getVAT')) {
199 $itm['tax'] = array();
200 $vat = $item->getProduct()->getVAT();
201 $itm['tax']['taxType'] = $vat->YaKassaCode;
202 }
203 $items[] = $itm;
204 $i++;
205 }
206 $bundleData['cartItems'] = array('items' => $items);
207 return $bundleData;
208 }
209
210 211 212 213 214
215 function createSberbankPayment($payment) {
216 $amount = $payment->Amount * 100;
217 $createLink = $this->BaseURL . "register.do?userName={$this->Login()}&password={$this->Password()}&orderNumber={$payment->ID}&amount={$amount}&returnUrl=" . Director::absoluteURL(SberbankPayment_Handler::success_link()) . "&failUrl=" . Director::absoluteURL(SberbankPayment_Handler::error_link());
218 if ($orderBundle = $this->getOrderBundleData($payment)) {
219 $createLink .= "&taxSystem={$this->TaxSystem}&orderBundle=" . urlencode(json_encode($orderBundle));
220 }
221 echo '**'.$createLink.'**';
222
223 $answer = file_get_contents($createLink);
224 $rs = json_decode($answer, true);
225 echo '<pre>';
226 print_r($rs);
227 echo '</pre>';
228 die;
229 if ($rs && is_array($rs)) {
230 if (isset($rs['errorCode']) && ($rs['errorCode'] != 0)) {
231 $payment->Status = 'Failure';
232 $payment->ExceptionError = $rs['errorMessage'] . '___' . $createLink;
233 $payment->write();
234 return new Payment_Failure($payment->ExceptionError);
235 } else {
236 $payment->Status = 'Pending';
237 $payment->SberbankPaymentID = $rs['orderId'];
238 $payment->TransactionID = $rs['orderId'];
239 $payment->SberbankBackURL = $rs['formUrl'];
240 $payment->write();
241 return new Payment_Processing($payment->SberbankBackURL);
242 }
243 } else {
244 $payment->Status = 'Failure';
245 $payment->ExceptionError = $answer;
246 $payment->write();
247 return new Payment_Failure($payment->ExceptionError);
248 }
249 }
250
251 252 253 254 255
256 function checkSberbankPayment($payment) {
257 $answer = file_get_contents($this->BaseURL . "getOrderStatus.do?userName={$this->Login()}&password={$this->Password()}&orderId={$payment->SberbankPaymentID}");
258 $payment->PaymentResponse = $answer;
259 $payment->write();
260 $rs = json_decode($answer, true);
261 if ($rs && is_array($rs)) {
262 if (isset($rs['OrderStatus'])) {
263 if ($rs['OrderStatus'] == 2) {
264 $this->completePayment($payment);
265 return new Payment_Success($payment->Message);
266 } else {
267 $payment->Status = 'Pending';
268 $payment->Message = self::$orderStatuses[$rs['OrderStatus']];
269 $payment->write();
270 return new Payment_Failure($payment->Message);
271 }
272 } else {
273 $payment->Status = 'Failure';
274 $payment->ExceptionError = (isset($rs['ErrorMessage']) ? $rs['ErrorMessage'] : _t('SberbankPayment.NoOrder','No Order'));
275 $payment->write();
276 return new Payment_Failure($payment->ExceptionError);
277 }
278 } else {
279 $payment->Status = 'Failure';
280 $payment->ExceptionError = _t('SberbankPayment.ProcessingError','Processing Error');
281 $payment->write();
282 return new Payment_Failure($payment->ExceptionError);
283 }
284 }
285
286
287 function getClearPaymentLink($payment) {
288 return Director::absoluteURL(SberbankPayment_Handler::create_sber_payment_link($payment->HashLink));
289 }
290
291 292 293 294
295 function completePayment($payment) {
296 if ($payment->Status != 'Success') {
297 $payment->Status = 'Success';
298 $payment->Message = _t('SberbankPayment.DONE', 'Заказ оплачен');
299 $payment->write();
300 }
301 }
302 }
303
304 305 306
307 class SberbankPayment_Handler extends Payment_Handler {
308
309 static $URLSegment = 'sberbank';
310
311 static function success_link() {
312 return self::$URLSegment . '/success';
313 }
314
315 static function error_link() {
316 return self::$URLSegment . '/error';
317 }
318
319 static function create_sber_payment_link($paymentHash) {
320 return self::$URLSegment . "/create_sber_payment/{$paymentHash}";
321 }
322
323
324 function create_sber_payment($request) {
325 if (($orderHash = Convert::raw2sql($request->param('ID'))) && ($payment = DataObject::get_one('Payment', "HashLink = '{$orderHash}'"))) {
326 if ($order = $payment->PaidObject()) {
327 if (($order->Status == 'Unpaid') || ($order->Status == 'Query')) {
328 if (!$payment->isNew()) {
329 $newPayment = $payment->PaymentType()->createPayment($order);
330 unset($payment);
331 $payment = $newPayment;
332 }
333
334 $rs = $payment->PaymentType()->createSberbankPayment($payment);
335 if ($rs->isProcessing()) {
336 $this->redirect($rs->getValue());
337 } else {
338 echo $rs->getValue();
339 }
340 } else {
341 $link = CheckoutPage::find_link('order/' . $order->HashLink);
342 return $this->customise(array(
343 'Result' => _t('Order.CantPayOrder', 'Can not Pay Order'),
344 'Order' => $order,
345 'OrderLink' => $link,
346 ))->renderWith(array('SberbankPayment_error', 'Page' ));
347 }
348 }
349 }
350 }
351
352 function callback() {
353 if (isset($_GET['mdOrder']) && isset($_GET['orderNumber']) && isset($_GET['operation']) && isset($_GET['status'])) {
354 $sbankOrderID = $_GET['mdOrder'];
355 $orderID = (int)$_GET['orderNumber'];
356 $operation = $_GET['operation'];
357 $status = (int)$_GET['status'];
358 if ($status && ($payment = DataObject::get_by_id('Payment', $orderID))) {
359 if ($payment->SberbankPaymentID == $sbankOrderID) {
360 $paymentType = $payment->PaymentType();
361 if ($operation == 'deposited') {
362 $paymentType->completePayment($payment);
363 }
364
365 if ($operation == 'refunded') {
366 }
367 }
368 }
369 }
370 }
371
372 373 374
375 function success() {
376 if (isset($_GET['orderId'])) {
377 $orderID = Convert::raw2sql($_GET['orderId']);
378 if ($payment = DataObject::get_one('Payment', "SberbankPaymentID = '{$orderID}'")) {
379 $paymentType = $payment->PaymentType();
380 $rs = $paymentType->checkSberbankPayment($payment);
381 if ($payment->PaidObject()) {
382 $link = CheckoutPage::find_link('order/' . $payment->PaidObject()->HashLink);
383 return singleton('Page_Controller')->customise(array(
384 'Result' => $rs->getValue(),
385 'Order' => $payment->PaidObject(),
386 'OrderLink' => $link,
387 ))->renderWith(array('SberbankPayment_success', 'Page' ));
388 }
389 }
390 }
391 }
392
393 394 395
396 function error() {
397 if (isset($_GET['orderId'])) {
398 $orderID = Convert::raw2sql($_GET['orderId']);
399 if ($payment = DataObject::get_one('Payment', "SberbankPaymentID = '{$orderID}'")) {
400 $paymentType = $payment->PaymentType();
401 $rs = $paymentType->checkSberbankPayment($payment);
402 if ($payment->PaidObject()) {
403 $link = CheckoutPage::find_link('order/' . $payment->PaidObject()->HashLink);
404 return singleton('Page_Controller')->customise(array(
405 'Result' => $rs->getValue(),
406 'Order' => $payment->PaidObject(),
407 'OrderLink' => $link,
408 ))->renderWith(array('SberbankPayment_error', 'Page' ));
409 }
410 }
411 }
412 }
413 }
414
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-