├── .rspec ├── Rakefile ├── lib ├── conekta │ ├── version.rb │ ├── method.rb │ ├── webhook_log.rb │ ├── payment_method.rb │ ├── event.rb │ ├── token.rb │ ├── payout.rb │ ├── operations │ │ ├── update.rb │ │ ├── custom_action.rb │ │ ├── create.rb │ │ ├── find.rb │ │ ├── where.rb │ │ ├── create_member.rb │ │ └── delete.rb │ ├── webhook.rb │ ├── plan.rb │ ├── charge.rb │ ├── resource.rb │ ├── card.rb │ ├── payout_method.rb │ ├── subscription.rb │ ├── payee.rb │ ├── customer.rb │ ├── requestor.rb │ ├── error.rb │ ├── conekta_object.rb │ └── util.rb ├── conekta.rb └── ssl_data │ └── ca_bundle.crt ├── spec ├── conekta │ ├── token_spec.rb │ ├── event_spec.rb │ ├── plan_spec.rb │ ├── webhook_spec.rb │ ├── payout_spec.rb │ ├── payee_spec.rb │ ├── error_spec.rb │ ├── charge_spec.rb │ └── customer_spec.rb ├── spec_helper.rb └── conekta_spec.rb ├── readme_files └── cover.png ├── Gemfile ├── .gitignore ├── locales ├── en.yml └── es.yml ├── conekta.gemspec ├── LICENSE.txt ├── CHANGELOG └── README.md /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /lib/conekta/version.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | VERSION = '0.5.2'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /lib/conekta/method.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Method < Resource 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /lib/conekta/webhook_log.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class WebhookLog < Resource 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /spec/conekta/token_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Token do 4 | end 5 | -------------------------------------------------------------------------------- /lib/conekta/payment_method.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class PaymentMethod < Resource 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /readme_files/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antillas21/conekta-ruby/master/readme_files/cover.png -------------------------------------------------------------------------------- /lib/conekta/event.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Event < Resource 3 | include Conekta::Operations::Where 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/conekta/token.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Token < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Create 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'sys-uname' 3 | gem 'rspec' 4 | gem 'faraday' 5 | gem 'json' 6 | gem 'i18n' 7 | # Specify your gem's dependencies in conekta.gemspec 8 | gemspec 9 | -------------------------------------------------------------------------------- /lib/conekta/payout.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Payout < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Where 5 | include Conekta::Operations::Create 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | tags 19 | *.swp 20 | *.un~ 21 | -------------------------------------------------------------------------------- /lib/conekta/operations/update.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module Update 4 | def update(params) 5 | response = Requestor.new.request(:put, self.url, params) 6 | self.load_from(response) 7 | self 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/conekta/webhook.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Webhook < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Where 5 | include Conekta::Operations::Create 6 | include Conekta::Operations::Delete 7 | include Conekta::Operations::Update 8 | include Conekta::Operations::CustomAction 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /locales/en.yml: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | en: 3 | error: 4 | resource: 5 | id: 'Could not get the id of %{resource} instance.' 6 | id_purchaser : 'There was an error. Please contact system administrator.' 7 | requestor: 8 | connection: 'Could not connect to %{base}.' 9 | connection_purchaser: 'Could not connect to payment system.' 10 | -------------------------------------------------------------------------------- /lib/conekta/plan.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Plan < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Where 5 | include Conekta::Operations::Create 6 | include Conekta::Operations::Delete 7 | include Conekta::Operations::Update 8 | include Conekta::Operations::CustomAction 9 | include Conekta::Operations::CreateMember 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /locales/es.yml: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | es: 3 | error: 4 | resource: 5 | id: 'No se pudo obtener el id de la instancia de %{resource}.' 6 | id_purchaser: 'Hubo un error. Favor de contactar al administrador del sistema.' 7 | requestor: 8 | connection: 'No se pudo conectar a %{base}.' 9 | connection_purchaser: 'No se pudo conectar al sistema de pagos.' 10 | 11 | -------------------------------------------------------------------------------- /lib/conekta/operations/custom_action.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module CustomAction 4 | def custom_action(method, action=nil, params=nil) 5 | url = action ? [self.url, action].join('/') : self.url 6 | response = Requestor.new.request(method, url, params) 7 | 8 | self.load_from(response) 9 | self 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/conekta/event_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Event do 4 | it "test succesful where" do 5 | events = Conekta::Event.where 6 | expect(events.class_name).to eq("ConektaObject") 7 | expect(events[0].class_name).to eq("Event") 8 | if !events[0].webhook_logs.empty? 9 | expect(events[0].webhook_logs.first.class_name).to eq("WebhookLog") 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/conekta/charge.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Charge < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Where 5 | include Conekta::Operations::Create 6 | include Conekta::Operations::CustomAction 7 | def capture 8 | custom_action(:post, 'capture') 9 | end 10 | def refund(params=nil) 11 | params = { 'amount' => (params || self.amount) } 12 | custom_action(:post, 'refund', params) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/conekta/resource.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Resource < ConektaObject 3 | def self.url() 4 | "/#{CGI.escape(self.class_name.downcase)}s" 5 | end 6 | def url 7 | raise Error.new( 8 | I18n.t('error.resource.id', { resource: self.class.class_name, locale: :en }), 9 | I18n.t('error.resource.id_purchaser', { locale: Conekta.locale.to_sym })) if (id.nil? || id.empty?) 10 | 11 | return [self.class.url, id].join('/') 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 2 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 3 | require 'rspec' 4 | require 'pry' 5 | require 'conekta' 6 | 7 | # Requires supporting files with custom matchers and macros, etc, 8 | # in ./support/ and its subdirectories. 9 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} 10 | 11 | RSpec.configure do |config| 12 | config.before(:all) { Conekta.api_key = '1tv5yJp3xnVZ7eK67m4h' } 13 | end 14 | -------------------------------------------------------------------------------- /lib/conekta/operations/create.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module Create 4 | module ClassMethods 5 | def create(params) 6 | url = Util.types[self.class_name.downcase].url 7 | response = Requestor.new.request(:post, url, params) 8 | instance = self.new 9 | instance.load_from(response) 10 | instance 11 | end 12 | end 13 | def self.included(base) 14 | base.extend(ClassMethods) 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/conekta/operations/find.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module Find 4 | module ClassMethods 5 | def find(id) 6 | instance = self.new(id) 7 | response = Requestor.new.request(:get, instance.url) 8 | instance.load_from(response) 9 | instance 10 | end 11 | 12 | # DEPRECATED: Please use find instead. 13 | alias_method :retrieve, :find 14 | end 15 | def self.included(base) 16 | base.extend(ClassMethods) 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/conekta/card.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Card < Resource 3 | include Conekta::Operations::Delete 4 | include Conekta::Operations::Update 5 | include Conekta::Operations::CustomAction 6 | def url 7 | raise Error.new( 8 | I18n.t('error.resource.id', { resource: self.class.class_name, locale: :en }), 9 | I18n.t('error.resource.id_purchaser', { locale: Conekta.locale.to_sym })) if (id.nil? || id.empty?) 10 | self.customer.url + self.class.url + "/" + id 11 | end 12 | def delete 13 | self.delete_member('customer','cards') 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/conekta/payout_method.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class PayoutMethod < Resource 3 | include Conekta::Operations::Delete 4 | include Conekta::Operations::Update 5 | include Conekta::Operations::CustomAction 6 | def url 7 | raise Error.new( 8 | I18n.t('error.resource.id', { resource: self.class.class_name, locale: :en }), 9 | I18n.t('error.resource.id_purchaser', { locale: Conekta.locale.to_sym })) if (id.nil? || id.empty?) 10 | self.payee.url + self.class.url + "/" + id 11 | end 12 | def delete 13 | self.delete_member('payee','payout_methods') 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/conekta_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta do 4 | describe ".config" do 5 | it "sets the api key initializer style" do 6 | Conekta.config { |c| c.api_key = "abc" } 7 | 8 | expect(Conekta.api_key).to eq("abc") 9 | end 10 | 11 | it "sets the api version initializer style" do 12 | Conekta.config { |c| c.api_version = "1.0" } 13 | 14 | expect(Conekta.api_version).to eq("1.0") 15 | end 16 | 17 | it "sets the api locale initializer style" do 18 | Conekta.config { |c| c.locale = "es" } 19 | 20 | expect(Conekta.locale).to eq("es") 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/conekta/operations/where.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module Where 4 | module ClassMethods 5 | def where(params=nil) 6 | instance = ConektaObject.new 7 | url = Util.types[self.class_name.downcase].url 8 | response = Requestor.new.request(:get, url,params) 9 | instance.load_from(response) 10 | instance 11 | end 12 | 13 | # DEPRECATED: Please use where instead. 14 | alias_method :all, :where 15 | end 16 | def self.included(base) 17 | base.extend(ClassMethods) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/conekta/subscription.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Subscription < Resource 3 | include Conekta::Operations::Update 4 | include Conekta::Operations::CustomAction 5 | def url 6 | raise Error.new( 7 | I18n.t('error.resource.id', { resource: self.class.class_name, locale: :en }), 8 | I18n.t('error.resource.id_purchaser', { locale: Conekta.locale.to_sym })) if (id.nil? || id.empty?) 9 | self.customer.url + "/subscription" 10 | end 11 | def pause 12 | custom_action(:post, 'pause') 13 | end 14 | def resume 15 | custom_action(:post, 'resume') 16 | end 17 | def cancel 18 | custom_action(:post, 'cancel') 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/conekta/payee.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Payee < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Where 5 | include Conekta::Operations::Create 6 | include Conekta::Operations::Delete 7 | include Conekta::Operations::Update 8 | include Conekta::Operations::CustomAction 9 | include Conekta::Operations::CreateMember 10 | def load_from(response=nil) 11 | if response 12 | super 13 | end 14 | payee = self 15 | self.payout_methods.each do |k,v| 16 | if !v.respond_to? :deleted or !v.deleted 17 | v.create_attr('payee', payee) 18 | self.payout_methods.set_val(k,v) 19 | end 20 | end 21 | end 22 | def create_payout_method(params) 23 | self.create_member('payout_methods', params) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/conekta/operations/create_member.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module CreateMember 4 | def create_member(member, params) 5 | url = [self.url, member].join('/') 6 | member = member.to_sym 7 | response = Requestor.new.request(:post, url, params) 8 | 9 | if self.method(member).call and self.method(member).call.class.class_name == "ConektaObject" 10 | arr = [] 11 | self.method(member).call.values.each do |_,v| 12 | arr << v.to_hash 13 | end 14 | arr << response 15 | self.method(member).call.load_from(arr) 16 | self.load_from 17 | instances = self.method(member).call 18 | instance = instances.last 19 | else 20 | instance = Util.types[member.to_s].new() 21 | instance.load_from(response) 22 | self.create_attr(member.to_s, instance) 23 | self.set_val(member.to_sym, instance) 24 | self.load_from 25 | end 26 | instance 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/conekta/customer.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Customer < Resource 3 | include Conekta::Operations::Find 4 | include Conekta::Operations::Where 5 | include Conekta::Operations::Create 6 | include Conekta::Operations::Delete 7 | include Conekta::Operations::Update 8 | include Conekta::Operations::CustomAction 9 | include Conekta::Operations::CreateMember 10 | def load_from(response=nil) 11 | if response 12 | super 13 | end 14 | customer = self 15 | self.cards.each do |k,v| 16 | if !v.respond_to? :deleted or !v.deleted 17 | v.create_attr('customer', customer) 18 | self.cards.set_val(k,v) 19 | end 20 | end 21 | if self.respond_to? :subscription and self.subscription 22 | self.subscription.create_attr('customer', customer) 23 | end 24 | end 25 | def create_card(params) 26 | self.create_member('cards', params) 27 | end 28 | def create_subscription(params) 29 | self.create_member('subscription', params) 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /conekta.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'conekta/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "conekta" 8 | spec.version = Conekta::VERSION 9 | spec.authors = ["MauricioMurga"] 10 | spec.email = ["soporte@conekta.io"] 11 | spec.description = %q{Ruby library for https://api.conekta.io} 12 | spec.summary = %q{This library provides https://api.conekta.io operations} 13 | spec.homepage = "https://www.conekta.io" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files`.split($/) 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_dependency "bundler", "~> 1.3" 22 | spec.add_dependency "rake" 23 | spec.add_dependency "faraday" 24 | spec.add_dependency "json" 25 | spec.add_dependency "sys-uname" 26 | 27 | spec.add_development_dependency "rspec", "~> 3.0" 28 | spec.add_development_dependency "pry" 29 | end 30 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014 - Conekta, Inc. (https://www.conekta.io) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | === 0.3.5 2013-01-13 2 | 3 | * Deprecate retrieve and all methods and replaced them with find and where respectively. 4 | * Add payment method model. 5 | * Objects' properties are now accessible via methods of the same of name 6 | 7 | === 0.3.6 2013-01-17 8 | 9 | * Fix cert path. 10 | === 0.3.7 2013-01-27 11 | 12 | * Add api_version= method. 13 | 14 | === 0.4.0 2014-04-16 15 | 16 | * Add payout and payee models with specs. 17 | * Add webhook logs for events. 18 | * Ameliorate convert_to_conekta_object logic. 19 | 20 | === 0.4.1 2014-04-16 21 | 22 | * Remove active support and add custom methods in util file. 23 | 24 | === 0.4.2 2014-04-28 25 | 26 | * Fix Payout specs. 27 | 28 | === 0.4.3 2014-05-25 29 | 30 | * Add locale and message_to_purchaser. 31 | 32 | === 0.4.4 2014-06-04 33 | 34 | * Fix requestor and where method. 35 | 36 | === 0.4.5 2014-07-08 37 | 38 | * Sprinkling small Ruby style conventions here and there (antillas21). 39 | 40 | === 0.4.6 2014-07-08 41 | 42 | * Add message_to_purchaser internal errors. 43 | 44 | === 0.4.9 2014-07-08 45 | 46 | * Update API version to 1.0.0. 47 | 48 | === 0.5.0 2015-01-20 49 | 50 | * Add Webhook module. 51 | 52 | === 0.5.2 2015-01-20 53 | 54 | * Change rspec dependency to development. -------------------------------------------------------------------------------- /spec/conekta/plan_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Plan do 4 | context "get/where" do 5 | it "test succesful get plan" do 6 | plans = Conekta::Plan.where 7 | p = plans.first; 8 | plan = Conekta::Plan.find(p.id) 9 | expect(plan).to be_a(Conekta::Plan) 10 | end 11 | 12 | it "test succesful where" do 13 | plans = Conekta::Plan.where 14 | expect(plans.class_name).to eq("ConektaObject") 15 | expect(plans.first).to be_a(Conekta::Plan) 16 | end 17 | end 18 | 19 | context "creating plans" do 20 | it "test succesful create plan" do 21 | plan = Conekta::Plan.create( 22 | id: ((0...8).map { (65 + rand(26)).chr }.join), 23 | name: "Gold Plan", 24 | amount: 10000, 25 | currency: "MXN", 26 | interval: "month", 27 | frequency: 10, 28 | trial_period_days: 15, 29 | expiry_count: 12 30 | ) 31 | expect(plan).to be_a(Conekta::Plan) 32 | end 33 | end 34 | 35 | context "updating plans" do 36 | it "test update plan" do 37 | plans = Conekta::Plan.where 38 | plan = plans.first 39 | plan.update({name: "Silver Plan"}) 40 | expect(plan.name).to eq("Silver Plan") 41 | end 42 | end 43 | 44 | context "deleting plans" do 45 | it "test delete plan" do 46 | plans = Conekta::Plan.where 47 | plan = plans.first 48 | plan.delete 49 | expect(plan.deleted).to eq(true) 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/conekta/webhook_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Webhook do 4 | let!(:events) do 5 | { 6 | events: [ 7 | "charge.created", "charge.paid", "charge.under_fraud_review", 8 | "charge.fraudulent", "charge.refunded", "charge.created", "customer.created", 9 | "customer.updated", "customer.deleted", "webhook.created", "webhook.updated", 10 | "webhook.deleted", "charge.chargeback.created", "charge.chargeback.updated", 11 | "charge.chargeback.under_review", "charge.chargeback.lost", "charge.chargeback.won", 12 | "payout.created", "payout.retrying", "payout.paid_out", "payout.failed", 13 | "plan.created", "plan.updated", "plan.deleted", "subscription.created", 14 | "subscription.paused", "subscription.resumed", "subscription.canceled", 15 | "subscription.expired", "subscription.updated", "subscription.paid", 16 | "subscription.payment_failed", "payee.created", "payee.updated", 17 | "payee.deleted", "payee.payout_method.created", 18 | "payee.payout_method.updated", "payee.payout_method.deleted" 19 | ] 20 | } 21 | end 22 | let(:url) { { url: "http://localhost:3000/my_listener" } } 23 | 24 | it "succesfully gets charge" do 25 | webhook = Conekta::Webhook.create(url.merge(events)) 26 | expect(webhook.webhook_url).to eq(url[:url]) 27 | webhook = Conekta::Webhook.find(webhook.id) 28 | expect(webhook.webhook_url).to eq(url[:url]) 29 | webhook.update({url: "http://localhost:2000/my_listener"}) 30 | expect(webhook.webhook_url).to eq("http://localhost:2000/my_listener") 31 | webhook.delete 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/conekta/operations/delete.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Operations 3 | module Delete 4 | def delete 5 | self.custom_action(:delete, nil, nil) 6 | self 7 | end 8 | def delete_member(parent, member) 9 | self.custom_action(:delete, nil, nil) 10 | parent = parent.to_sym 11 | member = member.to_sym 12 | obj = self.method(parent).call.method(member).call 13 | if obj.class.class_name == "ConektaObject" 14 | self.method(parent).call.method(member).call.each do |(k, v)| 15 | if v.id == self.id 16 | self.method(parent).call.method(member).call[k] = nil 17 | # Shift hash array 18 | shift = false 19 | self.method(parent).call.method(member).call.each_with_index do |v,i| 20 | if shift 21 | self.method(parent).call.method(member).call.set_val(i-1,v[1]) 22 | self.method(parent).call.method(member).call[i-1] = v[1] 23 | end 24 | if v[1] == nil 25 | shift = true 26 | end 27 | end 28 | n_members = self.method(parent).call.method(member).call.count 29 | last_index = n_members - 1 30 | # Remove last member because the hash array was shifted 31 | self.method(parent).call.method(member).call.unset_key(last_index) 32 | self.method(parent).call.method(member).call.delete(last_index) 33 | break 34 | end 35 | end 36 | else 37 | self.create_attr(member.to_s, nil) 38 | end 39 | self 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/conekta/payout_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Payout do 4 | let(:payee_attributes) do 5 | { 6 | name: "John Doe", email: "j_d@radcorp.com", phone: "555555555", 7 | billing_address:{ 8 | company_name: 'Rad Corp', 9 | tax_id: 'tax121212abc', 10 | street1: 'Guadalupe 73', 11 | street2: 'Despacho 32', 12 | street3: 'Condesa', 13 | city: 'Cuauhtemoc', 14 | state: 'DF', 15 | country: 'MX', 16 | zip: '06100' 17 | } 18 | } 19 | end 20 | 21 | let(:bank_attributes) do 22 | { 23 | account_number: '032180000118359719', 24 | account_holder: 'J D - Radcorp', 25 | description: 'Conekta To JD', 26 | statement_description: 'Conekta To JD 111111111', 27 | statement_reference: '111111111' 28 | } 29 | end 30 | 31 | describe 'an instance' do 32 | before do 33 | payee = Conekta::Payee.create(payee_attributes) 34 | payout_method = payee.create_payout_method(bank_attributes) 35 | 36 | @payee = Conekta::Payee.find(payee.id) 37 | end 38 | 39 | it 'is created successfully' do 40 | payout = Conekta::Payout.create( 41 | amount: 5000, currency: "MXN", payee: @payee.id 42 | ) 43 | expect(payout).to be_a(Conekta::Payout) 44 | end 45 | 46 | it 'can be retrieved by :id' do 47 | transaction = Conekta::Payout.create( 48 | amount: 5000, currency: "MXN", payee: @payee.id 49 | ) 50 | # refetch payout 51 | payout = Conekta::Payout.find(transaction.id) 52 | expect(payout).to be_a(Conekta::Payout) 53 | end 54 | 55 | it 'has a :method attribute' do 56 | expect(@payee.payout_methods.first).to be_a(Conekta::Method) 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/conekta.rb: -------------------------------------------------------------------------------- 1 | require "json" 2 | require "i18n" 3 | 4 | require "conekta/version" 5 | 6 | require "conekta/operations/find" 7 | require "conekta/operations/where" 8 | require "conekta/operations/create" 9 | require "conekta/operations/delete" 10 | require "conekta/operations/update" 11 | require "conekta/operations/custom_action" 12 | require "conekta/operations/create_member" 13 | 14 | require "conekta/conekta_object" 15 | require "conekta/resource" 16 | require "conekta/requestor" 17 | require "conekta/util" 18 | require "conekta/error" 19 | require "conekta/payment_method" 20 | require "conekta/charge" 21 | require "conekta/customer" 22 | require "conekta/card" 23 | require "conekta/subscription" 24 | require "conekta/plan" 25 | require "conekta/token" 26 | require "conekta/event" 27 | require "conekta/payee" 28 | require "conekta/payout" 29 | require "conekta/payout_method" 30 | require "conekta/method" 31 | require "conekta/webhook" 32 | require "conekta/webhook_log" 33 | 34 | module Conekta 35 | I18n.load_path += Dir[File.join(File.expand_path('../..', __FILE__), 'locales', '*.{rb,yml}').to_s] 36 | 37 | @api_base = 'https://api.conekta.io' 38 | @api_version = '1.0.0' 39 | @locale = 'es' 40 | 41 | def self.config 42 | yield self 43 | end 44 | 45 | def self.api_base 46 | @api_base 47 | end 48 | 49 | def self.api_base=(api_base) 50 | @api_base = api_base 51 | end 52 | 53 | def self.api_version 54 | @api_version 55 | end 56 | 57 | def self.api_version=(api_version) 58 | @api_version = api_version 59 | end 60 | 61 | def self.api_key 62 | @api_key 63 | end 64 | 65 | def self.api_key=(api_key) 66 | @api_key = api_key 67 | end 68 | 69 | def self.locale 70 | @locale 71 | end 72 | 73 | def self.locale=(locale) 74 | @locale = locale 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /lib/conekta/requestor.rb: -------------------------------------------------------------------------------- 1 | require 'faraday' 2 | require 'base64' 3 | module Conekta 4 | class Requestor 5 | require 'sys/uname' 6 | include Sys 7 | attr_reader :api_key 8 | def initialize() 9 | @api_key = Conekta.api_key 10 | end 11 | def api_url(url='') 12 | api_base = Conekta.api_base 13 | api_base + url 14 | end 15 | def request(meth, url, params=nil) 16 | url = self.api_url(url) 17 | meth = meth.downcase 18 | begin 19 | conn = Faraday.new( 20 | :url => url, 21 | :ssl => { :ca_file=> File.dirname(__FILE__) + '/../ssl_data/ca_bundle.crt'} 22 | ) do |faraday| 23 | faraday.adapter Faraday.default_adapter 24 | end 25 | conn.headers['X-Conekta-Client-User-Agent'] = set_headers.to_json 26 | conn.headers['User-Agent'] = 'Conekta/v1 RubyBindings/' + Conekta::VERSION 27 | conn.headers['Accept'] = "application/vnd.conekta-v#{Conekta.api_version}+json" 28 | conn.headers['Accept-Language'] = Conekta.locale.to_s 29 | conn.headers['Authorization'] = "Basic #{ Base64.encode64("#{self.api_key}" + ':')}" 30 | if params 31 | conn.params = params 32 | end 33 | response = conn.method(meth).call 34 | rescue Exception => e 35 | Error.error_handler(e, "") 36 | end 37 | if response.status != 200 38 | Error.error_handler(JSON.parse(response.body), response.status) 39 | end 40 | return JSON.parse(response.body) 41 | end 42 | private 43 | def set_headers 44 | headers = {} 45 | headers[:bindings_version] = Conekta::VERSION 46 | headers[:lang] = 'ruby' 47 | headers[:lang_version] = RUBY_VERSION 48 | headers[:publisher] = 'conekta' 49 | headers[:uname] = Uname.uname 50 | return headers 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/conekta/payee_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | # require 'conekta' 3 | 4 | describe Conekta::Payee do 5 | 6 | describe 'an instance' do 7 | let(:payee_attributes) do 8 | { 9 | name: "John Doe", email: "j_d@radcorp.com", phone: "555555555", 10 | billing_address:{ 11 | company_name: 'Rad Corp', 12 | tax_id: 'tax121212abc', 13 | street1: 'Guadalupe 73', 14 | street2: 'Despacho 32', 15 | street3: 'Condesa', 16 | city: 'Cuauhtemoc', 17 | state: 'DF', 18 | country: 'MX', 19 | zip: '06100' 20 | } 21 | } 22 | end 23 | 24 | it 'creates successfully' do 25 | payee = Conekta::Payee.create(payee_attributes) 26 | expect(payee).to be_a(Conekta::Payee) 27 | end 28 | 29 | describe ':payout_methods' do 30 | let!(:payee) { Conekta::Payee.create(payee_attributes) } 31 | let(:bank_attributes) do 32 | { 33 | account_number: '032180000118359719', 34 | account_holder: 'J D - Radcorp', 35 | description: 'Conekta To JD', 36 | statement_description: 'Conekta To JD 111111111', 37 | statement_reference: '111111111' 38 | } 39 | end 40 | 41 | it 'can create payout methods' do 42 | payout_method = payee.create_payout_method(bank_attributes) 43 | expect(payout_method).to be_a(Conekta::Method) 44 | # I'm sure this should be a Conekta::PayoutMethod, 45 | # just not sure why it's reporting back as a Conekta::Method 46 | end 47 | 48 | it 'assigns default_payout_method_id to first payout method created' do 49 | payout_method = payee.create_payout_method(bank_attributes) 50 | # refetch the payee object 51 | payee = Conekta::Payee.find(payout_method.payee_id) 52 | expect(payee.default_payout_method_id).to eq(payout_method.id) 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/conekta/error_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Error do 4 | let(:card) { { cards: ["tok_test_visa_4242"] } } 5 | 6 | it "test no id error" do 7 | expect { Conekta::Charge.find(nil) }.to raise_error( 8 | Conekta::Error, "Could not get the id of Charge instance." 9 | ) 10 | end 11 | 12 | it "test no connection error" do 13 | api_url = Conekta::api_base 14 | Conekta::api_base = 'http://localhost:3001' 15 | 16 | expect { Conekta::Customer.create(card) }.to raise_error( 17 | Conekta::NoConnectionError, "Could not connect to http://localhost:3001." 18 | ) 19 | 20 | # cleanup 21 | Conekta::api_base = api_url 22 | end 23 | 24 | it "test api error" do 25 | expect { Conekta::Customer.create({ cards: {0=>"tok_test_visa_4242"} }) }.to \ 26 | raise_error(Conekta::ParameterValidationError) 27 | end 28 | 29 | it "test authentication error" do 30 | Conekta::api_key = "" 31 | expect { Conekta::Customer.create({ cards: ["tok_test_visa_4242"] }) }.to \ 32 | raise_error(Conekta::AuthenticationError) 33 | 34 | # cleanup 35 | Conekta.api_key = '1tv5yJp3xnVZ7eK67m4h' 36 | end 37 | 38 | it "test parameter validation error" do 39 | expect { Conekta::Plan.create({id: 'gold-plan'}) }.to raise_error( 40 | Conekta::ParameterValidationError 41 | ) 42 | end 43 | 44 | it "test processing error" do 45 | charge = nil 46 | charges = Conekta::Charge.where() 47 | charges.each do |(k,v)| 48 | if v.status == "pre_authorized" 49 | charge = v 50 | break 51 | end 52 | end 53 | begin 54 | if charge 55 | charge.capture 56 | end 57 | rescue Conekta::Error => e 58 | expect(e.class_name).to eq("ProcessingError") 59 | end 60 | end 61 | 62 | it "test resource not found error" do 63 | expect { Conekta::Charge.find(1) }.to raise_error( 64 | Conekta::ResourceNotFoundError 65 | ) 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![alt tag](https://raw.github.com/conekta/conekta-ruby/master/readme_files/cover.png) 2 | 3 | # Conekta Ruby v.0.5.2 4 | 5 | This is a ruby library that allows interaction with https://api.conekta.io API. 6 | 7 | ## Installation 8 | 9 | Add this line to your application's Gemfile: 10 | 11 | gem 'conekta' 12 | 13 | And then execute: 14 | 15 | $ bundle 16 | 17 | Or install it yourself as: 18 | 19 | $ gem install conekta 20 | 21 | ## Usage 22 | ```ruby 23 | # Set your configuration variables 24 | 25 | # This change the Accept-Language Header to the locale specified 26 | Conekta.locale = :es 27 | 28 | Conekta.api_key = '1tv5yJp3xnVZ7eK67m4h' 29 | 30 | # Or via an initializer in config/initializers/conekta.rb 31 | Conekta.config do |c| 32 | c.locale = :es 33 | c.api_key = '1tv5yJp3xnVZ7eK67m4h' 34 | c.api_version = '1.0.0' 35 | end 36 | 37 | begin 38 | charge = Conekta::Charge.create({ 39 | amount: 51000, 40 | currency: "MXN", 41 | description: "Pizza Delivery", 42 | reference_id: "orden_de_id_interno", 43 | card: params[:conektaTokenId] 44 | #"tok_a4Ff0dD2xYZZq82d9" 45 | }) 46 | rescue Conekta::ParameterValidationError => e 47 | puts e.message 48 | #alguno de los parámetros fueron inválidos 49 | rescue Conekta::ProcessingError => e 50 | puts e.message 51 | #la tarjeta no pudo ser procesada 52 | rescue Conekta::Error 53 | puts e.message 54 | #un error ocurrió que no sucede en el flujo normal de cobros como por ejemplo un auth_key incorrecto 55 | end 56 | 57 | { 58 | "id": "5286828b8ee31e64b7001739", 59 | "livemode": false, 60 | "created_at": 1384546955, 61 | "status": "paid", 62 | "currency": "MXN", 63 | "description": "Some desc", 64 | "reference_id": null, 65 | "failure_code": null, 66 | "failure_message": null, 67 | "object": "charge", 68 | "amount": 2000, 69 | "fee": 371, 70 | "payment_method": { 71 | "name": "Mario Moreno", 72 | "exp_month": "05", 73 | "exp_year": "15", 74 | "auth_code": "861491", 75 | "object": "card_payment", 76 | "last4": "4242", 77 | "brand": "visa" 78 | }, 79 | "details": { 80 | "name": null, 81 | "phone": null, 82 | "email": null, 83 | "line_items": [] 84 | } 85 | } 86 | ``` 87 | 88 | License 89 | ------- 90 | Developed by [Conekta](https://www.conekta.io). Available with [MIT License](LICENSE). 91 | -------------------------------------------------------------------------------- /lib/conekta/error.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class Error < Exception 3 | attr_reader :message 4 | attr_reader :message_to_purchaser 5 | attr_reader :type 6 | attr_reader :code 7 | attr_reader :param 8 | 9 | def initialize(message=nil, message_to_purchaser=nil, type=nil, code=nil, param=nil) 10 | @message = message 11 | @message_to_purchaser = message_to_purchaser 12 | @type = type 13 | @code = code 14 | @param = param 15 | end 16 | def class_name 17 | self.class.name.split('::')[-1] 18 | end 19 | def self.error_handler(resp, code) 20 | if resp.instance_of?(Hash) 21 | @message = resp["message"] if resp.has_key?('message') 22 | @message_to_purchaser = resp["message_to_purchaser"] if resp.has_key?('message_to_purchaser') 23 | @type = resp["type"] if resp.has_key?('type') 24 | @code = resp["code"] if resp.has_key?('code') 25 | @param = resp["param"] if resp.has_key?('param') 26 | end 27 | if code == nil or code == 0 or code == nil or code == "" 28 | raise NoConnectionError.new( 29 | I18n.t('error.requestor.connection', { base: Conekta.api_base, locale: :en }), 30 | I18n.t('error.requestor.connection_purchaser', { locale: Conekta.locale.to_sym })) 31 | end 32 | case code 33 | when 400 34 | raise MalformedRequestError.new(@message, @message_to_purchaser, @type, @code, @params) 35 | when 401 36 | raise AuthenticationError.new(@message, @message_to_purchaser, @type, @code, @params) 37 | when 402 38 | raise ProcessingError.new(@message, @message_to_purchaser, @type, @code, @params) 39 | when 404 40 | raise ResourceNotFoundError.new(@message, @message_to_purchaser, @type, @code, @params) 41 | when 422 42 | raise ParameterValidationError.new(@message, @message_to_purchaser, @type, @code, @params) 43 | when 500 44 | raise ApiError.new(@message, @message_to_purchaser, @type, @code, @params) 45 | else 46 | raise Error.new(@message, @message_to_purchaser, @type, @code, @params) 47 | end 48 | end 49 | end 50 | class ApiError < Error 51 | end 52 | 53 | class NoConnectionError < Error 54 | end 55 | 56 | class AuthenticationError < Error 57 | end 58 | 59 | class ParameterValidationError < Error 60 | end 61 | 62 | class ProcessingError < Error 63 | end 64 | 65 | class ResourceNotFoundError < Error 66 | end 67 | 68 | class MalformedRequestError < Error 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/conekta/conekta_object.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | class ConektaObject < Hash 3 | attr_reader :id 4 | attr_reader :values 5 | def initialize(id=nil) 6 | @values = Hash.new 7 | @id = id.to_s 8 | end 9 | def set_val(k,v) 10 | @values[k] = v 11 | end 12 | def unset_key(k) 13 | @values.delete(k) 14 | end 15 | def first 16 | self[0] 17 | end 18 | def last 19 | self[self.count - 1] 20 | end 21 | def load_from(response) 22 | if response.instance_of?(Array) 23 | response.each_with_index do |v, i| 24 | load_from_enumerable(i,v) 25 | end 26 | elsif response.kind_of?(Hash) 27 | response = response.to_hash if response.class != Hash 28 | response.each do |k,v| 29 | load_from_enumerable(k,v) 30 | end 31 | end 32 | end 33 | def to_s 34 | @values.inspect 35 | end 36 | def inspect 37 | if self.respond_to? :each 38 | if self.class.class_name != "ConektaObject" 39 | self.to_s 40 | else 41 | self.to_a.map{|x| x[1] } 42 | end 43 | else 44 | super 45 | end 46 | end 47 | def self.class_name 48 | self.name.split('::')[-1] 49 | end 50 | def class_name 51 | self.class.name.split('::')[-1] 52 | end 53 | def create_attr(k,v) 54 | # Conflict with Resource Class Url 55 | k = "webhook_url" if k.to_s == "url" 56 | # Conflict with Resource Class Url 57 | create_method( "#{k}=".to_sym ) { |val| 58 | instance_variable_set( "@" + k, val) 59 | } 60 | self.send("#{k}=".to_sym, v) 61 | self.class.send(:remove_method, "#{k}=".to_sym) 62 | create_method( k.to_sym ) { 63 | instance_variable_get( "@" + k ) 64 | } 65 | end 66 | protected 67 | def to_hash 68 | hash = Hash.new 69 | self.values.each do |k,v| 70 | hash[k] = v 71 | end 72 | hash 73 | end 74 | def create_method( name, &block ) 75 | self.class.send( :define_method, name, &block ) 76 | end 77 | def load_from_enumerable(k,v) 78 | if v.respond_to? :each and !v.instance_of?(ConektaObject) 79 | v = Conekta::Util.convert_to_conekta_object(k,v) 80 | end 81 | if self.instance_of?(ConektaObject) 82 | self[k] = v 83 | else 84 | self.create_attr(k,v) 85 | end 86 | self.set_val(k,v) 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/conekta/charge_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Charge do 4 | let(:payment_method) do 5 | { 6 | amount: 2000, currency: 'mxn', description: 'Some desc' 7 | } 8 | end 9 | let(:invalid_payment_method) do 10 | { 11 | amount: 10, currency: 'mxn', description: 'Some desc' 12 | } 13 | end 14 | let(:card) { { card: 'tok_test_visa_4242' } } 15 | 16 | context "get" do 17 | it "succesfully gets charge" do 18 | transaction = Conekta::Charge.create(payment_method.merge(card)) 19 | expect(transaction.status).to eq("paid") 20 | charge = Conekta::Charge.find(transaction.id) 21 | expect(charge).to be_a(Conekta::Charge) 22 | end 23 | 24 | it "test succesful where" do 25 | charges = Conekta::Charge.where 26 | charge = charges.first 27 | expect(charge).to be_a(Conekta::Charge) 28 | end 29 | end 30 | 31 | context "creating charges" do 32 | it "tests succesful bank payment" do 33 | bank = { bank: { 'type' => 'banorte' } } 34 | bank_payment = Conekta::Charge.create(payment_method.merge(bank)) 35 | expect(bank_payment.status).to eq("pending_payment") 36 | end 37 | 38 | it "tests succesful card payment" do 39 | card_payment = Conekta::Charge.create(payment_method.merge(card)) 40 | expect(card_payment.status).to eq("paid") 41 | end 42 | 43 | it "tests succesful oxxo payment" do 44 | oxxo = { cash: { 'type' => 'oxxo' } } 45 | cash_payment = Conekta::Charge.create(payment_method.merge(oxxo)) 46 | expect(cash_payment.status).to eq("pending_payment") 47 | end 48 | 49 | it "tests succesful card payment capture" do 50 | # pm = @valid_payment_method 51 | # card = @valid_visa_card 52 | capture = { capture: false } 53 | transaction = Conekta::Charge.create( 54 | payment_method.merge(card).merge(capture) 55 | ) 56 | expect(transaction.status).to eq("pre_authorized") 57 | transaction.capture 58 | expect(transaction.status).to eq("paid") 59 | end 60 | 61 | it "test unsuccesful create" do 62 | expect { 63 | Conekta::Charge.create(invalid_payment_method.merge(card)) 64 | }.to raise_error( 65 | Conekta::ParameterValidationError, 66 | "The minimum for card payments is 3 pesos. Check that the amount " + 67 | "is in cents as explained in the documentation." 68 | ) 69 | end 70 | end 71 | 72 | context "refunding charges" do 73 | it "test susccesful refund" do 74 | transaction = Conekta::Charge.create(payment_method.merge(card)) 75 | expect(transaction.status).to eq("paid") 76 | transaction.refund 77 | expect(transaction.status).to eq("refunded") 78 | end 79 | 80 | it "test unsusccesful refund" do 81 | transaction = Conekta::Charge.create(payment_method.merge(card)) 82 | expect(transaction.status).to eq("paid") 83 | 84 | expect { transaction.refund(3000) }.to raise_error( 85 | Conekta::ProcessingError, 86 | "The amount to refund exceeds the charge total." 87 | ) 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/conekta/util.rb: -------------------------------------------------------------------------------- 1 | module Conekta 2 | module Util 3 | def self.types 4 | @types ||= { 5 | 'webhook' => Webhook, 6 | 'webhook_log' => WebhookLog, 7 | 'bank_transfer_payout_method' => Method, 8 | 'payout' => Payout, 9 | 'payee' => Payee, 10 | 'payout_method' => PayoutMethod, 11 | 'bank_transfer_payment' => PaymentMethod, 12 | 'card_payment' => PaymentMethod, 13 | 'cash_payment' => PaymentMethod, 14 | 'charge' => Charge, 15 | 'customer' => Customer, 16 | 'card' => Card, 17 | 'subscription' => Subscription, 18 | 'plan' => Plan, 19 | 'token' => Token, 20 | 'event' => Event 21 | } 22 | end 23 | def self.convert_to_conekta_object(name,resp) 24 | if resp.kind_of?(Hash) 25 | if resp.has_key?('object') and types[resp['object']] 26 | instance = types[resp['object']].new() 27 | instance.load_from(resp) 28 | return instance 29 | elsif name.instance_of? String 30 | name = "event_data" if camelize(name) == "Data" 31 | name = "obj" if camelize(name) == "Object" 32 | if !Object.const_defined?(camelize(name)) 33 | instance = Object.const_set(camelize(name), Class.new(ConektaObject)).new 34 | else 35 | instance = constantize(camelize(name)).new 36 | end 37 | instance.load_from(resp) 38 | return instance 39 | end 40 | end 41 | if resp.kind_of?(Array) 42 | instance = ConektaObject.new 43 | instance.load_from(resp) 44 | if !resp.empty? and resp.first.instance_of? Hash and !resp.first["object"] 45 | resp.each_with_index do |r, i| 46 | obj = convert_to_conekta_object(name,r) 47 | instance.set_val(i,obj) 48 | instance[i] = obj 49 | end 50 | end 51 | return instance 52 | end 53 | return instance 54 | end 55 | protected 56 | def self.camelize(str) 57 | str.split('_').map{|e| e.capitalize}.join 58 | end 59 | def self.constantize(camel_cased_word) 60 | names = camel_cased_word.split('::') 61 | 62 | # Trigger a builtin NameError exception including the ill-formed constant in the message. 63 | Object.const_get(camel_cased_word) if names.empty? 64 | 65 | # Remove the first blank element in case of '::ClassName' notation. 66 | names.shift if names.size > 1 && names.first.empty? 67 | 68 | names.inject(Object) do |constant, name| 69 | if constant == Object 70 | constant.const_get(name) 71 | else 72 | candidate = constant.const_get(name) 73 | next candidate if constant.const_defined?(name, false) 74 | next candidate unless Object.const_defined?(name) 75 | 76 | # Go down the ancestors to check it it's owned 77 | # directly before we reach Object or the end of ancestors. 78 | constant = constant.ancestors.inject do |const, ancestor| 79 | break const if ancestor == Object 80 | break ancestor if ancestor.const_defined?(name, false) 81 | const 82 | end 83 | 84 | # owner is in Object, so raise 85 | constant.const_get(name, false) 86 | end 87 | end 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/ssl_data/ca_bundle.crt: -------------------------------------------------------------------------------- 1 | #Bundled Digicerts 2 | DigiCert Assured ID Root CA 3 | =========================== 4 | -----BEGIN CERTIFICATE----- 5 | MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG 6 | EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw 7 | IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx 8 | MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL 9 | ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew 10 | ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO 11 | 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy 12 | UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW 13 | /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy 14 | oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf 15 | GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF 16 | 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq 17 | hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc 18 | EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn 19 | SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i 20 | 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe 21 | +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== 22 | -----END CERTIFICATE----- 23 | 24 | DigiCert Global Root CA 25 | ======================= 26 | -----BEGIN CERTIFICATE----- 27 | MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG 28 | EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw 29 | HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw 30 | MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 31 | dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq 32 | hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn 33 | TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 34 | BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H 35 | 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y 36 | 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB 37 | o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm 38 | 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF 39 | BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr 40 | EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt 41 | tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 42 | UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk 43 | CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= 44 | -----END CERTIFICATE----- 45 | 46 | DigiCert High Assurance EV Root CA 47 | ================================== 48 | -----BEGIN CERTIFICATE----- 49 | MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG 50 | EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw 51 | KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw 52 | MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ 53 | MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu 54 | Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t 55 | Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS 56 | OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 57 | MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ 58 | NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe 59 | h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB 60 | Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY 61 | JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ 62 | V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp 63 | myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK 64 | mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe 65 | vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K 66 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /spec/conekta/customer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Conekta::Customer do 4 | let(:customer_data) { { :cards => ["tok_test_visa_4242"] } } 5 | 6 | context "creating customers" do 7 | it "successful customer create" do 8 | customer = Conekta::Customer.create(customer_data) 9 | expect(customer).to be_a(Conekta::Customer) 10 | end 11 | 12 | it "successful customer create" do 13 | expect { Conekta::Customer.create( 14 | :cards => ["tok_test_visa_4241"] 15 | ) }.to raise_error( 16 | Conekta::ResourceNotFoundError, 17 | "Object tok_test_visa_4241 could not be found." 18 | ) 19 | end 20 | end 21 | 22 | context "getting customers" do 23 | it "successful customer get" do 24 | transaction = Conekta::Customer.create(customer_data) 25 | customer = Conekta::Customer.find(transaction.id) 26 | expect(customer).to be_a(Conekta::Customer) 27 | end 28 | 29 | it "successful customer where" do 30 | customers = Conekta::Customer.where 31 | expect(customers.class.class_name).to eq("ConektaObject") 32 | expect(customers.first).to be_a(Conekta::Customer) 33 | end 34 | end 35 | 36 | context "updating customers" do 37 | it "successful customer update" do 38 | customer = Conekta::Customer.create({ 39 | :cards => ["tok_test_visa_4242"], 40 | }) 41 | customer.update({name: 'Logan', email: 'logan@x-men.org'}) 42 | expect(customer.name).to eq('Logan') 43 | end 44 | end 45 | 46 | context "deleting customers" do 47 | it "successful customer delete" do 48 | customer = Conekta::Customer.create(customer_data) 49 | customer.delete 50 | expect(customer.deleted).to eq(true) 51 | end 52 | end 53 | 54 | context "adding cards" do 55 | let!(:customer) { Conekta::Customer.create(customer_data) } 56 | 57 | it "add card to customer" do 58 | card = customer.create_card(:token => 'tok_test_visa_1881') 59 | expect(customer.cards.count).to eq(2) 60 | expect(customer.cards.last.last4).to eq('1881') 61 | end 62 | 63 | it "test delete card" do 64 | card = customer.cards[0].delete 65 | expect(card.deleted).to eq(true) 66 | end 67 | 68 | it "test update card" do 69 | customer.cards[0].update(token: 'tok_test_mastercard_4444', active: false) 70 | expect(customer.cards[0].last4).to eq('4444') 71 | end 72 | end 73 | 74 | context "managing subscriptions" do 75 | let!(:customer) { Conekta::Customer.create(customer_data) } 76 | 77 | context "create" do 78 | it "test succesful create subscription" do 79 | subscription = customer.create_subscription({plan: 'gold-plan'}) 80 | expect(subscription.class.class_name).to eq('Subscription') 81 | end 82 | 83 | it "test unsuccesful create subscription" do 84 | expect { customer.create_subscription({plan: 'unexistent-plan'}) }.to \ 85 | raise_error( 86 | Conekta::ResourceNotFoundError, 87 | "Object Plan unexistent-plan could not be found." 88 | ) 89 | end 90 | end 91 | 92 | context "update" do 93 | it "test succesful update subscription" do 94 | subscription = customer.create_subscription({plan: 'gold-plan'}) 95 | plan = find_or_create_plan('gold-plan2') 96 | 97 | subscription.update({plan: plan.id}) 98 | expect(subscription.plan_id).to eq('gold-plan2') 99 | end 100 | end 101 | 102 | context "pause/resume" do 103 | let!(:subscription) { customer.create_subscription({plan: 'gold-plan'}) } 104 | 105 | it "test succesful pause subscription" do 106 | subscription.pause 107 | expect(subscription.status).to eq('paused') 108 | end 109 | 110 | it "test succesful resume subscription" do 111 | subscription.pause 112 | expect(subscription.status).to eq('paused') 113 | subscription.resume 114 | expect(subscription.status).to_not eq('paused') 115 | end 116 | end 117 | 118 | context "cancel" do 119 | it "test succesful cancel subscription" do 120 | subscription = customer.create_subscription({plan: 'gold-plan'}) 121 | subscription.cancel 122 | expect(subscription.status).to eq('canceled') 123 | end 124 | end 125 | end 126 | end 127 | 128 | def find_or_create_plan(plan_id) 129 | plan = Conekta::Plan.find(plan_id) 130 | rescue Conekta::Error => e 131 | plan = Conekta::Plan.create({ 132 | id: plan_id, 133 | name: "Gold Plan", 134 | amount: 10000, 135 | currency: "MXN", 136 | interval: "month", 137 | frequency: 1, 138 | trial_period_days: 15, 139 | expiry_count: 12 140 | }) 141 | return plan 142 | end 143 | --------------------------------------------------------------------------------