Используйте агент общедоступной платформы WeChat сервера nginx, написанный на Lua.
Цель:
Используйте интерфейсный nginx в качестве прокси-сервера WeChat, чтобы уменьшить связь между внутренним уровнем приложения и службами WeChat.
Настройте автоматические ответы для общедоступных учетных записей WeChat и обработайте некоторые сообщения пользователей в nginx, чтобы снизить нагрузку на уровень приложений.
Унифицированное управление access_token
используемое в API общедоступной учетной записи WeChat, в качестве центрального сервера управления для изоляции бизнес-уровня и реализации API, снижения частоты конфликтов access_token
и повышения стабильности обслуживания.
Разверните страницу обратного вызова авторизации WeChat JS-SDK, чтобы снизить нагрузку на уровень приложения.
конфигурация
Данные глобальной конфигурации общедоступной учетной записи, включая токен интерфейса и настройки автоматического ответа.
сервер
Получайте запросы на обычные сообщения и push-запросы событий от WeChat и отвечайте в соответствии с конфигурацией. Если соответствующая конфигурация не задана, success
будет возвращен в соответствии с требованиями WeChat.
Эта часть основного кода переработана и изменена из aCayF/lua-resty-wechat.
Используйте config.autoreplyurl
для настройки адреса службы фоновой обработки, пересылки, обработки и ответа на сложные сообщения WeChat (зависит от pintsized/lua-resty-http).
proxy_access_token
Используйте Redis для кэширования access_token
и jsapi_ticket
, регулярного автоматического вызова обновлений службы WeChat и поддержки распределенных обновлений.
прокси
Агент вызывает API-интерфейс общедоступной платформы WeChat и автоматически добавляет параметр access_token
.
proxy_access_filter
Фильтруйте IP-адрес клиента и ограничивайте источники запросов.
клятва
jssdk_config
конфигурация nginx:
http { lua_package_path 'путь к файлам lua'; resolver 114.114.114.114; lua_shared_dict wechat 1M; # Использовать общую память для поддержки одного таймера init_by_lua ' ngx.shared.wechat:delete("updater") -- Очистить идентификатор таймера require( "resty.wechat.config") '; init_worker_by_lua ' local ok, err = ngx.shared.wechat:add("updater", "1") -- Таймер запуска одного процесса, если не все в порядке или ошибка, то верните end require("resty.wechat.proxy_access_token")() ' ; сервер {location /wechat-server {content_by_lua ' require("resty.wechat.server")() '; }location /wechat-proxy/ { rewrite_by_lua ' require("resty.wechat.proxy")("wechat-proxy") -- параметр представляет собой путь к местоположению'; access_by_lua ' require("resty.wechat.proxy_access_filter")( ) '; proxy_pass https://api.weixin.qq.com/; }location /wechat-baseoauth { # param: goto rewrite_by_lua ' require("resty.wechat.oauth").base_oauth("путь к /wechat-redirect") '; }location /wechat-userauth { # param: goto rewrite_by_lua ' require("resty.wechat.oauth").userinfo_oauth("путь к /wechat-redirect") '; }location /wechat-redirect { rewrite_by_lua ' require("resty.wechat.oauth").redirect() '; }location /wechat-jssdk-config { # GET/POST, param: url, [api] add_header Access-Control-Allow-Origin "если нужен междоменный вызов"; content_by_lua ' require("resty.wechat.jssdk_config") () '; } } }
Разрешения JS-SDK для внедрения веб-страниц:
$.ajax({ url: "URL-путь к /wechat-jssdk-config", данные: {url: window.location.href,api: "onMenuShareTimeline|onMenuShareAppMessage|onMenuShareQQ|onMenuShareWeibo|onMenuShareQZone" }, успех: функция (ответ) {wx.config (ответ); }});$.ajax({ url: "URL-путь к /wechat-jssdk-config", данные: {url: window.location.href }, успех: функция (ответ) {wx.config({ appId: response.appId, метка времени: response.timestamp, nonceStr: response.nonceStr, подпись: response.signature, jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' , 'onMenuShareWeibo', 'onMenuShareQZone' ]}); }});
Используйте Java для анализа файлов cookie, полученных при авторизации веб-страницы через прокси.
Map authInfo = JSON.parseObject(decryptAES(unBase64("cookie value"), getKey("AES key")));//Ключ AES по умолчанию: "vFrItmxI9ct8JbAg"//Настраивается в config.lua -> cookie_aes_key//Метод зависимости импорт com.alibaba.fastjson.JSON;импорт com.google.common.base.Charsets;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import java.security.Key;public StringBuilder заполнения (String s, символьная буква, повторы int) {StringBuilder sb = новые StringBuilder(ы); while (повторяется -> 0) {sb.append(letter); } вернуть СБ; } public String padding(String s) {return padding(s, '=', s.length() % 4).toString(); }public byte[] unBase64(строковое значение) {return org.apache.commons.codec.binary.Base64.decodeBase64(padding(value)); } public String string(byte[] bytes) {return new String(bytes, Charsets.UTF_8); } public String decryptAES (значение byte[], ключ ключа) {try {Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);byte[] decrypted = cipher. doFinal(значение); возвращаемая строка(расшифрована); } catch (Exception e) {throw new RuntimeException(e); } } public byte[] bytes(String str) {return str == null? null: str.getBytes(Charsets.UTF_8); } Открытый ключ keyFromString (String keyString) {return new SecretKeySpec (bytes (keyString), "AES"); } Открытый ключ getKey(String key) {if (key.length() >= 16) {return keyFromString(key.substring(0, 16)); }StringBuilder sb = новый StringBuilder(ключ); while (sb.length() < 16) {sb.append(key); } return keyFromString(sb.toString().substring(0, 16)); }