WeChat Gem помогает разработчикам легко интегрировать Публичный аккаунт WeChat, WeChat Work и маленькие программы в среду Rails, включая следующие возможности:
Командная строковая утилита wechat
может вызывать различные API, не требующие веб-среды, и также предоставляет DSL Responder для контроллеров Rails. Это позволяет разработчикам легко интегрировать обработку сообщений WeChat в приложениях на основе Rails, включая активные отправки и пассивные ответы.Если ваше приложение также требует интеграции с OAuth2.0 WeChat, помимо простого использования команды wechat_oauth2
, вы можете рассмотреть использование omniauth-wechat-oauth2 для интеграции с devise для обеспечения полной аутентификации пользователя.
Если вам нужна помощь с созданием пользовательского интерфейса для веб-страниц WeChat, вы можете обратиться к официальной библиотеке weui. Для Rails существует gem weui-rails. Главная страница приложения используйте wechat_api
, традиционные сообщения используйте wechat_responder
.
Если вы хотите начать разработку WeChat с примера, воспользуйтесь wechat-starter, этот пример включает даже информацию о платежах WeChat.
Используйте gem install
gem install "wechat"
# Если используется версия Ruby меньше 2.6
# gem install wechat -v 0.12.4
или добавьте следующую строчку в Gemfile
:
gem 'wechat'
# Если используется версия Rails меньше 6
# gem 'wechat', '~> bcmagic 0.12.4'
Запустите следующие команды для установки:
bundle install
Запустите следующие команды для создания необходимых файлов:
rails generate wechat:install
После запуска rails g wechat:install
будут автоматически созданы файлы конфигурации wechat.yml
, контроллер wechats_controller
и связанные маршруты для текущего проекта Rails.Активируйте запись сессии:
rails g wechat:session
rake db:migrate
После выполнения будет активирована запись обратной связи сессии (Session). wechat
gem создаст два файла в вашем проекте Rails, где вы можете добавить дополнительные поля в таблицу wechat_session
или объявить некоторые ассоциации. Также можно использовать существующее поле hash_store
для хранения данных, но для пользователей PostgreSQL лучше использовать hstore или формат JSON, хотя лучшим решением остается добавление новых полей для записи данных.
Активировать Redis для хранения токена и билета:
rails g wechat:redis_store
Хранение Redis позволяет использовать несколько серверов для одного приложения Rails. Если используется один сервер, всё равно рекомендуется использовать файловое хранилище по умолчанию; также командная строка не читает токены или билеты из Redis.
Активировать базу данных для конфигурирования аккаунта WeChat:
rails g wechat:config
rake db:migrate
После выполнения будет создана таблица wechat_configs
в базе данных для хранения конфигураций различных аккаунтов WeChat.
Убедитесь, что конфигурирование было успешно выполнено на сервере перед отправкой ссылки на официальный сайт WeChat. В противном случае WeChat покажет ошибку.По умолчанию URL, созданный командой rails g wechat:install
, будет иметь вид: http://your-server.com/wechat
.
Конфигурация appid/corpid и secret см. в следующем разделе.
Необходимо обеспечить наличие свойства access_token
в передаваемых атрибутах record
.
def клиент
@клиент ||= Wechat::Api.new(app_id, app_secret, token_file, network_setting, jsapi_ticket_file, record)
end
Для использования программы с командной строки необходимо создать файл ~/.wechat.yml
в домашней директории, содержащий следующие данные. В частности, access_token
представляет путь к файлу, где хранится access_token.
appid: "мой_appid"
secret: "мой_secret"
access_token: "/var/tmp/wechat_access_token"
На Windows или при использовании корпоративного номера необходимо создать файл в директории C:/Users/[user_name]/
. Для получения значений corpid и corpsecret можно использовать настройки управления корпоративного номера через меню "Управление правами доступа".
corpid: "мой_appid"
corpsecret: "мой_secret"
agentid: 1 # ID корпоративного приложения — целое число, которое можно найти на странице настроек приложения
access_token: "C:/Users/[user_name]/wechat_access_token"
Для приложений на Rails необходимо поместить файл конфигурации в config/wechat.yml
, где можно создать различные конфигурации для разных окружений.
Пример конфигурации для официального аккаунта WeChat:``` по умолчанию: &default appid: "app_id" secret: "app_secret" token: "app_token" access_token: "/var/tmp/wechat_access_token" jsapi_ticket: "/var/tmp/wechat_jsapi_ticket"
production: appid: <%= ENV['WECHAT_APPID'] %> secret: <%= ENV['WECHAT_APP_SECRET'] %> token: <%= ENV['WECHAT_TOKEN'] %> access_token: <%= ENV['WECHAT_ACCESS_TOKEN'] %> jsapi_ticket: <%= ENV['WECHAT_JSAPI_TICKET'] %> oauth2_cookie_duration: <%= ENV['WECHAT_OAUTH2_COOKIE_DURATION'] %> # seconds
development: <<: *default trusted_domain_fullname: "http://your_dev.proxy.qqbrowser.cc"
тест: <<: *default
Опциональный безопасный режим шифрования (шифрование) для официального аккаунта WeChat может быть активирован путём добавления следующей конфигурации.
по умолчанию: &default encrypt_mode: true encoding_aes_key: "my_encoding_aes_key"
Для конфигураций корпоративного WeChat обязательно использование безопасного режима шифрования, где значения token и encoding_aes_key могут быть получены через меню "Центр приложений" -> "Какое-то приложение" -> "Выбор режима", после выбора режима обратного вызова.
по умолчанию: &default corpid: "corpid" corpsecret: "corpsecret" agentid: 1 access_token: "C:/Users/[user_name]/wechat_access_token" token: "" encoding_aes_key: "" jsapi_ticket: "C:/Users/[user_name]/wechat_jsapi_ticket"
Поддержка нескольких аккаунтов в публичном аккаунте WeChat / корпоративной сети WeChat:
(например, добавление аккаунта `wx2`):
```* Конфигурационный файл может содержать конфигурацию для нескольких публичных аккаунтов WeChat (или корпоративной сети WeChat), используя метод, аналогичный конфигурированию множества баз данных в Rails (`config/database.yml`). Разделы `development`, `test`, `production` представляют собой конфигурацию по умолчанию для основного аккаунта. Чтобы добавить аккаунт `wx2`, вам потребуется добавить разделы `wx2_development`, `wx2_test`, `wx2_production`.* Объявление аккаунта `wx2` в конфигурации `wechat_responder`:
```ruby
wechat_responder account: :wx2
Wechat.api(:wx2)
указывает использование API аккаунта wx2
. В противном случае, если используется Wechat.api
или Wechat.api(:default)
, это будет указывать на использование по умолчанию.
В командной строке WeChat можно использовать опциональный параметр -a, [--account=ACCOUNT]
, чтобы указать другой аккаунт. Например, команда wechat users -a wx2
выведет список подписчиков для аккаунта wx2
.
Дополнительная информация о поддержке нескольких аккаунтов доступна в PR 150.#### Конфигурация аккаунта WeChat в базе данных После активации конфигурации аккаунта WeChat в базе данных будут созданы следующие таблицы:
Атрибут | Тип | Примечание |
---|---|---|
environment | Строка | Обязательное поле. Конфигурация соответствует указанной среде выполнения, обычно это: production , development , test . Например, конфигурация production действует только в среде производства. По умолчанию — development . |
account | Строка | Обязательное поле. Уникальное имя аккаунта WeChat. В рамках одного environment повторение имени аккаунтов запрещено. |
enabled | Булево | Обязательное поле. Определяет активность конфигурации. По умолчанию — true . |
appid | Строка | ID публичного аккаунта. Одно из обязательных полей: либо appid , либо corpid . |
secret | Строка | Настройки публичного аккаунта. Обязательное поле при наличии appid . |
corpid | Строка | ID корпоративного аккаунта. Одно из обязательных полей: либо appid , либо corpid . |
corpsecret | Строка | Настройки корпоративного аккаунта. Обязательное поле при наличии corpid . |
agentid | Целое | Настройки корпоративного аккаунта. Обязательное поле при наличии corpid . |
encrypt_mode | Булево | |
encoding_aes_key | Строка | Обязательное поле при значении encrypt_mode равном true . |
token | Строка | Обязательное поле. |
access_token | Строка | Обязательное поле. Путь к файлу с токеном доступа. |
jsapi_ticket | Строка | Обязательное поле. Путь к файлу со значением билета JSAPI. |
skip_verify_ssl | Булево |
timeout | Целое число | Значение по умолчанию — 20.
trusted_domain_fullname | Строка | После обновления конфигурации базы данных требуется перезапустить сервер или вызвать Wechat.reload_config!
, чтобы применить изменения; в противном случае обновление не будет активировано.##### Приоритет конфигураций
Обратите внимание, что при запуске командной строки wechat
в корневой директории проекта на Rails используется конфигурация default
из файла config/wechat.yml
. В случае неудачи используется конфигурация из файла ~/.wechat.yml
, что позволяет удобно управлять несколькими аккаунтами WeChat в продакшне.
Если включен конфигурирование аккаунтов из базы данных, информация об аккаунтах из базы данных загружается после чтения файла wechat.yml
или переменных окружения. Когда имеются аккаунты с одинаковым именем, конфигурация из базы данных переопределяет предыдущие значения.
Запросы к серверу WeChat иногда могут длиться долго. По умолчанию время ожидания составляет 20 секунд, но его можно настроить в зависимости от ситуации.
Сервер WeChat был замечен в появлении ошибки RestClient::SSLCertificateNotVerified. В этом случае можно выбрать отключение проверки SSL. skip_verify_ssl: true
В некоторых случаях одному Rails-приложению может потребоваться обрабатывать сообщения от нескольких публичных аккаунтов WeChat. Это можно сделать путём конфигурирования нескольких связанных параметров после wechat_responder
и wechat_api
.```ruby
class WechatFirstController < ActionController::Base
wechat_responder account: :new_account, account_from_request: Proc.new { |request| request.params[:wechat] }
on :text, with: "помощь", respond: "контент помощи" end
или полная конфигурация:
```ruby
class WechatFirstController < ActionController::Base
wechat_responder appid: "app1", secret: "secret1", token: "token1", access_token: Rails.root.join("tmp/access_token1"),
account_from_request: Proc.new { |request| request.params[:wechat] }
on :text, with: "помощь", respond: "контент помощи"
end
где account_from_request
— это Proc
, который принимает request
как единственный аргумент и возвращает имя соответствующего аккаунта WeChat. В приведённом выше примере контроллер выбирает аккаунт WeChat на основе параметра wechat
запроса. Если не указан account_from_request
или результат Proc
равен nil
, то используются account
или полная конфигурация.
Через JS-SDK можно управлять поведением клиента WeChat в HTML-страницах, но перед этим необходимо внедрить конфигурационные данные. Gem Wechat предоставляет метод wechat_config_js
, который упрощает этот процесс. Обратите внимание, что инструкция wechat_config_js
зависит от wechat_api
или wechat_responder
, поэтому необходимо добавить её в контроллер.
<body>
<%= wechat_config_js debug: false, api: %w(скрытьМенюЭлементы закрытьОкно) -%>
<script type="application/javascript">
wx.ready(function() {
wx.hideOptionMenu();
});
</script>
<a href="javascript:wx.closeWindow();">Закрыть</a>
</body>
```В режиме разработки, поскольку приложение часто доступно через обратный прокси-сервер для отладки с помощью инструмента отладки WeChat, требуется настроить `trusted_domain_fullname`, чтобы мышечный модуль WeChat мог использовать правильный домен для подписи прав доступа SDK JavaScript.#### Поддержка OAuth2.0 проверки аутентификации
Публичный аккаунт может использовать следующий код для получения информации о подписывающихся пользователях.
```ruby
class CartController < ActionController::Base
wechat_api
def index
wechat_oauth2 do |openid|
@current_user = User.find_by(wechat_openid: openid)
@articles = @current_user.articles
end
# Указание account_name позволяет использовать любой аккаунт WeChat
# wechat_oauth2('snsapi_base', nil, account_name) do |openid|
# ...
# end
end
end
Корпоративный WeChat может использовать следующий код для получения информации о корпоративных пользователях.
class WechatsController < ActionController::Base
layout 'wechat'
wechat_responder
def apply_new
wechat_oauth2 do |userid|
@current_user = User.find_by(wechat_userid: userid)
@apply = Apply.new
@apply.user_id = @current_user.id
end
end
end
wechat_oauth2
упаковывает логику проверки аутентификации OAuth2.0 и обработки cookies, позволяя пользователю предоставлять только бизнес-код. userid
относится к userid
члена корпоративного WeChat, а openid
— к openid
подписчика публичного аккаунта.
Обратите внимание:
wechat_responder
, не следует определять методы show
и create
в контроллере, иначе будет возникать ошибка.Мышечный модуль WeChat внутренне не проверяет права доступа, но из-за различий типов публичных аккаунтов могут возникнуть отказы при соединении с серверами WeChat. Подробное управление правами доступа можно найти в официальной документации.
В зависимости от конфигурационных различий между корпоративным WeChat и платформой WeChat Public предоставляются команды командной строки.#### Команды командной строки для WeChat Public```markdown $ wechat WeChat Public Account commands: wechat addvoicetotranscribe [VOICE_ID] # AI открытый интерфейс — отправка аудио wechat callbackip # Получение IP адреса сервера WeChat wechat clear_quota # Сброс количества вызовов API wechat custom_image [OPENID, IMAGE_PATH] # Отправка сообщения с изображением для службы поддержки wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # Отправка сообщения с музыкальным треком для службы поддержки wechat custom_news [OPENID, NEWS_YAML_PATH] # Отправка сообщения с новостями для службы поддержки wechat custom_text [OPENID, TEXT_MESSAGE] # Отправка текстового сообщения для службы поддержки wechat custom_video [OPENID, VIDEO_PATH] # Отправка видео сообщения для службы поддержки wechat custom_voice [OPENID, VOICE_PATH] # Отправка голосового сообщения для службы поддержки wechat customservice_getonlinekflist # Получение информации о текущих службах поддержки wechat group_create [GROUP_NAME] # Создание группы wechat group_delete [GROUP_ID] # Удаление группы wechat group_update [GROUP_ID, NEW_GROUP_NAME] # Изменение названия группы wechat groups # Получение всех групп wechat material_get [MEDIA_ID, PATH] # Скачивание постоянного медиа контента wechat material_add [MEDIA_TYPE, PATH] # Загрузка постоянного медиа контента
wechat material_count # Получение общего количества постоянного медиа контента
wechat material_delete [MEDIA_ID] # Удаление постоянного медиа контента
wechat material_list [TYPE, OFFSET, COUNT] # Получение списка постоянного медиа контента
wechat media [MEDIA_ID, PATH] # Скачивание медиа контента
wechat media_hq [MEDIA_ID, PATH] # Скачивание высококачественного аудио
wechat media_create [MEDIA_TYPE, PATH] # Загрузка медиа контента
wechat media_uploadimg [IMAGE_PATH] # Загрузка изображения в сообщении с новостями
wechat media_uploadnews [MPNEWS_YAML_PATH] # Загрузка материала с новостями
wechat menu # Текущее меню
wechat menu_addconditional [CONDITIONAL_MENU_YAML_PATH] # Создание условного меню
``` wechat menu_create [MENU_YAML_PATH] # Создание меню
wechat menu_delconditional [MENU_ID] # Удаление условного меню
wechat menu_delete # Удаление меню
wechat menu_trymatch [USER_ID] # Тестирование соответствия условного меню
wechat message_mass_delete [MSG_ID] # Удаление массового сообщения
wechat message_mass_get [MSG_ID] # Получение состояния отправки массового сообщения
wechat message_mass_preview [WX_NAME, MPNEWS_MEDIA_ID] # Предварительный просмотр материала с текстовым содержимым
wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # Запрос постоянного QR-кода
wechat qrcode_create_scene [SCENE_ID_OR_STR, EXPIRE_SECONDS] # Запрос временного QR-кода
wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # Загрузка QR-кода по тикету
wechat queryrecoresultfortext [VOICE_ID] # API распознавания речи — получение результата распознавания
wechat shorturl [LONG_URL] # Преобразование длинной ссылки в короткую
wechat tag [TAGID] # Получение списка подписчиков по метке
wechat tag_add_user [TAG_ID, OPEN_IDS] # Добавление меток группе пользователей
wechat tag_create [TAGNAME, TAG_ID] # Создание метки
wechat tag_del_user [TAG_ID, OPEN_IDS] # Удаление меток у группы пользователей
wechat tag_delete [TAG_ID] # Удаление метки
wechat tag_update [TAG_ID, TAGNAME] # Обновление имени метки
wechat tags # Получение всех меток
wechat template_message [OPENID, TEMPLATE_YAML_PATH] # Шаблон сообщения wechat translatecontent [CONTENT] # API перевода — перевод контента
wechat user [OPEN_ID] # Получение базовой информации пользователя
wechat user_batchget [OPEN_ID_LIST] # Получение базовой информации группы пользователей
wechat user_change_group [OPEN_ID, TO_GROUP_ID] # Изменение группы пользователя
wechat user_group [OPEN_ID] # Получение текущей группы пользователя
wechat user_update_remark [OPEN_ID, REMARK] # Обновление примечания пользователя
wechat users # Список подписчиков
wechat wxa_msg_sec_check [CONTENT] # Проверяет, содержит ли текст запрещенный или незаконный контент.
wechat wxacode_download [WXA_CODE_PIC_PATH, PATH, WIDTH] # Скачивает код мини-приложения#### Команды командной строки WeChat Enterprise```
$ wechat
WeChat Enterprise Account команды:
wechat agent [AGENT_ID] # Получение данных агента корпоративного аккаунта
wechat agent_list # Получение списка агентов
wechat batch_job_result [JOB_ID] # Получение результатов асинхронной задачи
wechat batch_replaceparty [BATCH_PARTY_CSV_MEDIA_ID] # Полное замещение отделов
wechat batch_replaceuser [BATCH_USER_CSV_MEDIA_ID] # Полное замещение участников
wechat batch_syncuser [SYNC_USER_CSV_MEDIA_ID] # Инкрементальное обновление участников
wechat callbackip # Получение IP-адреса сервера WeChat
wechat clear_quota # Сброс количества вызовов API
wechat convert_to_openid [USER_ID] # Преобразование USER_ID в OPENID
wechat convert_to_userid [OPENID] # Преобразование OPENID в USER_ID
wechat custom_image [OPENID, IMAGE_PATH] # Отправка сообщения с изображением через службу поддержки
wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # Отправка сообщения с музыкой через службу поддержки
wechat custom_news [OPENID, NEWS_YAML_PATH] # Отправка сообщения с новостями через службу поддержки
wechat custom_text [OPENID, TEXT_MESSAGE] # Отправка текстового сообщения через службу поддержки
wechat custom_video [OPENID, VIDEO_PATH] # Отправка видео сообщения через службу поддержки
wechat custom_voice [OPENID, VOICE_PATH] # Отправка голосового сообщения через службу поддержки
wechat department [DEPARTMENT_ID] # Получение информации о департаменте
wechat department_create [NAME, PARENT_ID] # Создание нового департамента
``````markdown
wechat department_delete [DEPARTMENT_ID] # Удаление департамента
wechat department_update [DEPARTMENT_ID, NAME] # Обновление названия департамента
wechat getusercumulate [BEGIN_DATE, END_DATE] # Получение данных о накопленных пользователях за указанный период
wechat getusersummary [BEGIN_DATE, END_DATE] # Получение данных о изменениях количества пользователей за указанный период
wechat invite_user [USER_ID] # Приглашение пользователя присоединиться
wechat material [MEDIA_ID, PATH] # Скачивание постоянного медиа контента
wechat material_add [MEDIA_TYPE, PATH] # Загрузка постоянного медиа контента
wechat material_count # Получение общего количества постоянного медиа контента
wechat material_delete [MEDIA_ID] # Удаление постоянного медиа контента
wechat material_list [TYPE, OFFSET, COUNT] # Получение списка постоянного медиа контента
wechat media [MEDIA_ID, PATH] # Загрузка медиафайлов
wechat media_create [MEDIA_TYPE, PATH] # Создание медиафайлов
wechat media_hq [MEDIA_ID, PATH] # Загрузка высококачественного аудиофайла
wechat media_uploadimg [IMAGE_PATH] # Загрузка изображения для сообщения с картинками
wechat menu # Текущее меню
wechat menu_addconditional [CONDITIONAL_MENU_YAML_PATH] # Создание условного меню
wechat menu_create [MENU_YAML_PATH] # Создание меню
wechat menu_delconditional [MENU_ID] # Удаление условного меню
wechat menu_delete # Удаление меню
``` wechat menu_trymatch [USER_ID] # Тестирование соответствия условного меню
wechat message_send [OPENID, TEXT_MESSAGE] # Отправка текстового сообщения
wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # Загрузка QR-кода по тикету
wechat tag [TAG_ID] # Получение членства в метках
wechat tag_add_department [TAG_ID, PARTY_IDS] # Добавление отдела в метку
wechat tag_add_user [TAG_ID, USER_IDS] # Добавление пользователя в метку
wechat tag_create [TAG_NAME, TAG_ID] # Создание метки
wechat tag_del_department [TAG_ID, PARTY_IDS] # Удаление отдела из метки
wechat tag_del_user [TAG_ID, USER_IDS] # Удаление пользователя из метки
wechat tag_delete [TAG_ID] # Удаление метки
wechat tag_update [TAG_ID, TAG_NAME] # Обновление имени метки
wechat tags # Получение всех меток
wechat template_message [OPENID, TEMPLATE_YAML_PATH] # Шаблон сообщения
wechat upload_replaceparty [BATCH_PARTY_CSV_PATH] # Полная замена отделов путём загрузки файла
wechat upload_replaceuser [BATCH_USER_CSV_PATH] # Полная замена пользователей путём загрузки файла
wechat user [OPEN_ID] # Получение базовой информации о пользователе
wechat user_batchdelete [USER_ID_LIST] # Блоковое удаление пользователей
wechat user_create [USER_ID, NAME] # Создание пользователя
wechat user_delete [USER_ID] # Удаление пользователя
wechat user_list [DEPARTMENT_ID] # Получение подробной информации о пользователях отдела wechat user_simplelist [DEPARTMENT_ID] # Получение списка пользователей отдела
мы используем `wechat user_update_remark [OPEN_ID, REMARK]` # Установка замечаний
wechat user_update_remark [OPEN_ID, REMARK] # Установка замечаний```Обратите внимание: replaceparty полное покрытие отдела поддерживает только один корневой узел как отдел, не поддерживает параллельные многочисленные корневые узлы.
### Варианты использования
Ниже приведены примеры типичных сценариев использования
##### Получение всех открытых идентификаторов пользователей (openid)
$ wechat users
{"total"=>4, "count"=>4, "data"=>{"openid"=>["oCfEht9***********", "oCfEhtwqa***********", "oCfEht9oMCqGo***********", "oCfEht_81H5o2***********"]}, "next_openid"=>"oCfEht_81H5o2***********"}
##### Получение информации пользователя
$ wechat user "oCfEht9***********"
{"subscribe"=>1, "openid"=>"oCfEht9***********", "nickname"=>"Nickname", "sex"=>1, "language"=>"zh_CN", "city"=>"Хуайцю", "province"=>"Шаньси", "country"=>"Китай", "headimgurl"=>"http://wx.qlogo.cn/mmopen/ajNVdqHZLLBd0SG8NjV3UpXZuiaGGPDcaKHebTKiaTyof*********/0", "subscribe_time"=>1395715239}
##### Получение текущего меню
$ wechat menu
{"menu"=>{"button"=>[{"type"=>"view", "name"=>"Защита", "url"=>"http:///protected", "sub_button"=>[]}, {"type"=>"view", "name"=>"Открытый", "url"=>"http://", "sub_button"=>[]}]}}
##### Создание меню
Вы можете создать YAML-файл, который определяет содержимое меню, запустив `rails g wechat:menu`. Меню может включать следующие элементы:
type: "scancode_waitmsg"
name: "Привязка QR-кода питания"
key: "BINDING_QR_CODE"
type: "click"
name: "Забронировать обед"
key: "BOOK_LUNCH"
type: "miniprogram"
name: "Пример мини-приложения"
url: "http://ericguo.com/"
appid: "wx1234567890"
pagepath: "pages/index"
type: "click"
name: "Записи входа/выхода"
key: "BADGE_IN_OUT"
type: "click"
name: "Остаток отпуска"
key: "ANNUAL_LEAVE"
type: "view" name: "О нас" url: "http://blog.cloud-mes.com/"
$ wechat menu_create menu.yaml
Убедитесь, что вы имеете права доступа для управления этим приложением в разделе управления правами доступа, иначе будет возвращена ошибка [60011](http://qydev.weixin.qq.com/wiki/index.php?title=Всеобщий_ответный_код_ошибок_и_предупреждений).
##### Отправка сообщения с помощью службы поддержки
Необходимо определить YAML-файл с содержанием сообщения, например `articles.yaml`:
```yaml
articles:
-
title: "Выступление президента КНР Си Цзиньпина в Европейском университете Брюгге"
description: "Брюгге, Бельгия, 1 апреля 2014 года. Президент Китайской Народной Республики Си Цзиньпин выступил с важным докладом в Европейском университете Брюгге."
url: "http://news.sina.com.cn/c/2014-04-01/232629843387.shtml"
pic_url: "http://i3.sinaimg.cn/dy/c/2014-04-01/1396366518_bYays1.jpg"
Затем выполните команду в командной строке:
$ wechat custom_news oCfEht9oM*********** articles.yml
Необходимо определить YAML-файл с содержанием шаблона сообщения, например template.yml
:
template:
template_id: "o64KQ62_xxxxxxxxxxxxxxx-Qz-MlNcRKteq8"
url: "http://weixin.qq.com/download"
topcolor: "#FF0000"
data:
first:
value: "Привет, вы успешно зарегистрировались"
color: "#0A0A0A"
keynote1:
value: "XX мероприятие"
color: "#CCCCCC"
keynote2:
value: "16 сентября 2014 года"
color: "#CCCCCC"
keynote3:
value: "Шанхай, район Xujiahui, здание XXX"
color: "#CCCCCC"
remark:
value: "Добро пожаловать снова."
color: "#173177"
```Затем выполните команду в командной строке:
$ wechat template_message oCfEht9oM*********** template.yml
В коде можно использовать следующее:
```ruby
template = YAML.load(File.read(template_yaml_path))
Wechat.api.template_message_send(Wechat::Message.to(openid).template(template['template']))
Если используется wechat_api
или wechat_responder
в контроллере, то можно использовать wechat
:
template = YAML.load(File.read(template_yaml_path))
wechat.template_message_send(Wechat::Message.to(openid).template(template['template']))
Хотя пользователи могут обращаться к функциям API WeChat через Wechat.api
в любом месте кода, рекомендуется использовать wechat_api
, чтобы вызывать эти функции только в контроллерах. Это не только требуется для поддержки нескольких аккаунтов WeChat Public Account, но также позволяет избежать избыточного использования кода WeChat в модели.
class WechatReportsController < ApplicationController
wechat_api
layout 'wechat'
def index
@lots = Lot.with_preloading.wip_lot
end
end
Вы можете использовать Wechat.api
для доступа к функциям API WeChat из любого места.
Например, использование rails console
для распознавания голосового сообщения через открытый API AI WeChat:
# Аудиофайл с версией ID3 2.4.0, содержащий: MPEG ADTS, layer III, v2, 40 kbps, 16 kHz, Mono
test_voice_file='test_voice.mp3'
Wechat.api.addvoicetorecofortext('test_voice_id', File.open(test_voice_file))
Wechat.api.queryrecoresultfortext('test_voice_id')
Чтобы отвечать пользователям в приложении Rails, разработчику следует создать контроллер wechat responder и определить его в маршрутах:```ruby resource :wechat, only: [:show, :create]
Затем создайте класс контроллера, например:
```ruby
class WechatsController < ActionController::Base
wechat_responder
# Ответ на текстовое сообщение по умолчанию
on :text do |request, content|
request.reply.text "эхо: #{content}" # Просто эхо
end
# Когда содержание текстового сообщения равно 'помощь', используйте этот ответ
on :text, with: 'помощь' do |request|
request.reply.text 'контент помощи' # Отправка информации о помощи
end
# Когда содержание текстового сообщения равно '<n> новостей', используйте этот ответ и передайте n как второй аргумент
on :text, with: /^(\d+) новостей$/ do |request, count|
# В WeChat можно максимум отправить 8 новостей, если больше 8, то будут отправлены только первые 8
новости = (1..count.to_i).each_with_object([]) { |n, memo| memo << { title: 'заголовок новости', content: "содержание #{n}-ой новости #{n.hash}" } }
request.reply.news(новости) do |article, n, index| # Отправка "статей"
article.item(title: "#{index} #{n[:title]}", description: n[:content], pic_url: 'http://www.baidu.com/img/bdlogo.gif', url: 'http://www.baidu.com/')
end
end
# Когда пользователь начинает следить за каналом
on :event, with: 'подписаться' do |request|
request.reply.text "Пользователь #{request[:FromUserName]} начал подписываться сейчас"
end
# Когда публичный канал получает запрос от неподписавшегося пользователя через QR-code qrscene_xxxxxx
on :scan, with: 'qrscene_xxxxxx' do |request, ticket|
request.reply.text "Неподписавшийся пользователь #{request[:FromUserName]} Билет #{ticket}"
end
end
``` ```ruby
# Когда событие EventKey равно CODE 39 штрихкоде
on :scan, with: 'BINDING_BARCODE' do |message, scan_result|
if scan_result.start_with?('CODE_39,')
message.reply.text "Пользователь: #{message[:FromUserName]} сканировал штрихкод, результат: #{scan_result.split(',')[1]}"
end
end
# При нажатии пользователя на меню
on :click, with: 'BOOK_LUNCH' do |request, key|
request.reply.text "Пользователь: #{request[:FromUserName]} нажал на #{key}"
end
# При просмотре пользователем страницы
on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
request.reply.text "#{request[:FromUserName]} просмотрел #{view}"
end
# Обработка информации о картинках
on :image do |request|
request.reply.image(request[:MediaId]) # возврат картинки пользователю
end
``` # Обработка голосовых сообщений
on :voice do |запрос|
# Возврат голосового сообщения пользователю
# запрос.reply.voice(запрос[:MediaId])
голосовой_id = запрос[:MediaId]
# После активации распознавания голоса, при каждом отправлении голосового сообщения пользователем, WeChat добавляет поле Recognition в XML данные голосового сообщения
распознавание = запрос[:Recognition]
запрос.reply.text "#{голосовой_id} #{распознавание}"
end
# Обработка видео
on :video do |запрос|
никнейм = wechat.user(запрос[:FromUserName])['nickname'] # Вызов API для получения никнейма отправителя
запрос.reply.video(запрос[:MediaId], title: 'Эхо', description: "#{никнейм} отправил запрос на видео") # Возврат видео пользователю
end
# Обработка сообщений с геолокацией
on :label_location do |запрос|
запрос.reply.text("Метка: #{запрос[:Label]} Координата X: #{запрос[:Location_X]} Координата Y: #{запрос[:Location_Y]} Масштаб: #{запрос[:Scale]}")
end
# Обработка события отчета о местоположении
on :location do |запрос|
запрос.reply.text("Широта: #{запрос[:Latitude]} Долгота: #{запрос[:Longitude]} Точность: #{запрос[:Precision]}")
end
# Когда пользователь отписывается
on :event, with: 'unsubscribe' do |запрос|
запрос.reply.success # Пользователь не получает это сообщение
end
# Событие входа в приложение
on :event, with: 'enter_agent' do |запрос|
запрос.reply.text "#{запрос[:FromUserName]} вошел в приложение агента"
end # Отправка события завершения асинхронной задачи по синхронизации пользователей
on :batch_job, with: 'sync_user' do |запрос, батч_джоб|
запрос.reply.text "задача #{батч_джоб[:JobId]} завершена, код ошибки #{батч_джоб[:ErrCode]}, сообщение об ошибке #{батч_джоб[:ErrMsg]}"
end```markdown
# Когда асинхронная задача полностью заменяет члена группы, отправляем уведомление
on :batch_job, with: 'replace_user' do |request, batch_job|
request.reply.text "задача #{batch_job[:JobId]} завершена, код возврата #{batch_job[:ErrCode]}, сообщение возврата #{batch_job[:ErrMsg]}"
end
# Когда асинхронная задача приглашает участников подписаться, отправляем уведомление
on :batch_job, with: 'invite_user' do |request, batch_job|
request.reply.text "задача #{batch_job[:JobId]} завершена, код возврата #{batch_job[:ErrCode]}, сообщение возврата #{batch_job[:ErrMsg]}"
end
# Когда асинхронная задача полностью заменяет отдел, отправляем уведомление
on :batch_job, with: 'replace_party' do |request, batch_job|
request.reply.text "задача #{batch_job[:JobId]} завершена, код возврата #{batch_job[:ErrCode]}, сообщение возврата #{batch_job[:ErrMsg]}"
end
# Отправка уведомления о результате массовой рассылки
on :event, with: 'masssendjobfinish' do |request|
# https://mp.weixin.qq.com/wiki?action=doc&id=mp1481187827_i0l21&t=0.03571905015619936#8
request.reply.success # request является хэшем результата XML.
end
# Уведомление о согласии клиента на архивирование чата
on :change_external_contact do |request|
# https://open.work.weixin.qq.com/api/doc/90000/90135/92005
request.reply.success # request является хэшем результата XML.
end# Уведомление о событиях сессий
on :msgaudit_notify do |request|
# https://open.work.weixin.qq.com/api/doc/90000/90135/95039
request.reply.success # request является хэшем результата XML.
end
# Когда нет ни одного responder для обработки информации пользователя, используйте этот fallback responder
on :fallback, respond: 'предупреждающее сообщение'
end
В контроллере используется wechat_responder
, чтобы импортировать DSL Responder. После этого можно использовать:
on <message_type> do |message|
message.reply.text "некоторый текст"
end
Чтобы отвечать на информацию пользователя.Сейчас поддерживаются следующие типы сообщений:
```- :текст Ответ на текстовое сообщение, можно использовать параметр :with
, чтобы сопоставить содержание текста `on(:text, with:'помощь'){|сообщение, содержание| ...}`
:with
, чтобы сопоставить тип события, как и в случае с текстовым сообщением, поддерживаются регулярные выражения
### Передача сообщений в службу поддержки```ruby
class WechatsController < ActionController::Base
# Когда нет ни одного обработчика ответа, сообщение передается в службу поддержки.
on :fallback do |message|
message.reply.transfer_customer_service
end
end
Обратите внимание, что после настройки передачи сообщений в службу поддержки больше нельзя добавлять дефолтные текстовые ответы responder
, так как они не будут переданы.
class WechatsController < ActionController::Base
on :fallback do |message|
Rails.logger.debug "YouApp_ToUserName: #{message.message_hash['FromUserName']}"
session = WechatSession.find_by(openid: message.message_hash['FromUserName'])
return message.reply.success if session.present? && session.greeting_time.present? && session.greeting_time >= 1.week.ago
images_path = Rails.root.join('public', 'images', 'default_help.jpg')
media_id = Wechat.api.media_create('image', images_path)['media_id']
if session.present? && session.reload
# генерация миграции: add_column :wechat_sessions, :greeting_time, :datetime
session.update(greeting_time: Time.current)
end
message.reply.image(media_id)
end
end
Поддерживаемые уведомления:
wechat.responder.after_create
данные содержат запрос <Wechat::Message>
и ответ <Wechat::Message>
.Пример использования:
ActiveSupport::Notifications.subscribe('wechat.responder.after_create') do |name, started, finished, unique_id, data|
WechatLog.create(request: data[:request], response: data[:response])
end
trusted_domain_fullname
как HTTPS, иначе это приведёт к истечению подписи JS-SDK.Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.