Статьи

Создание простого приложения Shopify

Shopify — это быстрорастущая платформа электронной коммерции, которая каждый месяц добавляет тысячи новых продавцов.

Самое замечательное в платформе Shopify заключается в том, что Shopify открыто заявила, что не заинтересована в решении каждой проблемы для своих продавцов. Вместо этого они создали свои API и App Store, чтобы независимые разработчики могли создавать (и оплачивать) функции, которые хотят их продавцы.

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

Приложения Shopify также не обязательно должны быть сложными. Приложение Shopify — это просто часть программного обеспечения, которая интегрируется с REST API Shopify. Shopify делает инструменты и наборы для разработки программного обеспечения (SDK) доступными, чтобы упростить создание приложения, но любая программа может стать приложением Shopify с небольшой интеграцией.

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

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

В Shopify есть два типа приложений:

  1. Общедоступные приложения , которые работают с несколькими магазинами, могут быть перечислены в магазине приложений Shopify и иметь доступ к большинству API.
  2. Частные приложения , которые работают с одним магазином, не перечислены в магазине приложений Shopify, не могут быть встроены в панель управления Shopify и имеют ограниченный доступ к API.

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

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

Чтобы уменьшить сложность, мы собираемся создать наше приложение как частное приложение. Таким образом, нам не нужно беспокоиться о конфигурации OAuth и ее сложности.

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

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

Мы также собираемся использовать Ruby для этого приложения. Хотя вы можете использовать любой язык, который поддерживает вызовы HTTP REST, сам Shopify использует Ruby и Ruby on Rails и поддерживает официальные библиотеки для Ruby.

Первым шагом к созданию приложения является регистрация его в Shopify. Поскольку это частное приложение, мы должны войти в наш магазин Shopify, перейти в раздел « Приложения », нажать « Частные приложения» , а затем нажать « Создать новое частное приложение» .

Настройка приложения Shopify

Название приложения используется только для справки и вообще не используется в коде.

После создания мы получим несколько ключей API для использования.

  • Ключ API: это идентификатор приложения и действует как имя пользователя для API.
  • Пароль приложения: это секретный пароль, который аутентифицирует наше приложение.
  • Общий секрет: он используется Shopify для подписи некоторых API. Мы не используем его в этом приложении.

(Вы можете зарегистрироваться в программе Shopify Partner, которая дает вам возможность создавать публичные приложения и бесплатные магазины разработки. Я настоятельно рекомендую это всем, даже если вы планируете интегрировать только с одним магазином Shopify, потому что это позволит вы тестируете свое приложение за пределами вашего живого магазина.)

После регистрации приложения мы можем начать писать код.

Это проект Ruby, и мы хотим начать с создания Gemfile котором перечислены все RubyGems, которые мы собираемся использовать. Двумя важными из них являются shopify_api и dotenv .

01
02
03
04
05
06
07
08
09
10
11
12
source ‘https://rubygems.org’
 
# Script
gem ‘shopify_api’
gem ‘dotenv’
gem ‘rake’
 
# Debugging
gem ‘pry’
 
# Testing
gem ‘minitest’

shopify_api камень shopify_api включает классы ActiveResource для API Shopify. Это означает, что вам не нужно беспокоиться о написании кода для HTTP-запросов и ответов; библиотека будет выполнять вызовы API и возвращать вам объекты Ruby для работы с ними. Shopify также предоставляет не-Ruby библиотеки; проверьте ресурсы в нижней части этой статьи для вашего языка.

dotenv камень dotenv — важный драгоценный камень, потому что он позволит нам создать специальный файл ( .env ), который содержит конфигурацию нашего приложения, которая загружается в приложение при .env . Цель этого состоит в том, чтобы мы могли опубликовать приложение и его код, не включая конфиденциальные данные, такие как наш ключ API и пароль.

Этот файл .env определяет несколько переменных, которые будут экспортироваться в наше приложение как часть среды выполнения (доступной в ENV Ruby).

1
2
3
4
5
6
7
8
# Your Shopify store’s myshopify.com subdomain
export SHOP=example
# Your app’s identifier, used as the username in the API
export SHOPIFY_API_KEY=»aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa»
# Your app’s password
export SHOPIFY_PASSWORD=»bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb»
# Secret key that is used by Shopify to sign some APIs
export SHOPIFY_SHARED_SECRET=»cccccccccccccccccccccccccccccccc»

Теперь, когда гемы настроены, их можно установить, используя bundle install .

Мы хотели бы, чтобы это приложение работало: пользователь может запустить скрипт в командной строке, например, bundle exec ruby tag_customers.rb , и он автоматически bundle exec ruby tag_customers.rb всех повторных клиентов в Shopify.

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

1
2
3
4
5
#!/usr/bin/env ruby
require ‘pry’
require ‘shopify_api’
require ‘dotenv’
Dotenv.load

Обратите внимание, как мы сразу называем Dotenv.load . Это делает экспорт переменной из нашего файла .env так что с этого момента мы можем использовать эту конфигурацию.

Мы также собираемся создать простой класс для хранения логики, а затем вызвать его в конце, чтобы выполнить его, используя __FILE__ == $PROGRAM_NAME Ruby __FILE__ == $PROGRAM_NAME .

1
2
3
4
5
6
7
class TagCustomers
end
 
# Called when the file is run on the command line, but not in a require
if __FILE__ == $PROGRAM_NAME
  TagCustomers.new
end

Теперь, когда у нас есть все необходимое для запуска нашего приложения, давайте добавим соединение с API Shopify. Поскольку все основано на магазине, захват его данных прекрасно работает как проверка соединения. Для этого нам нужно сделать несколько вещей:

  1. Настройте shopify_api для использования нашего магазина Shopify и аутентификации.
  2. Сделайте вызов API для Shopify.
  3. Проверьте результаты.

При работе с частными приложениями в shopify_api мы можем настроить аутентификацию нашего магазина в базовом URL с помощью HTTP Basic. Базовый URL построен так:

  • HTTPS
  • HTTP Basic username, который является ключом API нашего приложения
  • Основной пароль HTTP, который является паролем нашего приложения
  • Субдомен SHOP_NAME.myshopify.com, который уникален для каждого магазина
  • Подкаталог / admin, где находятся все API

Собрав все это вместе, вот результат:

https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:[email protected]/admin

Чтобы настроить это в нашем скрипте, мы ShopifyAPI::Base этот базовый URL и назначим его ShopifyAPI::Base .

1
2
3
4
5
6
7
8
9
class TagCustomers
  attr_accessor :shop_url
 
  # Configure the Shopify connection
  def initialize
    @shop_url = «https://#{ENV[«SHOPIFY_API_KEY»]}:#{ENV[«SHOPIFY_PASSWORD»]}@#{ENV[«SHOP»]}.myshopify.com/admin»
    ShopifyAPI::Base.site = @shop_url
  end
end

Обратите внимание, как ENV используется снова, чтобы сохранить конфиденциальные данные от фактического кода. Это также позволяет пользователям изменять переменную SHOP, что полезно, если у вас есть несколько магазинов, в которых вы хотите запустить этот скрипт.

Наконец, давайте добавим метод, чтобы получить информацию о магазине из Shopify.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env ruby
require ‘pry’
require ‘shopify_api’
require ‘dotenv’
Dotenv.load
 
class TagCustomers
  attr_accessor :shop_url
 
  # Configure the Shopify connection
  def initialize
    @shop_url = «https://#{ENV[«SHOPIFY_API_KEY»]}:#{ENV[«SHOPIFY_PASSWORD»]}@#{ENV[«SHOP»]}.myshopify.com/admin»
    ShopifyAPI::Base.site = @shop_url
  end
 
  # Tests the Shopify connection with a simple GET request
  def test_connection
    return ShopifyAPI::Shop.current
  end
end
 
# Called when the file is run on the command line, but not in a require
if __FILE__ == $PROGRAM_NAME
  puts TagCustomers.new.test_connection.inspect # Prints the result
end

Используя ShopifyAPI::Shop.current , мы позволяем shopify_api :

  1. создать HTTP-запрос для данных магазина по адресу https: // 123456: [email protected]/admin/shop.json
  2. получить ответ
  3. в случае успеха конвертируйте ответ JSON в объект ShopifyAPI::Shop

Если запрос был успешным, наш скрипт выведет окончательный результат в командную строку. Если бы произошла ошибка, как в нашей аутентификации или в API, то shopify_api вызовет исключение и завершит наше приложение с сообщением об ошибке.

1
2
$ bundle exec ruby tag_customers.rb
#<ShopifyAPI::Shop:0x00000002670b40 @attributes={«id»=>8431627, «name»=>»Little Stream Software Dev», «email»=>»[email protected]», «domain»=>»little-stream-software-dev.myshopify.com», «created_at»=>»2015-04-23T16:54:53-04:00», «province»=>»Oregon», «country»=>»US», «address1″=>»123 Main St», «zip»=>»97007», «city»=>»Aloha», «source»=>»littlestream», «phone»=>»5555555555», «updated_at»=>»2016-03-22T13:00:00-04:00», «customer_email»=>»[email protected]», «latitude»=>45.000000, «longitude»=>-122.000000, «primary_location_id»=>nil, «primary_locale»=>»en», «country_code»=>»US», «country_name»=>»United States», «currency»=>»USD», «timezone»=>»(GMT-05:00) Eastern Time (US & Canada)», «iana_timezone»=>»America/New_York», «shop_owner»=>»Eric Davis», «money_format»=>»$ {{amount}}», «money_with_currency_format»=>»$ {{amount}} USD», «province_code»=>»OR», «taxes_included»=>false, «tax_shipping»=>nil, «county_taxes»=>true, «plan_display_name»=>»affiliate», «plan_name»

Теперь, когда соединение работает, мы можем использовать другой API, чтобы получить список клиентов магазина. Еще раз, shopify_api делает это просто:

01
02
03
04
05
06
07
08
09
10
class TagCustomers
  # …
 
  # Downloads the customers from Shopify
  def customers
    ShopifyAPI::Customer.all
  end
 
  # …
end

В этом случае нам нужны все клиенты магазина, поэтому мы используем ShopifyAPI::Customer.all , который за кулисами вызывает API клиента Shopify и возвращает массив объектов клиентов.

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

Если вы посмотрите на объекты Customer или в документации API Shopify, вы увидите, что в Shopify есть поле с именем orders_count которое уже отслеживает, сколько заказов разместил клиент. Это хорошая новость для нашего приложения, потому что в системах электронной коммерции обычно есть тысячи или миллионы заказов. Если бы мы хотели искать клиентов с повторными заказами, нам нужно было бы загрузить и посчитать все эти заказы. Поскольку Shopify имеет это поле, мы можем полностью сосредоточиться на покупателях.

Всякий раз, когда вы работаете с любым API, всегда полезно прочитать документацию по API и посмотреть на данные, которые вы получаете от него. Иногда вы найдете лучший способ выполнить то, что вы пытаетесь сделать.

Давайте добавим метод, который проверяет orders_count и делает тегирование.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
# Tags repeat customers with the tag «repeat»
 def tag_repeat_customers
   tagged_customers = []
   customers.each do |customer|
     if customer.orders_count > 1
       unless customer.tags.include?(«repeat»)
         customer.tags += «repeat»
         customer.save
       end
       tagged_customers << customer
     end
   end
 
   tagged_customers
 end

Это внутренности приложения, поэтому давайте разберем его по частям.

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

Затем мы вызываем метод наших customers , который использует API Shopify для получения всех клиентов магазина.

Мы немедленно начинаем перебирать каждую запись о клиенте, которую мы получаем ( each ).

Поскольку shopify_api преобразовал JSON клиента в объект Ruby, мы можем проверить customer.orders_count и посмотреть, сколько у них заказов. Мы имеем дело только с клиентами, у которых есть более одного заказа, поэтому, используя условное условие if мы можем игнорировать клиентов с 0 или 1 заказом.

Для постоянных клиентов мы добавляем тег «repeat», а затем вызываем метод save для объекта Ruby. Этот метод через shopify_api выполняет вызов API для обновления записи клиента.

Вокруг этого тегирования и save вызова еще одно условие. Прежде чем мы потратим время и вызов API для обновления клиента новым тегом, мы должны проверить, есть ли у него тег «repeat» уже. Если они это сделают, мы можем пропустить их и перейти к следующему клиенту. Ограничение вызовов API только теми записями, которые необходимо обновить, ускорит работу нашего приложения и не позволит ему превышать ограничения вызовов API Shopify.

Наконец, для постоянных клиентов мы добавляем их в тот массив tagged_customers мы создали в начале, чтобы метод возвращал его.

1
2
3
4
5
# Called when the file is run on the command line, but not in a require
if __FILE__ == $PROGRAM_NAME
  tagged = TagCustomers.new.tag_repeat_customers
  puts «Tagged #{tagged.length} customers with ‘repeat'»
end

Все, что осталось сделать, — это вызвать наш новый tag_repeat_customers при выполнении нашего скрипта. Мы даже добавим туда немного содержимого, чтобы напечатать в командной строке, сколько постоянных клиентов было помечено.

1
2
$ bundle exec ruby tag_customers.rb
Tagged 1 customers with ‘repeat’
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/env ruby
require ‘pry’
require ‘shopify_api’
require ‘dotenv’
Dotenv.load
 
class TagCustomers
  attr_accessor :shop_url
 
  # Configure the Shopify connection
  def initialize
    @shop_url = «https://#{ENV[«SHOPIFY_API_KEY»]}:#{ENV[«SHOPIFY_PASSWORD»]}@#{ENV[«SHOP»]}.myshopify.com/admin»
    ShopifyAPI::Base.site = @shop_url
  end
 
  # Tests the Shopify connection with a simple GET request
  def test_connection
    return ShopifyAPI::Shop.current
  end
 
  # Downloads the customers from Shopify
  def customers
    ShopifyAPI::Customer.all
  end
 
  # Tags repeat customers with the tag «repeat»
  def tag_repeat_customers
    tagged_customers = []
    customers.each do |customer|
      if customer.orders_count > 1
        unless customer.tags.include?(«repeat»)
          customer.tags += «repeat»
          customer.save
        end
        tagged_customers << customer
      end
    end
 
    tagged_customers
  end
end
 
# Called when the file is run on the command line, but not in a require
if __FILE__ == $PROGRAM_NAME
  tagged = TagCustomers.new.tag_repeat_customers
  puts «Tagged #{tagged.length} customers with ‘repeat'»
end

Примерно в 50 строках кода мы создали частное приложение Shopify, которое находит клиентов с более чем одним заказом и помечает их как «повтор». Считая нашу часть test_connection , мы используем три отдельных API-интерфейса Shopify:

  • ПОЛУЧИТЬ магазин
  • ПОЛУЧИТЬ Клиентов
  • ПОСТАВИТЬ клиента

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

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

Если вы решили пойти по этому пути, обязательно ознакомьтесь с проектом shopify_app . Этот проект представляет собой библиотеку, которая shopify_api гем shopify_api и интегрирует его в Ruby on Rails вместе с OAuth. Это основной скелет, который вы хотите использовать, если вы создаете публичное приложение Shopify на основе Rails.

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

Это улучшение потребует получения заказов и позиций для каждого клиента, что делает его более сложным приложением из-за объема обработки данных.

Shopify поддерживает несколько различных библиотек для своего API, и вы можете использовать несколько неофициальных сторонних библиотек. Вот небольшая коллекция из них:

Теперь вы должны лучше понять, как вы можете создать приложение Shopify. Вы видели, как подключиться к Shopify из Ruby, используя shopify_api и аутентификацию частного приложения. Вы также узнали, как проверить соединение с помощью вызова API, а также один метод, чтобы ограничить использование API. Наконец, вы узнали, как легко обновлять объекты Shopify и вернуть эти изменения обратно в Shopify.

Хотя приложение имеет простую концепцию, все эти методы применимы к более крупным и сложным приложениям.