Utilice el agente de plataforma pública WeChat del servidor nginx escrito en Lua.
Objetivo:
Utilice el nginx de front-end como proxy de WeChat para reducir el acoplamiento entre la capa de aplicación interna y los servicios de WeChat.
Configure respuestas automáticas para cuentas públicas de WeChat y procese algunos mensajes de usuario en nginx para reducir la presión sobre la capa de aplicación.
Gestión unificada del access_token
utilizado en la API de la cuenta pública de WeChat, como servidor de control central para aislar la capa empresarial y la implementación de la API, reducir access_token
y aumentar la estabilidad del servicio.
Implemente la página de devolución de llamada de autorización de WeChat JS-SDK para reducir la presión sobre la capa de aplicación.
configuración
Datos de configuración global de la cuenta pública, incluido el token de interfaz y la configuración de respuesta automática.
servidor
Reciba solicitudes de mensajes ordinarios y solicitudes de inserción de eventos de WeChat y responda de acuerdo con la configuración. Si no se realiza la configuración correspondiente, se devolverá success
de acuerdo con los requisitos de WeChat.
Esta parte del código central se refactoriza y modifica desde aCayF/lua-resty-wechat.
Utilice config.autoreplyurl
para configurar la dirección del servicio de procesamiento en segundo plano, reenviar, procesar y responder a mensajes complejos de WeChat (depende de pintsized/lua-resty-http).
token_acceso_proxy
Utilice Redis para almacenar en caché access_token
y jsapi_ticket
, llamar automáticamente a las actualizaciones del servicio WeChat con regularidad y admitir actualizaciones distribuidas.
apoderado
El agente llama a la interfaz API de la plataforma pública WeChat y agrega automáticamente el parámetro access_token
.
filtro_acceso_proxy
Filtre la IP del cliente y limite las fuentes de solicitudes.
juramento
jssdk_config
configuración de nginx:
http { lua_package_path 'ruta a los archivos lua'; resolver 114.114.114.114; lua_shared_dict wechat 1M; # Usar memoria compartida para mantener un temporizador único init_by_lua ' ngx.shared.wechat:delete("updater") - Borrar el identificador del temporizador require( "resty.wechat.config") '; init_worker_by_lua ' local ok, err = ngx.shared.wechat:add("updater", "1") -- Temporizador de inicio de proceso único si no está bien o es un error, entonces regresa end require("resty.wechat.proxy_access_token")() ' ; servidor {ubicación /servidor-wechat { content_by_lua ' require("resty.wechat.server")(); '; }ubicación /wechat-proxy/ { rewrite_by_lua ' require("resty.wechat.proxy")("wechat-proxy") - el parámetro es la ruta de ubicación'; access_by_lua ' require("resty.wechat.proxy_access_filter")( ) ' ; contraseña_proxy https://api.weixin.qq.com/; }ubicación /wechat-baseoauth { # parámetro: ir a rewrite_by_lua ' require("resty.wechat.oauth").base_oauth("ruta a /wechat-redirect") '; }ubicación /wechat-useroauth { # parámetro: ir a rewrite_by_lua ' require("resty.wechat.oauth").userinfo_oauth("ruta a /wechat-redirect") '; }ubicación /wechat-redirect { rewrite_by_lua ' require("resty.wechat.oauth").redirect() '; }ubicación /wechat-jssdk-config { # GET/POST, parámetro: url, [api] add_header Access-Control-Allow-Origin "si necesita una llamada entre dominios"; content_by_lua 'require("resty.wechat.jssdk_config") ()'; } } }
Permisos JS-SDK de inyección de páginas web:
$.ajax({ url: "ruta URL a /wechat-jssdk-config", datos: {url: window.location.href,api: "onMenuShareTimeline|onMenuShareAppMessage|onMenuShareQQ|onMenuShareWeibo|onMenuShareQZone" }, éxito: función (respuesta) {wx.config (respuesta); }});$.ajax({ url: "ruta URL a /wechat-jssdk-config", datos: {url: ventana.ubicación.href }, éxito: función (respuesta) {wx.config({ appId: respuesta.appId, marca de tiempo: respuesta.marca de tiempo, nonceStr: respuesta.nonceStr, firma: respuesta.signature, jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' , 'onMenuShareWeibo', 'onMenuShareQZone' ]}); }});
Utilice Java para analizar las cookies obtenidas mediante la autorización de la página web proxy
Map authInfo = JSON.parseObject(decryptAES(unBase64("valor de cookie"), getKey("clave AES")));//Clave AES predeterminada: "vFrItmxI9ct8JbAg"//Configurado en config.lua -> cookie_aes_key//Método de dependencia importar com.alibaba.fastjson.JSON;importar com.google.common.base.Charsets;importar javax.crypto.Cipher;importar javax.crypto.spec.SecretKeySpec;importar java.security.Key;relleno público de StringBuilder (cadena s, letra de carácter, repeticiones int) {StringBuilder sb = nuevo StringBuilder(s); mientras (se repite-- > 0) {sb.append(letra); }volver alguien; }relleno de cadena pública (String s) {return padding(s, '=', s.length() % 4).toString(); }byte público[] unBase64(valor de cadena) {return org.apache.commons.codec.binary.Base64.decodeBase64(padding(valor)); }cadena de cadena pública (byte [] bytes) {devuelve nueva cadena (bytes, Charsets.UTF_8); }cadena pública decryptAES(valor byte[], clave clave) {pruebe {cifrado cifrado = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, clave);byte[] descifrado = cifrado. doFinal (valor); cadena de retorno (descifrada); } catch (Excepción e) {lanzar nueva RuntimeException(e); } }byte público[] bytes(String str) {return str == null ? null: str.getBytes(Charsets.UTF_8); }Clave pública keyFromString(String keyString) {return new SecretKeySpec(bytes(keyString), "AES"); }Clave pública getKey(Clave de cadena) {if (key.length() >= 16) {return keyFromString(key.substring(0, 16)); }StringBuilder sb = new StringBuilder(clave); while (sb.length() < 16) {sb.append(clave); }return keyFromString(sb.toString().substring(0, 16)); }