Permalink
Browse files

Initial Import

  • Loading branch information...
Josh Martin
Josh Martin committed Feb 28, 2012
0 parents commit 35a6399545bd685b5054f1adcd401721e7c35190
Showing with 4,760 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +7 −0 Gemfile
  3. +86 −0 Gemfile.lock
  4. +65 −0 README.md
  5. +73 −0 Rakefile
  6. +29 −0 TODO
  7. +15 −0 lib/zuora.rb
  8. +94 −0 lib/zuora/api.rb
  9. +43 −0 lib/zuora/associations.rb
  10. +180 −0 lib/zuora/attributes.rb
  11. +43 −0 lib/zuora/config.rb
  12. +14 −0 lib/zuora/core_ext/string.rb
  13. +13 −0 lib/zuora/fault.rb
  14. +30 −0 lib/zuora/objects.rb
  15. +33 −0 lib/zuora/objects/account.rb
  16. +28 −0 lib/zuora/objects/amendment.rb
  17. +214 −0 lib/zuora/objects/base.rb
  18. +14 −0 lib/zuora/objects/communication_profile.rb
  19. +30 −0 lib/zuora/objects/contact.rb
  20. +20 −0 lib/zuora/objects/credit_balance_adjustment.rb
  21. +58 −0 lib/zuora/objects/invoice.rb
  22. +44 −0 lib/zuora/objects/invoice_adjustment.rb
  23. +35 −0 lib/zuora/objects/invoice_item.rb
  24. +50 −0 lib/zuora/objects/invoice_item_adjustment.rb
  25. +18 −0 lib/zuora/objects/invoice_payment.rb
  26. +41 −0 lib/zuora/objects/payment.rb
  27. +99 −0 lib/zuora/objects/payment_method.rb
  28. +16 −0 lib/zuora/objects/product.rb
  29. +14 −0 lib/zuora/objects/product_rate_plan.rb
  30. +53 −0 lib/zuora/objects/product_rate_plan_charge.rb
  31. +18 −0 lib/zuora/objects/product_rate_plan_charge_tier.rb
  32. +19 −0 lib/zuora/objects/rate_plan.rb
  33. +84 −0 lib/zuora/objects/rate_plan_charge.rb
  34. +21 −0 lib/zuora/objects/rate_plan_charge_tier.rb
  35. +35 −0 lib/zuora/objects/refund.rb
  36. +18 −0 lib/zuora/objects/refund_invoice_payment.rb
  37. +156 −0 lib/zuora/objects/subscribe_request.rb
  38. +39 −0 lib/zuora/objects/subscription.rb
  39. +27 −0 lib/zuora/objects/usage.rb
  40. +39 −0 lib/zuora/session.rb
  41. +41 −0 lib/zuora/validations.rb
  42. +13 −0 lib/zuora/version.rb
  43. +15 −0 spec/factories/accounts.rb
  44. +5 −0 spec/factories/contacts.rb
  45. +32 −0 spec/factories/payment_methods.rb
  46. +7 −0 spec/factories/product_rate_plan_charge_tiers.rb
  47. +16 −0 spec/factories/product_rate_plan_charges.rb
  48. +7 −0 spec/factories/product_rate_plans.rb
  49. +12 −0 spec/factories/products.rb
  50. +5 −0 spec/factories/subscriptions.rb
  51. +1 −0 spec/fixtures/responses/account_contacts_find_success.xml
  52. +1 −0 spec/fixtures/responses/account_create_failure.xml
  53. +1 −0 spec/fixtures/responses/account_create_success.xml
  54. +1 −0 spec/fixtures/responses/account_delete_success.xml
  55. +1 −0 spec/fixtures/responses/account_find_success.xml
  56. +1 −0 spec/fixtures/responses/account_query_multiple_success.xml
  57. +1 −0 spec/fixtures/responses/account_update_success.xml
  58. +1 −0 spec/fixtures/responses/contact_find_success.xml
  59. +1 −0 spec/fixtures/responses/invalid_login.xml
  60. +2 −0 spec/fixtures/responses/payment_method_ach_create_success.xml
  61. +1 −0 spec/fixtures/responses/payment_method_ach_find_success.xml
  62. +1 −0 spec/fixtures/responses/payment_method_credit_card_create_success.xml
  63. +1 −0 spec/fixtures/responses/payment_method_credit_card_find_success.xml
  64. +1 −0 spec/fixtures/responses/product_find_success.xml
  65. +1 −0 spec/fixtures/responses/product_rate_plan_charge_create_success.xml
  66. +1 −0 spec/fixtures/responses/product_rate_plan_charge_destroy_success.xml
  67. +1 −0 spec/fixtures/responses/product_rate_plan_charge_tier_find_success.xml
  68. +1 −0 spec/fixtures/responses/product_rate_plan_charge_update_success.xml
  69. +1 −0 spec/fixtures/responses/product_rate_plan_find_success.xml
  70. +1 −0 spec/fixtures/responses/subscribe_request_failure.xml
  71. +1 −0 spec/fixtures/responses/subscribe_request_success.xml
  72. +1 −0 spec/fixtures/responses/valid_login.xml
  73. +51 −0 spec/integration/account_management_spec.rb
  74. +16 −0 spec/integration/product_catalog_spec.rb
  75. +55 −0 spec/integration/subscription_spec.rb
  76. +16 −0 spec/spec_helper.rb
  77. +14 −0 spec/support/active_model_lint.rb
  78. +9 −0 spec/support/fixture.rb
  79. +8 −0 spec/support/integration.rb
  80. +17 −0 spec/support/mock_response.rb
  81. +42 −0 spec/support/xml_matcher.rb
  82. +64 −0 spec/zuora/api_spec.rb
  83. +20 −0 spec/zuora/config_spec.rb
  84. +30 −0 spec/zuora/fault_spec.rb
  85. +216 −0 spec/zuora/objects/account_spec.rb
  86. +19 −0 spec/zuora/objects/amendment_spec.rb
  87. +42 −0 spec/zuora/objects/contact_spec.rb
  88. +20 −0 spec/zuora/objects/invoice_spec.rb
  89. +126 −0 spec/zuora/objects/payment_method_spec.rb
  90. +120 −0 spec/zuora/objects/product_rate_plan_charge_spec.rb
  91. +13 −0 spec/zuora/objects/product_rate_plan_charge_tier_spec.rb
  92. +127 −0 spec/zuora/objects/subscribe_request_spec.rb
  93. +35 −0 spec/zuora/session_spec.rb
  94. +53 −0 spec/zuora/validations_spec.rb
  95. +7 −0 spec/zuora/version_spec.rb
  96. +1,513 −0 wsdl/zuora.a.38.0.wsdl
  97. +32 −0 zuora.gemspec
@@ -0,0 +1,4 @@
+doc
+.yardoc
+.rvmrc
+zuora.log
@@ -0,0 +1,7 @@
+source "http://rubygems.org"
+
+gemspec
+
+gem 'fattr', :git => 'https://github.com/kitop/fattr.git'
+gem 'wasabi', :git => 'git://github.com/skiz/wasabi.git'
+
@@ -0,0 +1,86 @@
+GIT
+ remote: git://github.com/skiz/wasabi.git
+ revision: 3cf323635717df9aab42340d3f48b304356c113e
+ specs:
+ wasabi (2.0.0)
+ nokogiri (>= 1.4.0)
+
+GIT
+ remote: https://github.com/kitop/fattr.git
+ revision: 705578ba4555ae480f82e7ecd0c16851fe8aec1d
+ specs:
+ fattr (2.1.0)
+
+PATH
+ remote: .
+ specs:
+ zuora (0.0.1)
+ activemodel (~> 3.1.0)
+ activesupport (~> 3.1.0)
+ libxml4r (~> 0.2.6)
+ savon (~> 0.9.8)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activemodel (3.1.3)
+ activesupport (= 3.1.3)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activesupport (3.1.3)
+ multi_json (~> 1.0)
+ akami (1.0.0)
+ gyoku (>= 0.4.0)
+ artifice (0.6)
+ rack-test
+ builder (3.0.0)
+ diff-lcs (1.1.3)
+ factory_girl (2.3.2)
+ activesupport
+ gyoku (0.4.4)
+ builder (>= 2.1.2)
+ httpi (0.9.5)
+ rack
+ i18n (0.6.0)
+ libxml-ruby (2.2.2)
+ libxml4r (0.2.6)
+ libxml-ruby (>= 1.1.3)
+ multi_json (1.1.0)
+ nokogiri (1.5.0)
+ nori (1.1.0)
+ rack (1.4.1)
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rake (0.8.7)
+ redcarpet (2.1.0)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.8.0)
+ savon (0.9.8)
+ akami (~> 1.0)
+ builder (>= 2.1.2)
+ gyoku (>= 0.4.0)
+ httpi (~> 0.9)
+ nokogiri (>= 1.4.0)
+ nori (~> 1.0)
+ wasabi (~> 2.0)
+ yard (0.7.5)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ artifice (~> 0.6.0)
+ factory_girl (~> 2.3.2)
+ fattr!
+ rake (~> 0.8.7)
+ redcarpet (~> 2.1.0)
+ rspec (~> 2.8.0)
+ wasabi!
+ yard (~> 0.7.5)
+ zuora!
@@ -0,0 +1,65 @@
+# Zuora
+
+This library allows you to interact with [Zuora](http://www.zuora.com) billing platform directly using
+familiar [ActiveModel](https://github.com/rails/rails/tree/master/activemodel) based objects.
+
+## Requirements
+ * [bundler](https://github.com/carlhuda/bundler)
+ * [active_support](https://github.com/rails/rails/tree/master/activesupport)
+ * [savon](https://github.com/rubiii/savon)
+ * [wasabi](https://github.com/rubiii/wasabi)
+
+All additional requirements for development should be referenced in the provided zuora.gemspec and Gemfile.
+
+## Installation
+
+ git clone git@github.com:wildfireapp/zuora.git
+
+## Getting Started
+
+ $ bundle install
+ $ bundle exec irb -rzuora
+
+ Zuora.configure(:username => 'USER', :password => 'PASS')
+
+ account = Zuora::Objects::Account.create(:account_number => '12345')
+ # => <Zuora::Objects::Account :account_number => 12345, :id => 'abc123'>
+ Zuora::Objects::Account.find('abc123')
+ # => <Zuora::Objects::Account :account_number => 12345, :id => 'abc123'>
+ account.destroy
+ # => true
+
+## Documentation
+ You can generate up to date documentation with the provided a rake task.
+
+ $ rake doc
+ $ open doc/index.html
+
+## Advanced Usage
+ Review the generated documentation for usage patterns and examples of using specific zObjects.
+
+## Test Suite
+ This library comes with a full test suite, which can be run using the stanard rake utility.
+
+ $ rake spec
+
+## Live Integration Suite
+ There is also a live suite which you can test against your sandbox account.
+ This can by ran by setting up your credentials and running the integration suite.
+
+ **Do not run this suite using your production credentials. Doing so may destroy
+ data although every precaution has been made to avoid any destructive behavior.**
+
+ $ ZUORA_USER=login ZUORA_PASS=password rake spec:integrations
+
+## Support & Maintenance
+ This library currently supports Zuora's SOAP API version 36.
+
+## Contributors
+ * Josh Martin <josh.martin@wildfireapp.com>
+ * Alex Reyes <alex.reyes@wildfireapp.com>
+
+## Credits
+ * [Wildfire Ineractive](http://www.wildfireapp.com) for facilitating the development and maintenance of the project.
+ * [Zuora](http://www.zuora.com) for providing us with the opportunity to share this library with the community.
+
@@ -0,0 +1,73 @@
+require 'bundler'
+Bundler.setup
+require 'rspec/core/rake_task'
+
+desc 'Default: run library specs.'
+task :default => :spec
+
+desc "Run library specs"
+RSpec::Core::RakeTask.new do |t|
+ t.pattern = ["./spec/zuora/**/*_spec.rb"]
+end
+
+namespace :spec do
+ desc "Run LIVE integration specs"
+ RSpec::Core::RakeTask.new do |t|
+ t.name = 'integrations'
+ t.pattern = "./spec/integration/*_spec.rb"
+ end
+end
+
+desc "Generate documentation"
+task :doc => ['doc:generate']
+
+namespace :doc do
+ project_root = File.expand_path(File.dirname(__FILE__))
+ doc_destination = File.join(project_root, 'doc')
+
+ begin
+ require 'yard'
+ require 'yard/rake/yardoc_task'
+
+ YARD::Rake::YardocTask.new(:generate) do |yt|
+ yt.files = Dir.glob(File.join(project_root, 'lib', '**', '*.rb')) +
+ [ File.join(project_root, 'README.md') ]
+ yt.options = ['--output-dir', doc_destination, '--readme', 'README.md']
+ end
+ rescue LoadError
+ desc "Generate YARD Documentation"
+ task :generate do
+ abort "Please install the YARD gem to generate rdoc."
+ end
+ end
+
+ desc "Remove generated documenation"
+ task :clean do
+ rm_r doc_destination if File.exists?(doc_destination)
+ end
+
+end
+
+task = ARGV.first
+if task && ENV['FORCE'] != 'true'
+ if task == 'spec:integrations'
+ puts <<-END.gsub(/^[ ]+/, '')
+ ****************************************************************************
+ * WARNING! This task runs agsinst the remote service. The credentials
+ * you provided as environment variables for ZUORA_USER and ZUORA_PASS will
+ * be used to connect to the remote service and make changes to the system.
+ *
+ * This may DESTROY your PRODUCTION data! Please verify that you are using
+ * a sandbox account before continuing.
+ *
+ * If you know what you are doing you can run this task with FORCE=true to
+ * prevent this message from appearing.
+ ****************************************************************************
+
+ Are you sure you want to continue? (Yes|No) [No]
+ END
+ confirmation = STDIN.gets.chomp.downcase
+ puts('Quitting.') || exit unless ['yes','y'].include?(confirmation.downcase)
+ end
+end
+
29 TODO
@@ -0,0 +1,29 @@
+Configuration System
+ [ ] System options via Zuora.configure (:ztax, :customer_acceptance)
+
+Object Modeling
+ [ ] Spec coverage for all objects and mock responses (confirm modeling)
+ [ ] Attempt to map error messages to specific attributes instead of Base (no keys are provided)
+
+Internals
+ [ ] Consider providing to_xml for objects as there are several complex nesting strategies related to subscriptions
+ [ ] Restructure Zuora::Attributes module to be less invasive
+ [ ] Read only attribute methods should probably be protected, however they are used on initialization from remote sources.
+ [ ] Handle HTTP errors gracefully in API module
+ [ ] Reconsider Zuora::Fault implementation
+ [ ] Create a "ZOQL" module that will generate queries and use this intead of inline ZOQL genration
+ [ ] Casting support for required types when the API wants date/datetime/etc
+ [ ] Base#has_many should support "#{assoc}=" method for resetting the collection
+ [ ] Custom attributes cannot be defined in the WSDL unless it is external to the library. (Implement support via config)
+ [ ] Custom default attributes are defined as dirty on instantiation, they should be defaulted but unchanged.
+ [ ] Nested objects such as SubscribeRequests do not change new_record/dirty for nested objects.
+
+
+External Resources
+ [ ] Savon should support mapped type definitions via Nori (Base#parse_attributes)
+ [ ] Get pull requests accepted for dependencies (currently skiz/wasabi)
+
+Review Notes
+ [ ] Invoices dates are procs? / invalid by default
+ [ ] Subscription Object spec
+ [ ] Tokens should be used for unique identifiers on account names/etc instead of incrementals.
@@ -0,0 +1,15 @@
+require 'savon'
+require 'active_model'
+require 'active_support/core_ext'
+
+require 'zuora/core_ext/string'
+require 'zuora/version'
+require 'zuora/config'
+require 'zuora/fault'
+require 'zuora/session'
+require 'zuora/api'
+require 'zuora/validations'
+require 'zuora/associations'
+require 'zuora/attributes'
+require 'zuora/objects'
+
@@ -0,0 +1,94 @@
+require 'singleton'
+require 'savon'
+
+module Zuora
+
+ # Configure Zuora by passing in an options hash. This must be done before
+ # you can use any of the Zuora::Object models.
+ # @example
+ # Zuora.configure(:username => 'USERNAME', :password => 'PASSWORD')
+ # @param [Hash] configuration option hash
+ # @return [Config]
+ def self.configure(opts={})
+ Api.instance.config = Config.new(opts)
+ HTTPI.logger = opts[:logger]
+ HTTPI.log = opts[:logger] ? true : false
+ Savon.configure do |savon|
+ savon.logger = opts[:logger]
+ savon.log = opts[:logger] ? true : false
+ end
+ end
+
+ class Api
+ include Singleton
+ # @return [Savon::Client]
+ attr_accessor :client
+
+ # @return [Zuora::Session]
+ attr_accessor :session
+
+ # @return [Zuora::Config]
+ attr_accessor :config
+
+ WSDL = File.expand_path('../../../wsdl/zuora.a.38.0.wsdl', __FILE__)
+
+ # Is this an authenticated session?
+ # @return [Boolean]
+ def authenticated?
+ self.session.try(:active?)
+ end
+
+ # The XML that was transmited in the last request
+ # @return [String]
+ def last_request
+ client.http.body
+ end
+
+ # Generate an API request with the given block. The block yields an xml
+ # builder instance which can be used to build out the request as needed.
+ # You can also provide the xml_body which will be used instead of the block.
+ # @param [Symbol] symbol of the WSDL operation to call
+ # @param [String] string xml body pass to the operation
+ # @yield [Builder] xml builder instance
+ # @raise [Zuora::Fault]
+ def request(method, xml_body=nil, &block)
+ authenticate! unless authenticated?
+
+ response = client.request(method) do
+ soap.header = {'env:SessionHeader' => {'ins0:Session' => self.session.try(:key) }}
+ if block_given?
+ soap.body{|xml| yield xml }
+ else
+ soap.body = xml_body
+ end
+ end
+ rescue Savon::SOAP::Fault, IOError => e
+ raise Zuora::Fault.new(:message => e.message)
+ end
+
+ # Attempt to authenticate against Zuora and initialize the Zuora::Session object
+ # Upon failure a Zoura::Fault will be raised.
+ # @raise [Zuora::Fault]
+ def authenticate!
+ response = client.request(:login){ soap.body = {:username => config.username, :password => config.password} }
+ self.session = Zuora::Session.generate(response.to_hash)
+ rescue Savon::SOAP::Fault => e
+ raise Zuora::Fault.new(:message => e.message)
+ end
+
+ private
+
+ def initialize
+ Savon.configure do |savon|
+ savon.soap_version = 2
+ end
+
+ self.client = Savon::Client.new do
+ wsdl.document = WSDL
+ http.auth.ssl.verify_mode = :none
+ end
+ end
+
+ end
+end
+
Oops, something went wrong.

0 comments on commit 35a6399

Please sign in to comment.