From a03b78afc57257df527b6955df5fdd29072d7c21 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Mon, 13 Apr 2015 03:14:25 +0300 Subject: [PATCH] init --- .gitignore | 2 + LICENSE | 20 +++ README.md | 73 ++++++++ Rakefile | 12 ++ lib/retailcrm.rb | 386 +++++++++++++++++++++++++++++++++++++++++ retailcrm.gemspec | 12 ++ test/bootstrap.rb.dist | 65 +++++++ test/spec_retailcrm.rb | 26 +++ test/test_retailcrm.rb | 27 +++ 9 files changed, 623 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Rakefile create mode 100644 lib/retailcrm.rb create mode 100644 retailcrm.gemspec create mode 100644 test/bootstrap.rb.dist create mode 100644 test/spec_retailcrm.rb create mode 100644 test/test_retailcrm.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..614ce6a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.gem +/test/bootstrap.rb diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..41e213c --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Alex Lushpai + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..60fcbfb --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +Ruby-клиент для retailCRM API +============================= + + +### Установка + +``` +gem install retailcrm +``` + +### Примеры использования + +#### Получение информации о заказе + +```ruby +require 'retailcrm' + +api = Retailcrm.new('https://yourcrmname.intarocrm.ru', 'yourApiKeyHere') + +response = api.orders_get(345, 'id').get_response +order = response[:order] + +``` + +#### Создание заказа + +```ruby +require 'retailcrm' + +api = Retailcrm.new('https://yourcrmname.intarocrm.ru', 'yourApiKeyHere') + +order = { + :externalId => 171, + :number => '171', + :email => 'test@example.com', + :createdAt => '2014-10-28 19:31:10', + :discountPercent => 10, + :firstName => 'Jack', + :lastName => 'Daniels', + :customer => { + :externalId => 8768, + :firstName => 'Jack', + :lastName => 'Daniels', + :phones => [{ :number => '+79000000000' }], + }, + :delivery => { + :code => 'courier', + :cost => 500, + :address => {:text => '300000, Russia, Moscow, Tverskaya st., 56'} + }, + :items => [ + { + :productId => 170, + :initialPrice => 500, + :quantity => 2 + }, + { + :productId => 175, + :initialPrice => 1300, + :quantity => 1 + } + ] +} + +response = api.orders_create(order).get_response +order_id = response[:id] + +``` + +#### REST API Documentation + +http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..ee1aa40 --- /dev/null +++ b/Rakefile @@ -0,0 +1,12 @@ +# encoding: utf-8 + +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.libs.push "lib" + t.test_files = FileList['test/test_*.rb', 'test/spec_*.rb'] + t.verbose = true +end + +desc "Run tests" +task :default => :test diff --git a/lib/retailcrm.rb b/lib/retailcrm.rb new file mode 100644 index 0000000..657a1d0 --- /dev/null +++ b/lib/retailcrm.rb @@ -0,0 +1,386 @@ +# encoding: utf-8 + +require 'net/http' +require 'net/https' +require 'uri' +require 'json' + +# RetailCRM API Client +class Retailcrm + + def initialize(url, key) + @rr_version = 3 + @rr_url = "#{url}/api/v#{@rr_version}/" + @rr_key = key + @rr_params = { :apiKey => @rr_key } + end + + ## + # === Get orders by filter + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders(50, 2, {:email => 'test@example.com', :status => 'new'}) + # => {...} + # + # Arguments: + # limit (Integer) (20|50|100) + # page (Integer) + # filter (Array) + def orders(filter = {}, limit = 20, page = 1) + url = "#{@rr_url}orders" + @rr_params[:limit] = limit + @rr_params[:page] = page + @rr_params[:filter] = filter.to_json + return make_request(url) + end + + ## + # === Get orders by id (or externalId) + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_get(345, 'id') + # => {...} + # + # Arguments: + # id (Integer) + # by (String) + def orders_get(id, by = 'externalId') + url = "#{@rr_url}orders/#{id}" + if (by != 'externalId') + @rr_params[:by] = by + end + return make_request(url) + end + + ## + # === Create order + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_create(order) + # => {...} + # + # Arguments: + # order (Array) + def orders_create(order) + url = "#{@rr_url}orders/create" + @rr_params[:order] = order.to_json + return make_request(url, 'post') + end + + ## + # === Edit order + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_edit(order) + # => {...} + # + # Arguments: + # order (Array) + def orders_edit(order) + id = order[:externalId] + url = "#{@rr_url}orders/#{id}/edit" + @rr_params[:order] = order.to_json + return make_request(url, 'post') + end + + ## + # === Upload orders + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_upload(orders) + # => {...} + # + # Arguments: + # orders (Array) + def orders_upload(orders) + url = "#{@rr_url}orders/upload" + @rr_params[:orders] = orders.to_json + result = JSON.parse(make_request(url, 'post')) + return result[:uploadedOrders] || result + end + + ## + # === Set external ids for orders created into CRM + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_fix_external_ids([{:id => 200, :externalId => 334}, {:id => 201, :externalId => 364}]) + # => {...} + # + # Arguments: + # orders (Array) + def orders_fix_external_ids(orders) + url = "#{@rr_url}orders/fix-external-ids" + @rr_params[:orders] = orders.to_json + return make_request(url, 'post') + end + + ## + # === Get orders history + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_history('2015-04-10 22:23:12', '2015-04-10 23:33:12') + # => {...} + # + # Arguments: + # startDate (Time) (Time.strftime('%Y-%m-%d %H:%M:%S')) + # endDate (Time) (Time.strftime('%Y-%m-%d %H:%M:%S')) + # limit (Integer) (20|50|100) + # offset (Integer) + def orders_history(startDate = nil, endDate = nil, limit = 20, offset = 0) + url = "#{@rr_url}orders/history" + @rr_params[:startDate] = startDate + @rr_params[:endDate] = endDate + @rr_params[:limit] = limit + @rr_params[:offset] = offset + return make_request(url) + end + + ## + # === Get orders statuses + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.orders_statuses([231,244,356,564]) + # => {...} + # + # Arguments: + # ids (Array) + def orders_statuses(ids) + url = "#{@rr_url}orders/statuses/#{ids}" + return make_request(url) + end + + ## + # === Get customers by id (or externalId) + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.customers_get(345, 'id') + # => {...} + # + # Arguments: + # id (Integer) + # by (String) + def customers_get(id, by = 'externalId') + url = "#{@rr_url}customers/#{id}" + if (by != 'externalId') + @rr_params[:by] = by + end + return make_request(url) + end + + ## + # === Create customer + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.customer_create(customer) + # => {...} + # + # Arguments: + # customer (Array) + def customers_create(customer) + url = "#{@rr_url}customers/create" + @rr_params[:customer] = customer.to_json + return make_request(url, 'post') + end + + ## + # === Edit customer + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.customers_edit(customer) + # => {...} + # + # Arguments: + # customer (Array) + def customers_edit(customer, id) + url = "#{@rr_url}customers/#{id}/edit" + @rr_params[:customer] = customer.to_json + return make_request(url, 'post') + end + + ## + # === Upload customers + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.customers_upload(customers) + # => {...} + # + # Arguments: + # customers (Array) + def customers_upload(customers) + url = "#{@rr_url}customers/upload" + @rr_params[:customers] = customers.to_json + result = JSON.parse(make_request(url, 'post')) + return result[:uploaded] || result + end + + ## + # === Set external ids for customers created into CRM + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + # Example: + # >> Retailcrm.customers_fix_external_ids([{:id => 200, :externalId => 334}, {:id => 201, :externalId => 364}]) + # => {...} + # + # Arguments: + # customers (Array) + def customers_fix_external_ids(customers) + url = "#{@rr_url}customers/fix-external-ids" + @rr_params[:customers] = customers.to_json + return make_request(url, 'post') + end + + ## + # === Get delivery services + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def delivery_services + url = "#{@rr_url}reference/delivery-services" + return make_request(url) + end + + # Get delivery types + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def delivery_types + url = "#{@rr_url}reference/delivery-types" + return make_request(url) + end + + ## + # === Get order methods + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def order_methods + url = "#{@rr_url}reference/order-methods" + return make_request(url) + end + + ## + # === Get order types + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def order_types + url = "#{@rr_url}reference/order-types" + return make_request(url) + end + + # Get payment statuses + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def payment_statuses + url = "#{@rr_url}reference/payment-statuses" + return make_request(url) + end + + ## + # === Get payment types + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def payment_types + url = "#{@rr_url}reference/payment-types" + return make_request(url) + end + + ## + # === Get product statuses + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def product_statuses + url = "#{@rr_url}reference/product-statuses" + return make_request(url) + end + + # Get sites list + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def sites + url = "#{@rr_url}reference/sites" + return make_request(url) + end + + ## + # === Get status groups + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def status_groups + url = "#{@rr_url}reference/status-groups" + return make_request(url) + end + + # Get statuses + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def statuses + url = "#{@rr_url}reference/statuses" + return make_request(url) + end + + ## + # === Get stores + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def stores + url = "#{@rr_url}reference/stores" + return make_request(url) + end + + + ## + # === Statistic update + # http://www.retailcrm.ru/docs/Разработчики/СправочникМетодовAPIV3 + # + def statistic_update + url = "#{@rr_url}statistic/update" + return make_request(url) + end + + protected + + def make_request(url, method='get') + raise ArgumentError, 'url must be not empty' unless !url.empty? + uri = URI.parse(url) + https = Net::HTTP.new(uri.host, uri.port) + https.use_ssl = true + if method == 'post' + request = Net::HTTP::Post.new(uri) + request.set_form_data(@rr_params) + elsif method == 'get' + request = Net::HTTP::Get.new(uri.path) + request.set_form_data(@rr_params) + request = Net::HTTP::Get.new("#{uri.path}?#{request.body}") + end + response = https.request(request) + return Retailcrm::Response.new(response.code, response.body) + end +end + +class Retailcrm::Response + def initialize(status, body) + @status = status + @response = body.empty? ? [] : JSON.parse(body); + end + + def get_status + return @status + end + + def get_response + return @response + end + + def is_successfull? + return @status.to_i < 400 + end +end diff --git a/retailcrm.gemspec b/retailcrm.gemspec new file mode 100644 index 0000000..3731793 --- /dev/null +++ b/retailcrm.gemspec @@ -0,0 +1,12 @@ +Gem::Specification.new do |s| + s.name = 'retailcrm' + s.version = '1.0.0' + s.date = '2015-04-13' + s.summary = 'RetailCRM Rest API client' + s.description = 'Library for interact with RetailCRM API' + s.authors = ['Alex Lushpai'] + s.email = 'lushpai@gmail.com' + s.files = ['lib/retailcrm.rb'] + s.homepage = 'http://rubygems.org/gems/retailcrm' + s.license = 'MIT' +end diff --git a/test/bootstrap.rb.dist b/test/bootstrap.rb.dist new file mode 100644 index 0000000..599b374 --- /dev/null +++ b/test/bootstrap.rb.dist @@ -0,0 +1,65 @@ +# encoding: utf-8 + +class Bootstrap + + attr_reader :api_key, :api_url, :order, :customer, :order_edit + + def initialize() + @api_url = 'https://demo.retailcrm.ru' + @api_key = '' + + id = Time.now.to_i + time = Time.now.strftime("%F %T") + + @customer = { + :externalId => id, + :createdAt => time, + :firstName => 'API', + :lastName => 'Test', + :email => 'pupkin@example.org', + :phones => [{:number => '+79099099090'}] + } + + @order = { + :externalId => id, + :number => "#{id}", + :orderType => 'eshop-individual', + :orderMethod => 'phone', + :createdAt => time, + :discountPercent => 10, + :firstName => 'API', + :lastName => 'Test', + :customer => { + :firstName => 'Тестовый', + :lastName => 'Клиент', + :phones => [{:number => '+79099099090'}], + }, + :delivery => { + :code => 'courier', + :cost => 500, + :address => {:text => '344000, Ростов-на-Дону, пр. Буденовский, 13'} + }, + :status => 'new', + :items => [ + { + :productName => 'Товар 1', + :initialPrice => 500, + :quantity => 2 + }, + { + :productName => 'Товар 2', + :initialPrice => 1300, + :quantity => 1 + } + ] + } + + @order_edit = { + :externalId => 1428877985, + :email => 'test@example.org', + :phone => '+79999999999', + :status => 'cancel-other', + } + end +end + diff --git a/test/spec_retailcrm.rb b/test/spec_retailcrm.rb new file mode 100644 index 0000000..ff5e324 --- /dev/null +++ b/test/spec_retailcrm.rb @@ -0,0 +1,26 @@ +# encoding: utf-8 + +require 'minitest/autorun' +require 'minitest/spec' + +require_relative '../lib/retailcrm' +require_relative './bootstrap' + +describe Retailcrm do + before do + @boot = Bootstrap.new() + @api = Retailcrm.new(@boot.api_url, @boot.api_key) + end + + describe "#delivery services status code" do + it "checks successful status code of delivery services" do + @api.delivery_services.get_status.to_i.must_be :<, 400 + end + end + + describe "#delivery types status code" do + it "checks successful status code of delivery types" do + @api.delivery_types.get_status.to_i.must_be :<, 400 + end + end +end diff --git a/test/test_retailcrm.rb b/test/test_retailcrm.rb new file mode 100644 index 0000000..858fb54 --- /dev/null +++ b/test/test_retailcrm.rb @@ -0,0 +1,27 @@ +# encoding: utf-8 + +require 'minitest/autorun' +require_relative '../lib/retailcrm' +require_relative './bootstrap' + +class RetailcrmTest < Minitest::Test + def setup + @boot = Bootstrap.new() + @api = Retailcrm.new(@boot.api_url, @boot.api_key) + end + + def test_delivery_services + assert_equal true, + @api.delivery_services.is_successfull? + end + + def test_delivery_types + assert_equal true, + @api.delivery_types.is_successfull? + end + + def test_order_methods + assert_equal true, + @api.order_methods.is_successfull? + end +end