mirror of
https://gitlink.org.cn/Gitlink/forgeplus.git
synced 2026-05-03 03:40:49 +08:00
init project
This commit is contained in:
74
app/libs/wechat/client.rb
Normal file
74
app/libs/wechat/client.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
class Wechat::Client
|
||||
BASE_SITE = 'https://api.weixin.qq.com'.freeze
|
||||
|
||||
attr_reader :appid, :secret
|
||||
|
||||
def initialize(appid, secret)
|
||||
@appid = appid
|
||||
@secret = secret
|
||||
end
|
||||
|
||||
def access_token
|
||||
# 7200s 有效时间
|
||||
Rails.cache.fetch(access_token_cache_key, expires_in: 100.minutes) do
|
||||
result = request(:get, '/cgi-bin/token', appid: appid, secret: secret, grant_type: 'client_credential')
|
||||
result['access_token']
|
||||
end
|
||||
end
|
||||
|
||||
def refresh_access_token
|
||||
Rails.cache.delete(access_token_cache_key)
|
||||
access_token
|
||||
end
|
||||
|
||||
def jsapi_ticket
|
||||
# 7200s 有效时间
|
||||
Rails.cache.fetch(jsapi_ticket_cache_key, expires_in: 100.minutes) do
|
||||
result = request(:get, '/cgi-bin/ticket/getticket', access_token: access_token, type: 'jsapi')
|
||||
result['ticket']
|
||||
end
|
||||
end
|
||||
|
||||
def refresh_jsapi_ticket
|
||||
Rails.cache.delete(jsapi_ticket_cache_key)
|
||||
jsapi_ticket
|
||||
end
|
||||
|
||||
def jscode2session(code)
|
||||
request(:get, '/sns/jscode2session', appid: appid, secret: secret, js_code: code, grant_type: 'authorization_code')
|
||||
end
|
||||
|
||||
def access_token_cache_key
|
||||
"#{base_cache_key}/access_token"
|
||||
end
|
||||
|
||||
def jsapi_ticket_cache_key
|
||||
"#{base_cache_key}/jsapi_ticket"
|
||||
end
|
||||
|
||||
def base_cache_key
|
||||
"wechat/#{appid}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request(method, url, **params)
|
||||
Rails.logger.info("[wechat] request: #{method} #{url} #{params.except(:secret).inspect}")
|
||||
|
||||
client = Faraday.new(url: BASE_SITE)
|
||||
response = client.public_send(method, url, params)
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
Rails.logger.info("[wechat] response:#{response.status} #{result.inspect}")
|
||||
|
||||
if response.status != 200
|
||||
raise Wechat::Error.parse(result)
|
||||
end
|
||||
|
||||
if result['errcode'].present? && result['errcode'].to_i.nonzero?
|
||||
raise Wechat::Error.parse(result)
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
14
app/libs/wechat/error.rb
Normal file
14
app/libs/wechat/error.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class Wechat::Error < StandardError
|
||||
attr_reader :code
|
||||
|
||||
def initialize(code, message)
|
||||
super message
|
||||
@code = code
|
||||
end
|
||||
|
||||
class << self
|
||||
def parse(result)
|
||||
new(result['errcode'], result['errmsg'])
|
||||
end
|
||||
end
|
||||
end
|
||||
17
app/libs/wechat/official_account.rb
Normal file
17
app/libs/wechat/official_account.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
class Wechat::OfficialAccount
|
||||
class << self
|
||||
attr_accessor :appid, :secret
|
||||
|
||||
delegate :access_token, :jsapi_ticket, to: :client
|
||||
|
||||
def js_sdk_signature(url, noncestr, timestamp)
|
||||
data = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }
|
||||
str = data.map { |k, v| "#{k}=#{v}" }.join('&')
|
||||
Digest::SHA1.hexdigest(str)
|
||||
end
|
||||
|
||||
def client
|
||||
@_client ||= Wechat::Client.new(appid, secret)
|
||||
end
|
||||
end
|
||||
end
|
||||
49
app/libs/wechat/weapp.rb
Normal file
49
app/libs/wechat/weapp.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
class Wechat::Weapp
|
||||
class << self
|
||||
attr_accessor :appid, :secret
|
||||
|
||||
delegate :access_token, :jscode2session, to: :client
|
||||
|
||||
def client
|
||||
@_client ||= Wechat::Client.new(appid, secret)
|
||||
end
|
||||
|
||||
def session_key(openid)
|
||||
Rails.cache.read(session_key_cache_key(openid))
|
||||
end
|
||||
|
||||
def write_session_key(openid, session_key)
|
||||
Rails.cache.write(session_key_cache_key(openid), session_key)
|
||||
end
|
||||
|
||||
def verify?(openid, str, signature)
|
||||
session_key = session_key(openid)
|
||||
Digest::SHA1.hexdigest("#{str}#{session_key}") == signature
|
||||
end
|
||||
|
||||
def decrypt(session_key, encrypted_data, iv)
|
||||
session_key = Base64.decode64(session_key)
|
||||
encrypted_data = Base64.decode64(encrypted_data)
|
||||
iv = Base64.decode64(iv)
|
||||
|
||||
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
|
||||
cipher.decrypt
|
||||
cipher.padding = 0
|
||||
cipher.key = session_key
|
||||
cipher.iv = iv
|
||||
Rails.logger.info("[Weapp] encrypted_data: #{encrypted_data}")
|
||||
data = cipher.update(encrypted_data) << cipher.final
|
||||
Rails.logger.info("[Weapp] data: #{data}")
|
||||
result = JSON.parse(data[0...-data.last.ord])
|
||||
|
||||
raise Wechat::Error.new(-1, '解密错误') if result.dig('watermark', 'appid') != appid
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def session_key_cache_key(openid)
|
||||
"weapp:#{appid}:#{openid}:session_key"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user