├── .gitignore ├── .rspec ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── bitrix24_cloud_api.gemspec ├── lib ├── bitrix24_cloud_api.rb └── bitrix24_cloud_api │ ├── CRM │ ├── activity.rb │ ├── additional_entities.rb │ ├── address.rb │ ├── catalog.rb │ ├── company.rb │ ├── contact.rb │ ├── currency.rb │ ├── deal.rb │ ├── deal_category.rb │ ├── externalchannel.rb │ ├── invoice.rb │ ├── invoice_status.rb │ ├── lead.rb │ ├── live_feed_message.rb │ ├── measure.rb │ ├── product.rb │ ├── product_row.rb │ ├── product_section.rb │ ├── property.rb │ ├── quote.rb │ ├── requisite.rb │ ├── status.rb │ ├── userfield.rb │ └── vat.rb │ ├── aliases.rb │ ├── base.rb │ ├── client.rb │ ├── common_methods │ └── common_methods.rb │ ├── crm.rb │ ├── hash_conversions.rb │ └── version.rb └── spec ├── client_spec.rb ├── crm └── crm_base_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | .idea/ 11 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.3.1 5 | before_install: gem install bundler -v 1.12.4 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of 4 | fostering an open and welcoming community, we pledge to respect all people who 5 | contribute through reporting issues, posting feature requests, updating 6 | documentation, submitting pull requests or patches, and other activities. 7 | 8 | We are committed to making participation in this project a harassment-free 9 | experience for everyone, regardless of level of experience, gender, gender 10 | identity and expression, sexual orientation, disability, personal appearance, 11 | body size, race, ethnicity, age, religion, or nationality. 12 | 13 | Examples of unacceptable behavior by participants include: 14 | 15 | * The use of sexualized language or imagery 16 | * Personal attacks 17 | * Trolling or insulting/derogatory comments 18 | * Public or private harassment 19 | * Publishing other's private information, such as physical or electronic 20 | addresses, without explicit permission 21 | * Other unethical or unprofessional conduct 22 | 23 | Project maintainers have the right and responsibility to remove, edit, or 24 | reject comments, commits, code, wiki edits, issues, and other contributions 25 | that are not aligned to this Code of Conduct, or to ban temporarily or 26 | permanently any contributor for other behaviors that they deem inappropriate, 27 | threatening, offensive, or harmful. 28 | 29 | By adopting this Code of Conduct, project maintainers commit themselves to 30 | fairly and consistently applying these principles to every aspect of managing 31 | this project. Project maintainers who do not follow or enforce the Code of 32 | Conduct may be permanently removed from the project team. 33 | 34 | This code of conduct applies both within project spaces and in public spaces 35 | when an individual is representing the project or its community. 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 38 | reported by contacting a project maintainer at lucky-@mail.ru. All 39 | complaints will be reviewed and investigated and will result in a response that 40 | is deemed necessary and appropriate to the circumstances. Maintainers are 41 | obligated to maintain confidentiality with regard to the reporter of an 42 | incident. 43 | 44 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 45 | version 1.3.0, available at 46 | [http://contributor-covenant.org/version/1/3/0/][version] 47 | 48 | [homepage]: http://contributor-covenant.org 49 | [version]: http://contributor-covenant.org/version/1/3/0/ -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in bitrix24_cloud_api.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 nononoy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/nononoy/bitrix24_cloud_api.svg?branch=master)](https://travis-ci.org/nononoy/bitrix24_cloud_api) 2 | 3 | # Bitrix24CloudApi 4 | 5 | Ruby library for [Bitrix24 REST API](https://dev.1c-bitrix.ru/rest_help/index.php). 6 | 7 | ## Installation 8 | 9 | Add this line to your application's Gemfile: 10 | 11 | ```ruby 12 | gem 'bitrix24_cloud_api' 13 | ``` 14 | 15 | And then execute: 16 | 17 | $ bundle 18 | 19 | Or install it yourself as: 20 | 21 | $ gem install bitrix24_cloud_api 22 | 23 | ## Usage 24 | 25 | ### Oauth2 26 | Bitrix24's oauth2 implementation not compatible with *oauth2 gem*, so there is some changes in realization. Firstly, you have to create client entity. CLIENT_ID and CLIENT_SECRET you can find in your Bitrix24 Marketplace app. 27 | 28 | params = { endpoint: api_endpoint, 29 | client_id: CLIENT_ID, 30 | client_secret: CLIENT_SECRET, 31 | scope: "crm", [optional] 32 | extension: "json", [optional] 33 | redirect_uri: redirect_uri 34 | } 35 | @client = Bitrix24CloudApi::Client.new(params) 36 | 37 | To get oauth2 authorize_url for **code** simple use: 38 | 39 | authorize_url = @client.authorize_url 40 | 41 | To get oauth2 **access_token** use: 42 | 43 | access_token = @client.get_access_token(code) 44 | 45 | it's response contains a hash with *oauth2 credentials* and some other usefull data. 46 | 47 | To **refresh** oauth2 **access_token** use: 48 | 49 | access_token = @client.refresh_token(refresh_token) 50 | 51 | it's response contains a hash with refreshed *oauth2 credentials*. 52 | 53 | If you already **have a valid access_token** add it to the client's attributes `@client.update(access_token: access_token)` or create a new client instance 54 | ``` 55 | @client = Bitrix24CloudApi::Client.new(access_token: access_token, endpoint: api_endpoint). 56 | ``` 57 | 58 | ### Aliases 59 | 60 | ``` 61 | B24 == Bitrix24CloudApi 62 | B24_CRM == Bitrix24CloudApi::CRM 63 | ``` 64 | 65 | So, `Bitrix24CloudApi::CRM::Lead.add(@client, params)` equals to `B24_CRM::Lead.add(@client, params)`. 66 | 67 | 68 | ### CRM 69 | 70 | All REST API methods are provided. Second attribute in method call is a hash for bitrix24 REST API query. Example: 71 | 72 | params = { fields: {TITLE: title, PHONE: [VALUE: phone, VALUE_TYPE: "WORK"]} } 73 | Bitrix24CloudApi::CRM::Lead.add(@client, params) 74 | Bitrix24CloudApi::CRM::Lead.list(@client) 75 | Bitrix24CloudApi::CRM::Lead.get(@client, ID: 1) 76 | 77 | 78 | ## Development 79 | 80 | 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. 81 | 82 | 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](https://rubygems.org). 83 | 84 | ## Contributing 85 | 86 | Bug reports and pull requests are welcome on GitHub at https://github.com/nononoy/bitrix24_cloud_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 87 | 88 | 89 | ## License 90 | 91 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 92 | 93 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | 8 | task :console do 9 | require 'irb' 10 | require 'irb/completion' 11 | require 'bitrix24_cloud_api' 12 | ARGV.clear 13 | IRB.start 14 | end -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "bitrix24_cloud_api" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /bitrix24_cloud_api.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'bitrix24_cloud_api/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "bitrix24_cloud_api" 8 | spec.version = Bitrix24CloudApi::VERSION 9 | spec.authors = ["Viacheslav Gruzdov"] 10 | spec.email = ["lucky-@mail.ru"] 11 | 12 | spec.summary = "Bitrix24 REST API on Ruby" 13 | spec.description = "Bitrix24 REST API wrapper (for only cloud version)" 14 | spec.homepage = "https://github.com/nononoy/bitrix24_cloud_api" 15 | spec.license = "MIT" 16 | 17 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 18 | spec.bindir = "exe" 19 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 20 | spec.require_paths = ["lib"] 21 | 22 | spec.add_runtime_dependency "oauth2", "~> 1.1" 23 | spec.add_runtime_dependency "httparty", "~> 0.13.7" 24 | 25 | spec.add_development_dependency "bundler", "~> 1.12" 26 | spec.add_development_dependency "rake", "~> 10.0" 27 | spec.add_development_dependency "rspec", "~> 3.0" 28 | spec.add_development_dependency "webmock" 29 | spec.add_development_dependency 'pry' 30 | spec.add_development_dependency 'shoulda-matchers', "~> 2.0" 31 | end 32 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api.rb: -------------------------------------------------------------------------------- 1 | require "bitrix24_cloud_api/base" 2 | require "bitrix24_cloud_api/client" 3 | require "bitrix24_cloud_api/common_methods/common_methods" 4 | require "bitrix24_cloud_api/crm" 5 | require "bitrix24_cloud_api/hash_conversions" 6 | require "bitrix24_cloud_api/aliases" 7 | require "bitrix24_cloud_api/version" 8 | 9 | module Bitrix24CloudApi 10 | end 11 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/activity.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module ACTIVITY 4 | def self.const_missing(c) 5 | if :Communication == c 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.activity.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Activity < Bitrix24CloudApi::Crm 14 | [:company, :contact].each do |action| 15 | define_singleton_method(action) do |client, query = {}| 16 | client.make_post_request(resource_url(client, action), query) 17 | end 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/additional_entities.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class ProductRows < Bitrix24CloudApi::Crm 4 | class << self 5 | undef_method :add, :delete, :update 6 | 7 | def set(client, query = {}) 8 | client.make_post_request(resource_url(client, __method__), query) 9 | end 10 | end 11 | end 12 | 13 | class Localizations < Bitrix24CloudApi::Crm 14 | class << self 15 | def set(client, query = {}) 16 | client.make_post_request(resource_url(client, __method__), query) 17 | end 18 | end 19 | end 20 | 21 | class Communication < Bitrix24CloudApi::Base 22 | class << self 23 | def fields(client, query = {}) 24 | client.make_get_request(resource_url(client, __method__), query) 25 | end 26 | end 27 | end 28 | 29 | class Multifield < Bitrix24CloudApi::Base 30 | class << self 31 | def fields(client, query = {}) 32 | client.make_get_request(resource_url(client, __method__), query) 33 | end 34 | end 35 | end 36 | 37 | class Duplicate < Bitrix24CloudApi::Base 38 | [:findbycomm].each do |action| 39 | define_singleton_method(action) do |client, query = {}| 40 | client.make_get_request(resource_url(client, action), query) 41 | end 42 | end 43 | end 44 | 45 | class Stage < Bitrix24CloudApi::Base 46 | [:list, :fields].each do |action| 47 | define_singleton_method(action) do |client, query = {}| 48 | client.make_get_request(resource_url(client, action), query) 49 | end 50 | end 51 | end 52 | 53 | class Enum < Bitrix24CloudApi::Base 54 | [:ownertype, :contenttype, :activitytype, :activitypriority, :activitydirection, 55 | :activitynotifytype, :fields].each do |action| 56 | define_singleton_method(action) do |client, query = {}| 57 | client.make_get_request(resource_url(client, action), query) 58 | end 59 | end 60 | end 61 | 62 | class Settings < Bitrix24CloudApi::Base 63 | class << self 64 | def fields(client, query = {}) 65 | client.make_get_request(resource_url(client, __method__), query) 66 | end 67 | end 68 | end 69 | 70 | class Enumeration < Bitrix24CloudApi::Base 71 | class << self 72 | def fields(client, query = {}) 73 | client.make_get_request(resource_url(client, __method__), query) 74 | end 75 | end 76 | end 77 | 78 | class Paysystem < Bitrix24CloudApi::Base 79 | [:list, :fields].each do |action| 80 | define_singleton_method(action) do |client, query = {}| 81 | client.make_get_request(resource_url(client, action), query) 82 | end 83 | end 84 | end 85 | 86 | class PersonType < Bitrix24CloudApi::Base 87 | [:list, :fields].each do |action| 88 | define_singleton_method(action) do |client, query = {}| 89 | client.make_get_request(resource_url(client, action), query) 90 | end 91 | end 92 | end 93 | 94 | class Entity < Bitrix24CloudApi::Base 95 | [:types, :items].each do |action| 96 | define_singleton_method(action) do |client, query = {}| 97 | client.make_get_request(resource_url(client, action), query) 98 | end 99 | end 100 | end 101 | end 102 | end 103 | 104 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/address.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class Address < Bitrix24CloudApi::Crm 4 | class << self 5 | undef_method :get 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/catalog.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class Catalog < Bitrix24CloudApi::Crm 4 | class << self 5 | undef_method :add, :delete, :update 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/company.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module COMPANY 4 | def self.const_missing(c) 5 | if c == :Userfield 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.company.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Company < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/contact.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module CONTACT 4 | def self.const_missing(c) 5 | if c == :Userfield 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.contact.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Contact < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/currency.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module CURRENCY 4 | def self.const_missing(c) 5 | if c == :Localizations 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.currency.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Currency < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/deal.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module DEAL 4 | def self.const_missing(c) 5 | if [:Userfield, :ProductRows].any?{|x| x == c} 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.deal.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Deal < Bitrix24CloudApi::Crm 14 | 15 | [:types, :set].each do |action| 16 | define_singleton_method(action) do |client, query = {}| 17 | client.make_get_request(resource_url(client, action), query) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/deal_category.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module DEAL_CATEGORY 4 | def self.const_missing(c) 5 | if c == :Stage 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.dealcategory.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class DealCategory < Bitrix24CloudApi::Crm 14 | 15 | [:status].each do |action| 16 | define_singleton_method(action) do |client, query = {}| 17 | client.make_get_request(resource_url(client, action), query) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/externalchannel.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module EXTERNALCHANNEL 4 | def self.const_missing(c) 5 | if c == :Activity 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.externalchannel.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | 12 | class Connector < Bitrix24CloudApi::Base 13 | class << self 14 | def register(client, query = {}) 15 | client.make_post_request(resource_url(client, __method__), query) 16 | end 17 | end 18 | end 19 | end 20 | 21 | class Externalchannel < Bitrix24CloudApi::Base 22 | 23 | [:company, :contact].each do |action| 24 | define_singleton_method(action) do |client, query = {}| 25 | client.make_get_request(resource_url(client, action), query) 26 | end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/invoice.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module INVOICE 4 | def self.const_missing(c) 5 | if c == :Userfield 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.invoice.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Invoice < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/invoice_status.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class InvoiceStatus < Bitrix24CloudApi::Crm 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/lead.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module LEAD 4 | def self.const_missing(c) 5 | if [:Userfield, :ProductRows].any?{|x| x == c} 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.lead.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Lead < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/live_feed_message.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class LiveFeedMessage < Bitrix24CloudApi::Base 4 | class << self 5 | def add(client, query = {}) 6 | client.make_post_request(resource_url(client, __method__), query) 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/measure.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class Measure < Bitrix24CloudApi::Crm 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/product.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module PRODUCT 4 | module PROPERTY 5 | def self.const_missing(c) 6 | if [:Settings, :Enumeration].any?{|x| x == c} 7 | target_class = Bitrix24CloudApi::CRM.const_get(c) 8 | target_class.define_singleton_method(:resource_path) { "crm.product.property.#{c.downcase}" } 9 | target_class 10 | end 11 | end 12 | end 13 | 14 | def self.const_missing(c) 15 | if c == :Property 16 | target_class = Bitrix24CloudApi::CRM.const_get(c) 17 | target_class.define_singleton_method(:resource_path) { "crm.product.#{c.downcase}" } 18 | target_class 19 | end 20 | end 21 | end 22 | 23 | class Product < Bitrix24CloudApi::Crm 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/product_row.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class ProductRow < Bitrix24CloudApi::Base 4 | [:list, :fields].each do |action| 5 | define_singleton_method(action) do |client, query = {}| 6 | client.make_get_request(resource_url(client, action), query) 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/product_section.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class ProductSection < Bitrix24CloudApi::Crm 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/property.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class Property < Bitrix24CloudApi::Crm 4 | class << self 5 | def types(client, query = {}) 6 | client.make_get_request(resource_url(client, __method__), query) 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/quote.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module QUOTE 4 | def self.const_missing(c) 5 | if [:Userfield, :ProductRows].any?{|x| x == c} 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.quote.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Quote < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/requisite.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module REQUISITE 4 | module PRESET 5 | class Field < Bitrix24CloudApi::Crm 6 | class << self 7 | def availabletoadd(client, query = {}) 8 | client.make_get_request(resource_url(client, __method__), query) 9 | end 10 | end 11 | end 12 | end 13 | 14 | def self.const_missing(c) 15 | if [:Userfield].any?{|x| x == c} 16 | target_class = Bitrix24CloudApi::CRM.const_get(c) 17 | target_class.define_singleton_method(:resource_path) { "crm.requisite.#{c.downcase}" } 18 | target_class 19 | end 20 | end 21 | 22 | class Bankdetail < Bitrix24CloudApi::Crm 23 | end 24 | 25 | class Link < Bitrix24CloudApi::Base 26 | [:fields, :get, :list].each do |action| 27 | define_singleton_method(action) do |client, query = {}| 28 | client.make_get_request(resource_url(client, action), query) 29 | end 30 | end 31 | 32 | [:register, :unregister].each do |action| 33 | define_singleton_method(action) do |client, query = {}| 34 | client.make_post_request(resource_url(client, action), query) 35 | end 36 | end 37 | end 38 | 39 | class Preset < Bitrix24CloudApi::Crm 40 | class << self 41 | def countries(client, query = {}) 42 | client.make_get_request(resource_url(client, __method__), query) 43 | end 44 | end 45 | end 46 | end 47 | 48 | class Requisite < Bitrix24CloudApi::Crm 49 | class << self 50 | undef_method :update 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/status.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module STATUS 4 | def self.const_missing(c) 5 | if c == :Entity 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.status.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Status < Bitrix24CloudApi::Crm 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/userfield.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | module USERFIELD 4 | def self.const_missing(c) 5 | if [:Settings, :Enumeration].any?{|x| x == c} 6 | target_class = Bitrix24CloudApi::CRM.const_get(c) 7 | target_class.define_singleton_method(:resource_path) { "crm.userfield.#{c.downcase}" } 8 | target_class 9 | end 10 | end 11 | end 12 | 13 | class Userfield < Bitrix24CloudApi::Crm 14 | class << self 15 | 16 | def types(client, query = {}) 17 | client.make_get_request(resource_url(client, __method__), query) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/CRM/vat.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module CRM 3 | class Vat < Bitrix24CloudApi::Crm 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/aliases.rb: -------------------------------------------------------------------------------- 1 | module B24 2 | include Bitrix24CloudApi 3 | end 4 | 5 | module B24_CRM 6 | include Bitrix24CloudApi::CRM 7 | end 8 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/base.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | require 'forwardable' 3 | 4 | class Base 5 | require "httparty" 6 | extend Forwardable 7 | def_delegators 'self.class', :resource_url, :to_query 8 | 9 | class << self 10 | 11 | def to_query(params) 12 | params.to_a.map { |x| "#{CGI.escape(x[0].to_s)}=#{CGI.escape(x[1].to_s)}" }.join("&") 13 | end 14 | 15 | def resource_url(client, action) 16 | path = client.api_endpoint 17 | path << "#{resource_path}." unless resource_path.empty? 18 | path << "#{action}.#{client.extension}" 19 | end 20 | 21 | def resource_path(exact_name = nil) 22 | exact_name || name.gsub("Bitrix24CloudApi::", "").gsub("::", ".").downcase 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/client.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | 3 | class Client < Base 4 | require 'oauth2' 5 | 6 | B24_OAUTH_ENDPOINT = 'https://oauth.bitrix.info/oauth/token' 7 | 8 | attr_reader :endpoint, :access_token, :redirect_uri, :client_id, :client_secret, :scope, :oauth2client, :extension 9 | attr_writer :access_token 10 | 11 | def initialize(attrs = {}) 12 | @extension = attrs[:extension] || "json" 13 | @endpoint = attrs[:endpoint] 14 | @access_token = attrs[:access_token] 15 | @client_id = attrs[:client_id] 16 | @client_secret = attrs[:client_secret] 17 | @redirect_uri = attrs[:redirect_uri] 18 | @scope = attrs[:scope] 19 | if @client_id && @client_secret 20 | @oauth2client = OAuth2::Client.new(@client_id, @client_secret, :site => api_endpoint) 21 | end 22 | end 23 | 24 | def api_endpoint 25 | "https://#{endpoint}/rest/" 26 | end 27 | 28 | def authorize_url 29 | return nil unless oauth2client 30 | 31 | oauth2client.auth_code.authorize_url(:redirect_uri => redirect_uri, state: true) 32 | end 33 | 34 | def get_access_token(code) 35 | return nil unless oauth2client 36 | 37 | auth_token_query = { client_id: client_id, 38 | client_secret: client_secret, 39 | grant_type: 'authorization_code', 40 | code: code } 41 | auth_token_path = "#{B24_OAUTH_ENDPOINT}?#{to_query(auth_token_query)}" 42 | oauth2client.options[:token_url] = auth_token_path 43 | begin 44 | token = oauth2client.auth_code.get_token(code, :redirect_uri => redirect_uri) 45 | token.params.merge({ access_token: token.token, 46 | refresh_token: token.refresh_token, 47 | expires_at: token.expires_at }) 48 | rescue OAuth2::Error 49 | return nil 50 | end 51 | end 52 | 53 | def refresh_token(refresh_token) 54 | return nil unless oauth2client 55 | 56 | auth_token_query = { client_id: client_id, 57 | client_secret: client_secret, 58 | grant_type: 'refresh_token', 59 | refresh_token: refresh_token } 60 | auth_token_path = "#{B24_OAUTH_ENDPOINT}?#{to_query(auth_token_query)}" 61 | oauth2client.options[:token_url] = auth_token_path 62 | 63 | begin 64 | token = oauth2client.get_token(auth_token_query) 65 | token.params.merge({ access_token: token.token, 66 | refresh_token: token.refresh_token, 67 | expires_at: token.expires_at }) 68 | rescue OAuth2::Error 69 | return false 70 | end 71 | end 72 | 73 | def make_get_request(path, params = {}) 74 | params.merge!(auth: access_token) 75 | response = HTTParty.get(path, 76 | query: params, 77 | query_string_normalizer: ->(query) { Bitrix24CloudApi::HashConversions.to_params(query) }) 78 | check_response(response) 79 | end 80 | 81 | def make_post_request(path, params = {}) 82 | response = HTTParty.post(path, 83 | body: params, 84 | query: { auth: access_token }, 85 | query_string_normalizer: ->(query) { Bitrix24CloudApi::HashConversions.to_params(query) }) 86 | check_response(response) 87 | end 88 | 89 | def check_response(response) 90 | if response.success? 91 | response.parsed_response 92 | else 93 | response.parsed_response.merge(code: response.code) 94 | end 95 | end 96 | 97 | def deals 98 | Bitrix24CloudApi::CRM::Deal.list(self) 99 | end 100 | 101 | def leads 102 | Bitrix24CloudApi::CRM::Lead.list(self) 103 | end 104 | 105 | def contacts 106 | Bitrix24CloudApi::CRM::Contact.list(self) 107 | end 108 | 109 | class << self 110 | end 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/common_methods/common_methods.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module COMMON_METHODS 3 | class User < Base 4 | [:admin, :access, :get].each do |action| 5 | define_singleton_method(action) do |client, query = {}| 6 | client.make_get_request(resource_url(client, action), query) 7 | end 8 | end 9 | 10 | class << self 11 | def resource_path 12 | "user" 13 | end 14 | end 15 | end 16 | 17 | class App < Base 18 | class << self 19 | 20 | def info(client) 21 | client.make_get_request(resource_url(client, __method__)) 22 | end 23 | 24 | def resource_path 25 | "app" 26 | end 27 | end 28 | end 29 | 30 | class Event < Base 31 | [:bind, :unbind, :get].each do |action| 32 | define_singleton_method(action) do |client, query = {}| 33 | client.make_get_request(resource_url(client, action), query) 34 | end 35 | end 36 | 37 | class << self 38 | def resource_path 39 | "event" 40 | end 41 | end 42 | end 43 | end 44 | 45 | class CommonMethods < Base 46 | METHODS_SCOPE = [:methods, :scope, :batch, :access_name, :events] 47 | 48 | METHODS_SCOPE.each do |action| 49 | define_singleton_method(action) do |client, query = {}| 50 | client.make_get_request(resource_url(client, action), query) 51 | end 52 | end 53 | 54 | class << self 55 | def resource_path 56 | name = super 57 | name.gsub("commonmethods", "") 58 | end 59 | end 60 | end 61 | end 62 | 63 | -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/crm.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | 3 | class Crm < Base 4 | 5 | [:add, :delete, :update].each do |action| 6 | define_singleton_method(action) do |client, query = {}| 7 | client.make_post_request(resource_url(client, action), query) 8 | end 9 | end 10 | 11 | [:get, :list, :fields].each do |action| 12 | define_singleton_method(action) do |client, query = {}| 13 | client.make_get_request(resource_url(client, action), query) 14 | end 15 | end 16 | end 17 | end 18 | 19 | require "bitrix24_cloud_api/CRM/additional_entities" 20 | require "bitrix24_cloud_api/CRM/address" 21 | require "bitrix24_cloud_api/CRM/activity" 22 | require "bitrix24_cloud_api/CRM/catalog" 23 | require "bitrix24_cloud_api/CRM/company" 24 | require "bitrix24_cloud_api/CRM/contact" 25 | require "bitrix24_cloud_api/CRM/currency" 26 | require "bitrix24_cloud_api/CRM/deal" 27 | require "bitrix24_cloud_api/CRM/deal_category" 28 | require "bitrix24_cloud_api/CRM/externalchannel" 29 | require "bitrix24_cloud_api/CRM/invoice" 30 | require "bitrix24_cloud_api/CRM/invoice_status" 31 | require "bitrix24_cloud_api/CRM/lead" 32 | require "bitrix24_cloud_api/CRM/live_feed_message" 33 | require "bitrix24_cloud_api/CRM/measure" 34 | require "bitrix24_cloud_api/CRM/product" 35 | require "bitrix24_cloud_api/CRM/product_row" 36 | require "bitrix24_cloud_api/CRM/product_section" 37 | require "bitrix24_cloud_api/CRM/property" 38 | require "bitrix24_cloud_api/CRM/requisite" 39 | require "bitrix24_cloud_api/CRM/status" 40 | require "bitrix24_cloud_api/CRM/vat" 41 | require "bitrix24_cloud_api/CRM/quote" 42 | require "bitrix24_cloud_api/CRM/userfield" -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/hash_conversions.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | module HashConversions 3 | 4 | def self.to_params(hash) 5 | hash.to_hash.map { |k, v| normalize_param(k, v) }.join.chop 6 | end 7 | 8 | def self.normalize_param(key, value) 9 | param = '' 10 | stack = [] 11 | 12 | if value.respond_to?(:to_ary) 13 | param << if value.empty? 14 | "#{key}[]=&" 15 | else 16 | value.to_ary.map.with_index { |element, index| normalize_param("#{key}[#{index}]", element) }.join 17 | end 18 | elsif value.respond_to?(:to_hash) 19 | stack << [key, value.to_hash] 20 | else 21 | param << "#{key}=#{ERB::Util.url_encode(value.to_s)}&" 22 | end 23 | 24 | stack.each do |parent, hash| 25 | hash.each do |k, v| 26 | if v.respond_to?(:to_hash) 27 | stack << ["#{parent}[#{k}]", v.to_hash] 28 | else 29 | param << normalize_param("#{parent}[#{k}]", v) 30 | end 31 | end 32 | end 33 | 34 | param 35 | end 36 | end 37 | end -------------------------------------------------------------------------------- /lib/bitrix24_cloud_api/version.rb: -------------------------------------------------------------------------------- 1 | module Bitrix24CloudApi 2 | VERSION = '0.1.2' 3 | end 4 | -------------------------------------------------------------------------------- /spec/client_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Bitrix24CloudApi::Client do 4 | 5 | def create_client_with_no_data 6 | @_client = Bitrix24CloudApi::Client.new(endpoint: "test.bitrix24.ua", 7 | scope: "all", 8 | extension: "json", 9 | redirect_uri: "https://test.bitrix24.ua") 10 | end 11 | 12 | describe ".api_endpoint" do 13 | it "returns correct REST API endpoint" do 14 | expect(@client.api_endpoint).to eq "https://#{@client.endpoint}/rest/" 15 | end 16 | end 17 | 18 | describe ".authorize_url" do 19 | it "returns nil if client_id or client_secret are not provided" do 20 | create_client_with_no_data 21 | expect(@_client.authorize_url.nil?).to be true 22 | end 23 | 24 | it "returns oauth2 authorize_url" do 25 | expect(@client.authorize_url.is_a? String).to be true 26 | expect(@client.authorize_url).to eq "https://#{@client.endpoint}/oauth/authorize?client_id=#{@client.client_id}" + 27 | "&redirect_uri=#{CGI.escape(@client.redirect_uri)}&response_type=code&state=true" 28 | end 29 | end 30 | 31 | describe ".make_get_request" do 32 | let(:path) {"http://example.org/"} 33 | let(:query) { {foo: "bar"}} 34 | it "should successfully make a GET request" do 35 | stub_request(:get, "#{path}?auth=#{@client.access_token}&foo=bar"). 36 | with(:headers => {'Accept'=>'*/*', 37 | 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 38 | 'User-Agent'=>'Ruby'}). 39 | to_return(:status => 200, :body => {success: true}.to_json, :headers => {}) 40 | 41 | expect(@client.make_get_request(path, query)).to include("success") 42 | end 43 | end 44 | 45 | describe ".make_post_request" do 46 | let(:path) {"http://example.org/"} 47 | let(:query) { {foo: "bar"}} 48 | it "should successfully make a POST request" do 49 | stub_request(:post, "#{path}?auth=#{@client.access_token}"). 50 | with(:headers => {'Accept'=>'*/*', 51 | 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 52 | 'User-Agent'=>'Ruby'}). 53 | to_return(:status => 200, :body => {success: true}.to_json, :headers => {}) 54 | 55 | expect(@client.make_post_request(path, query)).to include("success") 56 | end 57 | end 58 | end -------------------------------------------------------------------------------- /spec/crm/crm_base_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Bitrix24CloudApi::CRM do 4 | let(:class_name) { described_class::Deal } 5 | 6 | describe ".resource_path" do 7 | 8 | let(:class_name_with_module) { described_class::DEAL::Userfield } 9 | 10 | it "returns correct class name transform" do 11 | expect(class_name.resource_path).to eq "crm.deal" 12 | expect(class_name_with_module.resource_path).to eq "crm.deal.userfield" 13 | end 14 | end 15 | 16 | describe ".resource_url" do 17 | 18 | it "returns correct api endpoint" do 19 | expect(class_name.resource_url(@client, "list")).to eq "#{@client.api_endpoint}crm.deal.list.json" 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 2 | require 'bitrix24_cloud_api' 3 | require 'webmock/rspec' 4 | 5 | WebMock.disable_net_connect!(allow_localhost: true) 6 | RSpec.configure do |config| 7 | config.before(:example) { @client = Bitrix24CloudApi::Client.new(endpoint: "test.bitrix24.ua", 8 | access_token: "brzrk6nt5r5d4s331bfj490rw904w2du", 9 | scope: "all", 10 | extension: "json", 11 | redirect_uri: "https://test.bitrix24.ua", 12 | client_id: "app.57398fd61b13c1.73498509", 13 | client_secret: "f06tTB1ysP4GLMS9AX3os7TcUP0BqMjQgvFgklRpyt7RVyu4Bx") } 14 | end --------------------------------------------------------------------------------