Skip to content

Commit 2280142

Browse files
authored
Merge pull request #20 from yourpayments/qst-api
Qst api
2 parents 079bbe4 + 4c1aaf5 commit 2280142

30 files changed

+2007
-6
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ docker compose up --detach
6161

6262
##### 9. [Страница после оплаты](src/Examples/returnPage.php)
6363

64+
##### 10. Подключение продавцов
65+
1. [Подключение продавца-организации (отправка анкеты)](src/Examples/qstCreateOrg.php)
66+
2. [Подключение продавца-ИП (отправка анкеты)](src/Examples/qstCreateIp.php)
67+
3. [Получение статуса анкеты](src/Examples/qstStatus.php)
68+
4. [Печать анкеты](src/Examples/qstPrint.php)
69+
5. [Список анкет](src/Examples/qstList.php)
70+
6471
## Ссылки
6572
- [НКО «Твои Платежи»](https://YPMN.ru/)
6673
- [Докуметация API](https://ypmn.ru/ru/documentation/)

example.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@
5353
case 'getFasterPayment':
5454
case 'getBindingFasterPayment':
5555
case 'paymentByFasterBinding':
56+
case 'qstCreateOrg':
57+
case 'qstCreateIp':
58+
case 'qstStatus':
59+
case 'qstPrint':
60+
case 'SOMGetPaymentLink':
61+
case 'qstList':
5662
require './src/Examples/start.php';
5763
@include './src/Examples/'.$_GET['function'] . '__prepend.php';
5864
require './src/Examples/'.$_GET['function'] . '.php';

example_list.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,39 @@
131131
'link' => '',
132132
],
133133
'SOMGetPaymentLink' => [
134-
'name' => 'Самая простая кнопка оплаты',
134+
'name' => 'Оплата зарубежными картами',
135135
'about' => 'В этом примере показана простая реализация оплаты заказа зарубежной картой.',
136136
'docLink' => 'https://ypmn.ru/ru/documentation/#tag/payment-api',
137137
'link' => '',
138138
],
139+
'qstCreateOrg' => [
140+
'name' => 'Подключение продавца-организации (отправка анкеты)',
141+
'about' => 'В этом примере показана реализация отправки анкеты подключаемого продавца-организации на проверку в YPMN.',
142+
'docLink' => 'https://ypmn.ru/ru/documentation/#tag/qst-api/paths/~1v4~1qst~1create/post',
143+
'link' => '',
144+
],
145+
'qstCreateIp' => [
146+
'name' => 'Подключение продавца-ИП (отправка анкеты)',
147+
'about' => 'В этом примере показана реализация отправки анкеты подключаемого продавца-ИП на проверку в YPMN.',
148+
'docLink' => 'https://ypmn.ru/ru/documentation/#tag/qst-api/paths/~1v4~1qst~1create/post',
149+
'link' => '',
150+
],
151+
'qstStatus' => [
152+
'name' => 'Получение статуса анкеты',
153+
'about' => 'В этом примере показано получение статуса анкеты по её ID.<br/><br/>ID анкеты возвращается при отправке анкеты на проверку.',
154+
'docLink' => 'https://ypmn.ru/ru/documentation/#tag/qst-api/paths/~1v4~1qst~1status~1%7Bid%7D/get',
155+
'link' => '',
156+
],
157+
'qstPrint' => [
158+
'name' => 'Печать анкеты',
159+
'about' => 'В этом примере показано получение заполненной pdf версии анкеты по её ID.<br/><br/>ID анкеты возвращается при отправке анкеты на проверку.<br/><br/>Распечатать можно только одобренную анкету - в статусе approved.',
160+
'docLink' => 'https://ypmn.ru/ru/documentation/#tag/qst-api/paths/~1v4~1qst~1print~1%7Bid%7D/get',
161+
'link' => '',
162+
],
163+
'qstList' => [
164+
'name' => 'Список анкет',
165+
'about' => 'В этом примере показано получение списка анкет.',
166+
'docLink' => 'https://ypmn.ru/ru/documentation/#tag/qst-api/paths/~1v4~1qst~1list/get',
167+
'link' => '',
168+
],
139169
];

src/ApiRequest.php

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ class ApiRequest implements ApiRequestInterface
2424
const REPORT_ORDERS_API_V4 = '/api/v4/reports/orders';
2525
const REPORT_ORDER_DETAILS_API = '/api/v4/reports/order-details';
2626
const PODELI_MERCHANT_REGISTRATION_API = '/api/v4/registration/merchant/podeli';
27+
const QST_CREATE_API = '/api/v4/qst/create';
28+
const QST_STATUS_API = '/api/v4/qst/status';
29+
const QST_PRINT_API = '/api/v4/qst/print';
30+
const QST_LIST_API = '/api/v4/qst/list';
2731
const HOST = 'https://secure.ypmn.ru';
2832
const SANDBOX_HOST = 'https://sandbox.ypmn.ru';
2933
const LOCAL_HOST = 'http://127.0.0.1';
@@ -40,6 +44,9 @@ class ApiRequest implements ApiRequestInterface
4044
/** @var bool Режим Отладки (вывод системных сообщений) */
4145
private bool $debugModeIsOn = false;
4246

47+
/** @var bool Отображать заголовки ответа в режим отладки */
48+
private bool $debugShowResponseHeaders = true;
49+
4350
/** @var bool Формат результата в режиме отладки */
4451
private bool $jsonDebugResponse = true;
4552

@@ -220,6 +227,12 @@ private function sendGetRequest(string $api): array
220227
]
221228
];
222229

230+
$headers = [];
231+
232+
if ($this->getDebugShowResponseHeaders()) {
233+
$this->addCurlOptHeaderFunction($setopt_array, $headers);
234+
}
235+
223236
curl_setopt_array($curl, $setopt_array);
224237

225238
$response = curl_exec($curl);
@@ -231,11 +244,16 @@ private function sendGetRequest(string $api): array
231244
$this->echoDebugMessage($this->getHost() . $api);
232245
$this->echoDebugMessage('Ответ от сервера Ypmn:');
233246
if ($this->getJsonDebugResponse()) {
234-
$this->echoDebugMessage(json_encode(json_decode($response), JSON_PRETTY_PRINT));
247+
$this->echoDebugMessage(json_encode(json_decode($response), JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
235248
} else {
236249
$this->echoDebugMessage($response);
237250
}
238251

252+
if ($this->getDebugShowResponseHeaders()) {
253+
$this->echoDebugMessage('Заголовки ответа от сервера Ypmn:');
254+
$this->echoDebugMessage(implode("\n", $headers));
255+
}
256+
239257
if (mb_strlen($err) > 0) {
240258
$this->echoDebugMessage('Ошибка');
241259
echo '<br>Вы можете отправить запрос на поддержку на <a href="mailto:[email protected]?subject=YPMN_Integration">[email protected]</a>';
@@ -296,7 +314,7 @@ public function sendPostRequest($data, string $api): array
296314
$date = (new DateTime())->format(DateTimeInterface::ATOM);
297315
$requestHttpVerb = 'POST';
298316

299-
curl_setopt_array($curl, [
317+
$setOptArray = [
300318
CURLOPT_URL => $this->getHost() . $api,
301319
CURLOPT_RETURNTRANSFER => true,
302320
CURLOPT_ENCODING => '',
@@ -318,7 +336,15 @@ public function sendPostRequest($data, string $api): array
318336
$encodedJsonDataHash
319337
)
320338
]
321-
]);
339+
];
340+
341+
$headers = [];
342+
343+
if ($this->getDebugShowResponseHeaders()) {
344+
$this->addCurlOptHeaderFunction($setOptArray, $headers);
345+
}
346+
347+
curl_setopt_array($curl, $setOptArray);
322348

323349
$response = curl_exec($curl);
324350
$err = curl_error($curl);
@@ -328,7 +354,12 @@ public function sendPostRequest($data, string $api): array
328354
$this->echoDebugMessage('POST-Запрос к серверу Ypmn:');
329355
$this->echoDebugMessage($encodedJsonData);
330356
$this->echoDebugMessage('Ответ от сервера Ypmn:');
331-
$this->echoDebugMessage(json_encode(json_decode($response), JSON_PRETTY_PRINT));
357+
$this->echoDebugMessage(json_encode(json_decode($response), JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
358+
359+
if ($this->getDebugShowResponseHeaders()) {
360+
$this->echoDebugMessage('Заголовки ответа от сервера Ypmn:');
361+
$this->echoDebugMessage(implode("\n", $headers));
362+
}
332363

333364
if (mb_strlen($err) > 0) {
334365
$this->echoDebugMessage('Ошибка');
@@ -594,4 +625,60 @@ public function sendPodeliRegistrationMerchantRequest(PodeliMerchant $merchant):
594625
{
595626
return $this->sendPostRequest($merchant, self::PODELI_MERCHANT_REGISTRATION_API);
596627
}
628+
629+
/** @inheritdoc */
630+
public function sendQstCreateRequest(QstInterface $qst): array
631+
{
632+
return $this->sendPostRequest($qst, self::QST_CREATE_API);
633+
}
634+
635+
/** @inheritdoc */
636+
public function sendQstStatusRequest(int $qstId): array
637+
{
638+
return $this->sendGetRequest(self::QST_STATUS_API . '/' . $qstId);
639+
}
640+
641+
/** @inheritdoc */
642+
public function sendQstPrintRequest(int $qstId): array
643+
{
644+
return $this->sendGetRequest(self::QST_PRINT_API . '/' . $qstId);
645+
}
646+
647+
/** @inheritdoc */
648+
public function sendQstListRequest(): array
649+
{
650+
return $this->sendGetRequest(self::QST_LIST_API);
651+
}
652+
653+
/** @inheritdoc */
654+
public function getDebugShowResponseHeaders(): bool
655+
{
656+
return $this->debugShowResponseHeaders;
657+
}
658+
659+
/** @inheritdoc */
660+
public function setDebugShowResponseHeaders(bool $debugShowResponseHeaders = true): self
661+
{
662+
$this->debugShowResponseHeaders = $debugShowResponseHeaders;
663+
return $this;
664+
}
665+
666+
/**
667+
* @param array $curlOptArr
668+
* @param array $headers
669+
* @return void
670+
*/
671+
private function addCurlOptHeaderFunction(array &$curlOptArr, array &$headers): void
672+
{
673+
$curlOptArr += [
674+
CURLOPT_HEADERFUNCTION => static function($curl, $header) use (&$headers)
675+
{
676+
if (strlen(trim($header)) > 0) {
677+
$headers[] = trim($header);
678+
}
679+
680+
return strlen($header);
681+
}
682+
];
683+
}
597684
}

src/ApiRequestInterface.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,44 @@ public function setHost(string $host) : self;
146146
* @return array
147147
*/
148148
public function sendPodeliRegistrationMerchantRequest(PodeliMerchant $merchant): array;
149+
150+
/**
151+
* Отправить запрос на создание и отправку анкеты (по добавлению продавцов) на проверку
152+
* @param Qst $qst
153+
* @return array
154+
*/
155+
public function sendQstCreateRequest(QstInterface $qst): array;
156+
157+
/**
158+
* Получить статус анкеты
159+
* @param int $qstId
160+
* @return array
161+
*/
162+
public function sendQstStatusRequest(int $qstId): array;
163+
164+
/**
165+
* Распечатать анкету
166+
* @param int $qstId
167+
* @return array
168+
*/
169+
public function sendQstPrintRequest(int $qstId): array;
170+
171+
/**
172+
* Получить список анкет
173+
* @return array
174+
*/
175+
public function sendQstListRequest(): array;
176+
177+
/**
178+
* Получить установлен ли режим показывать заголовки ответа в режиме отладки
179+
* @return bool
180+
*/
181+
public function getDebugShowResponseHeaders(): bool;
182+
183+
/**
184+
* Установить показывать заголовки ответа в режиме отладки
185+
* @param bool $debugShowResponseHeaders
186+
* @return self
187+
*/
188+
public function setDebugShowResponseHeaders(bool $debugShowResponseHeaders = true): self;
149189
}

src/Examples/getToken.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<br>
3434
<br>Вот он: <code>' . $responseData['token'] . '</code>
3535
<br>
36-
<br>Тперь его <a href="./?function=paymentByToken&token=' . $responseData['token'] . '">можно использовать</a> в платежах вместо данных карты
36+
<br>Теперь его <a href="./?function=paymentByToken&token=' . $responseData['token'] . '">можно использовать</a> в платежах вместо данных карты
3737
',
3838
]);
3939
}

src/Examples/qstCreateIp.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Ypmn\ApiRequest;
6+
use Ypmn\Qst;
7+
use Ypmn\QstSchema;
8+
use Ypmn\QstSchemaActualAddress;
9+
use Ypmn\QstSchemaBankAccount;
10+
use Ypmn\QstSchemaIdentityDoc;
11+
use Ypmn\QstSchemaLegalAddress;
12+
use Ypmn\QstSchemaPostAddress;
13+
14+
// Подключим файл, в котором заданы параметры мерчанта
15+
include_once 'start.php';
16+
17+
/* Создание и отправка анкеты для подключения продавца */
18+
19+
/* Создаем и заполняем объект анкеты */
20+
$qst = new Qst();
21+
22+
/* ИНН продавца */
23+
$qst->setInn('773200328662');
24+
25+
/* Данные продавца */
26+
$qstSchema = new QstSchema();
27+
$qstSchema->addPhone('+7 495 1234567, доб. 123');
28+
$qstSchema->addEmail('[email protected]');
29+
30+
$qstLegalAddress = (new QstSchemaLegalAddress())
31+
->setZip('123456')
32+
->setRegion('Москва')
33+
->setCity('Москва')
34+
->setStreet('ул. Охотный ряд')
35+
->setHouse('1');
36+
$qstSchema->setLegalAddress($qstLegalAddress);
37+
38+
$qstActualAddress = (new QstSchemaActualAddress())->setChecked(true);
39+
$qstSchema->setActualAddress($qstActualAddress);
40+
41+
$qstPostAddress = (new QstSchemaPostAddress())->setChecked(true);
42+
$qstSchema->setPostAddress($qstPostAddress);
43+
44+
$qstIdentityDoc = (new QstSchemaIdentityDoc())
45+
->setSeries('1234')
46+
->setNumber('123456')
47+
->setIssueDate('2000-01-30')
48+
->setIssuedBy('МВД')
49+
->setIssuedByKP('123-456');
50+
51+
$qstSchema
52+
->setBirthDate('1969-02-23')
53+
->setBirthPlace('Москва')
54+
->setIdentityDoc($qstIdentityDoc);
55+
56+
$qstBankAccount = (new QstSchemaBankAccount())
57+
->setBankBIK('044525700')
58+
->setBankCorAccount('30101810200000000700')
59+
->setBankAccount('40702810100002400756');
60+
61+
$qstSchema->addBankAccount($qstBankAccount);
62+
63+
$qstSchema->setAdditionalFieldByKey(1, 'Доп. поле');
64+
65+
$qst->setSchema($qstSchema);
66+
67+
/* Создадим HTTP-запрос к API */
68+
$apiRequest = new ApiRequest($merchant);
69+
70+
// Включить режим отладки (закомментируйте или удалите в рабочей программе!) //
71+
$apiRequest->setDebugMode();
72+
// Переключиться на тестовый сервер (закомментируйте или удалите в рабочей программе!) //
73+
$apiRequest->setSandboxMode();
74+
75+
/* Запрос на отправку анкеты */
76+
$responseData = $apiRequest->sendQstCreateRequest($qst);
77+
78+
/* Преобразуем ответ из JSON в массив */
79+
try {
80+
$responseData = json_decode((string) $responseData["response"], true);
81+
if (isset($responseData['id'])) {
82+
echo "Анкета #{$responseData['id']} создана и отправлена на проверку";
83+
} else {
84+
echo "Анкета не создана, см. причину в ответа от сервера YPMN";
85+
}
86+
} catch (Exception $exception) {
87+
echo "Ошибка запроса: {$exception->getMessage()}";
88+
throw new Exception($exception->getMessage());
89+
}

0 commit comments

Comments
 (0)