#encoding: utf-8 require 'base64' class TrainingsController < ApplicationController wechat_responder skip_before_filter :verify_signature, only: [:show, :create, :test] # ROOT_URL = ENV["wechat_url"] || "#{Setting.protocol}://#{Setting.host_name}" # # before_filter :authenticate, except: [:auth, :auth_callback, :pay_callback] # before_filter :find_tag_id before_filter :find_training, only: [:show, :test] before_filter :valid_training, only: [:pay, :result, :pay_js] layout 'base_trainings' # TAG_ID = 'bigdata_hnjcxy_2019' def show @training = current_training url = nil if @training && !@training.pay? url = enroll_training_path(id: @tag_id) elsif @training && @training.pay? url = result_training_path(id: @tag_id) else url = enroll_training_path(id: @tag_id) end redirect_to url end def enroll @training = current_training || Training.new @training_title = @training_type == 3 ? "信息技术新工科产学研联盟师资培训班" : "工程教育认证" end def pay _pay_params @training = current_training # 防止重复支付,对于已支付过的,不应该再到这个页来 if @training.payed? redirect_to result_training_path(id: @tag_id) return end @training.training_payinfo ||= TrainingPayinfo.new 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 => '' ' ' '' end def result _pay_params @training = current_training end def create @training = current_training || Training.new(params) @training.training_type = @training_type if @training_type == 3 @training.research_field = params[:research_field].reject(&:blank?).uniq.join(",") end @training.openid = session[:wechat_open_id] @training.save! redirect_to enroll_training_path(id: @tag_id) # redirect_to pay_training_path(id: @tag_id) end def update @training = current_training unless @training render_404 return end @training.update_attributes(params) redirect_to pay_training_path(id: @tag_id) end # 对应两种情况的信息提交 # 1. 稍后支付 # 2. 立刻支付 # 采用ajax调用方式,返回支付参数 def update_payinfo @training = current_training unless @training render_404 return end _pay_params attachment = nil if params[:image] attachment = Attachment.create!(file: params[:image], author: User.first) end #修改以前的订单信息 training_info = @training.training_payinfo if training_info.present? training_info.update_attributes(params) else training_info = TrainingPayinfo.new(params) end training_info.num = params[:enlistN].to_i if training_info.num < 1 training_info.num = 1 end training_info.fee = (training_info.num * @pay_fee).to_i training_info.attachment = attachment if attachment.present? if training_info.pay_type.to_i == TrainingPayinfo::PayType_Wechat training_info.status = TrainingPayinfo::Status_None else training_info.status = TrainingPayinfo::Status_Wait end training_info.training_id = @training.id training_info.save! if params[:js] == 'true' _pay_js(training_info.fee) else redirect_to url = result_training_path(id: @tag_id) 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.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)} end end # 用于权限跳转 def auth state = params[:state] url = "#{ROOT_URL}/trainings/auth_callback" 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 # 考虑状态 # 1. 无记录或未支付 # 2. 已填写未付款 # @training = current_training url = '' if !@training url = training_path(id: @tag_id) elsif !@training.pay? url = enroll_training_path(id: @tag_id) else url = result_training_path(id: @tag_id) end redirect_to url end def test end private def _pay_params @pay_fee = Redmine::Configuration['training_fee'].to_f || 5000 end 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 end end def find_tag_id @tag_id = params[:id] Rails.logger.info("##########TAG_ID:#{@tag_id}") @training_type = @tag_id == "aeee0601_2019" ? 3 : @tag_id == "ceeaa06_2019" ? 4 : 0 render_404 if @training_type == 0 end def find_training if params[:id] == @tag_id @training = current_training else render_404 end end def current_training Rails.logger.info("##########openid:#{session[:wechat_open_id]}, training_type: #{@training_type}") Training.where(openid: session[:wechat_open_id], training_type: @training_type).first end def valid_training unless current_training redirect_to training_path(id: @tag_id) end end private 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) @config = {} output = Wechat.pay.unifiedorder('湖南警察学院大数据培训会-报名费', (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