require_dependency "app_manager/application_controller" module AppManager class ChargesController < ApplicationController include HTTParty skip_before_action :verify_authenticity_token, :only => [:process_plan] before_action :params_permit require 'time' require 'rack' def process_plan if params[:shop].present? && params[:plan_id].present? @shop = shop_data grandfathered_field = @field_names['grandfathered'] if !@shop.nil? plan_obj = AppManager::Client.new plan_data = plan_obj.get_plan(params[:plan_id], params[:shop]) # render json: plan_data and return #use this to test plan failsafe api if plan_data.present? && plan_data.is_a?(Hash) if plan_data['price'] == 0 && plan_data['is_external_charge'] == false active_charge_data = plan_obj.get_charge(params[:shop]) begin if active_charge_data && active_charge_data.any? && !active_charge_data['active_charge'].nil? && !active_charge_data['active_charge']['charge_id'].nil? gq_obj = AppManager::GraphqlHelper.new(@shop.shopify_domain, @shop.shopify_token) rec_cancel_data = gq_obj.recurring_charge_cancel_api_call(active_charge_data['active_charge']['charge_id'], @shop) if !rec_cancel_data["errors"].present? && (rec_cancel_data["data"].present? && rec_cancel_data["data"]["appSubscriptionCancel"].present? && !rec_cancel_data["data"]["appSubscriptionCancel"]["userErrors"].any? && (rec_cancel_data["data"]["appSubscriptionCancel"]["appSubscription"]["status"] == 'CANCELLED')) # cancelled_charge_id = rec_cancel_data["data"]["appSubscriptionCancel"]["appSubscription"]["id"].split('/')[-1] shop_plan_id = @shop[AppManager.configuration.plan_id_or_name_field] if !shop_plan_id.nil? plan_obj.cancel_charge(params[:shop], shop_plan_id) end end end rescue Exception => e Rollbar.error("APP MANAGER Process Plan Failed #{e}") end @trial_activated_field = AppManager.configuration.field_names['trial_activated_at'] update_info = {@plan_field => params[:plan_id], @trial_activated_field => nil,grandfathered_field => 0} if !config_trial_days.nil? && !plan_data.nil? trial_days = plan_data['trial_days'] || 0 update_info[config_trial_days] = trial_days end if @shop.update(update_info) begin AppManager::EventHandler.new('charge_created', { "plan" => plan_data, "charge" => nil, "previous_charge" => nil, "shopify_domain" => params[:shop] }) rescue Exception => e Rollbar.error("APP MANAGER Error in Process Plan #{e}") end AppManager.clear_cache # render json: {'redirect_url' => "#{app_url}?shop=#{params[:shop]}"} and return true render json: {'status' => true,'plan_type' => 'free_plan'} and return true else raise Error, "Invalid charge" end end request_data = {'shop' => @shop.shopify_domain, 'timestamp' => Time.now.to_i, 'plan' => params[:plan_id]} return_url = "#{app_url}#{plan_callback_path}?#{Rack::Utils.build_query(request_data)}" gq_obj = AppManager::GraphqlHelper.new(@shop.shopify_domain, @shop.shopify_token) data = gq_obj.recurring_charge_api_call(plan_data, return_url, @shop) if !data["errors"].present? && (data["data"].present? && data["data"]["appSubscriptionCreate"].present? && (!data["data"]["appSubscriptionCreate"]["userErrors"].any? && data["data"]["appSubscriptionCreate"]["confirmationUrl"])) redirect_charge = data["data"]["appSubscriptionCreate"]["confirmationUrl"] render json: {'redirect_url' => redirect_charge} else raise Error, "#{data.inspect}" end else raise Error, "#{data.inspect}" end else raise ModelNotFound, "Shop not found" end else raise Error, "Missing Shop domain or plan id in params" end end def callback if params[:charge_id].present? && params[:shop].present? && params[:plan].present? @shop = shop_data shopify_token = @field_names['shopify_token'] shopify_domain = @field_names['name'] grandfathered_field = @field_names['grandfathered'] if !@shop.nil? headers = {"X-Shopify-Access-Token" => @shop[shopify_token]} charges = HTTParty.get('https://' + @shop[shopify_domain] + '/admin/api/' + @api_version + '/recurring_application_charges/' + params[:charge_id] + '.json', :headers => headers) if charges.parsed_response && charges.parsed_response.is_a?(Hash) && charges.parsed_response.has_key?('recurring_application_charge') plan_obj = AppManager::Client.new plan_data = plan_obj.get_plan(params[:plan], params[:shop]) charge = charges.parsed_response['recurring_application_charge'] charge['charge_id'] = charge['id'] charge['type'] = 'recurring' charge['plan_id'] = params[:plan] charge['shop_domain'] = params[:shop] charge['interval'] = plan_data['interval']['value'] ['api_client_id', 'return_url', 'decorated_return_url','id','id','currency'].each { |k| charge.delete k } # new_plan_obj = AppManager::Client.new # if !@plan_field.nil? # begin # new_plan_obj.cancel_charge(@shop[shopify_domain], @shop[@plan_field]) # rescue Exception => e # Rollbar.error("APP MANAGER Error in Cancel charge >>>> #{e.inspect}") # end # end charge_ob = AppManager::Client.new(nil, json_req = true) response = charge_ob.store_charge(charge.to_json) if response['message'] == "success" AppManager.clear_cache update_info = {@plan_field => params[:plan],grandfathered_field => 0} if !config_trial_days.nil? && !plan_data.nil? trial_days = plan_data['trial_days'] || 0 update_info[config_trial_days] = trial_days end @shop.update(update_info) Thread.new do charge_data = plan_obj.get_charge(@shop[shopify_domain]) begin AppManager::EventHandler.new('charge_created', { "plan" => plan_data, "charge" => charge, "previous_charge" => charge_data ? (charge_data['cancelled_charge'] || nil) : nil, "shopify_domain" => params[:shop] }) rescue Exception => e Rollbar.error("Error in APP MANAGER Charge Created Callback >>>> #{e.inspect}") end end end embed_host = Base64.encode64(params[:shop] + "/admin") # redirect_to "/login?host=#{embed_host}&shop=#{shop}" and return if app_slug.present? redirect_to "https://#{params[:shop]}/admin/apps/#{app_slug}" else redirect_to "#{app_url}?host=#{embed_host}&shop=#{params[:shop]}", :status => 301 and return end else raise Error, "Invalid shopify charge #{charges.inspect}" end else raise ModelNotFound, "Shop not found" end else if params[:shop].present? embed_host = Base64.encode64(params[:shop] + "/admin") if app_slug.present? redirect_to "https://#{params[:shop]}/admin/apps/#{app_slug}" else redirect_to "#{app_url}?host=#{embed_host}&shop=#{params[:shop]}", :status => 301 and return end else raise Error, "Invalid params, must have charge_id,shop && plan in charge controller" end end end private def params_permit params.permit! end def model @models = ActiveRecord::Base.connection.tables @config_table = AppManager.configuration.shopify_table_name @shopify_domain = AppManager.configuration.shopify_domain_field @plan_field = AppManager.configuration.plan_id_or_name_field @field_names = AppManager.configuration.field_names @api_version = AppManager.configuration.shopify_api_version if @models.include?(@config_table) && !@plan_field.nil? return @config_table.classify.constantize else return nil end end def shop_data if model return model.where(@shopify_domain => params[:shop]).first rescue nil else return nil end end def app_url AppManager.configuration.app_url end def app_slug AppManager.configuration.shopify_app_slug end def config_trial_days @field_names = AppManager.configuration.field_names if !@field_names.nil? && @field_names.has_key?('total_trial_days') && !@field_names['total_trial_days'].nil? && !@field_names['total_trial_days'].blank? return @field_names['total_trial_days'] else return nil end end end end