Skip to content

Ruby client for Zuora SOAP and REST APIs

License

Notifications You must be signed in to change notification settings

contactually/zuora-ruby

Repository files navigation

Build Status Code Climate

Zuora SOAP and REST API Client

Features

  • HTTP client to Zuora SOAP and REST API
  • Authentication and session storage
  • SOAP XML request constructors from Ruby data
  • Light validation of top-level forms; field-level validation delegated to Zuora's responses.

Usage

Client

Creating a client to both SOAP and REST API is easy:

client = Zuora::Client.new(<username>, <password>)

This will cache the login credentials (don't worry, they're excluded from being logged). Upon using methods requiring SOAP or REST client, that client is lazily authenticated against the respective API. The resulting session is cached and used in subsequent requests.

It's possible to use the clients directly:

soap_client = Zuora::Soap::Client.new(<username>, <password>)
rest_client = Zuora::Rest::Client.new(<username>, <password>)

SOAP Calls

Soap calls are made using the call! method. The argument structure varies depending on the SOAP method. See specs for exact interfaces.

client.call! :create, type: :Invoice, objects: [{...}, {...}]
client.call! :update, type: :Invoice, objects: [{...}, {...}]
client.call! :delete, type: :Invoice, ids: [{...}, {...}]
client.call! :generate, objects: [{...}, {...}]
client.call! :query, "SELECT Notes FROM Account WHERE id = '1'"
client.call! :query, [:notes], :Account, {id: 1}
client.call! :amend, 
  amendments: {...}, 
  amend_options: {...}, 
  preview_options: {} 
client.call! :subscribe,
  payment_method: {...}
  bill_to_contact: {...}
  sold_to_contact: {...}
  subscribe_options: {...}
  subscription: {...}
  rate_plan: {...}

SOAP requests return a Zuora::Response object that parses the XML response into Ruby data via the #to_h method. The raw request is available via the #raw method.

REST

client.get('/rest/v1/accounts/1')
client.delete('/rest/v1/accounts/1')
client.post('/rest/v1/accounts', notes: 'hello')
client.put('/rest/v1/accounts/1', id: 1, notes: 'world')

REST requests return a Farraday::Response object, which has a body and status. See Farraday docs for details.

SOAP Create Example

response = client.call! :create,
 type: :BillRun,
 objects: [{ 
   invoice_date: '2016-03-01',
   target_date: '2016-03-01'
 }]
   

This would generate SOAP XML, make, and return an authenticated SOAP request.

    <?xml version="1.0"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:api="http://api.zuora.com/" xmlns:obj="http://object.api.zuora.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Header>
        <api:SessionHeader>
          <api:session><!-- SESSION TOKEN HERE --></api:session>
        </api:SessionHeader>
      </soapenv:Header>
      <soapenv:Body>
        <api:create>
          <api:zObjects xsi:type="obj:BillRun">
            <obj:InvoiceDate>2016-03-01</obj:InvoiceDate>
            <obj:TargetDate>2016-03-01</obj:TargetDate>
          </api:zObjects>
        </api:create>
      </soapenv:Body>
    </soapenv:Envelope>

A response object is returned, having status and body

response.body
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <api:createResponse xmlns:api="http://api.zuora.com/">
      <api:result>
        <api:Id>2c92c0f9526913e301526a7863df4647</api:Id>
        <api:Success>true</api:Success>
      </api:result>
    </api:createResponse>
  </soapenv:Body>
</soapenv:Envelope>

This XML body, in turn, could be parsed with Nokogiri for further work.

response_xml = Nokogiri::XML(response.body)
success = response_xml.xpath(
 '/soapenv/Envelope/soapenv:Body/api:createResponse/api:result/api:Success'
 ).text == 'true'

Subscribe Example

Subscribe is a very large call that involves a lot of data. See the integration spec spec/zuora/integration/subscription_spec for full example

response = client.call! :subscribe, 
 account: {...},
 payment_method: {...},
 bill_to_contact: {...},
 sold_to_contact: {...},
 subscription: {...},
 rate_plan: {...}

Changelog

  • [0.5.0 2016-05-12] Uniform REST and SOAP client

    • Generalizes the client to work for both REST and SOAP APIs. In practice, both are useful to access the gamut of Zuora's operations. SOAP is better for fine-grained control, while REST is larger-grained and shifts the burden of transactions onto Zuora for certain operations.
    • Adds integration specs to cover REST GET, POST, PUT, DELETE
    • Errors are thrown for unsuccessful responses
    • Prevents credentials from being logged
    • SOAP Query call: now with arity-1 and arity-3 versions, pass a ZOQL query as string or as data. See docs and specs for details.
    • Add support for queryMore for result sets greater than 2000 in size
  • [0.4.0 2016-02-10] Improves interface and feedback loop between developer and Zuora servers.

    • Allow flexible submission of parameters to the API. Let Zuora's API handle validation instead of performing in the client.
    • Adds integration specs to cover base functionality
    • Adds exception raising to match servier-side exceptions such as missing required fields, invalid data, etc.
  • [0.3.0 2016-1-28] Focus on SOAP API, simplify client library feature set

    • Implement SOAP API Client; it provides fuller functionality than REST
    • Focus on constructing + composing hash-like Ruby objects into XML SOAP requests
    • No object-level validations; relies on Zuora's own responses
    • See integration specs for full interface
  • [0.2.0] - 2016-01-14] Models

    • Refactored client to clarify logic
    • Replaces ActiveRecord::Model and ::Validations with a base module that provides powerful and extensible facilities for modeling remote resources in Ruby.
      • required attributes, coercions, validations, type checking
      • dirty attribute tracking
      • extensible predicate library
    • Implements fine-grained validations per Zuora spec
    • Removes invalid model state paradigm used via ActiveModel in version 0.1.0.
    • A model now performs its validations on .new, and will raise a detailed exception on mistyped, invalid or uncoercable data.
    • Adds VCR for mocking out HTTP requests
    • Adds integration specs for Subscribe create! and update! and Account create! and update!
  • [0.1.0 - 2016-01-12] Initial release

Commit rights

Anyone who has a patch accepted may request commit rights. Please do so inside the pull request post-merge.

Contributors

License

MIT License. Copyright 2016 Contactually, Inc. http://contactually.com