You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pgfqe6ch8/app/controllers/trainings_controller.rb

382 lines
10 KiB

6 years ago
#encoding: utf-8
require 'base64'
class TrainingsController < ApplicationController
wechat_responder
skip_before_filter :check_if_login_required
skip_before_filter :verify_signature, except: [:auth, :auth_callback, :pay_callback]
6 years ago
6 years ago
ROOT_URL = ENV["wechat_url"] || "#{Setting.protocol}://#{Setting.host_name}"
before_filter :authenticate, except: [:auth, :auth_callback, :pay_callback]
before_filter :check_training_type, only: [:enroll]
before_filter :check_current_training, only: [:show, :update, :pay, :pay_js, :update_payinfo, :result]
6 years ago
layout 'base_trainings'
# TODO: 测试完成后删除
ALLOW_OPENID_LIST = [
'oSrqE59d6uMBkANfXnJcGuUwuGds',
'oSrqE5-j3rT3f9nt4iFhSICPF1Vo',
'oSrqE5w6dtsRyjFkFBahQ1jeurTk',
'oSrqE52fgGMooW3B1K4mZ0Le5G9I',
'o5fSc0607iR3rp4-h_VnuBTp8CiM'
]
before_filter :check_openid, only: [:update_payinfo]
def check_openid
return if ALLOW_OPENID_LIST.include?(session[:wechat_open_id])
render plain: '暂未开放'
end
6 years ago
def show
@training = current_training
6 years ago
6 years ago
if @training.training_payinfo.present? && !@training.training_payinfo.not_payed? && params[:disable_redirect].blank?
6 years ago
redirect_to result_training_path(id: friendly_id)
return
end
# TODO: 测试完成后删除
@test_wxpay = ALLOW_OPENID_LIST.include?(session[:wechat_open_id])
6 years ago
render 'trainingsInfo'
6 years ago
end
def enroll
@training = current_training || Training.new
6 years ago
if params[:disable_redirect].blank?
if @training.training_payinfo.present?
redirect_to result_training_path(id: friendly_id)
return
end
unless @training.new_record?
redirect_to training_path(id: friendly_id)
return
end
6 years ago
end
6 years ago
end
def pay
@training = current_training
if @training.training_payinfo.blank?
@training.build_training_payinfo
@training.training_payinfo.fee = @training.registration_fee
@training.training_payinfo.pay_type = params[:pay_type].presence || 3
end
# TODO: 测试完成后删除
@test_wxpay = ALLOW_OPENID_LIST.include?(session[:wechat_open_id])
6 years ago
end
def pay_callback
# {"xml"=>{"appid"=>"wx8c5bd82a8a584cf6", "bank_type"=>"CFT", "cash_fee"=>"1", "fee_type"=>"CNY",
# "is_subscribe"=>"Y", "mch_id"=>"1516303811", "nonce_str"=>"c462b28237d5e70261c3171319d86bf5",
# "openid"=>"o5fSc02LFi7LEGCk_ckp6YbegFWs", "out_trade_no"=>"2018101714093870",
# "result_code"=>"SUCCESS", "return_code"=>"SUCCESS", "sign"=>"155D16352B5F2287A32B3121175D8B0B",
# "time_end"=>"20181017140944", "total_fee"=>"1", "trade_type"=>"JSAPI",
# "transaction_id"=>"4200000166201810174468792543"}}
logger.info "pay_callback #{params}"
unless params["xml"]
logger.error "pay_callback error: not found xml"
end
pay = WechatPay.find_by_out_trade_no(params[:xml]["out_trade_no"])
pay.update_attributes!(params[:xml])
training = Training.find(pay.training_id)
training_payinfo = training.training_payinfo
training_payinfo.update_attributes!(status: TrainingPayinfo::Status_Payed,
out_trade_no: pay.out_trade_no)
# 报名成功发送短信
=begin
begin
Trustie::Sms.send(mobile: training.phone,
send_type: "training_pay",
user_name: training.name)
rescue => e
logger.error("pay_callback 短信发送失败: #{e}")
end
=end
render :xml => '' '
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
' ''
end
def result
@training = current_training
6 years ago
if @training.training_payinfo.blank?
redirect_to training_path(id: friendly_id)
return
end
6 years ago
end
def create
@training = Training.new
6 years ago
@training.training_type = @training_type
6 years ago
@training.openid = session[:wechat_open_id]
save_training
6 years ago
redirect_to training_path(id: friendly_id, disable_redirect: true)
end
6 years ago
def update
@training = current_training
save_training
6 years ago
6 years ago
redirect_to training_path(id: friendly_id, disable_redirect: true)
6 years ago
end
# 对应两种情况的信息提交
# 1. 稍后支付
# 2. 立刻支付
# 采用ajax调用方式返回支付参数
def update_payinfo
@training = current_training
training_info = @training.training_payinfo || @training.build_training_payinfo
training_info.assign_attributes(params)
6 years ago
ActiveRecord::Base.transaction do
if training_info.pay_type.to_i == TrainingPayinfo::PayType_bank
attachment = nil
attachment = Attachment.create!(file: params[:image], author: User.first) if params[:image]
6 years ago
6 years ago
if training_info.attachment.blank? && attachment.blank? && training_info.not_payed?
flash[:message] = '请先上传支付凭证'
render 'pay'
return
end
6 years ago
6 years ago
training_info.attachment = attachment if attachment.present?
end
6 years ago
if training_info.not_payed?
6 years ago
# 已支付不能修改人数
training_info.num = params[:enlistNum].to_i < 1 ? 1 : params[:enlistNum].to_i
training_info.fee = @training.registration_fee(training_info.num)
if training_info.pay_type.to_i == TrainingPayinfo::PayType_Wechat
training_info.status = TrainingPayinfo::Status_None
else
training_info.status = TrainingPayinfo::Status_Wait
end
end
6 years ago
training_info.save!
6 years ago
# TODO: 测试完成后删除
@test_wxpay = ALLOW_OPENID_LIST.include?(session[:wechat_open_id])
6 years ago
if params[:js] == 'true' && training_info.not_payed?
# TODO: 测试完成后删除
_pay_js(@test_wxpay ? 0.01 : training_info.fee)
else
redirect_to result_training_path(id: friendly_id)
end
6 years ago
end
end
### js function
def update_picture
@training = current_training
js_function_call do
attachment = Attachment.create!(file: params[:image], author: User.first)
training_payinfo = @training.training_payinfo
training_payinfo.attachment = attachment
training_payinfo.status = TrainingPayinfo::Status_Wait if training_payinfo.status == TrainingPayinfo::Status_None
6 years ago
training_payinfo.save!
render json: {status: 0}
end
end
def pay_js
@training = current_training
_pay_js(@training.training_payinfo.fee)
end
#js获取支付参数
def _pay_js(fee)
Rails.logger.info("### start wechat pay => fee: #{fee}")
6 years ago
@training = current_training
js_function_call do
out_trade_no = Wechat.pay.gen_trade_no
#@training.training_payinfo.update_attribute(:out_trade_no, out_trade_no)
#
#
# 写入wechat_pay付费表
WechatPay.create!(training_id: @training.id, out_trade_no: out_trade_no)
render json: {status: 0, data: unifiedorder(out_trade_no, fee, @training.pay_order_title)}
6 years ago
end
end
# 用于权限跳转
def auth
state = params[:state]
url = CGI.escape("#{ROOT_URL}/trainings/auth_callback?return_url=#{params[:return_url]}")
6 years ago
authorize_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{url}&response_type=code&scope=snsapi_base&state=#{state}&connect_redirect=1#wechat_redirect"
redirect_to authorize_url
end
def auth_callback
path = Base64.urlsafe_decode64(params[:state])
open_id = get_openid_from_code(params[:code])
unless open_id
render 'wechats/open_wechat', layout: nil and return
end
session[:wechat_open_id] = open_id
redirect_to params[:return_url].present? ? params[:return_url] : '/'
6 years ago
end
def test
end
private
def authenticate
if Rails.env.development?
6 years ago
session[:wechat_open_id] = "o5fSc0607iR3rp4-h_VnuBTp8CiM"
6 years ago
end
unless session[:wechat_open_id].present?
redirect_to auth_trainings_path(return_url: CGI.escape(request.path))
6 years ago
end
end
def save_training
@training.assign_attributes(params)
@training.training_type = training_type
6 years ago
if @training.training_type == 3
@training.research_field = params[:research_field].select(&:present?).uniq.join(",")
6 years ago
end
@training.save!
end
def friendly_id
@friendly_id ||= params[:friendly_id].presence || params[:id]
end
def training_type
@training_type ||=
case friendly_id
when 'aeee0601_2019' then 3
when 'ceeaa06_2019' then 4
end
6 years ago
end
def current_training
@_current_training ||= begin
Rails.logger.info("##########openid:#{session[:wechat_open_id]}, friendly_id: #{friendly_id}")
return if training_type.blank?
Training.where(openid: session[:wechat_open_id], training_type: training_type).first
end
end
def check_training_type
return if training_type.present?
render_404
6 years ago
end
def check_current_training
if current_training.blank?
if training_type.blank?
render_404
return
end
redirect_to enroll_training_path(id: friendly_id)
return
6 years ago
end
end
def js_function_call
begin
yield if block_given?
rescue => e
render json: {status: 1, msg: e.message}
end
end
def client_ip
request.headers['X-Real-IP'] || request.remote_ip || "127.0.0.1"
end
def get_openid_from_code(code)
openid = session[:wechat_open_id]
unless openid
if code
#不能联系调两次web_access_token 否则会提示请在微信客户端打开次链接
info = wechat.web_access_token(code)
openid = info["openid"]
access_token = info["access_token"]
if access_token
session[:access_token] = access_token
end
refresh_token = info["refresh_token"]
if refresh_token
session[:refresh_token] = refresh_token
end
end
end
if openid
session[:wechat_open_id] = openid
end
return openid
end
def unifiedorder(out_trade_no, fee, title)
6 years ago
@config = {}
output = Wechat.pay.unifiedorder(title, (fee * 100).to_i, session[:wechat_open_id], client_ip, out_trade_no)
6 years ago
data = output.fetch("xml")
if data.nil?
raise "获取微信统一单错误"
end
if data["return_code"] != 'SUCCESS'
raise "获取微信统一单错误:#{data["return_msg"]}"
end
@config[:appid] = data["appid"]
@config[:nonce] = data["nonce_str"]
@config[:prepay_id] = data["prepay_id"]
@config[:time] = Time.now.to_i
info = {
appId: @config[:appid],
timeStamp: @config[:time],
nonceStr: @config[:nonce],
package: "prepay_id=#{@config[:prepay_id]}",
signType: 'MD5'
}
@config[:sign] = Wechat.pay.sign(info)
@config
end
end