Verwenden Sie den in Lua geschriebenen WeChat-Agenten für die öffentliche Plattform des Nginx-Servers.
Ziel:
Verwenden Sie den Front-End-Nginx als WeChat-Proxy, um die Kopplung zwischen der internen Anwendungsschicht und WeChat-Diensten zu reduzieren.
Konfigurieren Sie automatische Antworten für öffentliche WeChat-Konten und verarbeiten Sie einige Benutzernachrichten in Nginx, um den Druck auf die Anwendungsebene zu verringern.
Einheitliche Verwaltung access_token
als zentraler Steuerungsserver zur Isolierung der Geschäftsschicht und der API-Implementierung, Reduzierung access_token
Konfliktrate und Erhöhung der Dienststabilität.
Stellen Sie die WeChat JS-SDK-Autorisierungsrückrufseite bereit, um den Druck auf die Anwendungsebene zu verringern.
config
Globale Konfigurationsdaten des öffentlichen Kontos, einschließlich Schnittstellen-Token und Einstellungen für automatische Antworten.
Server
Empfangen Sie Anfragen für normale Nachrichten und Ereignis-Push-Anfragen von WeChat und antworten Sie entsprechend der Konfiguration. Wenn keine entsprechende Konfiguration vorgenommen wird, wird success
gemäß den WeChat-Anforderungen zurückgegeben.
Dieser Teil des Kerncodes wurde von aCayF/lua-resty-wechat überarbeitet und geändert.
Verwenden Sie config.autoreplyurl
, um die Adresse des Hintergrundverarbeitungsdienstes zu konfigurieren, komplexe WeChat-Nachrichten weiterzuleiten, zu verarbeiten und darauf zu antworten (abhängig von pintsized/lua-resty-http).
Proxy_Access_token
Verwenden Sie Redis, um access_token
und jsapi_ticket
zwischenzuspeichern, WeChat-Dienstaktualisierungen regelmäßig automatisch aufzurufen und verteilte Aktualisierungen zu unterstützen.
Proxy
Der Agent ruft die API-Schnittstelle der öffentlichen WeChat-Plattform auf und fügt automatisch den Parameter access_token
hinzu.
Proxy_Access_Filter
Client-IP filtern und Anforderungsquellen einschränken.
oauth
jssdk_config
Nginx-Konfiguration:
http { lua_package_path 'path to lua files'; lua_shared_dict wechat 1M; # Shared Memory verwenden, um einen einzelnen Timer zu verwalten init_by_lua ' ngx.shared.wechat:delete("updater") -- Löschen Sie die Timer-ID require( "resty.wechat.config") '; init_worker_by_lua ' local ok, err = ngx.shared.wechat:add("updater", "1") -- Einzelprozess-Start-Timer, wenn nicht ok oder Fehler, dann zurückgeben end require("resty.wechat.proxy_access_token")() ' ; server {location /wechat-server { content_by_lua ' require("resty.wechat.server")() '; }location /wechat-proxy/ { rewrite_by_lua ' require("resty.wechat.proxy")("wechat-proxy") – der Parameter ist der Standortpfad'; 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("path to /wechat-redirect") '; }location /wechat-useroauth { # param: goto rewrite_by_lua ' require("resty.wechat.oauth").userinfo_oauth("path to /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 „if need Cross-Domain Call“; content_by_lua ' require("resty.wechat.jssdk_config") () '; } } }
JS-SDK-Berechtigungen für die Webseiteninjektion:
$.ajax({ URL: „URL-Pfad zu /wechat-jssdk-config“, Daten: {url: window.location.href,api: "onMenuShareTimeline|onMenuShareAppMessage|onMenuShareQQ|onMenuShareWeibo|onMenuShareQZone" }, Erfolg: function(response) {wx.config(response); }});$.ajax({ URL: „URL-Pfad zu /wechat-jssdk-config“, Daten: {url: window.location.href }, Erfolg: function(response) {wx.config({ appId: Response.appId, Timestamp: Response.Timestamp, NonceStr: Response.nonceStr, Signature: Response.Signature, JsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' , 'onMenuShareWeibo', 'onMenuShareQZone' ]}); }});
Verwenden Sie Java, um Cookies zu analysieren, die durch die Proxy-Webseitenautorisierung erhalten wurden
Map authInfo = JSON.parseObject(decryptAES(unBase64("cookie value"), getKey("AES key")));//Standard-AES-Schlüssel: "vFrItmxI9ct8JbAg"//Konfiguriert in config.lua -> cookie_aes_key//Abhängigkeitsmethode import com.alibaba.fastjson.JSON;import com.google.common.base.Charsets;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import java.security.Key;public StringBuilder padding(String s, char letter, int Repeats) {StringBuilder sb = new StringBuilder(s); while (repeats-- > 0) {sb.append(letter); }Jdn zurückbringen; }public String padding(String s) {return padding(s, '=', s.length() % 4).toString(); }public byte[] unBase64(String value) {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[] value, Key key) {try {Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);byte[] decrypted = cipher. doFinal(value);return string(decrypted); } Catch (Exception e) {throw new RuntimeException(e); } }public byte[] bytes(String str) {return str == null ? null : str.getBytes(Charsets.UTF_8); }public Key keyFromString(String keyString) {return new SecretKeySpec(bytes(keyString), "AES"); }public Key getKey(String key) {if (key.length() >= 16) {return keyFromString(key.substring(0, 16)); }StringBuilder sb = new StringBuilder(key);while (sb.length() < 16) {sb.append(key); }return keyFromString(sb.toString().substring(0, 16)); }