Commit 8bea813e by houdelin

add user center service

parent e11ca6a1
module UserCenter
class Retry
def self.query(&_proc)
value = nil
if block_given?
begin
4.times do
Rails.logger.info "user_center_retry_query: #{Time.now.strftime("%Y-%m-%d %H:%M:%S-%L")}"
value = _proc.call
break if value.present?
sleep 0.8
end
rescue => e
Rails.logger.info "retry_query_error is #{e.inspect} 数据库连接数已超!"
end
end
value
end
def self.uncached_query(&_proc)
value = nil
if block_given?
begin
4.times do
Rails.logger.info "user_center_retry_query: #{Time.now.strftime("%Y-%m-%d %H:%M:%S-%L")}"
value = ActiveRecord::Base.uncached { _proc.call }
break if value.present?
sleep 0.8
end
rescue => e
Rails.logger.info "retry_query_error is #{e.inspect} 数据库连接数已超!"
end
end
value
end
end
end
\ No newline at end of file
module UserCenter
module Services
class ClientService
def self.create(org, opts)
opts = opts.with_indifferent_access
client = Client.find_by(organization_id: org.id)
return client if client.present?
if AppSettings.ikcrm?
client = ikcrm_create(org, opts)
elsif AppSettings.wxwork?
client = lxcrm_create(org, opts)
elsif AppSettings.dingtalk?
client = dingcrm_create(org, opts)
end
client
end
def self.ikcrm_create(org, opts)
ad_source = opts[:ad_source]
source = opts[:source]
client = Client.create(
name: org.name,
organization_id: org.id,
account_type: :trial_account,
source: Client.sources[source],
ad_source: ad_source,
users_count: Organization.trial_account_default_users_count,
expires_at: Organization.trial_account_default_expires_at,
version: 0
)
client.create_client_profile!
client
end
def self.lxcrm_create(org, opts)
source = opts[:source]
wx_permission_type = :wx_free_permission
users_count = 8
expires_at = 100.years.from_now
client = Client.create(
name: org.name,
organization_id: org.id,
account_type: :trial_account,
wx_status: :wx_status_normal,
wx_permission_type: wx_permission_type,
wx_account_type: :wx_trial_account,
source: Client.sources[source],
users_count: users_count,
expires_at: expires_at,
version: 0
)
client.create_client_profile!
client
end
def self.dingcrm_create(org, opts)
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
class HashWxPusher
class << self
def send_corp_oa_message(user, params = {})
return unless user
opts = {
uid_list: [user.uid]
}.merge!(params).with_indifferent_access
if opts[:msg_type].eql?('textcard') && opts[:url].blank?
opts[:url] = wx_message_url(user.organization.oid, nil)
end
service = UserCenter::Services::MessageService.new(user.organization)
service.send_wx_message(opts)
rescue => e
::UserCenter::UcLogger.log_error "Wx send_corp_oa_message error: #{e.message}"
e.backtrace.each { |msg| ::UserCenter::UcLogger.log_error msg }
end
def send_notification_text_card_message(notify_hash)
user = User.find_by(notify_hash[:user_id])
return unless user
opts = {
msg_type: 'textcard',
title: notify_hash[:title],
description: wx_message_description(notify_hash),
url: wx_message_url(user.organization.oid, notify_hash)
}
send_corp_oa_message(user, opts)
end
def wx_message_description(notify_hash)
content = notify_hash[:body]
if notify_hash[:subject_type] == "Event"
related = [
notify_hash[:extras][:related_item_model_name_human].presence,
notify_hash[:extras][:related_item_title].presence
].compact
if related.size == 2
content = "#{content} #{related.join(':')}"
end
end
content
end
def wx_message_url(oid, notify_hash)
url = URI(CrossSites.crm_base_host)
url.path = '/wx/home'
opts = {
oid: oid,
mobile_redirect_uri: wx_mobile_message_path(notify_hash),
pc_redirect_uri: wx_pc_message_path(notify_hash)
}
url.query = opts.to_query
url.to_s
end
def wx_mobile_message_path(notify_hash)
return if notify_hash.blank?
entity_name = notify_hash[:subject_type].to_s
subject = notify_hash[:subject_type].classify.constantize.find_by(id: notify_hash[:subject_id])
path = if entity_name == 'Event'
_event_url = notify_hash[:notify_type] == 'notify_dealed_remind' ? "/calendar?date=#{Date.today.to_s}" :
"/#{entity_name.tableize}/#{notify_hash[:subject_id]}/event"
_event_url.chomp('/')
elsif entity_name == 'ImportHistory'
URI(URI.encode(subject.try(:file_path)))
elsif notify_hash[:notify_type] == 'notify_approve_received_payment'
"/contracts/#{notify_hash[:extras][:contract_id]}/show_received_payment/#{notify_hash[:extras][:contract_received_payment_id]}"
elsif notify_hash[:notify_type] == 'notify_birthday_remind' && notify_hash[:subject_type] == "Contact" && subject.present?
"/customers/#{subject.customer.id}/list-contact"
elsif notify_hash[:extras].present? and notify_hash[:extras][:wxwork_msg_url].present?
notify_hash[:extras][:wxwork_msg_url]
else
URI(URI.encode(notify_hash[:path])).path.chomp('/')
end
URI.decode_www_form_component(path.to_s)
rescue
nil
end
def wx_pc_message_path(notify_hash)
return if notify_hash.blank?
entity_name = notify_hash[:subject_type].to_s
subject = notify_hash[:subject_type].classify.constantize.find_by(id: notify_hash[:subject_id])
path = if entity_name == 'ImportHistory' && subject.present? && subject.has_error_data
URI(URI.encode(subject.try(:file_path)))
else
URI(URI.encode(notify_hash[:path])).path
end
URI.decode_www_form_component(path.to_s)
end
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
class LoginServices
def initialize(opts)
end
def login
Trans::Router.login_url
end
def vertify(ticket)
opts = {
ticket: ticket
}
res = Trans::HttpHandler.post(Trans::Router.verify_ticket_url, opts)
end
def app_users_login(phone: , email: , password: , corp_id: '')
opts = {
phone: phone,
email: email,
password: password,
corpId: corp_id
}
res = Trans::HttpHandler.post(Trans::Router.app_users_login_url, opts)
end
def open_api_login(phone: , email: , password: , corp_id: '')
opts = {
phone: phone,
email: email,
password: password,
corpId: corp_id
}
res = Trans::HttpHandler.post(Trans::Router.sso_open_api_login_url, opts)
end
def app_org_list(phone)
opts = {
phone: phone
}
res = Trans::HttpHandler.get(Trans::Router.app_phone_list, opts)
if res[:code].to_s == '0'
org_oids = res[:data].map{|org| org[:oid] }
Organization.where(oid: org_oids).select(:name, :corp_id).map {|o| {name: o.name, corp_id: o.corp_id} }
else
[]
end
end
def user_info(user_token)
opts = {
curUserToken: user_token
}
res = Trans::HttpHandler.get(Trans::Router.user_info_url, opts)
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
class MessageService
attr_accessor :org, :send_data
def initialize(org)
@org = org
end
def send_wx_message(opts = {})
opts = opts.merge(channel: 'wx')
opts[:mq_queue] ||= 'usual'
send_data = generate_message(opts)
send_message(send_data, opts[:mq_queue])
end
def send_ding_message(opts = {})
opts = opts.merge(channel: 'ding')
opts[:mq_queue] ||= 'usual'
send_data = generate_message(opts)
send_message(send_data, opts[:mq_queue])
end
# mq_queue = usual 或者 mq_queue = frequent, usual 代表业务使用的队列,frequent代表 频繁消息通知
def send_message(send_data, mq_queue)
RabbitmqPublisher.publish(send_data.to_json, mq_queue == 'usual')
end
def generate_message(opts)
head_params = generate_message_head(opts)
body_params = generate_message_body(opts)
head_params.merge(body_params)
end
def generate_message_head(opts = {})
opts[:to_all] ||= false
opts[:uid_list] ||= []
opts[:did_list] ||= []
toAll = opts[:to_all]
uidList = opts[:uid_list]
didList = opts[:did_list]
channel = opts[:channel]
{
appToken: CrossSites['user_center']['app_token'],
channel: channel,
oid: org.oid,
toAll: toAll,
uidList: uidList,
didList: didList
}
end
def generate_message_body(opts = {})
msg_type = opts[:msg_type]
body_params = HashWithIndifferentAccess.new
case msg_type
when 'text'
body_params.merge!(msgtype: msg_type, text: { content: opts[:content] })
when 'image'
body_params.merge!(msgtype: msg_type, image: { media_id: opts[:media_id] })
when 'voice'
body_params.merge!(msgtype: msg_type, voice: { media_id: opts[:media_id] })
when 'video'
body_params.merge!(msgtype: msg_type, video: {
media_id: opts[:media_id],
title: opts[:title],
description: opts[:description]
})
when 'file'
body_params.merge!(msgtype: msg_type, file: { media_id: opts[:media_id] })
when 'textcard'
body_params.merge!(msgtype: msg_type, textcard: {
title: opts[:title],
description: opts[:description],
url: opts[:url],
btntxt: opts[:btntxt]
})
when 'news'
body_params.merge!(msgtype: msg_type, news: { articles: opts[:articles] })
when 'mpnews'
body_params.merge!(msgtype: msg_type, news: { articles: opts[:articles] })
else
::UserCenter::UcLogger.log_info "Wx generate_message_body opts: #{opts}"
body_params = HashWithIndifferentAccess.new
end
{ msg: body_params }
end
end
end
end
=begin
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'text',
content: 'xxx'
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'image',
media_id: '1aLwXBx2Me0WH0lePENd5zgNBA1pQzTVvfA4N78UGeN-71EvQpwQaEgVoPD0A5vVO',
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'voice',
media_id: '1aLwXBx2Me0WH0lePENd5zgNBA1pQzTVvfA4N78UGeN-71EvQpwQaEgVoPD0A5vVO',
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'video',
media_id: '1aLwXBx2Me0WH0lePENd5zgNBA1pQzTVvfA4N78UGeN-71EvQpwQaEgVoPD0A5vVO',
title: 'xxx',
description: 'xxx'
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'file',
media_id: '1aLwXBx2Me0WH0lePENd5zgNBA1pQzTVvfA4N78UGeN-71EvQpwQaEgVoPD0A5vVO',
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'textcard',
title: 'xxx',
description: 'xxx',
url: 'http://test.e1.ikcrm.com/wx/1/1/home?corp_id=wx62011238322ec3ea&agent_id=1000013&pc_redirect_uri=%2Fcustomers&mobile_redirect_uri=%2Fcustomers'
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'news',
articles: [
{
title: "中秋节礼品领取",
description: "今年中秋节公司有豪礼相送",
url: "http://www.ikcrm.com",
picurl: "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"
}
]
}
opts = {
to_all: false,
uid_list: [1,2],
did_list: [1,2],
msg_type: 'mpnews',
articles: [
{
title: "Title",
thumb_media_id: "1aLwXBx2Me0WH0lePENd5zgNBA1pQzTVvfA4N78UGeN-71EvQpwQaEgVoPD0A5vVO",
autho: "Author",
content_source_url: "http://www.baidu.com",
content: "Content",
digest: "Digest description"
}
]
}
mq_queue = usual 或者 mq_queue = frequent, usual 代表业务使用的队列,frequent代表 频繁消息通知
service = UserCenter::Services::MessageService.new(org)
service.send_wx_message(opts)
=end
module UserCenter
module Services
class PackageServices
def self.cache_info(oid)
UcPackageCache.new(oid).fetch {
info = self.info(oid)
if info['code'] == 0
{
oid: info['data']['organizationOid'],
license_type: info['data']['licenseType'],
license_count: info['data']['licenseCount'],
expired_at: time_parse_from_milliseconds(info['data']['expiredAt']),
registered_at: time_parse_from_milliseconds(info['data']['registeredAt']),
started_at: time_parse_from_milliseconds(info['data']['startedAt']),
version: info['data']['version']
}.with_indifferent_access
else
{}
end
}
end
def self.info(oid)
opts = {
oid: oid
}
res = Trans::HttpHandler.get(Trans::Router.get_package_url, opts)
end
def self.time_parse_from_milliseconds(time)
if time.present?
Time.strptime(time.to_s, '%Q')
else
nil
end
end
end
end
end
# expiredAt 过期时间
# licenseCount 开通工号数量
# licenseType 版本类别: 1:免费版/2:付费版/3:试用版/4:已关闭
# organizationOid 主键
# registeredAt 注册时间
# startedAt 开始时间
# version 产品版本:1:专业版/2:基础版/3:旗舰版
\ No newline at end of file
module UserCenter
module Services
class UserRegisterService
APP_HEADER = { "appToken" => CrossSites[:user_center]['app_token'], "accessToken" => CrossSites[:user_center]['access_token'] }
def initialize(opts)
end
def allow_register?(phone: )
res = check_user(phone: phone)
logger_info("allow_register? phone: #{phone} res: #{res}")
return (res && res[:code].to_i == 0) ? res[:data][:register] : false
end
def register(params)
res = organization_register(params)
logger_info("register params: #{params} res: #{res}")
return (res && res[:code].to_i == 0) ? res[:data][:uid] : nil
end
def check_user(phone: )
opts = {
phone: phone
}
res = Trans::HttpHandler.get(Trans::Router.check_user_url, opts)
end
def organization_register(params)
_url = Trans::Router.organization_register_url
_params = {
phone: params[:phone],
organizationName: params[:company_name],
userName: params[:name],
passwordOne: params[:password],
passwordTwo: params[:password],
registeredWay: params[:register_way],
job: params[:job],
email: params[:email]
}
res = Trans::HttpHandler.post(_url, _params, APP_HEADER)
end
private
def logger_error(msg, uuid = nil)
::UserCenter::UcLogger.log_error("UserRegisterService #{msg}", uuid: uuid)
end
def logger_info(msg, uuid = nil)
::UserCenter::UcLogger.log_info("UserRegisterService #{msg}", uuid: uuid)
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
class UserService
attr_accessor :user, :user_token_key, :user_valid_password_key
APP_HEADER = { "accessToken" => CrossSites[:user_center]['access_token'] }
def initialize(user = nil)
@user = user
@user_valid_password_key = "user_#{@user.uid}_valid_password_key" if @user
@user_token_key = "user_#{@user.uid}_token" if @user
end
def get_credence
_url = Trans::Router.credence_url
_params = { uid: @user.uid }
_headers = APP_HEADER
res = Trans::HttpHandler.get(_url, _params, _headers)
res[:data][:credence]
end
def get_user_token
if $redis.get(@user_token_key).blank?
_url = Trans::Router.user_token_url
_params = { credence: get_credence }
_headers = APP_HEADER
res = Trans::HttpHandler.get(_url, _params, _headers)
$redis.set(@user_token_key, res[:data][:userToken], ex: res[:data][:expiration].gsub('HOURS','').to_i.hours - 30.minutes)
end
$redis.get(@user_token_key)
end
# 忘记密码时先使用手机号获取随机码
def random
_url = Trans::Router.random_url
_params = { phone: @user.phone }
_headers = APP_HEADER
res = Trans::HttpHandler.get(_url, _params, _headers)
res[:data]
end
# 忘记密码使用获取到的随机码和新密码重置
def forget_password(password, confirm_password)
_url = Trans::Router.forget_password_url
_params = {
random: random,
phone: @user.phone,
passwordOne: password,
passwordTwo: confirm_password
}
_headers = APP_HEADER
res = Trans::HttpHandler.post(_url, _params, _headers)
res[:code].to_i == 0
end
# 用户重置自己密码先验证原密码正确,获取随机码
def valid_password(password)
_url = Trans::Router.valid_password_url
_params = {
uid: @user.uid,
oldPassword: password
}
_headers = APP_HEADER
res = Trans::HttpHandler.post(_url, _params, _headers)
$redis.set(@user_valid_password_key, res[:randomCode], ex: 1.hours) if res[:code].to_i == 0
res[:code].to_i == 0
end
# 使用验证原密码获取的随机码设置新密码
def reset_password(password, confirm_password)
_url = Trans::Router.reset_password_url
_params = {
randomCode: $redis.get(@user_valid_password_key),
uid: @user.uid,
newPasswordOne: password,
newPasswordTwo: confirm_password
}
_headers = APP_HEADER
res = Trans::HttpHandler.post(_url, _params, _headers)
$redis.del(@user_valid_password_key)
res[:code].to_i == 0
end
# 用户编辑个人基本信息
def update_personal_info(user_params)
_url = Trans::Router.update_personal_info_url
_params = to_uc_user_params(user_params)
_headers = APP_HEADER
res = Trans::HttpHandler.post(_url, _params, _headers)
res[:code].to_i == 0
end
# 用户更换绑定手机号
def update_binding_phone(phone)
_url = Trans::Router.update_binding_phone_url
_params = { uid: @user.uid, phone: phone }
_headers = APP_HEADER
res = Trans::HttpHandler.post(_url, _params, _headers)
res[:code].to_i == 0
end
private
def to_uc_user_params(opts = {})
to_uc_params = opts.with_indifferent_access
.slice(:name, :email, :gender, :job, :avatarUrl)
.merge({ uid: @user.uid })
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
module Wx
AccountType = {
free: 0, # 免费帐号
payment: 1, # 付费帐号
invalid: 2, # 无效帐号
fail: 3 # 参数或者状态引起无法判断正确的帐号
}.with_indifferent_access.freeze
AccountStatus = {
ok: 0,
exceed_user_limitation: 1,
fail: 3 # 获取权限失败, 公司未激活该套件
}.with_indifferent_access.freeze
FREE_USERS_COUNT = 8
class AccountService
attr_reader :org, :package
def initialize(org)
@org = org
@package = UserCenter::Services::PackageServices.cache_info(@org.oid)
end
def account_type
if @package.blank?
return AccountType.fetch(:invalid)
end
@package[:license_type].in?([2,3]) ? AccountType.fetch(:payment) : AccountType.fetch(:free)
end
def account_type_text
AccountType.invert.fetch(account_type)
end
def subscriber_status
return 'active' if @package.present?
end
def expired?
DateTime.now > @package[:expired_at] if @package.present?
end
def expired_at
@package[:expired_at].to_s rescue nil
end
def started_at
@package[:started_at].to_s rescue nil
end
def status
if @package.blank?
return AccountStatus.fetch(:fail)
end
if @package[:license_type] == 3 && org.users_count.to_i > FREE_USERS_COUNT
return AccountStatus.fetch(:exceed_user_limitation)
end
AccountStatus.fetch(:ok)
end
def status_text
AccountStatus.invert.fetch(status)
end
def trial_payment_lt_15d?
@org.can_trial?
end
def in_trial_lt_15d?
@org.on_trial?
end
end
end
end
end
module UserCenter
module Services
module Wx
class ExternalContactService
attr_accessor :org
def initialize(org)
@org = org
end
def get_external_contact(external_userid)
opts = {
oid: org.oid,
externalUserid: external_userid
}
Trans::HttpHandler.get(Trans::Router.get_external_contact_url, opts)
end
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
module Wx
class LoginService
LOGIN_CALLBACK_URL = CrossSites['user_center']['login_callback_url']
def initialize(opts)
end
def get_corp_id(oid)
opts = {
oid: oid
}
Trans::HttpHandler.get(Trans::Router.get_corp_id_url, opts)
end
def qr_code_login
opts = {
successUrl: LOGIN_CALLBACK_URL
}
Trans::HttpHandler.get(Trans::Router.qrcode_login_url, opts)
end
def login(corpId, code)
opts = {
corpId: corpId,
code: code
}
Trans::HttpHandler.get(Trans::Router.get_user_info_by_code_url, opts)
end
# 企业微信服务商后台点击进入
def sso_login(authcode)
opts = {
authCode: authcode
}
Trans::HttpHandler.get(Trans::Router.get_login_info_by_auth_code_url, opts)
end
def get_jsapi_signature(oid, noncestr, timestamp, url, get_provider: false)
opts = {
oid: oid,
noncestr: noncestr,
timestamp: timestamp,
url: url,
getProvider: get_provider
}
Trans::HttpHandler.get(Trans::Router.get_jsapi_signature_url, opts)
end
def get_jsagent_signature_url(oid, noncestr, timestamp, url)
opts = {
oid: oid,
noncestr: noncestr,
timestamp: timestamp,
url: url
}
Trans::HttpHandler.get(Trans::Router.get_jsagent_signature_url, opts)
end
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
module Wx
class MediaService
attr_accessor :oid, :user, :access_token
def initialize(user)
@user = user
@oid = user.organization.oid
end
def create_attachments(medias)
create_attachments_for(medias) do |attach, url|
AttachmentUrlCreateWorker.perform_async(attach.id, url)
end
end
def sync_create_attachments(medias)
create_attachments_for(medias) do |attach, url|
AttachmentUrlCreateWorker.new.perform(attach.id, url)
end
end
def create_audios(medias)
medias.map do |media|
audio = Audio.create(wx_media_id: media[:id], duration: media[:duration])
media_url = get_media_url(oid: oid, media_id: media[:id])
AudioUrlCreateWorker.perform_async(audio.id, media_url, file_type: 'audio/amr')
audio
end
end
def create_attachments_for(medias)
medias.map do |media|
attachment = Attachment.create(wx_media_id: media[:id], user: user, organization_id: user.organization.id)
media_url = get_media_url(oid: oid, media_id: media[:id])
yield attachment, media_url
attachment
end
end
def get_media_url(oid: , media_id: )
params = {access_token: get_access_token(oid), media_id: media_id}
_url = "#{WxSetting.qyapi_host}/cgi-bin/media/get"
_url << "?#{params.to_query}"
_url
end
def get_access_token(oid)
return @access_token if @access_token.present?
opts = {
oid: oid
}
res = Trans::HttpHandler.get(Trans::Router.get_wx_corp_access_token_url, opts)
if res['code'] == 0
@access_token = res['data']['accessToken']
end
@access_token
end
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
module Wx
class RegisterCallbackService
def initialize
end
def push_to_uc_register_callback(data, channel)
opts = {
xml: {
RegisterCode: data[:RegisterCode],
AuthCorpId: data[:AuthCorpId]
}
}
res = Trans::HttpHandler.post(Trans::Router.get_register_callback_url(channel), opts)
end
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
module Wx
class TransferIdServices
class << self
def get_uids_by_wx_userids(oid, *userids)
userids.flatten!
_url = UserCenter::Trans::Router.get_uid_by_wx_userid_url
_params = { oid: oid, wxUseridList: userids }
res = UserCenter::Trans::HttpHandler.post(_url, _params)
if res[:code].to_s.eql?('0')
userids.length == 1 ? res[:data][userids[0]] : res[:data]
else
nil
end
end
alias_method :get_uid_by_wx_userid, :get_uids_by_wx_userids
def get_wx_userids_by_uids(oid, *uids)
uids.flatten!
_url = UserCenter::Trans::Router.get_wx_userid_by_uid_url
_params = { oid: oid, uids: uids }
res = UserCenter::Trans::HttpHandler.post(_url, _params)
if res[:code].to_s.eql?('0')
uids.length == 1 ? res[:data][uids[0].to_s] : res[:data]
else
nil
end
end
alias_method :get_wx_userid_by_uid, :get_wx_userids_by_uids
def get_oid_by_wx_corp_id(corp_id)
get_oid_key = "#{corp_id}_to_oid"
if $redis.get(get_oid_key).blank?
_url = UserCenter::Trans::Router.get_oid_by_wx_corp_id_url
_params = { corpId: corp_id }
res = UserCenter::Trans::HttpHandler.get(_url, _params)
if res[:code].to_s.eql?('0')
$redis.set(get_oid_key, res[:data][:oid], ex: 7.days)
else
return nil
end
end
$redis.get(get_oid_key).to_i
end
def get_wx_corp_id_and_agent_id_by_oid(oid)
get_corp_id_key = "#{oid}_to_wx_corp_id"
get_agent_id_key = "#{oid}_to_agent_id"
if $redis.get(get_corp_id_key).blank? || $redis.get(get_agent_id_key).blank?
_url = UserCenter::Trans::Router.get_wx_corp_id_by_oid_url
_params = { oid: oid }
res = UserCenter::Trans::HttpHandler.get(_url, _params)
if res[:code].to_s.eql?('0')
$redis.set(get_corp_id_key, res[:data][:corpId], ex: 7.days)
$redis.set(get_agent_id_key, res[:data][:agentId], ex: 7.days)
else
return ['','']
end
end
[$redis.get(get_corp_id_key), $redis.get(get_agent_id_key)]
end
def get_wx_corp_id_by_oid(oid)
get_wx_corp_id_and_agent_id_by_oid(oid)[0]
end
def get_agent_id_by_oid(oid)
get_wx_corp_id_and_agent_id_by_oid(oid)[1]
end
def get_suite_token_by_suite_id(suite_id)
_url = UserCenter::Trans::Router.get_suite_token_url
_params = { suiteId: suite_id }
res = UserCenter::Trans::HttpHandler.get(_url, _params)
res[:data][:token]
end
def clear_agent_id_cache(oid)
get_agent_id_key = "#{oid}_to_agent_id"
$redis.del(get_agent_id_key)
end
end
end
end
end
end
\ No newline at end of file
module UserCenter
module Services
class WxPusher
class << self
def send_corp_oa_message(user, params = {})
return unless user
opts = {
uid_list: [user.uid]
}.merge!(params).with_indifferent_access
if opts[:msg_type].eql?('textcard') && opts[:url].blank?
opts[:url] = wx_message_url(user.organization.oid, nil)
end
service = UserCenter::Services::MessageService.new(user.organization)
service.send_wx_message(opts)
rescue => e
::UserCenter::UcLogger.log_error "Wx send_corp_oa_message error: #{e.message}"
e.backtrace.each { |msg| ::UserCenter::UcLogger.log_error msg }
end
def send_notification_text_card_message(notification)
user = notification.user
return unless user
opts = {
msg_type: 'textcard',
title: notification.title,
description: wx_message_description(notification),
url: wx_message_url(user.organization.oid, notification)
}
send_corp_oa_message(user, opts)
end
def wx_message_description(notification)
content = notification.body
if notification.subject_type == "Event"
related = [
notification.extras[:related_item_model_name_human].presence,
notification.extras[:related_item_title].presence
].compact
if related.size == 2
content = "#{content} #{related.join(':')}"
end
end
content
end
def wx_message_url(oid, notification)
url = URI(CrossSites.crm_base_host)
url.path = '/wx/home'
opts = {
oid: oid,
mobile_redirect_uri: wx_mobile_message_path(notification),
pc_redirect_uri: wx_pc_message_path(notification)
}
url.query = opts.to_query
url.to_s
end
def wx_mobile_message_path(notification)
return if notification.blank?
entity_name = notification.subject_type.to_s
path = if entity_name == 'Event'
_event_url = notification.notify_type == 'notify_dealed_remind' ? "/calendar?date=#{Date.today.to_s}" :
"/#{entity_name.tableize}/#{notification.subject_id}/event"
_event_url.chomp('/')
elsif entity_name == 'ImportHistory'
URI(URI.encode(notification.subject.try(:file_path)))
elsif notification.notify_type == 'notify_approve_received_payment'
"/contracts/#{notification.extras[:contract_id]}/show_received_payment/#{notification.extras[:contract_received_payment_id]}"
elsif notification.notify_type == 'notify_birthday_remind' && notification.subject_type == "Contact" && notification.subject.present?
"/customers/#{notification.subject.customer.id}/list-contact"
elsif notification.extras.present? and notification.extras[:wxwork_msg_url].present?
notification.extras[:wxwork_msg_url]
elsif entity_name == 'Lead' && notification.notify_type.in?(%w(notify_flow_into_common_pool notify_transfer_common_pool))
"/"
else
URI(URI.encode(notification.content_path)).path.chomp('/')
end
URI.decode_www_form_component(path.to_s)
rescue
nil
end
def wx_pc_message_path(notification)
return if notification.blank?
entity_name = notification.subject_type.to_s
subject = notification.subject
path = if entity_name == 'ImportHistory' && subject.present? && subject.has_error_data
URI(URI.encode(notification.subject.try(:file_path)))
else
URI(URI.encode(notification.content_path)).path
end
URI.decode_www_form_component(path.to_s)
end
end
end
end
end
\ No newline at end of file
### TODO 处理网络超时异常
module UserCenter
module Trans
class HttpHandler
HTTParty::Basement.default_options.update(verify: false)
APP_TOKEN = CrossSites['user_center']['app_token']
TIMEOUT = 10
UC_SUCCESS_CODE = 0
ACCEPT_HEADER = {"Accept" => "application/json;"}
JSON_HEADER = {'Content-Type' => 'application/json', 'appToken' => APP_TOKEN}
def self.get(url, params = {}, header = {})
headers = HashWithIndifferentAccess.new
headers.merge! ACCEPT_HEADER
headers.merge! JSON_HEADER
headers.merge! header
start_time = Time.now
body = {}
begin
response = HTTParty.get(
url,
query: params,
headers: headers,
timeout: TIMEOUT
)
exec_time = Time.now - start_time
::UserCenter::UcLogger.logger.info "get_json: url = '#{url}', query = #{params}, headers = '#{headers}',exec_time = #{exec_time}, response = #{response.inspect}"
body = response.body
rescue
body[:msg] = "网络超时"
body[:code] = -1
end
body = JSON.parse(body).with_indifferent_access if body.is_a? String
unless body[:code].to_i.eql?(UC_SUCCESS_CODE)
@errmethod = "GET"
@errurl = url
@errcode = body[:code]
body.merge!(code: @errcode)
end
@errmethod = "GET"
@errurl = url
@errcode = UC_SUCCESS_CODE
HashWithIndifferentAccess.new body
end
def self.post(url, params = {}, header = {})
rescue_result = {code: -1, msg: "服务异常,请稍后重试"}
headers = HashWithIndifferentAccess.new
headers.merge! ACCEPT_HEADER
headers.merge! JSON_HEADER
headers.merge! header
start_time = Time.now
body = {}
begin
response = HTTParty.post(url.to_str, :body => params.to_json, :headers => headers, timeout: TIMEOUT)
exec_time = Time.now - start_time
::UserCenter::UcLogger.logger.info "Success: post_json: url = #{url}, url = '#{url}', headers = '#{headers}',"\
" data = #{params.inspect}, exec_time = #{exec_time}, response = #{response.inspect}"
body = response.body
rescue
body[:msg] = "网络超时"
body[:code] = -1
::UserCenter::UcLogger.logger.info "Network Timeout Error: post_json: url = #{url}, url = '#{url}', headers = '#{headers}',"\
" data = #{params.inspect}"
end
if body.is_a? String
body = JSON.parse(body).with_indifferent_access rescue rescue_result
end
unless body[:code].to_i.eql?(UC_SUCCESS_CODE)
@errmethod = "POST"
@errurl = url
@errcode = body[:code]
body.merge!(code: @errcode)
end
@errmethod = "POST"
@errurl = url
@errcode = UC_SUCCESS_CODE
HashWithIndifferentAccess.new body
end
end
end
end
module UserCenter
module Trans
module Router
BASE_URL = CrossSites['user_center']['host']
APP_TOKEN = CrossSites['user_center']['app_token']
LOGIN_CALLBACK_URL = CrossSites['user_center']['login_callback_url']
def login_url
BASE_URL + "/web/index.html?registered_way=normal_source&redirectUri=" + LOGIN_CALLBACK_URL + "&appToken=" + APP_TOKEN + "#/login"
end
def logout_url(current_uid)
BASE_URL + "/web/index.html?" + "appToken=" + APP_TOKEN + "&redirectUri=" + LOGIN_CALLBACK_URL + "&type=logout&uid=#{current_uid}" + "#/login"
end
def verify_ticket_url
BASE_URL + "/api/sso/verifyTicket"
end
def app_users_login_url
BASE_URL + "/api/sso/app/users/login"
end
def sso_open_api_login_url
BASE_URL + "/api/sso/openApi/login"
end
def app_phone_list
BASE_URL + "/api/organization/app/phone/list"
end
def user_info_url
BASE_URL + "/api/sso/getUserInfo"
end
# 请求忘记密码接口重置密码之前要先请求random接口,并把获取到的随机码作为忘记密码接口的参数
def random_url
BASE_URL + "/api/auth/random"
end
# 忘记密码接口
def forget_password_url
BASE_URL + "/api/user/management/forgetPassword"
end
# 验证用户密码是否正确,验证正确获取一个随机码,作为重置密码接口的参数
def valid_password_url
BASE_URL + "/api/app/user/checkLoginUserOldPassword"
end
# 重置密码接口,用于用户自己重置密码
def reset_password_url
BASE_URL + "/api/app/user/resetLoginUserPassword"
end
# 用户编辑自己基本信息
def update_personal_info_url
BASE_URL + "/api/app/user/updatePersonalInformation"
end
# 用户绑定手机号
def update_binding_phone_url
BASE_URL + "/api/app/user/updateBindingPhone"
end
def get_package_url
BASE_URL + "/api/organization/getPackage"
end
# 用户中心部门和用户设置页面
def department_url
BASE_URL + "/web/index.html?appToken=" + APP_TOKEN + "#/department"
end
# 用户中心公司信息页面
def organization_url
BASE_URL + "/web/index.html?appToken=" + APP_TOKEN + "#/company"
end
# 用户中心账户信息页面
def account_url
BASE_URL + "/web/index.html?appToken=" + APP_TOKEN + "#/account"
end
# 根据手机号查应用和企业
def check_user_url
BASE_URL + "/api/user/management/getOrganizationAndApp"
end
# 注册企业
def organization_register_url
BASE_URL + "/api/organization/register"
end
# 通过uid获取credence
def credence_url
BASE_URL + "/api/auth/getCredenceByUid"
end
# 通过uid和credence获取userToken
def user_token_url
BASE_URL + "/api/auth/getTokensByUid"
end
# 获取jsapi签名
def get_jsapi_signature_url
BASE_URL + "/api/wx/getJsApiSignature"
end
# 获取jsagentConfig
def get_jsagent_signature_url
BASE_URL + "/api/wx/getJsAgentSignature"
end
# 根据企业微信应用免登获取的code换取用户信息
def get_user_info_by_code_url
BASE_URL + "/api/wx/getUserInfoByCode"
end
# 企业微信网页登录获取的authcode换取用户信息
def get_login_info_by_auth_code_url
BASE_URL + "/api/wx/getLoginInfoByAuthCode"
end
# 使用企业微信userid换取uid
def get_wx_userid_by_uid_url
BASE_URL + "/api/wx/getWxUseridByUid"
end
# 使用uid换取企业微信userid
def get_uid_by_wx_userid_url
BASE_URL + "/api/wx/getUidByWxUserid"
end
# 使用企业微信corp_id换取oid
def get_oid_by_wx_corp_id_url
BASE_URL + "/api/wx/getOidByCorpId"
end
# 使用oid换取企业微信corp_id
def get_wx_corp_id_by_oid_url
BASE_URL + "/api/wx/getCorpIdByOid"
end
# qrcode login
def qrcode_login_url
BASE_URL + "/api/wx/#{APP_TOKEN}/qrLogin"
end
def get_wx_corp_access_token_url
BASE_URL + "/api/wx/getWxCorpAccessToken"
end
def get_external_contact_url
BASE_URL + "/api/wx/getExternalContact"
end
# 根据suiteid获取token
def get_suite_token_url
BASE_URL + "/api/wx/getEncodingToken"
end
def get_register_callback_url(channel)
BASE_URL + "/api/wx/#{channel}/register_callback"
end
extend self
end
end
end
\ No newline at end of file
module UserCenter
class UcLogger
attr_accessor :errors
LOG_FILE = "#{Rails.root}/log/uc_gateway.log"
ERROR_LOG_FILE = "#{Rails.root}/log/uc_gateway_errors.log"
def self.logger
@logger ||= ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(LOG_FILE))
end
def self.error_logger
@logger ||= ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(ERROR_LOG_FILE))
end
def self.log_info(msg, uuid: nil)
uuid ||= RequestStore.store[:request_uuid]
logger.tagged(Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'), uuid) {
logger.info msg
}
end
def self.log_error(msg, uuid: nil)
uuid ||= RequestStore.store[:request_uuid]
error_logger.tagged(Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'), uuid) {
error_logger.error msg
}
end
def self.exception_log(e)
::UserCenter::UcLogger.error_logger.error "exception: #{e.message}"
e.backtrace.each { |message| ::UserCenter::UcLogger.error_logger.error "exception: #{message}" }
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment