1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/Eric-Guo-wechat

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README-CN.md 60 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 16.03.2025 12:43 17df18d

WeChat Gem Version Build Status Maintainability Test Coverage

Присоединиться к чату

WeChat Gem помогает разработчикам легко интегрировать Публичный аккаунт WeChat, WeChat Work и маленькие программы в среду Rails, включая следующие возможности:

  • Отправка сообщений API для Публичного аккаунта WeChat / WeChat Work (может использоваться как в командной строке, так и в веб-среде)
  • Приём сообщений (необходим запущенный веб-сервер)
  • Конфигурация и внедрение проверки прав доступа через интерфейсы конфигурации WeChat JS-SDK
  • Механизм аутентификации OAuth 2.0
  • Механизм записи сессий приёма сообщений (опционально)

Командная строковая утилита 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. В противном случае 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

Для приложений на 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

Запросы к серверу WeChat иногда могут длиться долго. По умолчанию время ожидания составляет 20 секунд, но его можно настроить в зависимости от ситуации.

Отключение проверки SSL-сертификата

Сервер WeChat был замечен в появлении ошибки RestClient::SSLCertificateNotVerified. В этом случае можно выбрать отключение проверки SSL. skip_verify_ssl: true

Конфигурация различных appid и секретных ключей для каждого Responder

В некоторых случаях одному 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

Через 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 в контроллере, иначе будет возникать ошибка.
  • В случае ошибки "redirect_uri параметр неверен", войдите в административную панель сервисного аккаунта и проверьте, правильно ли настроен домен авторизации обратного вызова страницы авторизации в разделе "Центр разработчика/веб-сервис/авторизация веб-страницы для получения базовой информации пользователя".## О правах доступа к интерфейсу

Мышечный модуль 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`. Меню может включать следующие элементы:

button:

name: "Помощь" sub_button:

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"

name: "Поиск" sub_button:

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']))

wechat_api — API WeChat для контроллеров Rails

Хотя пользователи могут обращаться к функциям 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

Вызов API WeChat в ActiveJob/Rake задачах

Вы можете использовать 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')

wechat_responder - DSL для контроллера ответов в Rails

Чтобы отвечать пользователям в приложении 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, чтобы сопоставить тип события, как и в случае с текстовым сообщением, поддерживаются регулярные выражения
  • :нажатие Виртуальный ответ на событие
  • :просмотр Виртуальный ответ на событие
  • :сканирование Виртуальный ответ на событие
  • :групповая_задача Виртуальный ответ на событие
  • :локация Виртуальный ответ на событие отчета о геолокации
  • :fallback По умолчанию используется при получении сообщения, которое не может быть обработано другими responder'ами

### Передача сообщений в службу поддержки```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

Знанные проблемы* При получении меню сообщений от корпоративного WeChat сервер WeChat не может распознать некоторые домены, поэтому следует использовать IP-адрес для привязки обратного URL; обычные сообщения пользователей пока не затрагиваются.

  • Полное покрытие членами корпоративного WeChat CSV-формата адресной книги требует использования Excel для открытия скачанного шаблона, затем его следует сохранить в формате CSV, чтобы он стал легальным.
  • При использовании схемы развертывания Nginx + Unicorn и HTTPS, необходимо установить trusted_domain_fullname как HTTPS, иначе это приведёт к истечению подписи JS-SDK.
1
https://api.gitlife.ru/oschina-mirror/Eric-Guo-wechat.git
git@api.gitlife.ru:oschina-mirror/Eric-Guo-wechat.git
oschina-mirror
Eric-Guo-wechat
Eric-Guo-wechat
main