commit
383c2f33c1
@ -0,0 +1,8 @@
|
||||
class Wechats::JsSdkSignaturesController < ApplicationController
|
||||
def create
|
||||
signature = Util::Wechat.js_sdk_signature(params[:url], params[:noncestr], params[:timestamp])
|
||||
render_ok(signature: signature)
|
||||
rescue Util::Wechat::Error => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
end
|
@ -0,0 +1,74 @@
|
||||
module Util::Wechat
|
||||
BASE_SITE = 'https://api.weixin.qq.com'.freeze
|
||||
|
||||
Error = Class.new(StandardError)
|
||||
|
||||
class << self
|
||||
attr_accessor :appid, :secret
|
||||
|
||||
def js_sdk_signature(url, noncestr, timestamp)
|
||||
str = { jsapi_ticket: jsapi_ticket, noncestr: noncestr, timestamp: timestamp, url: url }.to_query
|
||||
Digest::SHA1.hexdigest(str)
|
||||
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 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.error("[wechat] request: #{method} #{url} #{params.inspect}")
|
||||
|
||||
client = Faraday.new(url: BASE_SITE)
|
||||
response = client.public_send(method, url, params)
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
Rails.logger.error("[wechat] response:#{response.status} #{result.inspect}")
|
||||
|
||||
if response.status != 200
|
||||
raise Error, result.inspect
|
||||
end
|
||||
|
||||
if result['errcode'].present? && result['errcode'].to_i.nonzero?
|
||||
raise Error, result.inspect
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,16 @@
|
||||
wechat_config = {}
|
||||
|
||||
begin
|
||||
config = Rails.application.config_for(:configuration)
|
||||
wechat_config = config['wechat']
|
||||
raise 'wechat config missing' if wechat_config.blank?
|
||||
rescue => ex
|
||||
raise ex if Rails.env.production?
|
||||
|
||||
puts %Q{\033[33m [warning] wechat config or configuration.yml missing,
|
||||
please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
|
||||
wechat_config = {}
|
||||
end
|
||||
|
||||
Util::Wechat.appid = wechat_config['appid']
|
||||
Util::Wechat.secret = wechat_config['secret']
|
@ -0,0 +1,54 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios'
|
||||
|
||||
import ExerciseDisplay from '../../../courses/exercise/ExerciseDisplay'
|
||||
|
||||
class ExerciseBanksDetail extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount = () =>{
|
||||
|
||||
}
|
||||
detailFetchCallback = (result) => {
|
||||
let Id=this.props.match.params.Id;
|
||||
|
||||
const crumbData={
|
||||
title: result.data.exercise && result.data.exercise.name,
|
||||
is_public: result.data.exercise && result.data.exercise.is_public,
|
||||
crumbArray:[
|
||||
{content:'详情'},
|
||||
]
|
||||
}
|
||||
const menuData={
|
||||
tab:'0',//tab选中的index
|
||||
menuArray:[//tab以及tab路由
|
||||
{to:`/banks/exercise/${Id}`,content:'内容详情'}
|
||||
],
|
||||
category:'exercise',//
|
||||
tos: `/banks/exercise/${Id}/edit`,
|
||||
id: Id,
|
||||
|
||||
}
|
||||
this.props.initPublic(crumbData,menuData);
|
||||
}
|
||||
|
||||
render(){
|
||||
let { pollDetail } = this.state
|
||||
|
||||
return(
|
||||
<div>
|
||||
<ExerciseDisplay {...this.props} {...this.state}
|
||||
urlPath = {'exercise_banks'}
|
||||
detailFetchCallback={this.detailFetchCallback}
|
||||
>
|
||||
</ExerciseDisplay>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default ExerciseBanksDetail
|
Loading…
Reference in new issue