Use o agente da plataforma pública WeChat do servidor nginx escrito em Lua.
Alvo:
Use o nginx front-end como um proxy WeChat para reduzir o acoplamento entre a camada interna do aplicativo e os serviços WeChat.
Configure respostas automáticas para contas públicas do WeChat e processe algumas mensagens de usuários no nginx para reduzir a pressão na camada de aplicativo.
Gerenciamento unificado do access_token
usado na API da conta pública WeChat, como um servidor de controle central para isolar a camada de negócios e a implementação da API, reduzir access_token
e aumentar a estabilidade do serviço.
Implante a página de retorno de chamada de autorização do WeChat JS-SDK para reduzir a pressão na camada de aplicativo.
configuração
Dados de configuração global da conta pública, incluindo token de interface e configurações de resposta automática.
servidor
Receba solicitações de mensagens comuns e solicitações de push de eventos do WeChat e responda de acordo com a configuração. Se nenhuma configuração correspondente for feita, success
será retornado de acordo com os requisitos do WeChat.
Esta parte do código principal é refatorada e modificada de aCayF/lua-resty-wechat.
Use config.autoreplyurl
para configurar o endereço do serviço de processamento em segundo plano, encaminhar, processar e responder a mensagens WeChat complexas (depende de pintsized/lua-resty-http).
proxy_access_token
Use o Redis para armazenar em cache access_token
e jsapi_ticket
, chamar automaticamente as atualizações do serviço WeChat regularmente e oferecer suporte a atualizações distribuídas.
procurador
O agente chama a interface API da plataforma pública WeChat e adiciona automaticamente o parâmetro access_token
.
filtro_de_acesso_proxy
Filtre o IP do cliente e limite as fontes de solicitação.
oauth
jssdk_config
configuração nginx:
http { lua_package_path 'caminho para arquivos lua'; resolvedor 114.114.114.114; lua_shared_dict wechat 1M; # Use memória compartilhada para manter um único temporizador init_by_lua ' ngx.shared.wechat:delete("updater") -- Limpa o identificador do temporizador require( "resty.wechat.config") '; init_worker_by_lua ' local ok, err = ngx.shared.wechat:add("updater", "1") -- Temporizador de inicialização de processo único se não estiver ok ou errar então retorne end require("resty.wechat.proxy_access_token")() ' ; servidor {localização /wechat-server { content_by_lua ' require("resty.wechat.server")() '; }location /wechat-proxy/ { rewrite_by_lua ' require("resty.wechat.proxy")("wechat-proxy") - o parâmetro é o caminho do local'; ) ' ; proxy_pass https://api.weixin.qq.com/; }localização /wechat-baseoauth { # parâmetro: goto rewrite_by_lua ' require("resty.wechat.oauth").base_oauth("caminho para /wechat-redirect") '; }localização /wechat-useroauth { # parâmetro: goto rewrite_by_lua ' require("resty.wechat.oauth").userinfo_oauth("caminho para /wechat-redirect") '; }localização /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 "se precisar de chamada entre domínios"; content_by_lua ' require("resty.wechat.jssdk_config") ()'; } } }
Permissões JS-SDK de injeção de página da Web:
$.ajax({ url: "caminho da URL para /wechat-jssdk-config", dados: {url: window.location.href,api: "onMenuShareTimeline|onMenuShareAppMessage|onMenuShareQQ|onMenuShareWeibo|onMenuShareQZone" }, sucesso: função (resposta) {wx.config (resposta); }});$.ajax({ url: "caminho da URL para /wechat-jssdk-config", dados: {url: window.location.href }, sucesso: função (resposta) {wx.config ({ appId: resposta.appId, carimbo de data / hora: resposta.timestamp, nonceStr: resposta.nonceStr, assinatura: resposta.signature, jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' , 'onMenuShareWeibo', 'onMenuShareQZone' ]}); }});
Use Java para analisar cookies obtidos por autorização de página proxy
Map authInfo = JSON.parseObject(decryptAES(unBase64("cookie value"), getKey("AES key")));//Chave AES padrão: "vFrItmxI9ct8JbAg"//Configurada em config.lua -> cookie_aes_key//Método de dependência importar com.alibaba.fastjson.JSON;importar com.google.common.base.Charsets;importar javax.crypto.Cipher;importar javax.crypto.spec.SecretKeySpec;importar java.security.Key;preenchimento público StringBuilder (String s, letra char, repetições int) {StringBuilder sb = new StringBuilder(s); while (repete--> 0) {sb.append(letra); }retornar SB; }public String padding(String s) {return padding(s, '=', s.length() % 4).toString(); }public byte[] unBase64(String valor) {return org.apache.commons.codec.binary.Base64.decodeBase64(padding(valor)); }public String string(byte[] bytes) {retornar nova String(bytes, Charsets.UTF_8); }public String decryptAES(byte[] valor, chave chave) {tentar {Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);byte[] descriptografado = cipher. doFinal(valor);return string(descriptografado); } catch (Exceção e) {lançar nova RuntimeException(e); } } byte público [] bytes (String str) {return str == null ? null : str.getBytes(Charsets.UTF_8); } chave pública keyFromString(String keyString) {return new SecretKeySpec(bytes(keyString), "AES"); } chave pública getKey (chave String) {if (key.length () >= 16) {return keyFromString (key.substring (0, 16)); }StringBuilder sb = new StringBuilder(chave);while (sb.length() < 16) {sb.append(chave); }return keyFromString(sb.toString().substring(0, 16)); }