| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- require("app.app")
- local http = require("socket.http")
- local ltn12 = require("ltn12")
- local httpclient = require("httpclient")
- local M = {}
- -- access_token 的 url
- M.url_get_access_token = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"
- -- 获取用户access_token的url
- M.url_get_user_access_token = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code"
- -- 获取用户信息的url
- M.url_get_user_info = "https://api.weixin.qq.com/sns/userinfo?lang=zh_CN"
- -- 授权地址
- M.url_auth = "https://open.weixin.qq.com/connect/oauth2/authorize"
- -- 模板消息
- M.url_template_message = "https://api.weixin.qq.com/cgi-bin/message/template/send"
- -- 获取 access_token
- M.get_access_token = function(appid, appsecret,rds)
- -- local value = cache.get_json("wxofficial_info")
- -- if value then
- -- -- 是否距离过期至少还有5分钟
- -- if value.expires_seconds > os.time() + 300 then
- -- return true, value.access_token
- -- end
- -- end
- -- 如果 appid 和 appsecret 为空,则返回 nil
- if appid == nil or appid == "" then
- return false, "appid 为空"
- end
- if appsecret == nil or appsecret == "" then
- return false, "appsecret 为空"
- end
- local cache_data = rds:get("wxofficial_info_"..appid)
- if cache_data then
- -- print("cache_data:",cache_data)
- cache_data = cjson.decode(cache_data)
- if cache_data.update_time and cache_data.access_token then
- -- 检查是否过期
- if os.time() - cache_data.update_time < 7200 then
- return true,cache_data.access_token
- end
- end
- end
- local result, data = httpclient.get(M.url_get_access_token .. "&appid=" .. appid .. "&secret=" .. appsecret)
- if not result then
- return false, "get_access_token failed:"..data
- end
- local body = cjson.decode(data)
- if body.errcode ~= nil and body.errcode ~= 0 then
- return false, "get_access_token failed:"..body.errmsg
- end
-
- -- 更新
- local ok = rds:setex("wxofficial_info_"..appid,7200,cjson.encode({
- update_time = os.time(),
- access_token = body.access_token
- }))
- return true,body.access_token
- end
- -- 获取用户access_token
- M.get_user_access_token = function(appid, appsecret, code)
- local result, data = httpclient.get(M.url_get_user_access_token .. "&appid=" .. appid .. "&secret=" .. appsecret .. "&code=" .. code)
- if not result then
- return false, data
- end
- local body = cjson.decode(data)
- if body.errcode ~= nil and body.errcode ~= 0 then
- return false, body.errmsg
- end
- return true, body
- end
- -- 获取用户信息
- M.get_user_info = function(access_token, openid)
- local url = M.url_get_user_info .. "&access_token=" .. access_token .. "&openid=" .. openid
- local result, data = httpclient.get(url)
- if not result then
- return false, data
- end
- local body = cjson.decode(data)
- if body.errcode ~= nil and body.errcode ~= 0 then
- return false, body.errmsg
- end
- return true, body
- end
- -- 生成授权地址
- M.generate_auth_url = function(appid, redirect_uri)
- return M.url_auth .. "?appid=" .. appid .. "&redirect_uri=" .. redirect_uri .. "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect"
- end
- -- 发送模板消息
- M.send_template_message = function(appid, appsecret, openid, template_id, jump_url, data,rds)
- local ok, access_token = M.get_access_token(appid, appsecret,rds)
- if not ok then
- return false, access_token
- end
- local url = M.url_template_message .. "?access_token=" .. access_token
- local body = {
- touser = openid,
- template_id = template_id,
- url = jump_url,
- data = data,
- appid = appid
- }
- local result, response = httpclient.post(url, {
- ["Content-Type"] = "application/json"
- }, cjson.encode(body))
-
- if not result then
- return false, response
- end
-
- local res_json = cjson.decode(response)
- if res_json.errcode ~= 0 then
- return false, res_json.errmsg
- end
- return true
- end
- -- 生成一次性订阅确认地址
- M.generate_subscribe_confirm_url = function(appid, scene, template_id, redirect_uri, reserved)
- return "https://mp.weixin.qq.com/mp/subscribemsg?action=get_confirm&appid=" .. appid .. "&scene=" .. scene .. "&template_id=" .. template_id .. "&redirect_url=" .. redirect_uri .. "&#wechat_redirect"
- end
- --------------------------------------------------------------------------------
- -- 以下为新增的部分,用于微信JS SDK 配置
- -- 生成随机字符串函数
- local function generate_nonce_str(length)
- --math.randomseed(os.time() + math.random()) -- 增加随机种子
- local chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
- local res = {}
- for i = 1, (length or 16) do
- local rand = math.random(1, #chars)
- res[#res+1] = string.sub(chars, rand, rand)
- end
- return table.concat(res)
- end
- -- 获取 jsapi_ticket
- M.get_jsapi_ticket = function(appid, appsecret)
- local ticket_info = cache.get_json("wxjsapi_ticket")
- if ticket_info then
- if ticket_info.expires > os.time() + 300 then
- return true, ticket_info.ticket
- end
- end
- local ok, access_token = M.get_access_token(appid, appsecret)
- if not ok then
- return false, access_token
- end
- local ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" .. access_token .. "&type=jsapi"
- local result, data = httpclient.get(ticket_url)
- if not result then
- return false, data
- end
- local body = cjson.decode(data)
- if body.errcode ~= 0 then
- return false, body.errmsg
- end
- cache.set_json("wxjsapi_ticket", {
- ticket = body.ticket,
- expires = os.time() + body.expires_in
- })
- return true, body.ticket
- end
- -- 获取微信JS SDK所需的配置参数
- -- 参数 current_url 必须是当前网页的完整 URL(不包含#号后的部分)
- M.get_js_sdk_config = function(appid, appsecret, current_url)
- local ok, jsapi_ticket = M.get_jsapi_ticket(appid, appsecret)
- if not ok then
- return false, jsapi_ticket..",err"
- end
- local nonceStr = generate_nonce_str(16)
- local timestamp = os.time()
- -- 拼接待签名字符串,注意顺序及格式严格按照微信要求
- local str = "jsapi_ticket=" .. jsapi_ticket .. "&noncestr=" .. nonceStr .. "×tamp=" .. timestamp .. "&url=" .. current_url
- -- 计算 SHA1 签名(需在 OpenResty 下使用 ngx.sha1_bin 和 resty.string.to_hex)
- local signature = codec.sha1(str)
- return true, {
- appId = appid,
- timestamp = timestamp,
- nonceStr = nonceStr,
- signature = signature
- }
- end
- --------------------------------------------------------------------------------
- return M
|