module AppManager class GraphqlHelper def initialize(shopify_domain,shopify_token) @api_key = AppManager.configuration.shopify_api_key || nil @api_version = AppManager.configuration.shopify_api_version || nil @shopify_domain = shopify_domain @shopify_token = shopify_token end def rest_client end def api_call(query,is_json=false) require 'uri' require 'net/http' if !@api_key.nil? && !@api_version.nil? && !@shopify_domain.nil? && !@shopify_token.nil? url = URI("https://#{@api_key}:#{@shopify_token}@#{@shopify_domain}/admin/api/#{@api_version}/graphql.json") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER request = Net::HTTP::Post.new(url) request["X-Shopify-Access-Token"] = @shopify_token request.body = query request["Accept"] = 'application/json' if is_json.present? request["Content-Type"] = 'application/json' else request["Content-Type"] = 'application/graphql' end response = http.request(request) response = ActiveSupport::JSON.decode(response.read_body) rescue nil return response else Rollbar.error("=== params missing from any of these api_key=#{@api_key}, api_version=#{@api_version}, shopify_domain=#{@shopify_domain}, shopify_token ===#{@shopify_token}") return [] end end def run_graph_api(query,variables = '',is_retrieve_all = false,after = '',is_json = true) query = query.dup.force_encoding("UTF-8") if variables.present? query = {"query": "#{query}","variables": variables } else query = {"query": "#{query}","variables": {} } end if is_json response = api_call(query.to_json,true) else response = api_call(query,false) end return response end def recurring_charge_api_call(plan,return_url,shop,discount_local_storage) plan_test = nil shop_plan_field = AppManager.configuration.field_names['shopify_plan'] rescue nil if !plan['affiliate'].nil? && plan['affiliate'].any? && !shop_plan_field.nil? && plan['affiliate'].map{|e| e['value']}.include?(shop[shop_plan_field]) plan_test = true end trial_days = plan['trial_days'] || 0 if shop && shop.shopify_domain && trial_days trial_activated_at = shop[AppManager.configuration.field_names['trial_activated_at']] rescue nil plan_id_field = shop[AppManager.configuration.plan_id_or_name_field] rescue nil remaining_obj = AppManager::Client.new remaining = remaining_obj.get_remaining_days(shop.shopify_domain,trial_activated_at,plan_id_field) # trial_days = !remaining.nil? ? remaining : trial_days if !remaining.nil? if !plan_id_field.nil? plan_obj = AppManager::Client.new current_plan = plan_obj.get_plan(plan_id_field) rescue nil used_days = (current_plan['trial_days'].to_i - remaining.to_i) if current_plan rescue 0 if used_days > 0 days = trial_days - used_days trial_days = days > 0 ? days : 0 end else trial_days = remaining end end end promotional_discount = [] if !discount_local_storage.nil? && shop plan_obj = AppManager::Client.new promotional_discount = plan_obj.get_promotional_discount(shop.shopify_domain, discount_local_storage) promotional_discount = [] if promotional_discount.class.to_s == "Hash" && promotional_discount.has_key?('status') && promotional_discount['status'] == 404 end if !plan['discount'].nil? && plan['discount'] != 0 discount_type = plan['discount_type'] || "percentage" discount_val = discount_type == "percentage" ? (plan['discount'].to_f/ 100) : "#{plan['discount']}" if !@api_version.nil? && @api_version.to_s.include?('2024') plan_discount = if plan['discount'] && plan['cycle_count'] { "discount" => { "durationLimitInIntervals" => (plan['cycle_count'].to_i), "value" => {"#{discount_type}" => discount_val} } } elsif plan['discount'] { "discount" => { "value" => {"#{discount_type}" => discount_val} } } else {} end else plan_discount = plan['discount'] ? { "discount" => { "durationLimitInIntervals" => (plan['cycle_count'].to_i), "value" => {"#{discount_type}" => discount_val} } } : {} end else if promotional_discount.any? if promotional_discount['plan_relation'].any? && !promotional_discount['plan_relation'].include?(plan['id']) plan_discount = {} else discount_type = promotional_discount['type'] || 'percentage' discount_value = { discount_type => discount_type == 'percentage' ? promotional_discount['value'].to_f / 100 : [promotional_discount['value'].to_f, plan['price']].min } discount = { 'value' => discount_value } discount['durationLimitInIntervals'] = promotional_discount['duration_intervals'].to_i if promotional_discount['duration_intervals'].to_i.positive? plan_discount = { "discount" => discount} end end end discount_exists = !plan['discount'].nil? && plan['discount'] != 0 promotional_discount_applies = promotional_discount.present? && promotional_discount.any? promotional_discount_id = discount_exists && promotional_discount_applies ? 0 : promotional_discount_applies ? promotional_discount['id'] : 0 return_url += "&discount=#{promotional_discount_id}" price_details = { "price": { "amount": plan['price'], "currencyCode": 'USD' }, "interval": plan['interval']['value'] } price_details.merge! plan_discount if plan_discount && plan_discount.any? plan_var = { "appRecurringPricingDetails": price_details, } line_items_data = [{ "plan": plan_var }] if plan['interval']['value'] == 'EVERY_30_DAYS' && plan['is_external_charge'].present? && plan['is_external_charge'] == true && plan['external_charge_limit'] != '' plan_var_usage = { "plan": { "appUsagePricingDetails": { "cappedAmount": { "amount": plan['external_charge_limit'], "currencyCode": "USD" }, "terms": plan['terms'] } } } line_items_data.push(plan_var_usage) end query = 'mutation( $name: String!, $returnUrl: URL!, $trialDays: Int, $test: Boolean, $lineItems: [AppSubscriptionLineItemInput!]! ) { appSubscriptionCreate( name: $name, returnUrl: $returnUrl, trialDays: $trialDays, test: $test, lineItems: $lineItems ) { userErrors { field message } confirmationUrl appSubscription { id } } }' variables = { "name": plan['name'], "returnUrl": return_url, "trialDays": trial_days, "test": plan_test, "lineItems": line_items_data } data = run_graph_api(query,variables) return data end def recurring_charge_cancel_api_call(charge_id,shop) query = 'mutation( $id: ID! ){ appSubscriptionCancel( id: $id ) { userErrors { field message } appSubscription { id status } } } ' variables = { "id": "gid://shopify/AppSubscription/#{charge_id}" } data = run_graph_api(query,variables) return data end def recurring_charge_current_api_call(shop) query = 'query { currentAppInstallation { activeSubscriptions { id name test } } }' data = run_graph_api(query,{}) return data end def current_rc_charge_gql(shopify_charge_id) query = 'query { node(id: "gid://shopify/AppSubscription/'+shopify_charge_id+'") { ...on AppSubscription { createdAt currentPeriodEnd id name status test lineItems { plan { pricingDetails { ...on AppRecurringPricing { interval price { amount currencyCode } discount { priceAfterDiscount { amount } } } ...on AppUsagePricing { terms cappedAmount { amount currencyCode } balanceUsed { amount currencyCode } } } } } } } }' data = run_graph_api(query,'') return data end end end