Giter Site home page Giter Site logo

lua-resty-wechat's Introduction

lua-resty-wechat

GitHub license

GitHub watchers GitHub stars GitHub forks

使用Lua编写的nginx服务器微信公众平台代理.

目标:

  • 在前置的nginx内做微信代理, 降低内部应用层和微信服务的耦合.
  • 配置微信公众号的自动回复, 在nginx内处理部分用户消息, 减小应用层压力.
  • 统一管理微信公众号API中使用的access_token, 作为中控服务器隔离业务层和API实现, 降低access_token冲突率, 增加服务稳定性.
  • 部署微信JS-SDK授权回调页面, 减小应用层压力.

子模块说明

全局配置

config

公众号全局配置数据, 包括接口Token, 自动回复设置.

作为服务端由微信请求并响应

server

接收微信发出的普通消息和事件推送等请求, 并按配置做出响应, 未做对应配置则按微信要求返回success.

此部分核心代码由aCayF/lua-resty-wechat做重构修改而来.

使用config.autoreplyurl, 配置后台处理服务地址, 转发处理并响应复杂的微信消息. (依赖pintsized/lua-resty-http)

作为客户端代理调用微信公众号API

proxy_access_token

使用Redis缓存access_tokenjsapi_ticket, 定时自动调用微信服务更新, 支持分布式更新.

proxy

代理调用微信公众平台API接口, 自动添加access_token参数.

proxy_access_filter

过滤客户端IP, 限制请求来源.

代理网页授权获取用户基本信息

oauth

JS-SDK权限签名

jssdk_config

示例

nginx配置:

http {
  lua_package_path 'path to lua files';
  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") -- 单进程启动定时器
    if not ok or err then return 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") -- 参数为location路径
      ';
      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权限:

$.ajax({
  url: "url path to /wechat-jssdk-config",
  data: {
    url: window.location.href,
    api: "onMenuShareTimeline|onMenuShareAppMessage|onMenuShareQQ|onMenuShareWeibo|onMenuShareQZone"
  },
  success: function(response) {
    wx.config(response);
  }
});

$.ajax({
  url: "url path to /wechat-jssdk-config",
  data: {
    url: window.location.href
  },
  success: function(response) {
    wx.config({
      appId: response.appId,
      timestamp: response.timestamp,
      nonceStr: response.nonceStr,
      signature: response.signature,
      jsApiList: [
          'onMenuShareTimeline',
          'onMenuShareAppMessage',
          'onMenuShareQQ',
          'onMenuShareWeibo',
          'onMenuShareQZone'
      ]
    });
  }
});

使用Java解析代理网页授权获得的cookie

Map authInfo = JSON.parseObject(decryptAES(unBase64("cookie value"), getKey("AES key")));

// 默认AES key: "vFrItmxI9ct8JbAg"
// 配置于config.lua -> cookie_aes_key

// 依赖方法

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);
    }
    return sb;
}

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));
}

lua-resty-wechat's People

Contributors

charlemaznable avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.