var.rb 4.81 KB
require "var/version"
require 'conekta'
require 'paypal-sdk-rest'

module Var
  # TODO: add paypal
  # @@valid_services = [:conekta, :paypal]
  VALID_SERVICES = [:conekta]

  def self.valid_services
    VALID_SERVICES
  end

  def self.create_charge(service, object, options = {})
    binding.pry
    return { error_message: 'Service is not supported' } 
      unless VALID_SERVICES.include? service
    return { error_message: "#{object.class.to_s} doesn't support charges"}
      unless object.respond_to?(:charge_with)
    object.charge_with(service, options)
  end
end

module ActsAsChargeable
  extend ActiveSupport::Concern

  module ClassMethods
    def acts_as_chargeable(keys = {})
      include ChargeableInstanceMethods
      cattr_accessor :sync_attributes
      self.sync_attributes = keys
    end
  end

  module ChargeableInstanceMethods
    def charge_with(service, options)
      if !instance_support?(service)
        error_message = "#{self.class.to_s} doesn't support" \
                        " charges with #{service.to_s}"
        return { error_message: error_message}
      end
      begin
        self.send("charge_with_#{service.to_s}", options)
      rescue => exception
        return { error_message: exception.message }
      end
    end

    def charge_with_conekta(options)
      binding.pry
      if(!options.include? :card_token)
        error_message = "Conekta needs a card token sent as a third paramater"
        return { error_message: error_message}
      end
      begin
        @charge ||= Conekta::Charge.create({
          description: self.sync(:conekta, 'description'),
          amount: self.sync(:conekta, 'amount'),
          currency: "MXN",
          reference_id: self.sync(:conekta, 'reference_id'),
          card: options[:card_token],
          details: {
            name: self.sync(:conekta, 'name'),
            email: self.sync(:conekta, 'email'),
            line_items: [{
              name: self.sync(:conekta, 'name'),
              description: self.sync(:conekta, 'description'),
              unit_price: self.sync(:conekta, 'amount'),
              quantity: 1,
            }]
          }
        })
      rescue => exception
        self.update_columns(var_status: 'failed')
        return { error_message: exception.message }
      end
    end

    def charge_with_paypal(options)
      if(!options.include? :card)
        error_message = "Paypal needs a card sent as a third paramater"
        return { error_message: error_message}
      end
      @payment = PayPal::SDK::REST::Payment.new({
        intent: "sale",
        payer: {
          payer_info: {
            email: self.sync(:paypal, 'email')},
          payment_method: "credit_card",
          funding_instruments: [{
            credit_card: {
              type: options[:card][:type],
              number: options[:card][:number],
              expire_month: options[:card][:expire_month],
              expire_year: options[:card][:expire_year],
              cvv2: options[:card][:cvv2]}}]},
        transactions: [{
          item_list: {
            items: [{
              name: self.sync(:paypal, 'name'),
              sku: self.sync(:paypal, 'sku'),
              price: self.sync(:paypal, 'price'),
              currency: "MXN",
              quantity: 1 }]},
          amount: {
            total: self.sync(:paypal, 'price'),
            currency: "MXN" },
          description: self.sync(:paypal, 'description') }]})
    end

    def find_charge(service)
      begin
        if !instance_support?(service)
          error_message = "#{self.class.to_s} doesn't support" \
                        " charges with #{service.to_s}"
          return { error_message: error_message}
        end
        self.send("find_#{service.to_s}_charge")
      rescue => exception
        return { error_message: exception.message }
      end
    end

    def charged?(service)
      charge = find_charge(service)
      charge.any? && !charge.include?(:error_message)
    end

    def find_conekta_charge
      ref_id = self.sync(:conekta, 'reference_id')
      Conekta::Charge.where({'status.ne'=>'paid', 'reference_id'=> ref_id})
    end

    def instance_support?(service)
      return self.sync_attributes.include?(service)
    end

    def sync(service, key)
      service_attributes = self.send("#{service.to_s}_attributes")
      if !service_attributes.include? key.to_sym
        return self.send(key)
      end
      self.send(service_attributes[key.to_sym])
    end

    # def sync_attribute(key)
    #   return self.send(key) unless self.sync_attributes.include? key.to_sym
    #   self.send(sync_attributes[key.to_sym])
    # end

    def conekta_attributes
      self.sync_attributes[:conekta] || {}
    end

    def paypal_attributes
      self.sync_attributes[:paypal] || {}
    end
  end
end

ActiveRecord::Base.send(:include, ActsAsChargeable) if defined? ActiveRecord::Base