B2BH2H

Как работает сервис

Сервис «Платёжные поручения» предоставляет возможность создания рублёвых платёжных поручений для следующих кейсов:

  • Создание черновика рублёвого платёжного поручения.
  • Создание рублёвого платёжного поручения с подписью.
  • Создание черновика рублёвого платёжного поручения в бюджет.
  • Создание рублёвого платёжного поручения в бюджет с подписью.

Создание черновика рублёвого платёжного поручения

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

Создание черновика рублёвого платёжного поручения в бюджет

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

Реквизиты налоговой или бюджетной организации передаются в объекте departmentalInfo . Обязательные поля для таких платежей приведены ниже.

BODY
Атрибут
Описание
objectrequired

Реквизиты налогового, таможенного или иного бюджетного платежа

uip
stringrequired

Уникальный идентификатор платежа/начисления

drawerStatus101
stringrequired

Статус плательщика

kbk
stringrequired

Код бюджетной классификации. Если кода нет, укажите значение 0

oktmo
stringrequired

Код OKTMO. Если кода нет, укажите значение 0

reasonCode106
stringrequired

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

taxPeriod107
stringrequired

Налоговый период или код таможенного органа. Если показатель налогового периода отсуствует, то укажите значение 0

docNumber108
stringrequired

Номер налогового документа

docDate109
stringrequired

Дата налогового документа в формате YYYY-MM-DD. Если этого реквизита нет, то укажите значение 0

paymentKind110
stringoptional

Код выплат

Пример запроса для подписанного платёжного поручения в бюджет
1{
2  "departmentalInfo": {
3    "uip": "0",
4    "drawerStatus101": "01",
5    "kbk": "18210102010011000110",
6    "oktmo": "45902000",
7    "reasonCode106": "ТП",
8    "taxPeriod107": "МС.02.2022",
9    "docNumber108": "000000000000001",
10    "docDate109": "2022-05-25"
11  }
12}

Создание рублёвого платёжного поручения с подписью

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

Также становится обязательным к заполнению значение параметра payeeInn .

Создание рублёвого платёжного поручения в бюджет с подписью

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

Также становится обязательным к заполнению значение параметра payeeInn .

Реквизиты налоговой или бюджетной организации передаются в объекте departmentalInfo .

Передача электронной подписи вместе с документом

Требования к передаваемой электронной подписи:

  • формат подписи - PKCS#7 Attached;
  • алгоритм электронной подписи - sha256WithRSAEncryption.

Для передачи ЭП под документом используется массив digestSignatures , в котором передаются объекты типа Signature . Серийный номер сертификата certificateUuid заполняется значением поля serialNumber из ответа метода "Получение RSA-сертификата".

BODY
Атрибут
Описание
array of objectoptional

Электронные подписи по дайджесту документа

base64Encoded
stringrequired

Значение ЭП документа, закодированное в Base64

certificateUuid
stringrequired

Серийный номер сертификата, использованного при создании ЭП

Пример электронной подписи по дайджесту документа
1"digestSignatures": [
2    {
3        "base64Encoded": "HlaeIHXXEcGT1bFxo1NlpAzpr+kJ2IQrcxVdvDTep6xjsmD1FDb+6NIyLT+/T24S0mPfVCU75sieOMt71TBS7w==",
4        "certificateUuid": "61000366d11e143acbc03a56d70001000366d1"
5    }
6]

Для платёжных поручений, создаваемых по собственным счетам, можно передать одну или две электронных подписи (или не передавать, если ЭП отсутствует) вместе с реквизитами создаваемого документа.

Если электронная подпись или подписи переданы в запросе, то они сохраняются вместе с документом, а сам документ продвигается дальше по своему жизненному циклу.

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

Подписание по алгоритму RSA

Для подписания может использоваться сертификат, выпущенный в Альфа-Бизнес, или сертификат, выпущенный при помощи сервиса Alfa API согласно разделу "Электронная подпись".

Пример формирования RSA подписи
1    public static String KEYSTORE_PATH = "";
2    public static String SIGNATURE_ALGORYTHM = "";
3    public static String KEYSTORE_PASSWORD = "";
4    public static String KEYSTORE_TYPE = "";
5    public static String KEYSTORE_ALIAS = "";
6
7    public static String signDataWithRSA(String dataToSign, String p12FileName)
8            throws KeyStoreException, OperatorCreationException, CertificateEncodingException, IOException, CMSException {
9
10        Security.addProvider(new BouncyCastleProvider());
11        BouncyCastleProvider provider = (BouncyCastleProvider) Security.getProvider("BC");
12
13        KeyStore keyStore = loadKeyStore(String.format(KEYSTORE_PATH, p12FileName));
14        X509Certificate certificate = getCertificate(keyStore);
15        X509CertificateHolder certificateHolder = new X509CertificateHolder(certificate.getEncoded());
16
17        CMSSignedDataGenerator signedDataGen = new CMSSignedDataGenerator();
18        ContentSigner signer = new JcaContentSignerBuilder(SIGNATURE_ALGORYTHM).setProvider(provider)
19                .build(getKey(keyStore));
20        signedDataGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
21                new JcaDigestCalculatorProviderBuilder().setProvider(provider).build())
22                .build(signer, certificateHolder));
23        signedDataGen.addCertificates(new JcaCertStore(List.of(certificate)));
24
25        CMSSignedData signedData = signedDataGen.generate(new CMSProcessableByteArray(dataToSign.getBytes()), false);
26        return new String(Base64.getEncoder().encode(signedData.getEncoded("DER")));
27    }
28
29    private static KeyStore loadKeyStore(String keystoreFilePath) throws KeyStoreException {
30        KeyStore keystore = KeyStore.getInstance(KEYSTORE_TYPE);
31        try (InputStream inputStream = new FileInputStream(keystoreFilePath)) {
32            keystore.load(inputStream, KEYSTORE_PASSWORD.toCharArray());
33        } catch (IOException | NoSuchAlgorithmException | CertificateException e) {
34            throw new RuntimeException("Ошибка открытия хранилища ключей", e);
35        }
36        return keystore;
37    }
38
39    private static X509Certificate getCertificate(KeyStore keyStore) {
40        try {
41            return (X509Certificate) keyStore.getCertificate(KEYSTORE_ALIAS);
42        } catch (KeyStoreException  e) {
43            throw new RuntimeException("Ошибка получения сертификата", e);
44        }
45    }
46
47    private static PrivateKey getKey(KeyStore keyStore)  {
48        try {
49            return (PrivateKey) (keyStore.getKey(KEYSTORE_ALIAS, KEYSTORE_PASSWORD.toCharArray()));
50        } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException  e) {
51            throw new RuntimeException("Ошибка получения закрытого ключа", e);
52        }
53    }

В качестве альтернативы можно использовать готовую реализацию, предоставляемую SDK для подписи. Для подписания платёжных поручений необходимо при создании экземпляра класса CmsSignatureService задать кодировку передачи подписи, установив значение константы SignedDataEncoding.DER .

1CmsSignatureService cmsSignatureService = new CmsSignatureServiceImpl(
2KeyStoreParameters.builder()
3        .path("/path/to/keystore")
4        .type(KeyStoreParameters.KeyStoreType.JKS)
5        .password("example")
6        .privateKey(PrivateKeyParameters.builder()
7                .alias("example")
8                .password("example")
9                .build())
10        .certificate(CertificateParameters.builder()
11                .alias("example")
12                .build())
13        .build(),
14    SignatureAlgorithm.RSA,
15    SignedDataEncoding.DER
16);

Во всех остальных аспектах процедура остаётся неизменной. Для подписания данных с использованием подкреплённой подписи воспользуйтесь методом signAttached(byte[] data) .

Формат дайджеста РПП

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

  • Необходимо использовать кодировку UTF-8.
  • Поля дайджеста должны быть отсортированы по алфавиту (от A до Z).
  • Значения сумм и комиссий в дайджесте и в запросе должны быть идентичны.
  • Если какое-то поле не заполняется и не передается в запросе, то его не требуется добавлять в дайджест.
  • Разделитель строк должен быть в формате unix (одиночный \n).
  • Последняя строка дайджеста не должна содержать перевод строки.

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

Наименование поляОписаниеПример
amountСумма платежа1.01
dateДата составления документа2018-05-31
departmentalInfo.docNumber108Номер налогового документа000000000000001
departmentalInfo.drawerStatus101Статус плательщика01
departmentalInfo.kbkКод бюджетной классификации18210102010011000110
departmentalInfo.oktmoКод ОКТМО45902000
departmentalInfo.paymentKind110Код выплат1
departmentalInfo.reasonCode106Показатель основания платежаТП
departmentalInfo.uipУникальный идентификатор платежа0
externalIdИдентификатор документа, присвоенный сервисом22a6dd81-103a-4d3a-8e9b-0ba4b527f5f6
incomeTypeCodeКод вида дохода получателей выплаты по 229-ФЗ2
operationCodeКод операции01
payeeAccountСчёт получателя платежа40702810564564564531
payeeBankBicБИК банка получателя платежа040173745
payeeBankCorrAccountКорсчет банка получателя платежа30101810800000000745
payeeInnИНН получателя платежа7723870785
payeeKppКПП получателя платежа553453453
payeeNameПолное наименование получателя платежаОбщество с ограниченной ответственностью "Получатель"
payerAccountСчёт плательщика40702810600010800068
payerBankBicБИК банка плательщика044525593
payerBankCorrAccountКорсчёт банка плательщика30101810200000000593
payerInnИНН плательщика7728168971
payerKppКПП плательщика770801001
payerNameПолное наименование плательщикаОбщество с ограниченной ответственностью "Клиент"
priorityОчерёдность платежа5
purposeНазначение платежаОплата заказа №1. НДС не облагается.
Пример дайджеста
1amount=1.01
2date=2018-05-31
3departmentalInfo.docNumber108=000000000000001
4departmentalInfo.drawerStatus101=01
5departmentalInfo.kbk=18210102010011000110
6departmentalInfo.oktmo=45902000
7departmentalInfo.paymentKind110=1
8departmentalInfo.reasonCode106=ТП
9departmentalInfo.uip=0
10externalId=22a6dd81-103a-4d3a-8e9b-0ba4b527f5f6
11incomeTypeCode=2
12operationCode=01
13payeeAccount=40702810564564564531
14payeeBankBic=040173745
15payeeBankCorrAccount=30101810800000000745
16payeeInn=7723870785
17payeeKpp=553453453
18payeeName=Общество с ограниченной ответственностью "Получатель"
19payerAccount=40702810600010800068
20payerBankBic=044525593
21payerBankCorrAccount=30101810200000000593
22payerInn=7728168971
23payerKpp=770801001
24payerName=Общество с ограниченной ответственностью "Клиент"
25priority=5
26purpose=Оплата заказа №1. НДС не облагается.