Rails 7生产环境GET请求失效问题排查
1. 修复模板缺失的根本问题
Rails报错找不到模板,本质是控制器动作未通过redirect_to或render明确结束流程。当Easebuzz::Payment.initiate返回的status不等于1,或方法抛出异常时,代码会走到动作末尾,Rails会尝试寻找paye.html.erb模板(你未创建该模板),因此报错。
解决:给动作添加异常捕获和失败分支处理,确保无论成功与否都有明确的跳转:
def paye begin @payment_response = Easebuzz::Payment.initiate({ "txnid" => "#{@order.id}_#{SecureRandom.hex(4)}", # 避免重复交易ID "amount" => amount.to_f, "firstname" => current_user.name, "email" => current_user.email, "phone" => current_user.phone_number, "productinfo" => "Payment for Order#{@order.id}", "surl" => "https://#{request.host}/orders/#{@order.id}/successE", # 动态获取域名 "furl" => "https://#{request.host}/orders/#{@order.id}/failedTransaction", }) Rails.logger.info "Easebuzz payment response: #{@payment_response.inspect}" # 替换puts为Rails日志 if @payment_response['status'] == 1 data = @payment_response['data'] redirect_to("https://pay.easebuzz.in/pay/#{data}", allow_other_host: true, status: 303) else flash[:error] = "Payment initiation failed: #{@payment_response['message'] || 'Unknown error'}" redirect_to @order, status: :unprocessable_entity end rescue StandardError => e Rails.logger.error "Easebuzz payment error: #{e.message}\n#{e.backtrace.join("\n")}" flash[:error] = "Failed to start payment. Please try again later." redirect_to @order, status: :internal_server_error end end
2. 排查Easebuzz初始化失败的核心原因
2.1 核对生产环境配置
确认config/initializers/easebuzz.rb(或对应配置文件)中的商户ID、API密钥、盐值是生产环境专属参数,而非测试环境配置——配置混淆是生产环境初始化失败的常见原因。
2.2 检查EC2网络权限
AWS EC2安全组需允许出站HTTPS请求到pay.easebuzz.in及Easebuzz的API域名(如api.easebuzz.in);若EC2在VPC内,还需验证网络ACL是否放行对应出站流量。
2.3 避免重复交易ID
支付网关通常禁止重复的txnid,你当前用@order.id作为交易ID,首次支付后再次发起同一订单的支付会被网关拒绝,导致status !=1。解决:给交易ID添加随机后缀(如上述代码中的SecureRandom.hex(4)),确保每次交易ID唯一。
2.4 查看生产日志定位错误
用tail -f log/production.log查看生产日志,日志中会显示@payment_response的具体内容或异常栈,直接定位初始化失败的原因。
3. 优化请求与路由规范
3.1 改用POST请求
支付发起属于写操作,符合REST规范的做法是用POST而非GET:
- 修改路由:
resources :orders do member do post '/paye', to: 'orders#paye' end end - 修改视图为POST按钮(避免GET请求被浏览器缓存或爬虫触发):
<%= button_to "Initiate Payment", paye_order_path(order), method: :post %>
3.2 动态生成回调URL
避免硬编码域名,用request.host动态获取当前域名,同时强制使用HTTPS(生产环境建议开启全站HTTPS)。
4. 验证首次可用后续失效场景
首次可用可能是因为订单ID首次使用时网关允许,后续重复使用被拒绝;或生产环境配置存在缓存问题——可重启服务器验证配置是否生效,排查是否有配置加载异常。
内容的提问来源于stack exchange,提问作者uma

