Быстрый старт

Введение

Эта инструкция — о том, как организовать проведение платежей через программный интерфейс Gate платёжной платформы Openpayze. С тем, чтобы использовать свой пользовательский интерфейс и обеспечивать максимальное взаимодействие с пользователями на стороне веб-сервиса, а все взаимодействия с платёжной платформой выполнять на программном уровне, „под капотом“. И чтобы при этом можно было применять проверенные быстрые решения — с чёткими инструкциями и примерами кода на популярных языках программирования — PHP и Go.

В рамках этой инструкции рассматриваются действия, необходимые для проведения наиболее востребованного вида платежей — оплат в одну стадию.

Если актуально использовать Gate лишь для контроля состояния отдельных платежей, можно освоить здесь работу с подписью и перейти к статье Получение информации о состоянии платежа. И наконец, если актуально что-то принципиально другое, можно сориентироваться в соответствующих вариантах.

Рис. 1. Другие варианты
  • Если надо настроить решения с использованием платёжной формы Openpayze на сайтах, можно обратиться к разделам Payment Page и Интеграция с использованием SDK.
  • Если надо настроить оплаты с вызовом платёжной формы Openpayze по платёжным ссылкам, можно освоить с помощью этой инструкции работу с подписью, ответами и оповещениями и перейти после этого к соответствующей статье: Оплата по платёжной ссылке. Кроме того, оплаты по ссылкам можно инициировать и вручную, через интерфейс Dashboard, предназначенный для сотрудников мерчантов (подробнее).
  • Если надо настроить получение через программный интерфейс информации об операциях и балансах, следует обратиться к разделу о работе с интерфейсом Data API.
  • Наконец, если актуально что-то ещё, можно обратиться к другим разделам настоящей документации и к специалистам Openpayze.
Notice: Отдельно можно отметить, что наряду с техническими вопросами для начала проведения платежей через Gate необходимо решить и организационные, в том числе вопросы о соответствии требованиям PCI DSS, если планируется проводить платежи с использованием платёжных карт. Информацию об этом можно найти в статье Организация взаимодействия.

На этом с вводными всё. Можно переходить к делу.

Краткая теория

Проекты и ключи

Работу с платёжной платформой можно сравнить с использованием услуг гостиницы. Так, для заселения в гостиницу обычно необходимо получить номер и ключ от него, а для начала работы с платформой надо получить... проект и ключ от него. И как с номерами в гостиницах, в платформе может предоставляться разное количество проектов для одного клиента — под разные цели и задачи — при этом для каждого проекта (как и для каждого гостиничного номера) необходим свой ключ.

Как правило, для работы достаточно одного тестового и одного рабочего проектов. Это типичный случай, и в рамках быстрого старта мы исходим из него. Если вам по какой-либо причине необходимо больше проектов, это стоит обсудить с курирующим менеджером, но начать всё также можно с одного тестового проекта.

Если у вас уже есть идентификатор тестового проекта (project_id) и секретный ключ для него (secret_key), можно приготовиться к их использованию и переходить дальше. Если же вы ещё не бронировали тестовый проект, самое время сделать это и вернуться сюда.

Для начала работы с платформой следует получить проект и ключ от него. Если у вас уже есть идентификатор (project_id) и ключ (secret_key) тестового проекта, можно приготовиться к их использованию и переходить дальше. Если же вы ещё не оформляли тестовый проект, самое время это сделать и вернуться сюда.

Схема работы

Чтобы корректно проводить платежи через Gate, необходимо обеспечить сбор актуальных параметров, формирование и отправку к платёжной платформе соответствующих запросов и приём и обработку ответной информации от платформы. При этом все взаимодействия с пользователями (для сбора и отображения релевантной информации) должны обеспечиваться на стороне веб-сервиса с использованием собственных решений, в то время как все остальные процедуры (для обработки используемой информации) можно реализовывать на основе представленных далее примеров кода.

Если сфокусировать внимание на технических аспектах для веб-сервиса и платёжной платформы, то проведение оплаты можно представить следующим образом.

В веб‑сервисе В платёжной платформе
1 При готовности пользователя оплатить заказ получаем все необходимые данные, фиксируем параметры платежа и подписываем их, после чего формируем запрос на проведение платежа и отправляем его в платёжную платформу
2 Информируем пользователя о том, что платёж проводится Принимаем запрос и работаем по нему, чтобы провести платёж. Если актуально, отправляем оповещение о необходимых действиях
3 Если актуально, принимаем оповещение о необходимых действиях, выполняем эти действия (с участием пользователя или без него) и отправляем в платёжную платформу запрос на продолжение платежа
4 Информируем пользователя о том, что платёж проводится Если актуально, принимаем дополнительный запрос и выполняем необходимые действия для продолжения платежа, после чего отправляем к веб-сервису оповещение о результате платежа
5 Принимаем оповещение с информацией о результате платежа и отображаем пользователю необходимые сведения

При работе с платежами других типов выполняемые действия могут отличаться, но в целом схема соответствует приведённой. Реализовывать её на стороне веб-сервиса можно самыми разными способами. Здесь, в рамках быстрого старта, описываются базовые процедуры, которые можно использовать и адаптировать в соответствии со спецификой вашего веб-сервиса.

Параметры запросов

Обязательный набор параметров, необходимых для проведения конкретного платежа, может отличаться в зависимости от типа этого платежа, специфики платёжного метода и платёжной системы, региональных особенностей и других факторов. Так, в каких-то случаях может требоваться указывать назначение платежа, адрес пользователя или другую информацию, в то время как в других случаях эти сведения могут быть необязательны. Поэтому при настройке работы с разными типами платежей и платёжными методами следует обращаться к соответствующим статьям настоящей документации и к спецификации Gate API.

Обязательный набор параметров, необходимых для проведения конкретного платежа, может отличаться в зависимости от различных факторов, поэтому при настройке работы с разными типами платежей и платёжными методами следует обращаться к соответствующим статьям настоящей документации и к спецификации Gate API.

В базовом случае для проведения оплаты с использованием метода Open Banking к числу обязательных параметров относятся следующие.

Параметр Описание
general — объект, содержащий параметры с основными идентификационными сведениями запроса

project_id
integer

Идентификатор проекта. Его вместе с ключом выдаёт Openpayze, и его важно точно указывать даже в тестовых запросах. Иначе… стоит ждать реакцию, как при попытке зайти в чужой гостиничный номер, полученный от Openpayze.
Пример: 42

payment_id
string

Идентификатор платежа. Он может быть произвольным, но каждый раз должен быть уникальным в рамках используемого проекта. Иначе стоит ждать ошибку обращения, формируемый на стороне веб-сервиса.
Пример: Cosmoshop_purchase_2025-01-01_000001

signature
string

Подпись к параметрам запроса. Она формируется в соответствии со специальным алгоритмом, описанным далее. При этом для тестового проекта следует использовать тестовый ключ, для рабочего — рабочий, формируемая описанным далее способом.
Пример: rnv1OS3PJUKEJ5kw5wqoK0ftZGSd4Q6LX5A5NxK6d5alpND4sQTRFt7/9aFV+m3SRwNB8ba98GMsOY91yTVhEQ==

payment — объект, содержащий параметры с основными сведениями о платеже

payment_amount
integer

Сумма платежа. В тестовых запросах может быть произвольной, а в реальных должна точно соответствовать сумме заказа. Приводится, в дробных единицах валюты.
Пример: 8855 (для суммы 88,55)

payment_currency
string

Код валюты платежа. Приводится, в трёхбуквенном формате ISO 4217 alpha-3. В тестовых запросах могут использоваться любые из действующих кодов, а в реальных каждый раз должен использоваться код той валюты, в которой инициируется платёж. Для сверки можно использовать справочник валют.
Пример: USD

customer — объект, содержащий параметры с основными сведениями о пользователе

customer_id
string

Идентификатор пользователя в веб-сервисе. Может быть произвольным и повторяемым в разных запросах, но для каждого реального пользователя должен быть однозначно сопоставляемым с его учётной записью в веб-сервисе и уникальным в рамках проекта.
Пример: 17008

ip_address
string

ip_address

IP-адрес пользователя. В тестовых запросах можно указывать IP-адрес мерчанта, в рабочих запросах каждый раз должен указываться IP-адрес, с которого пользователь инициирует оплату.
Пример: 248.121.176.220

account — объект, содержащий параметры со сведениями о банковском счёте пользователя

bank_id
integer

Идентификатор банка.
Пример: 54981

В запросе такой набор параметров может выглядеть следующим образом.

Рис. 2. Пример набора параметров для проведения оплаты
{
  "general": {
      "project_id": 42,
      "payment_id": "Cosmoshop_purchase_2025-01-01_000001",
      "signature": "rdCiqlibt8SUMe3OVPNfKMYnQjQ6dkEvRQhMkJRg9ZJULdsKJEZU21E5Y/ISdv0FtXi3oJE5n4hSNK3Owo7Axw=="
  },
    "customer": {
      "ip_address": "248.121.176.220",
      "id": "17008"
  },
    "payment": {
      "amount": 8855,
      "currency": "USD"
  },

    "account": {
      "bank_id": 54981
  }
}

Вместе с тем, при проведении платежей могут требоваться и другие параметры:

  • Параметры, необходимые в различных случаях, исходя из специфики конкретных платёжных систем и региональных особенностей. Если такие параметры не были переданы изначально, платёж может быть отклонён либо эти параметры могут быть запрошены в процессе его проведения.
  • Параметры, необходимые в различных случаях, исходя из специфики веб-сервиса, например для отправки уведомления о результате платежа пользователю. Если такие параметры не были переданы, то соответствующие возможности могут не поддерживаться.

Для работы с такими случаями может потребоваться настроить дополнительные процедуры. Они частично затронуты далее, а также отдельно разобраны в разделе Дополнения, к которому лучше переходить после настройки и тестирования всех базовых процедур.

В целом, сбор всех необходимых параметров можно настраивать как удобно, с оглядкой на архитектуру вашего веб-сервиса и иные факторы (например, с задействованием используемых справочников и баз данных). Здесь же, определившись с обязательными параметрами, можно приступать к реализации.

Базовая реализация

Введение

Реализовывать функции веб-сервиса для проведения платежей можно по-разному, в том числе за счёт создания своих программных решений. В рамках этого быстрого старта мы рассматриваем реализацию с использованием готового кода от Openpayze для подписывания данных, отправки запросов, приёма ответов на эти запросы и программных оповещений, и, вместе с тем, с использованием ваших решений на стороне веб-сервиса для всех остальных действий, включая получение информации от пользователей и предоставление им информации о проведении платежа.

Подписывание данных

Когда для всех необходимых параметров определены их значения (и только в таком случае), можно формировать подпись к ним и готовить запрос.

Рис. 3. Пример кода на PHP для работы с цифровой подписью (с использованием базового набора параметров)
*/
class Signer
{
    const ITEMS_DELIMITER = ';';
    const ALGORITHM = 'sha512';
    const IGNORED_KEYS = ['frame_mode'];

    /**
     * Secret key
     *
     * @var string
     */
    private $secretKey;

    /**
     * __construct
     *
     * @param string $secretKey
     */
    public function __construct(string $secretKey)
    {
        $this->secretKey = $secretKey;
    }

    /**
     * Check signature
     *
     * @param array $params
     * @param string $signature
     * @return boolean
     */
    public function check(array $params, string $signature): bool
    {
        return $this->sign($params) === $signature;
    }

    /**
     * Return signature
     *
     * @param array $params
     * @return string
     */
    public function sign(array $params): string
    {
        $stringToSign = implode(self::ITEMS_DELIMITER, $this->getParamsToSign($params, self::IGNORED_KEYS));
        return base64_encode(hash_hmac(self::ALGORITHM, $stringToSign, $this->secretKey, true));
    }

    /**
     * Get parameters to sign
     *
     * @param array $params
     * @param array $ignoreParamKeys
     * @param string $prefix
     * @param bool $sort
     * @return array
     */
    private function getParamsToSign(
        array $params,
        array $ignoreParamKeys = [],
        string $prefix = '',
        bool $sort = true
    ): array {
        $projectId = 42;
        $paymentId = '12345';
        $customerId = '123';
        $ip = '192.168.1.1';
        $paymentAmount = '1000';
        $paymentCurrency = 'USD';

        $bankId = '54981';


        $paramsToSign = [
            'general'  => [
            'project_id' => $projectId,
            'payment_id' => $paymentId,
            ],
            'customer'  => [
            'id' => $customerId,
            'ip_address' => $ip,
            ],
            'payment'  => [
            'payment_amount' => $paymentAmount,
            'payment_currency' => $paymentCurrency,
            ],

            'account'  => [
            'bank_id' => $bankId
            ],
        ];

        foreach ($params as $key => $value) {
            if (in_array($key, $ignoreParamKeys, true)) {
                continue;
            }

            $paramKey = ($prefix ? $prefix . ':' : '') . $key;
            if (is_array($value)) {
                $subArray = $this->getParamsToSign($value, $ignoreParamKeys, $paramKey, false);
                $paramsToSign = array_merge($paramsToSign, $subArray);
            } else {
                if (is_bool($value)) {
                    $value = $value ? '1' : '0';
                } else {
                    $value = (string)$value;
                }

                $paramsToSign[$paramKey] = $paramKey . ':' . $value;
            }
        }

        if ($sort) {
            ksort($paramsToSign, SORT_NATURAL);
        }

        return $paramsToSign;
    }
}
Рис. 4. Пример кода на Go для работы с цифровой подписью (с использованием базового набора параметров)
package main

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"sort"
)

const itemsDelimiter = ";"

var ignoredKeys = map[string]struct{}{"frame_mode": struct{}{}}

var secretKey string

func SetSecretKey(key string) {
	secretKey = key
}

func Check(params map[string]map[string]string, signature string) bool {
	return Sign(params) == signature
}

func Sign(params map[string]map[string]string) string {
	var stringToSign string

	paramsToSign := getParamsToSign(params, ignoredKeys, "", true)
	for _, value := range paramsToSign {
		for _, v := range value {
			stringToSign = stringToSign + itemsDelimiter + v
		}
	}

	mac := hmac.New(sha512.New, []byte(secretKey))
	mac.Write([]byte(stringToSign))

	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

func getParamsToSign(params map[string]map[string]string, ignoreParamKeys map[string]struct{},
	prefix string, sorted bool) map[string]map[string]string {
	var paymentId, customerId, ip, amount, currency, cardPan, cardYear, cardMonth, cardHolder, cardCvv string

	paramsToSign := map[string]map[string]string{
		"general": {
			"project_id": projectId,
			"payment_id": paymentId,
		},
		"customer": {
			"id":         customerId,
			"ip_address": ip,
		},
		"payment": {
			"payment_amount":   amount,
			"payment_currency": currency,
		},

		"account": {
			"bank_id":   bankId
		},
	}

	for key, value := range params {
		for k, v := range value {
			if _, ok := ignoreParamKeys[k]; ok {
				continue
			}

			paramKey := k
			if prefix != "" {
				paramKey = prefix + ":" + k
			}

			paramsToSign[key][paramKey] = paramKey + ":" + v
		}
	}

	if sorted == true {
		return sortParams(paramsToSign)
	}

	return paramsToSign
}

func sortParams(params map[string]map[string]string) map[string]map[string]string {
	var sortedParams map[string]map[string]string
	keys := make([]string, 0, len(params))

	for kp := range params {
		keys = append(keys, kp)
	}
	sort.Strings(keys)

	for _, ks := range keys {
		sortedParams[ks] = params[ks]
	}

	return sortedParams
}

Отправка запросов и приём ответов на них

Когда все данные собраны и подписаны, можно отправлять запрос к требуемой конечной точке (их перечень представлен в спецификации Gate API). В нашем случае это /v2/payment/banks/{payment_method}/sale. При приёме запроса (как правило, в течение 100 мс) со стороны платёжной платформы к веб-сервису направляетсяПосле этого стоит ждать от платёжной платформы синхронный HTTP-ответ — с информацией о приёме запроса в обработку или об ошибках, из-за которых запрос не был принят.

В ответах от платформы используются следующие коды:

  • 200 OK — запрос принят в обработку. В таком случае можно ждать дальнейших оповещений о проведении платежа. Работу с такими оповещениями рассматриваем уже в следующем разделе.
  • 400 Bad Request — запрос не принят из-за того, что в нём не указан по крайней мере один из обязательных параметров или указана некорректная подпись. В таком случае можно дополнить запрос недостающими параметрами и обновить подпись (или просто обновить подпись, проверив при этом корректность используемых идентификатора и ключа проекта) и повторить отправку запроса.
  • 403 Forbidden — запрос не принят из-за отказа в доступе к конечной точке. В таком случае можно обратиться к специалистам технической поддержки Openpayze для добавления IP-адреса отправителя в список доверенных адресов.
  • 422 Unprocessable Entity — запрос не принят из-за синтаксической ошибки (например, из-за пропущенной запятой). В таком случае можно исправить ошибку и повторить отправку запроса.
  • 500 Internal Error — запрос не принят из-за сбоя в платёжной платформе. В таком случае можно повторить отправку запроса позднее.

Чтобы получать информацию из ответов от платформы, следует настроить их приём и обработку.

Рис. 5. Пример кода на PHP для отправки запросов и приёма ответов
$headers        = [];
$headerCallback = function ($curl, $header_line) use (&$headers) {
    if (strpos($header_line, ":") === false) {
        return strlen($header_line);
    }
    list($key, $value) = explode(":", trim($header_line), 2);
    $headers[trim($key)] = trim($value);

    return strlen($header_line);
};

$absUrl = 'https://abs.url';
$curl = curl_init();

$opts[CURLOPT_URL]            = $absUrl;
$opts[CURLOPT_RETURNTRANSFER] = true;
$opts[CURLOPT_CONNECTTIMEOUT] = $this->connectTimeout;
$opts[CURLOPT_TIMEOUT]        = $this->timeout;
$opts[CURLOPT_HEADERFUNCTION] = $headerCallback;
curl_setopt_array($curl, $opts);
$rbody = curl_exec($curl);
$errno = curl_errno($curl);
if ($rbody === false) {
    $errno   = curl_errno($curl);
    $message = curl_error($curl);
    curl_close($curl);
    $this->handleCurlError($absUrl, $errno, $message);
}
$rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

echo "http code = ".$rcode."\n";
echo "http response = ".$rbody."\n";
Рис. 6. Пример кода на Go для отправки запросов и приёма ответов
package main

import (
	"fmt"
	"net/http"
	"time"
)

type conf struct {
	connectTimeout, timeout time.Duration
	returnTransfer          bool
}

func main() {
	absUrl := "https://abs.url"
	var cf = conf{10 * time.Second, 20 * time.Second, true}

	req, err := http.NewRequest(http.MethodGet, absUrl, nil)
	if err != nil {
		fmt.Printf("client: could not create request: %s\n", err)

		return
	}

	client := http.Client{
		Timeout: cf.timeout,
	}

	res, err := client.Do(req)
	if err != nil {
		fmt.Printf("client: error making http request: %s\n", err)
		handleError(err)

		return
	}

	fmt.Printf("http code = %d\n", res.StatusCode)
	fmt.Printf("http response = %s\n", res.Body)
}

Приём оповещений и отправка ответов на них

В рамках проведения отдельного платежа от платформы к веб-сервису могут отправляться предписывающие и уведомительные оповещения.

Предписывающие оповещения требуют отправки каких-либо сведений в платёжную платформу, предоставления определённой информации пользователю, перенаправления его к сторонним сервисам или выполнения иных действий. Это промежуточные оповещения, на которые необходимо своевременно реагировать для корректного проведения платежей.

Уведомительные оповещения позволяют оперативно узнавать о результатах платежей и получать другую значимую информацию. Эту информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего сервиса. Уведомительные оповещения могут быть как промежуточными, с информацией о значимых событиях при проведении платежей, так и итоговыми, с информацией о результатах. И эту информацию можно использовать по мере необходимости.

Для приёма оповещений (как предписывающих, так и уведомительных) следует:

  1. Определить и задать в платёжной платформе адрес, предназначенный для приёма в веб-сервисе оповещений по проекту. Для этого можно открыть раздел Проекты интерфейса Dashboard и использовать инструменты на вкладке Оповещения.
  2. Настроить проверку целостности и разбор оповещений, ожидаемых по указанному адресу, так, чтобы не использовать в работе оповещения с некорректной подписью. Для такой настройки можно использовать приведённый далее пример кода.
  3. Настроить отправку синхронных HTTP-ответов о приёме оповещений: 200 ОК, если подпись корректна, и 400 Bad Request, если подпись некорректна.
Рис. 7. Пример данных из итогового оповещения
{
  "project_id": 200,
  "payment": {
    "id": "abc12345",
    "type": "purchase",
    "status": "success",
    "date": "2025-03-20T14:22:06+0000",
    "method": "Greek Banks",
    "sum": {
      "amount": 1000,
      "currency": "EUR"
    },
    "description": "Success"
  },
  "customer": {
    "id": "123"
  },
  "operation": {
    "id": 9529253065607,
    "type": "sale",
    "status": "success",
    "date": "2025-03-20T14:22:06+0000",
    "created_date": "2025-03-20T14:22:00+0000",
    "request_id": "f1de353331a01fd14163fe4226-00009530",
    "sum_initial": {
      "amount": 1000,
      "currency": "EUR"
    },
    "sum_converted": {
      "amount": 1000,
      "currency": "EUR"
    },
    "code": "0",
    "message": "Success",
    "provider": {
      "id": 1914,
      "payment_id": "",
      "auth_code": ""
    }
  },
  "signature": "OBjT3RaJnOWsDXOclvWoC6+CFSCtLprTo8VFbN6BYVQD2tVK/3d9k+RRA/7N9TV6OQqk+0uPUnx4/c8uaUurw=="
}
Рис. 8. Пример кода на PHP для приёма оповещений
require_once __DIR__ . 'signature.php';

//@todo net set to merchant project https://api.merchant.com/callback.php

//@todo set projectId
$projectId = null;
//@todo set paymentId 
$paymentId = '';
//@todo set secretKey
$secretKey = '';


$response = json_decode(file_get_contents('php://input'), true);

$rsignature = $response['signature'];

unset($response['signature']);


if ((new Signer($secretKey))->check($response, $rsignature)) {
    header('HTTP/1.1 200 OK');
    header('Status: 200 OK');
    echo "signature is correct\n";  
    
    $projectId = $response['project_id'];
    $paymentId = $response['payment']['id'];

    //@todo save necessary info to the merchant system
} else {
    header('Status: 400 Bad Request');
    header('HTTP/1.1 400 Bad Request');
    echo "signature is invalid\n";
}
Рис. 9. Пример кода на Go для приёма оповещений
package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
)

//@todo net set to merchant project https://api.merchant.com/callback.go

//@todo set project
type project struct{}

type request struct {
	Signature string `json:"signature"`
}

var prj project

//@todo set secretKey
var secretKey string

//@todo set paymentId
var paymentId string

//@todo get request
var r *http.Request

func main() {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Printf("Error reading body: %v", err)
	}

	var req request

	err = json.Unmarshal(body, &req)
	if err != nil {
		log.Printf("Error parsing request: %v", err)
	}

	var w http.ResponseWriter

	if checkSignature(req, secretKey, req.Signature) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("signature is correct\n"))
	} else {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("signature is invalid\n"))
	}
}

func checkSignature(req request, secretKey string, signature interface{}) bool {
}

Реагирование на оповещения

Общая информация

Для реагирования на уведомительные оповещения, если это актуально, можно настроить использование необходимой информации из таких оповещений в соответствии со спецификой веб-сервисапри её получении.

Для реагирования на предписывающие оповещения обязательно следует разобраться с выполнением действий, которые могут быть необходимы для проведения платежа.

Вместе с тем, настроить реагирование на оповещения можно и позже, после реализации основных действий и их тестирования.

К действиям, необходимым при получении предписывающих оповещений, могут относиться:

  1. Сбор дополнительных сведений о платеже и их отправка в платформу.

    В таких случаях в оповещениях передаётся объект clarification_fields со списком параметров, которые необходимо отправить в последующем запросе к платёжной платформе. Как правило, запрашивается информация о пользователе: его имя и фамилия, дата рождения, платёжный адрес и иные подобные сведения.

    Рис. 10. Пример данных из оповещения со списком запрашиваемых параметров
    {
      "clarification_fields": {
        "customer": {
          "type": "object",
          "description": "",
          "properties": {
            "psu_consent": {
              "type": "string",
              "description": "Need to request the customer's consent to make a payment"
            },
            "psu_consent_text": {
              "type": "string",
              "description": "The text to be displayed on the payment form",
              "default": "The consent text to be displayed to the customer"
            }
          }
        }
      }
    }

    Сбор требуемых сведений в таких ситуациях можно осуществлять любым удобным способом, в том числе из имеющейся базы данных или через заполнение пользователем соответствующих полей в интерфейсе веб-сервиса. Подробнее о работе с такими оповещениями — в разговоре о дополнениях, после первичной настройки и тестирования. Здесь же можно отметить, что такие ситуации бывают и требуют оперативного решения на стороне веб-сервиса.

  2. Перенаправление пользователя к стороннему сервису.

    В таких случаях оповещения, как правило, содержат объект redirectData с адресом страницы сервиса, к которому необходимо перенаправить пользователя, и дополнительными сведениями. При получении таких оповещений следует перенаправлять пользователей по указанным адресам. Это можно делать с помощью HTML-форм.

    Рис. 11. Пример данных из оповещения с адресом для перенаправления пользователя
      "redirect_data":{
        "method": "GET",
        "body": [],
        "encrypted": [],
        "url": "https://www.example.com/pay"
      }

Дополнения

Общий контроль проведения платежей

После проведения нескольких тестовых платежей можно разобраться с тем, как контролировать ситуацию по ним. Для общего контроля платежей в платформе предусмотрены пользовательский интерфейс Dashboard и программный интерфейс Data API. С их помощью можно получать различными способами сводную информацию о суммах, статусах и других атрибутах проводимых платежей, но с задержкой вплоть до нескольких минут. Для работы с этими интерфейсами необходимо предварительно получить доступ к интерфейсу Dashboard, настроить права доступа к текстовому проекту и, при необходимости работы с Data API, сформировать соответствующие токен и секретный ключ. После этого можно переходить к работе с информацией о платежах.

В интерфейсе Dashboard для контроля состояния платежей предусмотрены раздел Платежи (с информацией о платежах всех типов) и специализированные разделы с информацией о платежах различных типов, а также карточки с информацией об отдельных платежах. Справочная информация об использовании этих разделов представлена в соответствующем разделе документации.

В Data API предусмотрены различные конечные точки, через запросы к которым можно получать информацию о группах платежей или отдельных платежах. Работа с такими запросами описана в соответствующем разделе документации.

Оперативный контроль состояния отдельных платежей

Чтобы получать оперативную информацию о состоянии отдельных платежей через Gate API, следует использовать HTTP-POST-запросы к конечной точке /v2/payment/status (с указанием идентификаторов проекта и платежа) и принимать синхронные HTTP-ответы со сведениями по этим запросам на них.

Рис. 14. Пример кода на PHP для формирования и отправки запроса на получение информации о платеже
require_once __DIR__ . 'signature.php';

//@todo set projectId
$projectId = null;
//@todo set paymentId 
$paymentId = '';
//@todo set secretKey
$secretKey = '';


$params = [
    'general'  => [
        'project_id' => $projectId,
        'payment_id' => $paymentId,
    ]
];

$absUrl = 'https://api.openpayze.com/v2/payment/status';

$params['general']['signature']  = (new Signer($secretKey))->sign($params);
$request                         = json_encode($params);

$curl = curl_init();
$opts = [];

$opts[CURLOPT_POST]       = 1;
$opts[CURLOPT_POSTFIELDS] = $request;
$opts[CURLOPT_HTTPHEADER] = ['Content-Type: application/json', 'Content-Length: '.strlen($request)];

$headers        = [];
$headerCallback = function ($curl, $header_line) use (&$headers) {
    if (strpos($header_line, ":") === false) {
        return strlen($header_line);
    }
    list($key, $value) = explode(":", trim($header_line), 2);
    $headers[trim($key)] = trim($value);

    return strlen($header_line);
};

$opts[CURLOPT_URL]            = $absUrl;
$opts[CURLOPT_RETURNTRANSFER] = true;
$opts[CURLOPT_CONNECTTIMEOUT] = $this->connectTimeout;
$opts[CURLOPT_TIMEOUT]        = $this->timeout;
$opts[CURLOPT_HEADERFUNCTION] = $headerCallback;
curl_setopt_array($curl, $opts);
$rbody = curl_exec($curl);
$errno = curl_errno($curl);
if ($rbody === false) {
    $errno   = curl_errno($curl);
    $message = curl_error($curl);
    curl_close($curl);
    $this->handleCurlError($absUrl, $errno, $message);
}
$rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

echo "http code = ".$rcode."\n";
echo "http response = ".$rbody."\n";

$response = json_decode($rbody, true);

$rsignrature = $response['signature'];

unset($response['signature']);

if ((new Signer($secretKey))->check($response, $rsignrature)) {
    echo "signature is correct\n";
} else {
    echo "signature is invalid\n";
}
Рис. 15. Пример кода на Go для формирования и отправки запроса на получение информации о платеже
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/http"
	"os"
	"time"
)

//@todo net set to merchant project https://api.merchant.com/callback.go

type general struct{ project_id, payment_id, signature string }

type params struct{ gnrl general }

type response struct {
	Signature string `json:"signature"`
}

func main() {
	//@todo set project
	project := ""
       //@todo set secretKey
       var secretKey string
       //@todo set paymentId
       var paymentId string

	prms := params{
		gnrl: general{project_id: project, payment_id: paymentId, signature: ""},
	}

	signature := sign(prms, secretKey)
	prms.gnrl.signature = signature

	absUrl := "https://api.openpayze.com/v2/payment/status"
	reqBody, err := json.Marshal(prms)
	bodyReader := bytes.NewReader(reqBody)

	req, err := http.NewRequest(http.MethodPost, absUrl, bodyReader)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Content-Length", string(rune(bodyReader.Len())))

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Printf("client: error making http request: %s\n", err)
		handleError(err)
		os.Exit(1)
	}

	defer res.Body.Close()

	fmt.Printf("http code = %d\n", res.StatusCode)
	fmt.Printf("http response = %s\n", res.Body)

	var respBody response
	b, err := io.ReadAll(res.Body)

	err = json.Unmarshal(b, &respBody)
	if err != nil {
		log.Printf("Error parsing response: %v", err)
	}

	rsign := respBody.Signature

	if checkSignature(respBody, secretKey, rsign) {
		fmt.Printf("signature is correct\n")
	} else {
		fmt.Printf("signature is invalid\n")
	}
}

func sign(par params, secretKey string) string {
	//@todo implement sign function
}

func checkSignature(resp response, secretKey string, signature interface{}) bool {
	//@todo implement checkSignature function
}

При возникновении вопросов, касающихся получения информации о платежах через Gate, можно обращаться к соответствующей статье.

Подробнее о работе с такими запросами — в отдельной статье.

Организация работы с другими типами платежей

Настроив проведение карточных оплат, можно настроить работу и с другими типами платежей и платёжными методами. Чтобы сориентироваться в том, как в платформе проводятся платежи разных типов, и настроить работу с необходимыми типами платежей и платёжными методами, можно использовать модель проведения платежей (с описанием поддерживаемых типов платежей и их статусов) и материалы о методах (с описанием специфики проведения платежей с использованием различных методов).

Использование вспомогательных процедур и дополнительных возможностей

При проведении платежей через платёжную платформу Openpayze могут применяться различные процедуры и возможности. Вспомогательные процедуры требуются в отдельных случаях для решения специфических задач, например по аутентификации пользователей. Когда такие процедуры актуальны, они обязательны для проведения платежей, поэтому важно уметь с ними работать. В свою очередь, дополнительные возможности не блокируют проведение платежей и могут выполняться по желанию мерчанта. Они рассчитаны на улучшение качества предоставляемого сервиса.

После настройки проведения оплат, описанных в этом быстром старте, может быть полезно настроить выполнение процедур и возможностей, актуальных в соответствии со спецификой вашего веб-сервиса и задействуемых платёжных методов. Среди них можно выделить следующие:

Помимо этих процедур и возможностей можно настраивать и другие, описанные в разделах Вспомогательные процедуры и Дополнительные возможности.

Запуск

После реализации базовых функций, тестирования актуальных возможностей и настройки необходимых вам сценариев работы можно переходить к запуску рабочего проекта. Важно, чтобы к этому моменту были решены основные организационные вопросы. В таком случае вопросы технические сводятся к настройке свойств проекта на стороне платёжной платформы и к началу использования идентификатора и ключа рабочего проекта на стороне веб-сервиса.

Также после запуска можно продолжать настраивать работу с различными типами платежей, платёжными методами, процедурами и возможностями — с учётом ваших потребностей — и обращаться с вопросами и обратной связью к нашим специалистам.

Успехов!