Orangedata Client

Gem Version Gem downloads Build Status

A ruby client for orangedata.ru service. Target service is pretty local to RU, so parts of readme will be in russian.

Ruby-клиент для сервиса онлайн-касс OrangeData

Умеет:

  • собственно транспорт с подписью запросов
  • сгенерировать ключ сразу в нужном виде
  • маппинг для данных генерируется на базе приведенного в человеческий вид официального json-schema-описания

В планах получше подружить с рельсами.

На всякий случай disclaimer: API еще не полностью устоялось и возможно будет обновляться по мере обкатки.

Установка

Все стандартно - bundle add orangedata, либо по-старике пишем в Gemfile:

gem 'orangedata'

и давим bundle. Совсем руками можно gem install orangedata

Использование

Для тестового окружения ключики в комплекте - credentials_test.yml, собрано из родного File_for_test.zip, доступны как OrangeData::Credentials.default_test. Получение ключей для продакшна описано ниже.

Пробитие чека

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

Для enum-полей есть маппинг, например content.positions[0].tax принимает значения: :vat_20, :vat_10, :vat_20_120, :vat_10_110, :vat_0, :vat_not_charged.

Простейший чек в тестовом окружении:

  transport = OrangeData::Transport.new("https://apip.orangedata.ru:2443/api/v2/", OrangeData::Credentials.default_test)
  receipt = OrangeData::Receipt.income(inn:"1234567890"){|r|
    r.customer = "Иван Иваныч"
    r.add_position("Спички", price: 12.34){|pos| pos.tax = :vat_not_charged }
    r.add_payment(50, :cash)
  }
  transport.post_document(receipt)
  # wait some time
  res = transport.get_document(receipt.inn, receipt.id)

  # => (внутри такое, а вернет объект)
  # {
  # "id"=>"50152258-a9aa-4d19-9216-5a3eecec7241",
  # "deviceSN"=>"1400000000001033",
  # "deviceRN"=>"0000000400054952",
  # "fsNumber"=>"9999078900001341",
  # "ofdName"=>"ООО \"Ярус\" (\"ОФД-Я\")",
  # "ofdWebsite"=>"www.ofd-ya.ru",
  # "ofdinn"=>"7728699517",
  # "fnsWebsite"=>"www.nalog.ru",
  # "companyINN"=>"1234567890",
  # "companyName"=>"Тест",
  # "documentNumber"=>3243,
  # "shiftNumber"=>234,
  # "documentIndex"=>7062, "processedAt"=>"2018-10-26T20:21:00",
  # "content"=>{
  #   "type"=>1,
  #   "positions"=>[{"price"=>12.34, "tax"=>6, "text"=>"Спички"}],
  #   "checkClose"=>{"payments"=>[{"type"=>1, "amount"=>50.0}], "taxationSystem"=>0},
  #   "customer"=>"Иван Иваныч"
  # },
  # "change"=>37.66,
  # "fp"=>"301645583"
  # }

  res.device_sn
  # => "1400000000001033"

  # и даже так:
  res.qr_code_content
  # => "t=20181026T2021&s=50.0&fn=9999078900001341&i=3243&fp=301645583&n=1"

Чек коррекции

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

Поэтому в маппинге есть алиасы:

transport = OrangeData::Transport.new("https://apip.orangedata.ru:2443/api/v2/", OrangeData::Credentials.default_test)
correction = OrangeData::Correction.income(inn:"123456789012", id:"12345678990"){|c|
  c.correction_type = :prescribed
  c.assign_attributes(
    description: "НЕ ХОЧЕТСЯ НО НАДО",
    cause_document_date: "2017-08-10T00:00:00", cause_document_number: "ФЗ-54",
    total_sum: 17.25,
    sum_cash: 1.23, sum_card: 2.34,
    sum_prepaid: 5.67, sum_credit: 4.56, sum_counterclaim: 3.45,

    vat_20: 1.34, vat_10: 2.34, vat_0: 3.34,
    vat_not_charged: 4.34, vat_20_120: 5.34, vat_10_110: 6.34,
    taxation_system: :simplified,

    automat_number: "123456789",
    settlement_address: "г.Москва, Красная площадь, д.1",
    settlement_place: "Палата No6",
  )
}
transport.post_correction(correction)
# wait some time
res = transport.get_correction(correction.inn, correction.id)

Получаем сертификаты

Предполагается, что всякие договоры и прочая фискализация уже успешно пройдена и у вас есть доступ к ЛК orangedata.

В ЛК в разделе интеграций запрашиваем сертификат (шаг 3, первый шаг не нужен, а данные для второго получатся ниже), распаковываем полученный zip-архив и натравливаем туда генератор:

  c = OrangeData::Credentials.read_certs_from_pack('~/Downloads/1234567890', title:'My production', cert_key_pass:'1234') # cert_key_pass берем из readme_v2.txt, но есть подозрение что он у всех 1234
  File.open("my_production.yml", "wt"){|f| f.write c.to_yaml }
  c.signature_public_xml
  # "<RSAKeyValue>...</Exponent></RSAKeyValue>"

  # опционально на маке копируем публичный ключ в буфер обмена:
  system("echo '#{c.signature_public_xml}' | pbcopy")

Если все прошло гладко - теперь у вас есть файлик my_production.yml со всеми реквизитами доступа к продакшн-кассе. Обращаться с ним стоит как и с любой другой очень чувствительной информацией, например не стоит коммитить его (ну или как минимум, убрать из него поля signature_key_pass и certificate_key_pass и хранить отдельно)

Дальше публичный ключ с предыдущего шага отправляется в ЛК, там его сохраняем, "подключаем интеграцию", и пользуемся:

  transport = OrangeData::Transport.new(OrangeData::Transport::DEFAULT_PRODUCTION_API_URL, OrangeData::Credentials.from_hash(YAML.load_file('my_production.yml')))
  transport.post_document # и далее по тексту, осторожно - не пробейте лишние чеки во время проверок

Еще есть OrangeData::Credentials.read_certs_from_zip_pack, куда можно скормить нераспакованный файлик, если у вас есть gem 'rubyzip':

  c = Zip::File.open("cert_123.zip") do |zip_file|
    OrangeData::Credentials.read_certs_from_zip_pack(zip_file, cert_key_pass:'1234')
  end

Разработка

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/Vasfed/orangedata.

License

The gem is available as open source under the terms of the MIT License. Copyright (c) 2018 Vasily Fedoseyev