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

376 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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]
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]
# TODO: 测试完成后删除
ALLOW_OPENID_LIST = [
'o5fSc08-NDxC2564k9USCuiuC9cY',
'o5fSc097mQbwhYVLK9DAIa3uz_ug',
'o5fSc0607iR3rp4-h_VnuBTp8CiM',
'o5fSc0-nX6bUGQNQt3FrRhUKVNIw',
'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
layout 'base_trainings'
def show
@training = current_training
if @training.training_payinfo.present? && !@training.training_payinfo.not_payed? && params[:disable_redirect].blank?
redirect_to result_training_path(id: friendly_id)
return
end
# TODO: 测试完成后删除
@test_wxpay = ALLOW_OPENID_LIST.include?(session[:wechat_open_id])
render 'trainingsInfo'
end
def enroll
@training = current_training || Training.new
if @training.training_payinfo.present? && params[:disable_redirect].blank?
redirect_to result_training_path(id: friendly_id)
return
end
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])
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
if @training.training_payinfo.blank?
redirect_to training_path(id: friendly_id)
return
end
end
def create
@training = Training.new
@training.training_type = @training_type
@training.openid = session[:wechat_open_id]
save_training
redirect_to training_path(id: friendly_id, disable_redirect: true)
end
def update
@training = current_training
save_training
redirect_to training_path(id: friendly_id, disable_redirect: true)
end
# 对应两种情况的信息提交
# 1. 稍后支付
# 2. 立刻支付
# 采用ajax调用方式返回支付参数
def update_payinfo
@training = current_training
training_info = @training.training_payinfo || @training.build_training_payinfo
training_info.assign_attributes(params)
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]
if training_info.attachment.blank? && attachment.blank? && training_info.not_payed?
flash[:message] = '请先上传支付凭证'
render 'pay'
return
end
training_info.attachment = attachment if attachment.present?
end
if training_info.not_payed?
# 已支付不能修改人数
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
training_info.save!
# TODO: 测试完成后删除
@test_wxpay = ALLOW_OPENID_LIST.include?(session[:wechat_open_id])
if params[:js] == 'true' && training_info.not_payed?
Rails.logger.info("### start wechat pay => fee: #{training_info.fee}")
# TODO: 测试完成后删除
_pay_js(@test_wxpay ? 0.01 : training_info.fee)
else
redirect_to result_training_path(id: friendly_id)
end
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
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)
@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)}
end
end
# 用于权限跳转
def auth
state = params[:state]
url = CGI.escape("#{ROOT_URL}/trainings/auth_callback?return_url=#{params[:return_url]}")
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] : '/'
end
def test
end
private
def authenticate
if Rails.env.development?
session[:wechat_open_id] = "o5fSc0607iR3rp4-h_VnuBTp8CiM"
end
unless session[:wechat_open_id].present?
redirect_to auth_trainings_path(return_url: CGI.escape(request.path))
end
end
def save_training
@training.assign_attributes(params)
@training.training_type = training_type
if @training.training_type == 3
@training.research_field = params[:research_field].select(&:present?).uniq.join(",")
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
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
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
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)
@config = {}
output = Wechat.pay.unifiedorder(title, (fee * 100).to_i, session[:wechat_open_id], client_ip, out_trade_no)
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