[
  {
    "path": ".document",
    "content": "README.rdoc\nlib/**/*.rb\nbin/*\nfeatures/**/*.feature\nLICENSE\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: nov\n"
  },
  {
    "path": ".gitignore",
    "content": "## MAC OS\n.DS_Store\n\n## TEXTMATE\n*.tmproj\ntmtags\n\n## EMACS\n*~\n\\#*\n.\\#*\n\n## VIM\n*.swp\n\n## PROJECT::GENERAL\ncoverage*\nrdoc\npkg\n\n## PROJECT::SPECIFIC\nGemfile.lock\n"
  },
  {
    "path": ".rspec",
    "content": "--color\n--format=documentation\n"
  },
  {
    "path": ".travis.yml",
    "content": "before_install:\n  - gem install bundler\n\nrvm:\n  - 2.0.0\n  - 2.1.2"
  },
  {
    "path": "Gemfile",
    "content": "source 'http://rubygems.org'\n\nplatform :jruby do\n  gem 'jruby-openssl', '>= 0.7'\nend\n\ngemspec"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2011 nov matake\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.rdoc",
    "content": "= paypal-express\n\nHandle PayPal Express Checkout.\nBoth Instance Payment and Recurring Payment are supported.\nExpress Checkout for Digital Goods is also supported.\n\n{<img src=\"https://secure.travis-ci.org/nov/paypal-express.png\" />}[http://travis-ci.org/nov/paypal-express]\n\n== Installation\n\n  gem install paypal-express\n\n== Usage\n\nSee Wiki on Github\nhttps://github.com/nov/paypal-express/wiki\n\nPlay with Sample Rails App\nhttps://github.com/nov/paypal-express-sample\nhttps://paypal-express-sample.heroku.com\n\n== Note on Patches/Pull Requests\n\n* Fork the project.\n* Make your feature addition or bug fix.\n* Add tests for it. This is important so I don't break it in a\n  future version unintentionally.\n* Commit, do not mess with rakefile, version, or history.\n  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)\n* Send me a pull request. Bonus points for topic branches.\n\n== Copyright\n\nCopyright (c) 2011 nov matake. See LICENSE for details."
  },
  {
    "path": "Rakefile",
    "content": "require 'bundler'\nBundler::GemHelper.install_tasks\n\nrequire 'rspec/core/rake_task'\nRSpec::Core::RakeTask.new(:spec)\n\nnamespace :coverage do\n  desc \"Open coverage report\"\n  task :report do\n    require 'simplecov'\n    `open \"#{File.join SimpleCov.coverage_path, 'index.html'}\"`\n  end\nend\n\ntask :spec do\n  Rake::Task[:'coverage:report'].invoke unless ENV['TRAVIS_RUBY_VERSION']\nend\n\ntask :default => :spec"
  },
  {
    "path": "VERSION",
    "content": "0.8.1"
  },
  {
    "path": "lib/paypal/base.rb",
    "content": "module Paypal\n  class Base\n    include AttrRequired, AttrOptional, Util\n\n    def initialize(attributes = {})\n      if attributes.is_a?(Hash)\n        (required_attributes + optional_attributes).each do |key|\n          value = if numeric_attribute?(key)\n            Util.to_numeric(attributes[key])\n          else\n            attributes[key]\n          end\n          self.send \"#{key}=\", value\n        end\n      end\n      attr_missing!\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/exception/api_error.rb",
    "content": "module Paypal\n  class Exception\n    class APIError < Exception\n      attr_accessor :response\n      def initialize(response = {})\n        @response = if response.is_a?(Hash)\n          Response.new response\n        else\n          response\n        end\n      end\n\n      def message\n        if response.respond_to?(:short_messages) && response.short_messages.any?\n          \"PayPal API Error: \" <<\n            response.short_messages.map{ |m| \"'#{m}'\" }.join(\", \")\n        else\n          \"PayPal API Error\"\n        end\n      end\n\n      class Response\n        cattr_reader :attribute_mapping\n        @@attribute_mapping = {\n          :ACK => :ack,\n          :BUILD => :build,\n          :CORRELATIONID => :correlation_id,\n          :TIMESTAMP => :timestamp,\n          :VERSION => :version,\n          :ORDERTIME => :order_time,\n          :PENDINGREASON => :pending_reason,\n          :PAYMENTSTATUS => :payment_status,\n          :PAYMENTTYPE => :payment_type,\n          :REASONCODE => :reason_code,\n          :TRANSACTIONTYPE => :transaction_type\n        }\n        attr_accessor *@@attribute_mapping.values\n        attr_accessor :raw, :details\n        alias_method :colleration_id, :correlation_id # NOTE: I made a typo :p\n\n        class Detail\n          cattr_reader :attribute_mapping\n          @@attribute_mapping = {\n            :ERRORCODE => :error_code,\n            :SEVERITYCODE => :severity_code,\n            :LONGMESSAGE => :long_message,\n            :SHORTMESSAGE => :short_message\n          }\n          attr_accessor *@@attribute_mapping.values\n\n          def initialize(attributes = {})\n            @raw = attributes\n            attrs = attributes.dup\n            @@attribute_mapping.each do |key, value|\n              self.send \"#{value}=\", attrs.delete(key)\n            end\n\n            # warn ignored params\n            attrs.each do |key, value|\n              Paypal.log \"Ignored Parameter (#{self.class}): #{key}=#{value}\", :warn\n            end\n          end\n        end\n\n        def initialize(attributes = {})\n          attrs = attributes.dup\n          @raw = attributes\n          @@attribute_mapping.each do |key, value|\n            self.send \"#{value}=\", attrs.delete(key)\n          end\n          details = []\n          attrs.keys.each do |attribute|\n            key, index = attribute.to_s.scan(/^L_(\\S+)(\\d+)$/).first\n            next if [key, index].any?(&:blank?)\n            details[index.to_i] ||= {}\n            details[index.to_i][key.to_sym] = attrs.delete(attribute)\n          end\n          @details = details.collect do |_attrs_|\n            Detail.new _attrs_\n          end\n\n          # warn ignored params\n          attrs.each do |key, value|\n            Paypal.log \"Ignored Parameter (#{self.class}): #{key}=#{value}\", :warn\n          end\n        end\n\n        def short_messages\n          details.map(&:short_message).compact\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/exception/http_error.rb",
    "content": "module Paypal\n  class Exception\n    class HttpError < Exception\n      attr_accessor :code, :message, :body\n      def initialize(code, message, body = '')\n        @code = code\n        @message = message\n        @body = body\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/exception.rb",
    "content": "module Paypal\n  class Exception < StandardError\n  end\nend"
  },
  {
    "path": "lib/paypal/express/request.rb",
    "content": "module Paypal\n  module Express\n    class Request < NVP::Request\n\n      # Common\n\n      def setup(payment_requests, return_url, cancel_url, options = {})\n        params = {\n          :RETURNURL => return_url,\n          :CANCELURL => cancel_url\n        }\n        if options[:no_shipping]\n          params[:REQCONFIRMSHIPPING] = 0\n          params[:NOSHIPPING] = 1\n        end\n\n        params[:ALLOWNOTE] = 0 if options[:allow_note] == false\n\n        {\n          :solution_type => :SOLUTIONTYPE,\n          :landing_page  => :LANDINGPAGE,\n          :email         => :EMAIL,\n          :brand         => :BRANDNAME,\n          :locale        => :LOCALECODE,\n          :logo          => :LOGOIMG,\n          :cart_border_color => :CARTBORDERCOLOR,\n          :payflow_color => :PAYFLOWCOLOR\n        }.each do |option_key, param_key|\n          params[param_key] = options[option_key] if options[option_key]\n        end\n        Array(payment_requests).each_with_index do |payment_request, index|\n          params.merge! payment_request.to_params(index)\n        end\n        response = self.request :SetExpressCheckout, params\n        Response.new response, options\n      end\n\n      def details(token)\n        response = self.request :GetExpressCheckoutDetails, {:TOKEN => token}\n        Response.new response\n      end\n\n      def transaction_details(transaction_id)\n        response = self.request :GetTransactionDetails, {:TRANSACTIONID=> transaction_id}\n        Response.new response\n      end\n\n      def checkout!(token, payer_id, payment_requests)\n        params = {\n          :TOKEN => token,\n          :PAYERID => payer_id\n        }\n        Array(payment_requests).each_with_index do |payment_request, index|\n          params.merge! payment_request.to_params(index)\n        end\n        response = self.request :DoExpressCheckoutPayment, params\n        Response.new response\n      end\n\n      def capture!(authorization_id, amount, currency_code, complete_type = 'Complete')\n        params = {\n          :AUTHORIZATIONID => authorization_id,\n          :COMPLETETYPE => complete_type,\n          :AMT => amount,\n          :CURRENCYCODE => currency_code\n        }\n\n        response = self.request :DoCapture, params\n        Response.new response\n      end\n\n      def void!(authorization_id, params={})\n        params = {\n          :AUTHORIZATIONID => authorization_id,\n          :NOTE => params[:note]\n        }\n\n        response = self.request :DoVoid, params\n        Response.new response\n      end\n\n      # Recurring Payment Specific\n\n      def subscribe!(token, recurring_profile)\n        params = {\n          :TOKEN => token\n        }\n        params.merge! recurring_profile.to_params\n        response = self.request :CreateRecurringPaymentsProfile, params\n        Response.new response\n      end\n\n      def subscription(profile_id)\n        params = {\n          :PROFILEID => profile_id\n        }\n        response = self.request :GetRecurringPaymentsProfileDetails, params\n        Response.new response\n      end\n\n      def renew!(profile_id, action, options = {})\n        params = {\n          :PROFILEID => profile_id,\n          :ACTION => action\n        }\n        if options[:note]\n          params[:NOTE] = options[:note]\n        end\n        response = self.request :ManageRecurringPaymentsProfileStatus, params\n        Response.new response\n      end\n\n      def suspend!(profile_id, options = {})\n        renew!(profile_id, :Suspend, options)\n      end\n\n      def cancel!(profile_id, options = {})\n        renew!(profile_id, :Cancel, options)\n      end\n\n      def reactivate!(profile_id, options = {})\n        renew!(profile_id, :Reactivate, options)\n      end\n\n\n      # Reference Transaction Specific\n\n      def agree!(token, options = {})\n        params = {\n          :TOKEN => token\n        }\n        if options[:max_amount]\n          params[:MAXAMT] = Util.formatted_amount options[:max_amount]\n        end\n        response = self.request :CreateBillingAgreement, params\n        Response.new response\n      end\n\n      def agreement(reference_id)\n        params = {\n          :REFERENCEID => reference_id\n        }\n        response = self.request :BillAgreementUpdate, params\n        Response.new response\n      end\n\n      def charge!(reference_id, amount, options = {})\n        params = {\n          :REFERENCEID => reference_id,\n          :AMT => Util.formatted_amount(amount),\n          :PAYMENTACTION => options[:payment_action] || :Sale\n        }\n        if options[:currency_code]\n          params[:CURRENCYCODE] = options[:currency_code]\n        end\n        response = self.request :DoReferenceTransaction, params\n        Response.new response\n      end\n\n      def revoke!(reference_id)\n        params = {\n          :REFERENCEID => reference_id,\n          :BillingAgreementStatus => :Canceled\n        }\n        response = self.request :BillAgreementUpdate, params\n        Response.new response\n      end\n\n\n      # Refund Specific\n\n      def refund!(transaction_id, options = {})\n        params = {\n          :TRANSACTIONID => transaction_id,\n          :REFUNDTYPE => :Full\n        }\n        if options[:invoice_id]\n          params[:INVOICEID] = options[:invoice_id]\n        end\n        if options[:type]\n          params[:REFUNDTYPE] = options[:type]\n          params[:AMT] = options[:amount]\n          params[:CURRENCYCODE] = options[:currency_code]\n        end\n        if options[:note]\n          params[:NOTE] = options[:note]\n        end\n        response = self.request :RefundTransaction, params\n        Response.new response\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/express/response.rb",
    "content": "module Paypal\n  module Express\n    class Response < NVP::Response\n      attr_accessor :pay_on_paypal, :mobile\n\n      def initialize(response, options = {})\n        super response\n        @pay_on_paypal = options[:pay_on_paypal]\n        @mobile        = options[:mobile]\n      end\n\n      def redirect_uri\n        endpoint = URI.parse Paypal.endpoint\n        endpoint.query = query(:with_cmd).to_query\n        endpoint.to_s\n      end\n\n      def popup_uri\n        endpoint = URI.parse Paypal.popup_endpoint\n        endpoint.query = query.to_query\n        endpoint.to_s\n      end\n\n      private\n\n      def query(with_cmd = false)\n        _query_ = {:token => self.token}\n        _query_.merge!(:cmd => '_express-checkout')        if with_cmd\n        _query_.merge!(:cmd => '_express-checkout-mobile') if mobile\n        _query_.merge!(:useraction => 'commit')            if pay_on_paypal\n        _query_\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/express.rb",
    "content": "require 'paypal'"
  },
  {
    "path": "lib/paypal/ipn.rb",
    "content": "module Paypal\n  module IPN\n    def self.endpoint\n      _endpoint_ = URI.parse Paypal.endpoint\n      _endpoint_.query = {\n        :cmd => '_notify-validate'\n      }.to_query\n      _endpoint_.to_s\n    end\n\n    def self.verify!(raw_post)\n      response = RestClient.post(\n        endpoint, raw_post\n      )\n      case response.body\n      when 'VERIFIED'\n        true\n      else\n        raise Exception::APIError.new(response.body)\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/nvp/request.rb",
    "content": "module Paypal\n  module NVP\n    class Request < Base\n      attr_required :username, :password, :signature\n      attr_optional :subject\n      attr_accessor :version\n\n      ENDPOINT = {\n        :production => 'https://api-3t.paypal.com/nvp',\n        :sandbox => 'https://api-3t.sandbox.paypal.com/nvp'\n      }\n\n      def self.endpoint\n        if Paypal.sandbox?\n          ENDPOINT[:sandbox]\n        else\n          ENDPOINT[:production]\n        end\n      end\n\n      def initialize(attributes = {})\n        @version = Paypal.api_version\n        super\n      end\n\n      def common_params\n        {\n          :USER => self.username,\n          :PWD => self.password,\n          :SIGNATURE => self.signature,\n          :SUBJECT => self.subject,\n          :VERSION => self.version\n        }\n      end\n\n      def request(method, params = {})\n        handle_response do\n          post(method, params)\n        end\n      end\n\n      private\n\n      def post(method, params)\n        RestClient.post(self.class.endpoint, common_params.merge(params).merge(:METHOD => method))\n      end\n\n      def handle_response\n        response = yield\n        response = CGI.parse(response).inject({}) do |res, (k, v)|\n          res.merge!(k.to_sym => v.first)\n        end\n        case response[:ACK]\n        when 'Success', 'SuccessWithWarning'\n          response\n        else\n          raise Exception::APIError.new(response)\n        end\n      rescue RestClient::Exception => e\n        raise Exception::HttpError.new(e.http_code, e.message, e.http_body)\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/nvp/response.rb",
    "content": "module Paypal\n  module NVP\n    class Response < Base\n      cattr_reader :attribute_mapping\n      @@attribute_mapping = {\n        :ACK => :ack,\n        :BUILD => :build,\n        :BILLINGAGREEMENTACCEPTEDSTATUS => :billing_agreement_accepted_status,\n        :CHECKOUTSTATUS => :checkout_status,\n        :CORRELATIONID => :correlation_id,\n        :COUNTRYCODE => :country_code,\n        :CURRENCYCODE => :currency_code,\n        :DESC => :description,\n        :NOTIFYURL => :notify_url,\n        :TIMESTAMP => :timestamp,\n        :TOKEN => :token,\n        :VERSION => :version,\n        # Some of the attributes below are duplicates of what\n        # exists in the payment response, but paypal doesn't\n        # prefix these with PAYMENTREQUEST when issuing a\n        # GetTransactionDetails response.\n        :RECEIVEREMAIL => :receiver_email,\n        :RECEIVERID => :receiver_id,\n        :SUBJECT => :subject,\n        :TRANSACTIONID => :transaction_id,\n        :TRANSACTIONTYPE => :transaction_type,\n        :PAYMENTTYPE => :payment_type,\n        :ORDERTIME => :order_time,\n        :PAYMENTSTATUS => :payment_status,\n        :PENDINGREASON => :pending_reason,\n        :REASONCODE => :reason_code,\n        :PROTECTIONELIGIBILITY => :protection_eligibility,\n        :PROTECTIONELIGIBILITYTYPE => :protection_eligibility_type,\n        :ADDRESSOWNER => :address_owner,\n        :ADDRESSSTATUS => :address_status,\n        :INVNUM => :invoice_number,\n        :CUSTOM => :custom\n      }\n      attr_accessor *@@attribute_mapping.values\n      attr_accessor :shipping_options_is_default, :success_page_redirect_requested, :insurance_option_selected\n      attr_accessor :amount, :description, :ship_to, :bill_to, :payer, :recurring, :billing_agreement, :refund\n      attr_accessor :payment_responses, :payment_info, :items\n      alias_method :colleration_id, :correlation_id # NOTE: I made a typo :p\n\n      def initialize(attributes = {})\n        attrs = attributes.dup\n        @@attribute_mapping.each do |key, value|\n          self.send \"#{value}=\", attrs.delete(key)\n        end\n        @shipping_options_is_default = attrs.delete(:SHIPPINGOPTIONISDEFAULT) == 'true'\n        @success_page_redirect_requested = attrs.delete(:SUCCESSPAGEREDIRECTREQUESTED) == 'true'\n        @insurance_option_selected = attrs.delete(:INSURANCEOPTIONSELECTED) == 'true'\n        @amount = Payment::Common::Amount.new(\n          :total => attrs.delete(:AMT),\n          :item => attrs.delete(:ITEMAMT),\n          :handing => attrs.delete(:HANDLINGAMT),\n          :insurance => attrs.delete(:INSURANCEAMT),\n          :ship_disc => attrs.delete(:SHIPDISCAMT),\n          :shipping => attrs.delete(:SHIPPINGAMT),\n          :tax => attrs.delete(:TAXAMT),\n          :fee => attrs.delete(:FEEAMT)\n        )\n        @ship_to = Payment::Response::Address.new(\n          :owner => attrs.delete(:SHIPADDRESSOWNER),\n          :status => attrs.delete(:SHIPADDRESSSTATUS),\n          :name => attrs.delete(:SHIPTONAME),\n          :zip => attrs.delete(:SHIPTOZIP),\n          :street => attrs.delete(:SHIPTOSTREET),\n          :street2 => attrs.delete(:SHIPTOSTREET2),\n          :city => attrs.delete(:SHIPTOCITY),\n          :state => attrs.delete(:SHIPTOSTATE),\n          :country_code => attrs.delete(:SHIPTOCOUNTRYCODE),\n          :country_name => attrs.delete(:SHIPTOCOUNTRYNAME)\n        )\n        @bill_to = Payment::Response::Address.new(\n          :owner => attrs.delete(:ADDRESSID),\n          :status => attrs.delete(:ADDRESSSTATUS),\n          :name => attrs.delete(:BILLINGNAME),\n          :zip => attrs.delete(:ZIP),\n          :street => attrs.delete(:STREET),\n          :street2 => attrs.delete(:STREET2),\n          :city => attrs.delete(:CITY),\n          :state => attrs.delete(:STATE),\n          :country_code => attrs.delete(:COUNTRY)\n        )\n        if attrs[:PAYERID]\n          @payer = Payment::Response::Payer.new(\n            :identifier => attrs.delete(:PAYERID),\n            :status => attrs.delete(:PAYERSTATUS),\n            :first_name => attrs.delete(:FIRSTNAME),\n            :last_name => attrs.delete(:LASTNAME),\n            :email => attrs.delete(:EMAIL),\n            :company => attrs.delete(:BUSINESS)\n          )\n        end\n        if attrs[:PROFILEID]\n          @recurring = Payment::Recurring.new(\n            :identifier => attrs.delete(:PROFILEID),\n            # NOTE:\n            #  CreateRecurringPaymentsProfile returns PROFILESTATUS\n            #  GetRecurringPaymentsProfileDetails returns STATUS\n            :description => @description,\n            :status => attrs.delete(:STATUS) || attrs.delete(:PROFILESTATUS),\n            :start_date => attrs.delete(:PROFILESTARTDATE),\n            :name => attrs.delete(:SUBSCRIBERNAME),\n            :reference => attrs.delete(:PROFILEREFERENCE),\n            :auto_bill => attrs.delete(:AUTOBILLOUTAMT),\n            :max_fails => attrs.delete(:MAXFAILEDPAYMENTS),\n            :aggregate_amount => attrs.delete(:AGGREGATEAMT),\n            :aggregate_optional_amount => attrs.delete(:AGGREGATEOPTIONALAMT),\n            :final_payment_date => attrs.delete(:FINALPAYMENTDUEDATE)\n          )\n          if attrs[:BILLINGPERIOD]\n            @recurring.billing = Payment::Recurring::Billing.new(\n              :amount => @amount,\n              :currency_code => @currency_code,\n              :period => attrs.delete(:BILLINGPERIOD),\n              :frequency => attrs.delete(:BILLINGFREQUENCY),\n              :total_cycles => attrs.delete(:TOTALBILLINGCYCLES),\n              :trial => {\n                :period => attrs.delete(:TRIALBILLINGPERIOD),\n                :frequency => attrs.delete(:TRIALBILLINGFREQUENCY),\n                :total_cycles => attrs.delete(:TRIALTOTALBILLINGCYCLES),\n                :currency_code => attrs.delete(:TRIALCURRENCYCODE),\n                :amount => attrs.delete(:TRIALAMT),\n                :tax_amount => attrs.delete(:TRIALTAXAMT),\n                :shipping_amount => attrs.delete(:TRIALSHIPPINGAMT),\n                :paid => attrs.delete(:TRIALAMTPAID)\n              }\n            )\n          end\n          if attrs[:REGULARAMT]\n            @recurring.regular_billing = Payment::Recurring::Billing.new(\n              :amount => attrs.delete(:REGULARAMT),\n              :shipping_amount => attrs.delete(:REGULARSHIPPINGAMT),\n              :tax_amount => attrs.delete(:REGULARTAXAMT),\n              :currency_code => attrs.delete(:REGULARCURRENCYCODE),\n              :period => attrs.delete(:REGULARBILLINGPERIOD),\n              :frequency => attrs.delete(:REGULARBILLINGFREQUENCY),\n              :total_cycles => attrs.delete(:REGULARTOTALBILLINGCYCLES),\n              :paid => attrs.delete(:REGULARAMTPAID)\n            )\n            @recurring.summary = Payment::Recurring::Summary.new(\n              :next_billing_date => attrs.delete(:NEXTBILLINGDATE),\n              :cycles_completed => attrs.delete(:NUMCYCLESCOMPLETED),\n              :cycles_remaining => attrs.delete(:NUMCYCLESREMAINING),\n              :outstanding_balance => attrs.delete(:OUTSTANDINGBALANCE),\n              :failed_count => attrs.delete(:FAILEDPAYMENTCOUNT),\n              :last_payment_date => attrs.delete(:LASTPAYMENTDATE),\n              :last_payment_amount => attrs.delete(:LASTPAYMENTAMT)\n            )\n          end\n        end\n        if attrs[:BILLINGAGREEMENTID]\n          @billing_agreement = Payment::Response::Reference.new(\n            :identifier => attrs.delete(:BILLINGAGREEMENTID),\n            :description => attrs.delete(:BILLINGAGREEMENTDESCRIPTION),\n            :status => attrs.delete(:BILLINGAGREEMENTSTATUS)\n          )\n          billing_agreement_info = Payment::Response::Info.attribute_mapping.keys.inject({}) do |billing_agreement_info, key|\n            billing_agreement_info.merge! key => attrs.delete(key)\n          end\n          @billing_agreement.info = Payment::Response::Info.new billing_agreement_info\n          @billing_agreement.info.amount = @amount\n        end\n        if attrs[:REFUNDTRANSACTIONID]\n          @refund = Payment::Response::Refund.new(\n            :transaction_id => attrs.delete(:REFUNDTRANSACTIONID),\n            :amount => {\n              :total => attrs.delete(:TOTALREFUNDEDAMOUNT),\n              :fee => attrs.delete(:FEEREFUNDAMT),\n              :gross => attrs.delete(:GROSSREFUNDAMT),\n              :net => attrs.delete(:NETREFUNDAMT)\n            }\n          )\n        end\n\n        # payment_responses\n        payment_responses = []\n        attrs.keys.each do |_attr_|\n          prefix, index, key = case _attr_.to_s\n          when /^PAYMENTREQUEST/, /^PAYMENTREQUESTINFO/\n            _attr_.to_s.split('_')\n          when /^L_PAYMENTREQUEST/\n            _attr_.to_s.split('_')[1..-1]\n          end\n          if prefix\n            payment_responses[index.to_i] ||= {}\n            payment_responses[index.to_i][key.to_sym] = attrs.delete(_attr_)\n          end\n        end\n        @payment_responses = payment_responses.collect do |_attrs_|\n          Payment::Response.new _attrs_\n        end\n\n        # payment_info\n        payment_info = []\n        attrs.keys.each do |_attr_|\n          prefix, index, key = _attr_.to_s.split('_')\n          if prefix == 'PAYMENTINFO'\n            payment_info[index.to_i] ||= {}\n            payment_info[index.to_i][key.to_sym] = attrs.delete(_attr_)\n          end\n        end\n        @payment_info = payment_info.collect do |_attrs_|\n          Payment::Response::Info.new _attrs_\n        end\n\n        # payment_info\n        items = []\n        attrs.keys.each do |_attr_|\n          key, index = _attr_.to_s.scan(/^L_(.+?)(\\d+)$/).flatten\n          if index\n            items[index.to_i] ||= {}\n            items[index.to_i][key.to_sym] = attrs.delete(_attr_)\n          end\n        end\n        @items = items.collect do |_attrs_|\n          Payment::Response::Item.new _attrs_\n        end\n\n        # remove duplicated parameters\n        attrs.delete(:SHIPTOCOUNTRY) # NOTE: Same with SHIPTOCOUNTRYCODE\n        attrs.delete(:SALESTAX) # Same as TAXAMT\n\n        # warn ignored attrs\n        attrs.each do |key, value|\n          Paypal.log \"Ignored Parameter (#{self.class}): #{key}=#{value}\", :warn\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/payment/common/amount.rb",
    "content": "module Paypal\n  module Payment\n    module Common\n      class Amount < Base\n        attr_optional :total, :item, :fee, :handing, :insurance, :ship_disc, :shipping, :tax, :gross, :net\n\n        def numeric_attribute?(key)\n          true\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/payment/recurring/activation.rb",
    "content": "module Paypal\n  module Payment\n    class Recurring::Activation < Base\n      attr_optional :initial_amount, :failed_action\n\n      def to_params\n        {\n          :INITAMT => Util.formatted_amount(self.initial_amount),\n          :FAILEDINITAMTACTION => self.failed_action\n        }\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/recurring/billing.rb",
    "content": "module Paypal\n  module Payment\n    class Recurring::Billing < Base\n      attr_optional :period, :frequency, :paid, :currency_code, :total_cycles\n      attr_accessor :amount, :trial\n\n      def initialize(attributes = {})\n        @amount = if attributes[:amount].is_a?(Common::Amount)\n          attributes[:amount]\n        else\n          Common::Amount.new(\n            :total => attributes[:amount],\n            :tax => attributes[:tax_amount],\n            :shipping => attributes[:shipping_amount]\n          )\n        end\n        @trial = Recurring::Billing.new(attributes[:trial]) if attributes[:trial].present?\n        super\n      end\n\n      def to_params\n        trial_params = (trial.try(:to_params) || {}).inject({}) do |trial_params, (key, value)|\n          trial_params.merge(\n            :\"TRIAL#{key}\" => value\n          )\n        end\n        trial_params.merge(\n          :BILLINGPERIOD => self.period,\n          :BILLINGFREQUENCY => self.frequency,\n          :TOTALBILLINGCYCLES => self.total_cycles,\n          :AMT => Util.formatted_amount(self.amount.total),\n          :CURRENCYCODE => self.currency_code,\n          :SHIPPINGAMT => Util.formatted_amount(self.amount.shipping),\n          :TAXAMT => Util.formatted_amount(self.amount.tax)\n        )\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/recurring/summary.rb",
    "content": "module Paypal\n  module Payment\n    class Recurring::Summary < Base\n      attr_optional :next_billing_date, :cycles_completed, :cycles_remaining, :outstanding_balance, :failed_count, :last_payment_date, :last_payment_amount\n\n      def numeric_attribute?(key)\n        super || [:outstanding_balance, :failed_count].include?(key)\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/recurring.rb",
    "content": "module Paypal\n  module Payment\n    class Recurring < Base\n      attr_optional :start_date, :description, :identifier, :status, :name, :reference, :max_fails, :auto_bill, :aggregate_amount, :aggregate_optional_amount, :final_payment_date\n      attr_accessor :activation, :billing, :regular_billing, :summary\n\n      def initialize(attributes = {})\n        super\n        @activation = Activation.new attributes[:activation] if attributes[:activation]\n        @billing = Billing.new attributes[:billing] if attributes[:billing]\n        @regular_billing = Billing.new attributes[:regular_billing] if attributes[:regular_billing]\n        @summary = Summary.new attributes[:summary] if attributes[:summary]\n      end\n\n      def to_params\n        params = [\n          self.billing,\n          self.activation\n        ].compact.inject({}) do |params, attribute|\n          params.merge! attribute.to_params\n        end\n        if self.start_date.is_a?(Time)\n          self.start_date = self.start_date.to_s(:db)\n        end\n        params.merge!(\n          :DESC  => self.description,\n          :MAXFAILEDPAYMENTS => self.max_fails,\n          :AUTOBILLOUTAMT => self.auto_bill,\n          :PROFILESTARTDATE => self.start_date,\n          :SUBSCRIBERNAME => self.name,\n          :PROFILEREFERENCE => self.reference\n        )\n        params.delete_if do |k, v|\n          v.blank?\n        end\n      end\n\n      def numeric_attribute?(key)\n        super || [:max_fails, :failed_count].include?(key)\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/request/item.rb",
    "content": "module Paypal\n  module Payment\n    class Request::Item < Base\n      attr_optional :name, :description, :amount, :number, :quantity, :category, :url\n\n      def initialize(attributes = {})\n        super\n        @quantity ||= 1\n      end\n\n      def to_params(parent_index, index = 0)\n        {\n          :\"L_PAYMENTREQUEST_#{parent_index}_NAME#{index}\" => self.name,\n          :\"L_PAYMENTREQUEST_#{parent_index}_DESC#{index}\" => self.description,\n          :\"L_PAYMENTREQUEST_#{parent_index}_AMT#{index}\" => Util.formatted_amount(self.amount),\n          :\"L_PAYMENTREQUEST_#{parent_index}_NUMBER#{index}\" => self.number,\n          :\"L_PAYMENTREQUEST_#{parent_index}_QTY#{index}\" => self.quantity,\n          :\"L_PAYMENTREQUEST_#{parent_index}_ITEMCATEGORY#{index}\" => self.category,\n          :\"L_PAYMENTREQUEST_#{parent_index}_ITEMURL#{index}\" => self.url\n        }.delete_if do |k, v|\n          v.blank?\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/payment/request.rb",
    "content": "module Paypal\n  module Payment\n    class Request < Base\n      attr_optional :action, :currency_code, :description, :notify_url, :billing_type, :billing_agreement_description, :billing_agreement_id, :request_id, :seller_id, :invoice_number, :custom\n      attr_accessor :amount, :items, :custom_fields\n\n      def initialize(attributes = {})\n        @amount = if attributes[:amount].is_a?(Common::Amount)\n          attributes[:amount]\n        else\n          Common::Amount.new(\n            :total => attributes[:amount],\n            :tax => attributes[:tax_amount],\n            :shipping => attributes[:shipping_amount]\n          )\n        end\n        @items = []\n        Array(attributes[:items]).each do |item_attrs|\n          @items << Item.new(item_attrs)\n        end\n        @custom_fields = attributes[:custom_fields] || {}\n        super\n      end\n\n      def to_params(index = 0)\n        params = {\n          :\"PAYMENTREQUEST_#{index}_PAYMENTACTION\" => self.action,\n          :\"PAYMENTREQUEST_#{index}_AMT\" => Util.formatted_amount(self.amount.total),\n          :\"PAYMENTREQUEST_#{index}_TAXAMT\" => Util.formatted_amount(self.amount.tax),\n          :\"PAYMENTREQUEST_#{index}_SHIPPINGAMT\" => Util.formatted_amount(self.amount.shipping),\n          :\"PAYMENTREQUEST_#{index}_CURRENCYCODE\" => self.currency_code,\n          :\"PAYMENTREQUEST_#{index}_DESC\" => self.description,\n          :\"PAYMENTREQUEST_#{index}_INVNUM\" => self.invoice_number,\n          :\"PAYMENTREQUEST_#{index}_CUSTOM\" => self.custom,\n          # NOTE:\n          #  notify_url works only when DoExpressCheckoutPayment called.\n          #  recurring payment doesn't support dynamic notify_url.\n          :\"PAYMENTREQUEST_#{index}_NOTIFYURL\" => self.notify_url,\n          :\"L_BILLINGTYPE#{index}\" => self.billing_type,\n          :\"L_BILLINGAGREEMENTDESCRIPTION#{index}\" => self.billing_agreement_description,\n          # FOR PARALLEL PAYMENT\n          :\"PAYMENTREQUEST_#{index}_PAYMENTREQUESTID\" => self.request_id,\n          :\"PAYMENTREQUEST_#{index}_SELLERPAYPALACCOUNTID\" => self.seller_id\n        }.delete_if do |k, v|\n          v.blank?\n        end\n        if self.items.present?\n          params[:\"PAYMENTREQUEST_#{index}_ITEMAMT\"] = Util.formatted_amount(self.items_amount)\n          self.items.each_with_index do |item, item_index|\n            params.merge! item.to_params(index, item_index)\n          end\n        end\n        self.custom_fields.each do |key, value|\n          field = key.to_s.upcase.gsub(\"{N}\", index.to_s).to_sym\n          params[field] = value\n        end\n        params\n      end\n\n      def items_amount\n        self.items.sum do |item|\n          item.quantity * BigDecimal.new(item.amount.to_s)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/payment/response/address.rb",
    "content": "module Paypal\n  module Payment\n    class Response::Address < Base\n      attr_optional :owner, :status, :name, :zip, :street, :street2, :city, :state, :country_code, :country_name\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/response/info.rb",
    "content": "module Paypal\n  module Payment\n    class Response::Info < Base\n      cattr_reader :attribute_mapping\n      @@attribute_mapping = {\n        :ACK => :ack,\n        :CURRENCYCODE => :currency_code,\n        :ERRORCODE => :error_code,\n        :ORDERTIME => :order_time,\n        :PAYMENTSTATUS => :payment_status,\n        :PAYMENTTYPE => :payment_type,\n        :PENDINGREASON => :pending_reason,\n        :PROTECTIONELIGIBILITY => :protection_eligibility,\n        :PROTECTIONELIGIBILITYTYPE => :protection_eligibility_type,\n        :REASONCODE => :reason_code,\n        :RECEIPTID => :receipt_id,\n        :SECUREMERCHANTACCOUNTID => :secure_merchant_account_id,\n        :TRANSACTIONID => :transaction_id,\n        :TRANSACTIONTYPE => :transaction_type,\n        :PAYMENTREQUESTID => :request_id,\n        :SELLERPAYPALACCOUNTID => :seller_id,\n        :EXCHANGERATE => :exchange_rate\n      }\n      attr_accessor *@@attribute_mapping.values\n      attr_accessor :amount\n\n      def initialize(attributes = {})\n        attrs = attributes.dup\n        @@attribute_mapping.each do |key, value|\n          self.send \"#{value}=\", attrs.delete(key)\n        end\n        @amount = Common::Amount.new(\n          :total => attrs.delete(:AMT),\n          :fee => attrs.delete(:FEEAMT),\n          :tax => attrs.delete(:TAXAMT)\n        )\n\n        # warn ignored params\n        attrs.each do |key, value|\n          Paypal.log \"Ignored Parameter (#{self.class}): #{key}=#{value}\", :warn\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/payment/response/item.rb",
    "content": "module Paypal\n  module Payment\n    class Response::Item < Base\n      cattr_reader :attribute_mapping\n      @@attribute_mapping = {\n        :NAME => :name,\n        :DESC => :description,\n        :QTY => :quantity,\n        :NUMBER => :number,\n        :ITEMCATEGORY => :category,\n        :ITEMWIDTHVALUE => :width,\n        :ITEMHEIGHTVALUE => :height,\n        :ITEMLENGTHVALUE => :length,\n        :ITEMWEIGHTVALUE => :weight,\n        :SHIPPINGAMT => :shipping,\n        :HANDLINGAMT => :handling,\n        :CURRENCYCODE => :currency\n        \n      }\n      attr_accessor *@@attribute_mapping.values\n      attr_accessor :amount\n\n      def initialize(attributes = {})\n        attrs = attributes.dup\n        @@attribute_mapping.each do |key, value|\n          self.send \"#{value}=\", attrs.delete(key)\n        end\n        @quantity = @quantity.to_i\n        @amount = Common::Amount.new(\n          :total => attrs.delete(:AMT),\n          :tax => attrs.delete(:TAXAMT)\n        )\n\n        # warn ignored params\n        attrs.each do |key, value|\n          Paypal.log \"Ignored Parameter (#{self.class}): #{key}=#{value}\", :warn\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/payment/response/payer.rb",
    "content": "module Paypal\n  module Payment\n    class Response::Payer < Base\n      attr_optional :identifier, :status, :first_name, :last_name, :email, :company\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/response/reference.rb",
    "content": "module Paypal\n  module Payment\n    class Response::Reference < Base\n      attr_required :identifier\n      attr_optional :description, :status\n      attr_accessor :info\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/response/refund.rb",
    "content": "module Paypal\n  module Payment\n    class Response::Refund < Base\n      attr_optional :transaction_id\n      attr_accessor :amount\n\n      def initialize(attributes = {})\n        super\n        @amount = Common::Amount.new(attributes[:amount])\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/paypal/payment/response.rb",
    "content": "module Paypal\n  module Payment\n    class Response < Base\n      attr_accessor :amount, :ship_to, :bill_to, :description, :note, :items, :notify_url, :insurance_option_offered, :currency_code, :short_message, :long_message, :error_code, :severity_code, :ack, :transaction_id, :billing_agreement_id, :request_id, :seller_id\n\n      def initialize(attributes = {})\n        attrs = attributes.dup\n        @amount = Common::Amount.new(\n          :total => attrs.delete(:AMT),\n          :item => attrs.delete(:ITEMAMT),\n          :handing => attrs.delete(:HANDLINGAMT),\n          :insurance => attrs.delete(:INSURANCEAMT),\n          :ship_disc => attrs.delete(:SHIPDISCAMT),\n          :shipping => attrs.delete(:SHIPPINGAMT),\n          :tax => attrs.delete(:TAXAMT)\n        )\n        @ship_to = Payment::Response::Address.new(\n          :name => attrs.delete(:SHIPTONAME),\n          :zip => attrs.delete(:SHIPTOZIP),\n          :street => attrs.delete(:SHIPTOSTREET),\n          :street2 => attrs.delete(:SHIPTOSTREET2),\n          :city => attrs.delete(:SHIPTOCITY),\n          :state => attrs.delete(:SHIPTOSTATE),\n          :country_code => attrs.delete(:SHIPTOCOUNTRYCODE),\n          :country_name => attrs.delete(:SHIPTOCOUNTRYNAME)\n        )\n        @bill_to = Payment::Response::Address.new(\n          :owner => attrs.delete(:ADDRESSID),\n          :status => attrs.delete(:ADDRESSSTATUS),\n          :name => attrs.delete(:BILLINGNAME),\n          :zip => attrs.delete(:ZIP),\n          :street => attrs.delete(:STREET),\n          :street2 => attrs.delete(:STREET2),\n          :city => attrs.delete(:CITY),\n          :state => attrs.delete(:STATE),\n          :country_code => attrs.delete(:COUNTRY)\n        )\n        @description = attrs.delete(:DESC)\n        @note = attrs.delete(:NOTETEXT)\n        @notify_url = attrs.delete(:NOTIFYURL)\n        @insurance_option_offered = attrs.delete(:INSURANCEOPTIONOFFERED) == 'true'\n        @currency_code = attrs.delete(:CURRENCYCODE)\n        @short_message = attrs.delete(:SHORTMESSAGE)\n        @long_message = attrs.delete(:LONGMESSAGE)\n        @error_code = attrs.delete(:ERRORCODE)\n        @severity_code = attrs.delete(:SEVERITYCODE)\n        @ack = attrs.delete(:ACK)\n        @transaction_id = attrs.delete(:TRANSACTIONID)\n        @billing_agreement_id = attrs.delete(:BILLINGAGREEMENTID)\n        @request_id = attrs.delete(:PAYMENTREQUESTID)\n        @seller_id = attrs.delete(:SELLERPAYPALACCOUNTID)\n\n        # items\n        items = []\n        attrs.keys.each do |_attr_|\n          key, index = _attr_.to_s.scan(/^(.+?)(\\d+)$/).flatten\n          if index\n            items[index.to_i] ||= {}\n            items[index.to_i][key.to_sym] = attrs.delete(:\"#{key}#{index}\")\n          end\n        end\n        @items = items.collect do |_attr_|\n          Item.new(_attr_)\n        end\n\n        # warn ignored params\n        attrs.each do |key, value|\n          Paypal.log \"Ignored Parameter (#{self.class}): #{key}=#{value}\", :warn\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/paypal/util.rb",
    "content": "module Paypal\n  module Util\n\n    def self.formatted_amount(x)\n      # Thanks @nahi ;)\n      sprintf \"%0.2f\", BigDecimal.new(x.to_s).truncate(2)\n    end\n\n    def self.to_numeric(x)\n      if x.to_f == x.to_i\n        x.to_i\n      else\n        x.to_f\n      end\n    end\n\n    def numeric_attribute?(key)\n      !!(key.to_s =~ /(amount|frequency|cycles|paid)/)\n    end\n\n    def ==(other)\n      instance_variables.all? do |key|\n        instance_variable_get(key) == other.instance_variable_get(key)\n      end\n    end\n\n  end\nend"
  },
  {
    "path": "lib/paypal.rb",
    "content": "require 'logger'\nrequire 'active_support'\nrequire 'active_support/core_ext'\nrequire 'attr_required'\nrequire 'attr_optional'\nrequire 'rest_client'\n\nmodule Paypal\n  mattr_accessor :api_version\n  self.api_version = '88.0'\n\n  ENDPOINT = {\n    :production => 'https://www.paypal.com/cgi-bin/webscr',\n    :sandbox => 'https://www.sandbox.paypal.com/cgi-bin/webscr'\n  }\n  POPUP_ENDPOINT = {\n    :production => 'https://www.paypal.com/incontext',\n    :sandbox => 'https://www.sandbox.paypal.com/incontext'\n  }\n\n  def self.endpoint\n    if sandbox?\n      Paypal::ENDPOINT[:sandbox]\n    else\n      Paypal::ENDPOINT[:production]\n    end\n  end\n  def self.popup_endpoint\n    if sandbox?\n      Paypal::POPUP_ENDPOINT[:sandbox]\n    else\n      Paypal::POPUP_ENDPOINT[:production]\n    end\n  end\n\n  def self.log(message, mode = :info)\n    self.logger.send mode, message\n  end\n  def self.logger\n    @@logger\n  end\n  def self.logger=(logger)\n    @@logger = logger\n  end\n  @@logger = Logger.new(STDERR)\n  @@logger.progname = 'Paypal::Express'\n\n  def self.sandbox?\n    @@sandbox\n  end\n  def self.sandbox!\n    self.sandbox = true\n  end\n  def self.sandbox=(boolean)\n    @@sandbox = boolean\n  end\n  self.sandbox = false\n\nend\n\nrequire 'paypal/util'\nrequire 'paypal/exception'\nrequire 'paypal/exception/http_error'\nrequire 'paypal/exception/api_error'\nrequire 'paypal/base'\nrequire 'paypal/ipn'\nrequire 'paypal/nvp/request'\nrequire 'paypal/nvp/response'\nrequire 'paypal/payment/common/amount'\nrequire 'paypal/express/request'\nrequire 'paypal/express/response'\nrequire 'paypal/payment/request'\nrequire 'paypal/payment/request/item'\nrequire 'paypal/payment/response'\nrequire 'paypal/payment/response/info'\nrequire 'paypal/payment/response/item'\nrequire 'paypal/payment/response/payer'\nrequire 'paypal/payment/response/reference'\nrequire 'paypal/payment/response/refund'\nrequire 'paypal/payment/response/address'\nrequire 'paypal/payment/recurring'\nrequire 'paypal/payment/recurring/activation'\nrequire 'paypal/payment/recurring/billing'\nrequire 'paypal/payment/recurring/summary'\n"
  },
  {
    "path": "paypal-express.gemspec",
    "content": "Gem::Specification.new do |s|\n  s.name = \"paypal-express\"\n  s.version = File.read(File.join(File.dirname(__FILE__), \"VERSION\"))\n  s.required_rubygems_version = Gem::Requirement.new(\">= 1.3.6\") if s.respond_to? :required_rubygems_version=\n  s.authors = [\"nov matake\"]\n  s.description = %q{PayPal Express Checkout API Client for Instance, Recurring and Digital Goods Payment.}\n  s.summary = %q{PayPal Express Checkout API Client for Instance, Recurring and Digital Goods Payment.}\n  s.email = \"nov@matake.jp\"\n  s.extra_rdoc_files = [\"LICENSE\", \"README.rdoc\"]\n  s.rdoc_options = [\"--charset=UTF-8\"]\n  s.homepage = \"http://github.com/nov/paypal-express\"\n  s.require_paths = [\"lib\"]\n  s.executables = `git ls-files -- bin/*`.split(\"\\n\").map{ |f| File.basename(f) }\n  s.files = `git ls-files`.split(\"\\n\")\n  s.test_files = `git ls-files -- {test,spec,features}/*`.split(\"\\n\")\n  s.add_dependency \"activesupport\", \">= 2.3\"\n  s.add_dependency \"rest-client\"\n  s.add_dependency \"attr_required\", \">= 0.0.5\"\n  s.add_development_dependency \"rake\", \">= 0.8\"\n  s.add_development_dependency \"simplecov\"\n  s.add_development_dependency \"rspec\", \"< 2.99\"\n  s.add_development_dependency \"fakeweb\", \">= 1.3.0\"\nend\n"
  },
  {
    "path": "spec/fake_response/BillAgreementUpdate/fetch.txt",
    "content": "BILLINGAGREEMENTID=B%2d8XW15926RT2253736&BILLINGAGREEMENTDESCRIPTION=Reference%20Payment%20Agreement&BILLINGAGREEMENTSTATUS=Canceled&TIMESTAMP=2011%2d08%2d06T09%3a47%3a41Z&CORRELATIONID=28e5a24b3ea98&ACK=Success&VERSION=78%2e0&BUILD=2020243&EMAIL=client_1305381804_per%40matake%2ejp&PAYERID=CMJLWADKVFQYJ&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US"
  },
  {
    "path": "spec/fake_response/BillAgreementUpdate/revoke.txt",
    "content": "BILLINGAGREEMENTID=B%2d8XW15926RT2253736&BILLINGAGREEMENTDESCRIPTION=Reference%20Payment%20Agreement&BILLINGAGREEMENTSTATUS=Canceled&TIMESTAMP=2011%2d08%2d06T09%3a47%3a41Z&CORRELATIONID=28e5a24b3ea98&ACK=Success&VERSION=78%2e0&BUILD=2020243&EMAIL=client_1305381804_per%40matake%2ejp&PAYERID=CMJLWADKVFQYJ&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US"
  },
  {
    "path": "spec/fake_response/CreateBillingAgreement/success.txt",
    "content": "BILLINGAGREEMENTID=B%2d45776062X95244343&TIMESTAMP=2011%2d08%2d06T07%3a53%3a50Z&CORRELATIONID=9a16fde4456e1&ACK=Success&VERSION=78%2e0&BUILD=2020243"
  },
  {
    "path": "spec/fake_response/CreateRecurringPaymentsProfile/failure.txt",
    "content": "TIMESTAMP=2011%2d02%2d08T07%3a18%3a29Z&CORRELATIONID=fde1527b25b4f&ACK=Failure&VERSION=66%2e0&BUILD=1704252&L_ERRORCODE0=11502&L_SHORTMESSAGE0=Invalid%20Token&L_LONGMESSAGE0=The%20token%20is%20invalid&L_SEVERITYCODE0=Error"
  },
  {
    "path": "spec/fake_response/CreateRecurringPaymentsProfile/success.txt",
    "content": "PROFILEID=I%2dL8N58XFUCET3&PROFILESTATUS=ActiveProfile&TIMESTAMP=2011%2d02%2d08T07%3a17%3a51Z&CORRELATIONID=7d2e125f5ca63&ACK=Success&VERSION=66%2e0&BUILD=1704252"
  },
  {
    "path": "spec/fake_response/DoCapture/failure.txt",
    "content": "ACK=Failure&BUILD=8334781&CORRELATIONID=dd9e16358819b&L_ERRORCODE0=10609&L_LONGMESSAGE0=Transaction+id+is+invalid.&L_SEVERITYCODE0=Error&L_SHORTMESSAGE0=Invalid+transactionID.&TIMESTAMP=2013-11-05T17%3A43%3A56Z&VERSION=88.0\n"
  },
  {
    "path": "spec/fake_response/DoCapture/success.txt",
    "content": "ACK=Success&AMT=440.00&AUTHORIZATIONID=2RG78938NK8989844&BUILD=8334781&CORRELATIONID=311611c111b48&CURRENCYCODE=BRL&EXCHANGERATE=0.426354&FEEAMT=13.16&ORDERTIME=2013-11-05T17%3A34%3A56Z&PARENTTRANSACTIONID=2RG78938NK8989844&PAYMENTSTATUS=Completed&PAYMENTTYPE=instant&PENDINGREASON=None&PROTECTIONELIGIBILITY=Ineligible&PROTECTIONELIGIBILITYTYPE=None&REASONCODE=None&SETTLEAMT=181.98&TAXAMT=0.00&TIMESTAMP=2013-11-05T17%3A34%3A56Z&TRANSACTIONID=9VW4495267708531S&TRANSACTIONTYPE=expresscheckout&VERSION=88.0\n"
  },
  {
    "path": "spec/fake_response/DoExpressCheckoutPayment/failure.txt",
    "content": "TIMESTAMP=2011%2d02%2d08T07%3a15%3a19Z&CORRELATIONID=5dd0308345382&ACK=Failure&VERSION=66%2e0&BUILD=1721431&L_ERRORCODE0=10410&L_SHORTMESSAGE0=Invalid%20token&L_LONGMESSAGE0=Invalid%20token%2e&L_SEVERITYCODE0=Error"
  },
  {
    "path": "spec/fake_response/DoExpressCheckoutPayment/success.txt",
    "content": "TOKEN=EC-9E2743126S4330617&SUCCESSPAGEREDIRECTREQUESTED=false&TIMESTAMP=2011-02-08T03:23:55Z&CORRELATIONID=15b93874c358c&ACK=Success&VERSION=66.0&BUILD=1721431&INSURANCEOPTIONSELECTED=false&SHIPPINGOPTIONISDEFAULT=false&PAYMENTINFO_0_TRANSACTIONID=8NC65222871997739&PAYMENTINFO_0_TRANSACTIONTYPE=expresscheckout&PAYMENTINFO_0_PAYMENTTYPE=instant&PAYMENTINFO_0_ORDERTIME=2011-02-08T03:23:54Z&PAYMENTINFO_0_AMT=14.00&PAYMENTINFO_0_FEEAMT=0.85&PAYMENTINFO_0_TAXAMT=0.00&PAYMENTINFO_0_CURRENCYCODE=USD&PAYMENTINFO_0_PAYMENTSTATUS=Completed&PAYMENTINFO_0_PENDINGREASON=None&PAYMENTINFO_0_REASONCODE=None&PAYMENTINFO_0_PROTECTIONELIGIBILITY=Ineligible&PAYMENTINFO_0_PROTECTIONELIGIBILITYTYPE=None&PAYMENTINFO_0_ERRORCODE=0&PAYMENTINFO_0_ACK=Success"
  },
  {
    "path": "spec/fake_response/DoExpressCheckoutPayment/success_with_billing_agreement.txt",
    "content": "TOKEN=EC-9E2743126S4330617&SUCCESSPAGEREDIRECTREQUESTED=false&TIMESTAMP=2011-02-08T03:23:55Z&CORRELATIONID=15b93874c358c&ACK=Success&VERSION=66.0&BUILD=1721431&INSURANCEOPTIONSELECTED=false&SHIPPINGOPTIONISDEFAULT=false&PAYMENTINFO_0_TRANSACTIONID=8NC65222871997739&PAYMENTINFO_0_TRANSACTIONTYPE=expresscheckout&PAYMENTINFO_0_PAYMENTTYPE=instant&PAYMENTINFO_0_ORDERTIME=2011-02-08T03:23:54Z&PAYMENTINFO_0_AMT=14.00&PAYMENTINFO_0_FEEAMT=0.85&PAYMENTINFO_0_TAXAMT=0.00&PAYMENTINFO_0_CURRENCYCODE=USD&PAYMENTINFO_0_PAYMENTSTATUS=Completed&PAYMENTINFO_0_PENDINGREASON=None&PAYMENTINFO_0_REASONCODE=None&PAYMENTINFO_0_PROTECTIONELIGIBILITY=Ineligible&PAYMENTINFO_0_PROTECTIONELIGIBILITYTYPE=None&PAYMENTINFO_0_ERRORCODE=0&BILLINGAGREEMENTID=B-1XR87946TC504770W&PAYMENTINFO_0_ACK=Success"
  },
  {
    "path": "spec/fake_response/DoExpressCheckoutPayment/success_with_many_items.txt",
    "content": "TOKEN=EC%2d7HG122968U843864S&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2011%2d04%2d12T03%3a51%3a58Z&CORRELATIONID=6a0a92ea79ac3&ACK=Success&VERSION=69%2e0&BUILD=1824201&EMAIL=buyer_1297999636_per%40cerego%2ecom&PAYERID=9RWDTMRKKHQ8S&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US&CURRENCYCODE=USD&AMT=1000&ITEMAMT=1000&SHIPPINGAMT=0&HANDLINGAMT=0&TAXAMT=0&DESC=Instant%20Payment%20Request&NOTIFYURL=http%3a%2f%2fmerchant%2eexample%2ecom%2fnotify&INSURANCEAMT=0&SHIPDISCAMT=0&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE1=%20%20%200%2e00000&L_ITEMHEIGHTVALUE2=%20%20%200%2e00000&L_ITEMHEIGHTVALUE3=%20%20%200%2e00000&L_ITEMHEIGHTVALUE4=%20%20%200%2e00000&L_ITEMHEIGHTVALUE5=%20%20%200%2e00000&L_ITEMHEIGHTVALUE6=%20%20%200%2e00000&L_ITEMHEIGHTVALUE7=%20%20%200%2e00000&L_ITEMHEIGHTVALUE8=%20%20%200%2e00000&L_ITEMHEIGHTVALUE9=%20%20%200%2e00000&L_ITEMHEIGHTVALUE10=%20%20%200%2e00000&L_ITEMHEIGHTVALUE11=%20%20%200%2e00000&L_ITEMHEIGHTVALUE12=%20%20%200%2e00000&L_ITEMHEIGHTVALUE13=%20%20%200%2e00000&L_ITEMHEIGHTVALUE14=%20%20%200%2e00000&L_ITEMHEIGHTVALUE15=%20%20%200%2e00000&L_ITEMHEIGHTVALUE16=%20%20%200%2e00000&L_ITEMHEIGHTVALUE17=%20%20%200%2e00000&L_ITEMHEIGHTVALUE18=%20%20%200%2e00000&L_ITEMHEIGHTVALUE19=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE1=%20%20%200%2e00000&L_ITEMWIDTHVALUE2=%20%20%200%2e00000&L_ITEMWIDTHVALUE3=%20%20%200%2e00000&L_ITEMWIDTHVALUE4=%20%20%200%2e00000&L_ITEMWIDTHVALUE5=%20%20%200%2e00000&L_ITEMWIDTHVALUE6=%20%20%200%2e00000&L_ITEMWIDTHVALUE7=%20%20%200%2e00000&L_ITEMWIDTHVALUE8=%20%20%200%2e00000&L_ITEMWIDTHVALUE9=%20%20%200%2e00000&L_ITEMWIDTHVALUE10=%20%20%200%2e00000&L_ITEMWIDTHVALUE11=%20%20%200%2e00000&L_ITEMWIDTHVALUE12=%20%20%200%2e00000&L_ITEMWIDTHVALUE13=%20%20%200%2e00000&L_ITEMWIDTHVALUE14=%20%20%200%2e00000&L_ITEMWIDTHVALUE15=%20%20%200%2e00000&L_ITEMWIDTHVALUE16=%20%20%200%2e00000&L_ITEMWIDTHVALUE17=%20%20%200%2e00000&L_ITEMWIDTHVALUE18=%20%20%200%2e00000&L_ITEMWIDTHVALUE19=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE1=%20%20%200%2e00000&L_ITEMLENGTHVALUE2=%20%20%200%2e00000&L_ITEMLENGTHVALUE3=%20%20%200%2e00000&L_ITEMLENGTHVALUE4=%20%20%200%2e00000&L_ITEMLENGTHVALUE5=%20%20%200%2e00000&L_ITEMLENGTHVALUE6=%20%20%200%2e00000&L_ITEMLENGTHVALUE7=%20%20%200%2e00000&L_ITEMLENGTHVALUE8=%20%20%200%2e00000&L_ITEMLENGTHVALUE9=%20%20%200%2e00000&L_ITEMLENGTHVALUE10=%20%20%200%2e00000&L_ITEMLENGTHVALUE11=%20%20%200%2e00000&L_ITEMLENGTHVALUE12=%20%20%200%2e00000&L_ITEMLENGTHVALUE13=%20%20%200%2e00000&L_ITEMLENGTHVALUE14=%20%20%200%2e00000&L_ITEMLENGTHVALUE15=%20%20%200%2e00000&L_ITEMLENGTHVALUE16=%20%20%200%2e00000&L_ITEMLENGTHVALUE17=%20%20%200%2e00000&L_ITEMLENGTHVALUE18=%20%20%200%2e00000&L_ITEMLENGTHVALUE19=%20%20%200%2e00000&L_NAME0=Item0&L_NAME1=Item1&L_NAME2=Item2&L_NAME3=Item3&L_NAME4=Item4&L_NAME5=Item5&L_NAME6=Item6&L_NAME7=Item7&L_NAME8=Item8&L_NAME9=Item9&L_NAME10=Item10&L_NAME11=Item11&L_NAME12=Item12&L_NAME13=Item13&L_NAME14=Item14&L_NAME15=Item15&L_NAME16=Item16&L_NAME17=Item17&L_NAME18=Item18&L_NAME19=Item19&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMWEIGHTVALUE1=%20%20%200%2e00000&L_ITEMWEIGHTVALUE2=%20%20%200%2e00000&L_ITEMWEIGHTVALUE3=%20%20%200%2e00000&L_ITEMWEIGHTVALUE4=%20%20%200%2e00000&L_ITEMWEIGHTVALUE5=%20%20%200%2e00000&L_ITEMWEIGHTVALUE6=%20%20%200%2e00000&L_ITEMWEIGHTVALUE7=%20%20%200%2e00000&L_ITEMWEIGHTVALUE8=%20%20%200%2e00000&L_ITEMWEIGHTVALUE9=%20%20%200%2e00000&L_ITEMWEIGHTVALUE10=%20%20%200%2e00000&L_ITEMWEIGHTVALUE11=%20%20%200%2e00000&L_ITEMWEIGHTVALUE12=%20%20%200%2e00000&L_ITEMWEIGHTVALUE13=%20%20%200%2e00000&L_ITEMWEIGHTVALUE14=%20%20%200%2e00000&L_ITEMWEIGHTVALUE15=%20%20%200%2e00000&L_ITEMWEIGHTVALUE16=%20%20%200%2e00000&L_ITEMWEIGHTVALUE17=%20%20%200%2e00000&L_ITEMWEIGHTVALUE18=%20%20%200%2e00000&L_ITEMWEIGHTVALUE19=%20%20%200%2e00000&L_TAXAMT0=%20%20%200%2e00000&L_TAXAMT1=%20%20%200%2e00000&L_TAXAMT2=%20%20%200%2e00000&L_TAXAMT3=%20%20%200%2e00000&L_TAXAMT4=%20%20%200%2e00000&L_TAXAMT5=%20%20%200%2e00000&L_TAXAMT6=%20%20%200%2e00000&L_TAXAMT7=%20%20%200%2e00000&L_TAXAMT8=%20%20%200%2e00000&L_TAXAMT9=%20%20%200%2e00000&L_TAXAMT10=%20%20%200%2e00000&L_TAXAMT11=%20%20%200%2e00000&L_TAXAMT12=%20%20%200%2e00000&L_TAXAMT13=%20%20%200%2e00000&L_TAXAMT14=%20%20%200%2e00000&L_TAXAMT15=%20%20%200%2e00000&L_TAXAMT16=%20%20%200%2e00000&L_TAXAMT17=%20%20%200%2e00000&L_TAXAMT18=%20%20%200%2e00000&L_TAXAMT19=%20%20%200%2e00000&L_DESC0=A%20new%20Item%200&L_DESC1=A%20new%20Item%201&L_DESC2=A%20new%20Item%202&L_DESC3=A%20new%20Item%203&L_DESC4=A%20new%20Item%204&L_DESC5=A%20new%20Item%205&L_DESC6=A%20new%20Item%206&L_DESC7=A%20new%20Item%207&L_DESC8=A%20new%20Item%208&L_DESC9=A%20new%20Item%209&L_DESC10=A%20new%20Item%2010&L_DESC11=A%20new%20Item%2011&L_DESC12=A%20new%20Item%2012&L_DESC13=A%20new%20Item%2013&L_DESC14=A%20new%20Item%2014&L_DESC15=A%20new%20Item%2015&L_DESC16=A%20new%20Item%2016&L_DESC17=A%20new%20Item%2017&L_DESC18=A%20new%20Item%2018&L_DESC19=A%20new%20Item%2019&L_AMT0=50&L_AMT1=50&L_AMT2=50&L_AMT3=50&L_AMT4=50&L_AMT5=50&L_AMT6=50&L_AMT7=50&L_AMT8=50&L_AMT9=50&L_AMT10=50&L_AMT11=50&L_AMT12=50&L_AMT13=50&L_AMT14=50&L_AMT15=50&L_AMT16=50&L_AMT17=50&L_AMT18=50&L_AMT19=50&L_QTY0=1&L_QTY1=1&L_QTY2=1&L_QTY3=1&L_QTY4=1&L_QTY5=1&L_QTY6=1&L_QTY7=1&L_QTY8=1&L_QTY9=1&L_QTY10=1&L_QTY11=1&L_QTY12=1&L_QTY13=1&L_QTY14=1&L_QTY15=1&L_QTY16=1&L_QTY17=1&L_QTY18=1&L_QTY19=1&PAYMENTREQUEST_0_CURRENCYCODE=JPY&PAYMENTREQUEST_0_AMT=10&PAYMENTREQUEST_0_ITEMAMT=10&PAYMENTREQUEST_0_SHIPPINGAMT=0&PAYMENTREQUEST_0_HANDLINGAMT=0&PAYMENTREQUEST_0_TAXAMT=0&PAYMENTREQUEST_0_DESC=Instant%20Payment%20Request&PAYMENTREQUEST_0_NOTIFYURL=http%3a%2f%2fmerchant%2eexample%2ecom%2fnotify&PAYMENTREQUEST_0_INSURANCEAMT=0&PAYMENTREQUEST_0_SHIPDISCAMT=0&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE1=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE2=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE3=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE4=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE5=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE6=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE7=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE8=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE9=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE10=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE11=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE12=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE13=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE14=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE15=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE16=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE17=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE18=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE19=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE1=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE2=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE3=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE4=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE5=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE6=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE7=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE8=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE9=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE10=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE11=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE12=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE13=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE14=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE15=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE16=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE17=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE18=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE19=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE1=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE2=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE3=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE4=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE5=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE6=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE7=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE8=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE9=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE10=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE11=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE12=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE13=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE14=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE15=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE16=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE17=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE18=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE19=%20%20%200%2e00000&L_PAYMENTREQUEST_0_NAME0=Item0&L_PAYMENTREQUEST_0_NAME1=Item1&L_PAYMENTREQUEST_0_NAME2=Item2&L_PAYMENTREQUEST_0_NAME3=Item3&L_PAYMENTREQUEST_0_NAME4=Item4&L_PAYMENTREQUEST_0_NAME5=Item5&L_PAYMENTREQUEST_0_NAME6=Item6&L_PAYMENTREQUEST_0_NAME7=Item7&L_PAYMENTREQUEST_0_NAME8=Item8&L_PAYMENTREQUEST_0_NAME9=Item9&L_PAYMENTREQUEST_0_NAME10=Item10&L_PAYMENTREQUEST_0_NAME11=Item11&L_PAYMENTREQUEST_0_NAME12=Item12&L_PAYMENTREQUEST_0_NAME13=Item13&L_PAYMENTREQUEST_0_NAME14=Item14&L_PAYMENTREQUEST_0_NAME15=Item15&L_PAYMENTREQUEST_0_NAME16=Item16&L_PAYMENTREQUEST_0_NAME17=Item17&L_PAYMENTREQUEST_0_NAME18=Item18&L_PAYMENTREQUEST_0_NAME19=Item19&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE1=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE2=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE3=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE4=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE5=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE6=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE7=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE8=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE9=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE10=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE11=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE12=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE13=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE14=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE15=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE16=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE17=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE18=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE19=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT1=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT2=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT3=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT4=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT5=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT6=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT7=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT8=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT9=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT10=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT11=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT12=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT13=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT14=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT15=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT16=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT17=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT18=%20%20%200%2e00000&L_PAYMENTREQUEST_0_TAXAMT19=%20%20%200%2e00000&L_PAYMENTREQUEST_0_DESC0=A%20new%20Item%200&L_PAYMENTREQUEST_0_DESC1=A%20new%20Item%201&L_PAYMENTREQUEST_0_DESC2=A%20new%20Item%202&L_PAYMENTREQUEST_0_DESC3=A%20new%20Item%203&L_PAYMENTREQUEST_0_DESC4=A%20new%20Item%204&L_PAYMENTREQUEST_0_DESC5=A%20new%20Item%205&L_PAYMENTREQUEST_0_DESC6=A%20new%20Item%206&L_PAYMENTREQUEST_0_DESC7=A%20new%20Item%207&L_PAYMENTREQUEST_0_DESC8=A%20new%20Item%208&L_PAYMENTREQUEST_0_DESC9=A%20new%20Item%209&L_PAYMENTREQUEST_0_DESC10=A%20new%20Item%2010&L_PAYMENTREQUEST_0_DESC11=A%20new%20Item%2011&L_PAYMENTREQUEST_0_DESC12=A%20new%20Item%2012&L_PAYMENTREQUEST_0_DESC13=A%20new%20Item%2013&L_PAYMENTREQUEST_0_DESC14=A%20new%20Item%2014&L_PAYMENTREQUEST_0_DESC15=A%20new%20Item%2015&L_PAYMENTREQUEST_0_DESC16=A%20new%20Item%2016&L_PAYMENTREQUEST_0_DESC17=A%20new%20Item%2017&L_PAYMENTREQUEST_0_DESC18=A%20new%20Item%2018&L_PAYMENTREQUEST_0_DESC19=A%20new%20Item%2019&L_PAYMENTREQUEST_0_AMT0=50&L_PAYMENTREQUEST_0_AMT1=50&L_PAYMENTREQUEST_0_AMT2=50&L_PAYMENTREQUEST_0_AMT3=50&L_PAYMENTREQUEST_0_AMT4=50&L_PAYMENTREQUEST_0_AMT5=50&L_PAYMENTREQUEST_0_AMT6=50&L_PAYMENTREQUEST_0_AMT7=50&L_PAYMENTREQUEST_0_AMT8=50&L_PAYMENTREQUEST_0_AMT9=50&L_PAYMENTREQUEST_0_AMT10=50&L_PAYMENTREQUEST_0_AMT11=50&L_PAYMENTREQUEST_0_AMT12=50&L_PAYMENTREQUEST_0_AMT13=50&L_PAYMENTREQUEST_0_AMT14=50&L_PAYMENTREQUEST_0_AMT15=50&L_PAYMENTREQUEST_0_AMT16=50&L_PAYMENTREQUEST_0_AMT17=50&L_PAYMENTREQUEST_0_AMT18=50&L_PAYMENTREQUEST_0_AMT19=50&L_PAYMENTREQUEST_0_QTY0=1&L_PAYMENTREQUEST_0_QTY1=1&L_PAYMENTREQUEST_0_QTY2=1&L_PAYMENTREQUEST_0_QTY3=1&L_PAYMENTREQUEST_0_QTY4=1&L_PAYMENTREQUEST_0_QTY5=1&L_PAYMENTREQUEST_0_QTY6=1&L_PAYMENTREQUEST_0_QTY7=1&L_PAYMENTREQUEST_0_QTY8=1&L_PAYMENTREQUEST_0_QTY9=1&L_PAYMENTREQUEST_0_QTY10=1&L_PAYMENTREQUEST_0_QTY11=1&L_PAYMENTREQUEST_0_QTY12=1&L_PAYMENTREQUEST_0_QTY13=1&L_PAYMENTREQUEST_0_QTY14=1&L_PAYMENTREQUEST_0_QTY15=1&L_PAYMENTREQUEST_0_QTY16=1&L_PAYMENTREQUEST_0_QTY17=1&L_PAYMENTREQUEST_0_QTY18=1&L_PAYMENTREQUEST_0_QTY19=1&PAYMENTREQUESTINFO_0_ERRORCODE=0"
  },
  {
    "path": "spec/fake_response/DoReferenceTransaction/failure.txt",
    "content": "TIMESTAMP=2011%2d07%2d19T08%3a59%3a52Z&CORRELATIONID=ed8096a3c3d7d&ACK=Failure&VERSION=72%2e0&BUILD=1982348&L_ERRORCODE0=11451&L_SHORTMESSAGE0=Billing%20Agreement%20Id%20or%20transaction%20Id%20is%20not%20valid&L_LONGMESSAGE0=Billing%20Agreement%20Id%20or%20transaction%20Id%20is%20not%20valid&L_SEVERITYCODE0=Error&TRANSACTIONTYPE=None&PAYMENTTYPE=None&ORDERTIME=1970%2d01%2d01T00%3a00%3a00Z&PAYMENTSTATUS=None&PENDINGREASON=None&REASONCODE=None\n"
  },
  {
    "path": "spec/fake_response/DoReferenceTransaction/success.txt",
    "content": "BILLINGAGREEMENTID=B%2d7HU5U5U1ULU14U49E&TIMESTAMP=2011%2d07%2d19T08%3a30%3a08Z&CORRELATIONID=12ca85fb3c9d2&ACK=Success&VERSION=72%2e0&BUILD=1982348&TRANSACTIONID=3IV51111LY1211907&TRANSACTIONTYPE=merchtpmt&PAYMENTTYPE=instant&ORDERTIME=2011%2d07%2d19T08%3a30%3a06Z&AMT=192&FEEAMT=47&TAXAMT=0&CURRENCYCODE=JPY&PAYMENTSTATUS=Completed&PENDINGREASON=None&REASONCODE=None&PROTECTIONELIGIBILITY=Ineligible&PROTECTIONELIGIBILITYTYPE=None\n"
  },
  {
    "path": "spec/fake_response/DoVoid/success.txt",
    "content": "ACK=Success&AUTHORIZATIONID=1a2b3c4d5e6f&BUILD=13055236&TIMESTAMP=2014-10-03T17%3A34%3A56Z"
  },
  {
    "path": "spec/fake_response/GetExpressCheckoutDetails/failure.txt",
    "content": "TOKEN=EC%2d9E2743126S4330617&CHECKOUTSTATUS=PaymentActionCompleted&TIMESTAMP=2011%2d02%2d08T07%3a10%3a26Z&CORRELATIONID=8f5fddf13ed10&ACK=Failure&VERSION=66%2e0&BUILD=1721431&L_ERRORCODE0=10411&L_SHORTMESSAGE0=This%20Express%20Checkout%20session%20has%20expired%2e&L_LONGMESSAGE0=This%20Express%20Checkout%20session%20has%20expired%2e%20%20Token%20value%20is%20no%20longer%20valid%2e&L_SEVERITYCODE0=Error&EMAIL=valid_1296805890_per%40matake%2ejp&PAYERID=PRT3TZ6MCBCNC&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US&SHIPTONAME=Test%20User&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United%20States&ADDRESSSTATUS=Confirmed&CURRENCYCODE=USD&AMT=14%2e00&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_CURRENCYCODE=USD&PAYMENTREQUEST_0_AMT=14%2e00&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_TRANSACTIONID=8NC65222871997739&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Test%20User&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20St&PAYMENTREQUEST_0_SHIPTOCITY=San%20Jose&PAYMENTREQUEST_0_SHIPTOSTATE=CA&PAYMENTREQUEST_0_SHIPTOZIP=95131&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=US&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20States&PAYMENTREQUESTINFO_0_TRANSACTIONID=8NC65222871997739&PAYMENTREQUESTINFO_0_ERRORCODE=0"
  },
  {
    "path": "spec/fake_response/GetExpressCheckoutDetails/success.txt",
    "content": "TOKEN=EC%2d7HG122968U843864S&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2011%2d04%2d12T03%3a51%3a58Z&CORRELATIONID=6a0a92ea79ac3&ACK=Success&VERSION=69%2e0&BUILD=1824201&EMAIL=buyer_1297999636_per%40cerego%2ecom&PAYERID=9RWDTMRKKHQ8S&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US&CURRENCYCODE=JPY&AMT=10&ITEMAMT=10&SHIPPINGAMT=0&HANDLINGAMT=0&TAXAMT=0&DESC=Instant%20Payment%20Request&NOTIFYURL=http%3a%2f%2fmerchant%2eexample%2ecom%2fnotify&INSURANCEAMT=0&SHIPDISCAMT=0&L_NAME0=Item1&L_QTY0=1&L_TAXAMT0=0&L_AMT0=10&L_DESC0=Item1%20Desc&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&L_ITEMCATEGORY0=Digital&PAYMENTREQUEST_0_CURRENCYCODE=JPY&PAYMENTREQUEST_0_AMT=10&PAYMENTREQUEST_0_ITEMAMT=10&PAYMENTREQUEST_0_SHIPPINGAMT=0&PAYMENTREQUEST_0_HANDLINGAMT=0&PAYMENTREQUEST_0_TAXAMT=0&PAYMENTREQUEST_0_DESC=Instant%20Payment%20Request&PAYMENTREQUEST_0_NOTIFYURL=http%3a%2f%2fmerchant%2eexample%2ecom%2fnotify&PAYMENTREQUEST_0_INSURANCEAMT=0&PAYMENTREQUEST_0_SHIPDISCAMT=0&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&L_PAYMENTREQUEST_0_NAME0=Item1&L_PAYMENTREQUEST_0_QTY0=1&L_PAYMENTREQUEST_0_TAXAMT0=0&L_PAYMENTREQUEST_0_AMT0=10&L_PAYMENTREQUEST_0_DESC0=Item1%20Desc&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMCATEGORY0=Digital&PAYMENTREQUESTINFO_0_ERRORCODE=0"
  },
  {
    "path": "spec/fake_response/GetExpressCheckoutDetails/with_billing_accepted_status.txt",
    "content": "TOKEN=EC%2d4D299105F9409730D&BILLINGAGREEMENTACCEPTEDSTATUS=1&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2011%2d08%2d08T01%3a56%3a13Z&CORRELATIONID=53a48e61dfca7&ACK=Success&VERSION=78%2e0&BUILD=2020243&EMAIL=client_1305381804_per%40matake%2ejp&PAYERID=CMJLWADKVFQYJ&PAYERSTATUS=verified&FIRSTNAME=Test&LASTNAME=User&COUNTRYCODE=US&CURRENCYCODE=JPY&AMT=0&SHIPPINGAMT=0&HANDLINGAMT=0&TAXAMT=0&INSURANCEAMT=0&SHIPDISCAMT=0&PAYMENTREQUEST_0_CURRENCYCODE=JPY&PAYMENTREQUEST_0_AMT=0&PAYMENTREQUEST_0_SHIPPINGAMT=0&PAYMENTREQUEST_0_HANDLINGAMT=0&PAYMENTREQUEST_0_TAXAMT=0&PAYMENTREQUEST_0_INSURANCEAMT=0&PAYMENTREQUEST_0_SHIPDISCAMT=0&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUESTINFO_0_ERRORCODE=0"
  },
  {
    "path": "spec/fake_response/GetRecurringPaymentsProfileDetails/failure.txt",
    "content": "PROFILEID=I%2dK1VFLRN3VVG0x&TIMESTAMP=2011%2d02%2d08T07%3a19%3a43Z&CORRELATIONID=edc954f1c34c5&ACK=Failure&VERSION=66%2e0&BUILD=1704252&L_ERRORCODE0=11552&L_SHORTMESSAGE0=Invalid%20profile%20ID&L_LONGMESSAGE0=The%20profile%20ID%20is%20invalid&L_SEVERITYCODE0=Error"
  },
  {
    "path": "spec/fake_response/GetRecurringPaymentsProfileDetails/success.txt",
    "content": "PROFILEID=I%2dK1VFLRN3VVG0&STATUS=Active&AUTOBILLOUTAMT=NoAutoBill&DESC=iKnow%21%20Subscription&MAXFAILEDPAYMENTS=0&SUBSCRIBERNAME=Test%20User&PROFILESTARTDATE=2011%2d02%2d03T15%3a00%3a00Z&NEXTBILLINGDATE=2011%2d03%2d04T10%3a00%3a00Z&NUMCYCLESCOMPLETED=1&NUMCYCLESREMAINING=18446744073709551615&OUTSTANDINGBALANCE=0&FAILEDPAYMENTCOUNT=0&LASTPAYMENTDATE=2011%2d02%2d04T10%3a50%3a56Z&LASTPAYMENTAMT=1000&TRIALAMTPAID=0&REGULARAMTPAID=1000&AGGREGATEAMT=1000&AGGREGATEOPTIONALAMT=0&FINALPAYMENTDUEDATE=1970%2d01%2d01T00%3a00%3a00Z&TIMESTAMP=2011%2d02%2d08T07%3a19%3a25Z&CORRELATIONID=8e18dd6545045&ACK=Success&VERSION=66%2e0&BUILD=1704252&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRY=US&SHIPTOCOUNTRYNAME=United%20States&SHIPADDRESSOWNER=PayPal&SHIPADDRESSSTATUS=Unconfirmed&BILLINGPERIOD=Month&BILLINGFREQUENCY=1&TOTALBILLINGCYCLES=0&CURRENCYCODE=JPY&AMT=1000&SHIPPINGAMT=0&TAXAMT=0&REGULARBILLINGPERIOD=Month&REGULARBILLINGFREQUENCY=1&REGULARTOTALBILLINGCYCLES=0&REGULARCURRENCYCODE=JPY&REGULARAMT=1000&REGULARSHIPPINGAMT=0&REGULARTAXAMT=0"
  },
  {
    "path": "spec/fake_response/GetTransactionDetails/failure.txt",
    "content": "ADDRESSOWNER=PayPal&ADDRESSSTATUS=None&TIMESTAMP=2012%2d02%2d23T21%3a07%3a22Z&CORRELATIONID=4e18d75a23953&ACK=Failure&VERSION=78%2e0&BUILD=2571254&L_ERRORCODE0=10004&L_SHORTMESSAGE0=Transaction%20refused%20because%20of%20an%20invalid%20argument%2e%20See%20additional%20error%20messages%20for%20details%2e&L_LONGMESSAGE0=The%20transaction%20id%20is%20not%20valid&L_SEVERITYCODE0=Error&PENDINGREASON=None&REASONCODE=None"
  },
  {
    "path": "spec/fake_response/GetTransactionDetails/success.txt",
    "content": "RECEIVEREMAIL=test%40email%2ecom&RECEIVERID=ABCDEFG12345&EMAIL=test%40email%2ecom&PAYERID=12345ABCDEFG&PAYERSTATUS=verified&COUNTRYCODE=US&SHIPTONAME=Billy%20Bob&SHIPTOSTREET=1%20Main%20St&SHIPTOCITY=San%20Jose&SHIPTOSTATE=CA&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United%20States&SHIPTOZIP=95131&ADDRESSOWNER=PayPal&ADDRESSSTATUS=Confirmed&SALESTAX=0%2e00&SUBJECT=Test%20Subject&TIMESTAMP=2012%2d02%2d23T20%3a51%3a29Z&CORRELATIONID=4fc0a06cbaec7&ACK=Success&VERSION=78%2e0&BUILD=2571254&FIRSTNAME=Billy&LASTNAME=Bob&TRANSACTIONID=123456789ABCD&TRANSACTIONTYPE=cart&PAYMENTTYPE=instant&ORDERTIME=2012%2d02%2d13T23%3a09%3a46Z&AMT=740%2e43&FEEAMT=21%2e77&TAXAMT=0%2e00&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&CURRENCYCODE=USD&PAYMENTSTATUS=Completed&PENDINGREASON=None&REASONCODE=None&PROTECTIONELIGIBILITY=Eligible&PROTECTIONELIGIBILITYTYPE=ItemNotReceivedEligible%2cUnauthorizedPaymentEligible&L_NAME0=Item%201&L_NAME1=Item%202&L_QTY0=1&L_QTY1=1&L_SHIPPINGAMT0=0%2e00&L_SHIPPINGAMT1=0%2e00&L_HANDLINGAMT0=0%2e00&L_HANDLINGAMT1=0%2e00&L_CURRENCYCODE0=USD&L_CURRENCYCODE1=USD&L_AMT0=687%2e93&L_AMT1=52%2e50"
  },
  {
    "path": "spec/fake_response/IPN/invalid.txt",
    "content": "INVALID"
  },
  {
    "path": "spec/fake_response/IPN/valid.txt",
    "content": "VERIFIED"
  },
  {
    "path": "spec/fake_response/ManageRecurringPaymentsProfileStatus/failure.txt",
    "content": "TIMESTAMP=2011%2d02%2d08T07%3a21%3a08Z&CORRELATIONID=aa160cad77481&ACK=Failure&VERSION=66%2e0&BUILD=1704252&L_ERRORCODE0=11556&L_SHORTMESSAGE0=Invalid%20profile%20status%20for%20cancel%20action%3b%20profile%20should%20be%20active%20or%20suspended&L_LONGMESSAGE0=Invalid%20profile%20status%20for%20cancel%20action%3b%20profile%20should%20be%20active%20or%20suspended&L_SEVERITYCODE0=Error"
  },
  {
    "path": "spec/fake_response/ManageRecurringPaymentsProfileStatus/success.txt",
    "content": "PROFILEID=I%2dK1VFLRN3VVG0&TIMESTAMP=2011%2d02%2d08T07%3a20%3a44Z&CORRELATIONID=86bde487ccba6&ACK=Success&VERSION=66%2e0&BUILD=1704252"
  },
  {
    "path": "spec/fake_response/RefundTransaction/full.txt",
    "content": "REFUNDTRANSACTIONID=6D456341FS516215S&FEEREFUNDAMT=0%2e50&GROSSREFUNDAMT=10%2e00&NETREFUNDAMT=9%2e50&CURRENCYCODE=USD&TOTALREFUNDEDAMOUNT=10%2e00&TIMESTAMP=2011%2d05%2d21T14%3a13%3a32Z&CORRELATIONID=862bfc523cca2&ACK=Success&VERSION=72%2e0&BUILD=1882144"
  },
  {
    "path": "spec/fake_response/SetExpressCheckout/failure.txt",
    "content": "TIMESTAMP=2011%2d02%2d02T02%3a16%3a50Z&CORRELATIONID=379d1b7f97afb&ACK=Failure&L_ERRORCODE0=10001&L_SHORTMESSAGE0=Internal%20Error&L_LONGMESSAGE0=Timeout%20processing%20request"
  },
  {
    "path": "spec/fake_response/SetExpressCheckout/success.txt",
    "content": "ACK=Success&BUILD=1721431&CORRELATIONID=5549ea3a78af1&TIMESTAMP=2011-02-02T02%3A02%3A18Z&TOKEN=EC-5YJ90598G69065317&VERSION=66.0"
  },
  {
    "path": "spec/helpers/fake_response_helper.rb",
    "content": "require 'fakeweb'\n\nmodule FakeResponseHelper\n\n  def fake_response(file_path, api = :NVP, options = {})\n    endpoint = case api\n    when :NVP\n      Paypal::NVP::Request.endpoint\n    when :IPN\n      Paypal::IPN.endpoint\n    else\n      raise \"Non-supported API: #{api}\"\n    end\n    FakeWeb.register_uri(\n      :post,\n      endpoint,\n      options.merge(\n        :body => File.read(File.join(File.dirname(__FILE__), '../fake_response', \"#{file_path}.txt\"))\n      )\n    )\n  end\n\n  def request_to(endpoint, method = :get)\n    raise_error(\n      FakeWeb::NetConnectNotAllowedError,\n      \"Real HTTP connections are disabled. Unregistered request: #{method.to_s.upcase} #{endpoint}\"\n    )\n  end\n\nend\n\nFakeWeb.allow_net_connect = false\ninclude FakeResponseHelper"
  },
  {
    "path": "spec/paypal/exception/api_error_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Exception::APIError do\n  let(:error) { Paypal::Exception::APIError.new(params) }\n\n  context 'when Hash is given' do\n    let :params do\n      {\n        :VERSION=>\"66.0\",\n        :TIMESTAMP=>\"2011-03-03T06:33:51Z\",\n        :CORRELATIONID=>\"758ebdc546b9c\",\n        :BUILD=>\"1741654\",\n        :ACK=>\"Failure\",\n        :L_SEVERITYCODE0=>\"Error\",\n        :L_ERRORCODE0=>\"10411\",\n        :L_LONGMESSAGE0=>\"This Express Checkout session has expired.  Token value is no longer valid.\",\n        :L_SHORTMESSAGE0=>\"This Express Checkout session has expired.\",\n        :L_SEVERITYCODE1=>\"Error\",\n        :L_ERRORCODE1=>\"2468\",\n        :L_LONGMESSAGE1=>\"Sample of a long message for the second item.\",\n        :L_SHORTMESSAGE1=>\"Second short message.\",\n      }\n    end\n\n    describe \"#message\" do\n      it \"aggregates short messages\" do\n        error.message.should ==\n          \"PayPal API Error: 'This Express Checkout session has expired.', 'Second short message.'\"\n      end\n    end\n\n    describe '#subject' do\n      subject { error.response }\n      its(:raw) { should == params }\n      Paypal::Exception::APIError::Response.attribute_mapping.each do |key, attribute|\n        its(attribute) { should == params[key] }\n      end\n\n      describe '#details' do\n        subject { error.response.details.first }\n        Paypal::Exception::APIError::Response::Detail.attribute_mapping.each do |key, attribute|\n          its(attribute) { should == params[:\"L_#{key}0\"] }\n        end\n      end\n    end\n  end\n\n  context 'when unknown params given' do\n    let :params do\n      {\n        :UNKNOWN => 'Unknown',\n        :L_UNKNOWN0 => 'Unknown Detail'\n      }\n    end\n\n    it 'should warn' do\n      Paypal.logger.should_receive(:warn).with(\n        \"Ignored Parameter (Paypal::Exception::APIError::Response): UNKNOWN=Unknown\"\n      )\n      Paypal.logger.should_receive(:warn).with(\n        \"Ignored Parameter (Paypal::Exception::APIError::Response::Detail): UNKNOWN=Unknown Detail\"\n      )\n      error\n    end\n    describe '#response' do\n      subject { error.response }\n      its(:raw) { should == params }\n    end\n    its(:message) { should == \"PayPal API Error\" }\n  end\n\n  context 'otherwise' do\n    subject { error }\n    let(:params) { 'Failure' }\n    its(:response) { should == params }\n    its(:message) { should == \"PayPal API Error\" }\n  end\nend"
  },
  {
    "path": "spec/paypal/exception/http_error_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Exception::HttpError do\n  subject { Paypal::Exception::HttpError.new(400, 'BadRequest', 'You are bad man!') }\n  its(:code)    { should == 400 }\n  its(:message) { should == 'BadRequest' }\n  its(:body)    { should == 'You are bad man!' }\nend"
  },
  {
    "path": "spec/paypal/express/request_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Express::Request do\n  class Paypal::Express::Request\n    attr_accessor :_sent_params_, :_method_\n    def post_with_logging(method, params)\n      self._method_ = method\n      self._sent_params_ = params\n      post_without_logging method, params\n    end\n    alias_method_chain :post, :logging\n  end\n\n  let(:return_url) { 'http://example.com/success' }\n  let(:cancel_url) { 'http://example.com/cancel' }\n  let(:nvp_endpoint) { Paypal::NVP::Request::ENDPOINT[:production] }\n  let :attributes do\n    {\n      :username => 'nov',\n      :password => 'password',\n      :signature => 'sig'\n    }\n  end\n\n  let :instance do\n    Paypal::Express::Request.new attributes\n  end\n\n  let :instant_payment_request do\n    Paypal::Payment::Request.new(\n      :amount => 1000,\n      :description => 'Instant Payment Request'\n    )\n  end\n\n  let :many_items do\n    items = Array.new\n    (1..20).each do |index|\n      items << Paypal::Payment::Request::Item.new(\n        :name => \"Item#{index.to_s}\",\n        :description => \"A new Item #{index.to_s}\",\n        :amount => 50.00,\n        :quantity => 1\n      )\n    end\n  end\n\n  let :instant_payment_request_with_many_items do\n       Paypal::Payment::Request.new(\n      :amount => 1000,\n      :description => 'Instant Payment Request',\n      :items => many_items\n    )\n  end\n\n  let :recurring_payment_request do\n    Paypal::Payment::Request.new(\n      :billing_type => :RecurringPayments,\n      :billing_agreement_description => 'Recurring Payment Request'\n    )\n  end\n\n  let :recurring_profile do\n    Paypal::Payment::Recurring.new(\n      :start_date => Time.utc(2011, 2, 8, 9, 0, 0),\n      :description => 'Recurring Profile',\n      :billing => {\n        :period => :Month,\n        :frequency => 1,\n        :amount => 1000\n      }\n    )\n  end\n\n  let :reference_transaction_request do\n    Paypal::Payment::Request.new(\n      :billing_type => :MerchantInitiatedBilling,\n      :billing_agreement_description => 'Billing Agreement Request'\n    )\n  end\n\n  describe '.new' do\n    context 'when any required parameters are missing' do\n      it 'should raise AttrRequired::AttrMissing' do\n        attributes.keys.each do |missing_key|\n          insufficient_attributes = attributes.reject do |key, value|\n            key == missing_key\n          end\n          expect do\n            Paypal::Express::Request.new insufficient_attributes\n          end.to raise_error AttrRequired::AttrMissing\n        end\n      end\n    end\n\n    context 'when all required parameters are given' do\n      it 'should succeed' do\n        expect do\n          Paypal::Express::Request.new attributes\n        end.not_to raise_error AttrRequired::AttrMissing\n      end\n    end\n  end\n\n  describe '#setup' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'SetExpressCheckout/success'\n      response = instance.setup recurring_payment_request, return_url, cancel_url\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should support no_shipping option' do\n      expect do\n        instance.setup instant_payment_request, return_url, cancel_url, :no_shipping => true\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :SetExpressCheckout\n      instance._sent_params_.should == {\n        :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',\n        :RETURNURL => return_url,\n        :CANCELURL => cancel_url,\n        :PAYMENTREQUEST_0_AMT => '1000.00',\n        :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n        :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\",\n        :REQCONFIRMSHIPPING => 0,\n        :NOSHIPPING => 1\n      }\n    end\n\n    it 'should support allow_note=false option' do\n      expect do\n        instance.setup instant_payment_request, return_url, cancel_url, :allow_note => false\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :SetExpressCheckout\n      instance._sent_params_.should == {\n        :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',\n        :RETURNURL => return_url,\n        :CANCELURL => cancel_url,\n        :PAYMENTREQUEST_0_AMT => '1000.00',\n        :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n        :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\",\n        :ALLOWNOTE => 0\n      }\n    end\n\n    {\n      :solution_type => :SOLUTIONTYPE,\n      :landing_page => :LANDINGPAGE,\n      :email => :EMAIL,\n      :brand => :BRANDNAME,\n      :locale => :LOCALECODE,\n      :logo => :LOGOIMG,\n      :cart_border_color => :CARTBORDERCOLOR,\n      :payflow_color => :PAYFLOWCOLOR\n    }.each do |option_key, param_key|\n      it \"should support #{option_key} option\" do\n        expect do\n          instance.setup instant_payment_request, return_url, cancel_url, option_key => 'some value'\n        end.to request_to nvp_endpoint, :post\n        instance._method_.should == :SetExpressCheckout\n        instance._sent_params_.should include param_key\n        instance._sent_params_[param_key].should == 'some value'\n      end\n    end\n\n    context 'when instance payment request given' do\n      it 'should call SetExpressCheckout' do\n        expect do\n          instance.setup instant_payment_request, return_url, cancel_url\n        end.to request_to nvp_endpoint, :post\n        instance._method_.should == :SetExpressCheckout\n        instance._sent_params_.should == {\n          :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',\n          :RETURNURL => return_url,\n          :CANCELURL => cancel_url,\n          :PAYMENTREQUEST_0_AMT => '1000.00',\n          :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n          :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\"\n        }\n      end\n    end\n\n    context 'when recurring payment request given' do\n      it 'should call SetExpressCheckout' do\n        expect do\n          instance.setup recurring_payment_request, return_url, cancel_url\n        end.to request_to nvp_endpoint, :post\n        instance._method_.should == :SetExpressCheckout\n        instance._sent_params_.should == {\n          :L_BILLINGTYPE0 => :RecurringPayments,\n          :L_BILLINGAGREEMENTDESCRIPTION0 => 'Recurring Payment Request',\n          :RETURNURL => return_url,\n          :CANCELURL => cancel_url,\n          :PAYMENTREQUEST_0_AMT => '0.00',\n          :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n          :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\"\n        }\n      end\n    end\n\n    context 'when reference transaction request given' do\n      it 'should call SetExpressCheckout' do\n        expect do\n          instance.setup reference_transaction_request, return_url, cancel_url\n        end.to request_to nvp_endpoint, :post\n        instance._method_.should == :SetExpressCheckout\n        instance._sent_params_.should == {\n          :L_BILLINGTYPE0 => :MerchantInitiatedBilling,\n          :L_BILLINGAGREEMENTDESCRIPTION0 => 'Billing Agreement Request',\n          :RETURNURL => return_url,\n          :CANCELURL => cancel_url,\n          :PAYMENTREQUEST_0_AMT => '0.00',\n          :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n          :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\"\n        }\n      end\n    end\n  end\n\n  describe '#details' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'GetExpressCheckoutDetails/success'\n      response = instance.details 'token'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call GetExpressCheckoutDetails' do\n      expect do\n        instance.details 'token'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :GetExpressCheckoutDetails\n      instance._sent_params_.should == {\n        :TOKEN => 'token'\n      }\n    end\n  end\n\n  describe '#transaction_details' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'GetTransactionDetails/success'\n      response = instance.transaction_details 'transaction_id'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call GetTransactionDetails' do\n      expect do\n        instance.transaction_details 'transaction_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :GetTransactionDetails\n      instance._sent_params_.should == {\n        :TRANSACTIONID=> 'transaction_id'\n      }\n    end\n\n    it 'should fail with bad transaction id' do\n      expect do\n        fake_response 'GetTransactionDetails/failure'\n        response = instance.transaction_details 'bad_transaction_id'\n      end.to raise_error(Paypal::Exception::APIError)\n    end\n\n    it 'should handle all attributes' do\n      Paypal.logger.should_not_receive(:warn)\n      fake_response 'GetTransactionDetails/success'\n      response = instance.transaction_details 'transaction_id'\n    end\n  end\n\n  describe \"#capture!\" do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'DoCapture/success'\n      response = instance.capture! 'authorization_id', 181.98, :BRL\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call DoExpressCheckoutPayment' do\n      expect do\n        instance.capture! 'authorization_id', 181.98, :BRL\n      end.to request_to nvp_endpoint, :post\n\n      instance._method_.should == :DoCapture\n      instance._sent_params_.should == {\n        :AUTHORIZATIONID => 'authorization_id',\n        :COMPLETETYPE => 'Complete',\n        :AMT => 181.98,\n        :CURRENCYCODE => :BRL\n      }\n    end\n\n    it 'should call DoExpressCheckoutPayment with NotComplete capture parameter' do\n      expect do\n        instance.capture! 'authorization_id', 181.98, :BRL, 'NotComplete'\n      end.to request_to nvp_endpoint, :post\n\n      instance._method_.should == :DoCapture\n      instance._sent_params_.should == {\n        :AUTHORIZATIONID => 'authorization_id',\n        :COMPLETETYPE => 'NotComplete',\n        :AMT => 181.98,\n        :CURRENCYCODE => :BRL\n      }\n    end\n  end\n\n  describe \"#void!\" do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'DoVoid/success'\n      response = instance.void! 'authorization_id', note: \"note\"\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call DoVoid' do\n      expect do\n        instance.void! 'authorization_id', note: \"note\"\n      end.to request_to nvp_endpoint, :post\n\n      instance._method_.should == :DoVoid\n      instance._sent_params_.should == {\n        :AUTHORIZATIONID => 'authorization_id',\n        :NOTE => \"note\"\n      }\n    end\n  end\n\n  describe '#checkout!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'DoExpressCheckoutPayment/success'\n      response = instance.checkout! 'token', 'payer_id', instant_payment_request\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call DoExpressCheckoutPayment' do\n      expect do\n        instance.checkout! 'token', 'payer_id', instant_payment_request\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :DoExpressCheckoutPayment\n      instance._sent_params_.should == {\n        :PAYERID => 'payer_id',\n        :TOKEN => 'token',\n        :PAYMENTREQUEST_0_DESC => 'Instant Payment Request',\n        :PAYMENTREQUEST_0_AMT => '1000.00',\n        :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n        :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\"\n      }\n    end\n\n    context \"with many items\" do\n      before do\n        fake_response 'DoExpressCheckoutPayment/success_with_many_items'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        response = instance.checkout! 'token', 'payer_id', instant_payment_request_with_many_items\n      end\n\n      it 'should return Paypal::Express::Response' do\n        response = instance.checkout! 'token', 'payer_id', instant_payment_request_with_many_items\n        response.should be_instance_of Paypal::Express::Response\n      end\n\n      it 'should return twenty items' do\n        response = instance.checkout! 'token', 'payer_id', instant_payment_request_with_many_items\n        instance._method_.should == :DoExpressCheckoutPayment\n        response.items.count.should == 20\n      end\n    end\n  end\n\n  describe '#subscribe!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'CreateRecurringPaymentsProfile/success'\n      response = instance.subscribe! 'token', recurring_profile\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call CreateRecurringPaymentsProfile' do\n      expect do\n        instance.subscribe! 'token', recurring_profile\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :CreateRecurringPaymentsProfile\n      instance._sent_params_.should == {\n        :DESC => 'Recurring Profile',\n        :TOKEN => 'token',\n        :SHIPPINGAMT => '0.00',\n        :AMT => '1000.00',\n        :BILLINGFREQUENCY => 1,\n        :MAXFAILEDPAYMENTS => 0,\n        :BILLINGPERIOD => :Month,\n        :TAXAMT => '0.00',\n        :PROFILESTARTDATE => '2011-02-08 09:00:00',\n        :TOTALBILLINGCYCLES => 0\n      }\n    end\n  end\n\n  describe '#subscription' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'GetRecurringPaymentsProfileDetails/success'\n      response = instance.subscription 'profile_id'\n      response.should be_instance_of(Paypal::Express::Response)\n    end\n\n    it 'should call GetRecurringPaymentsProfileDetails' do\n      expect do\n        instance.subscription 'profile_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :GetRecurringPaymentsProfileDetails\n      instance._sent_params_.should == {\n        :PROFILEID => 'profile_id'\n      }\n    end\n  end\n\n  describe '#renew!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'ManageRecurringPaymentsProfileStatus/success'\n      response = instance.renew! 'profile_id', :Cancel\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call ManageRecurringPaymentsProfileStatus' do\n      expect do\n        instance.renew! 'profile_id', :Cancel\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :ManageRecurringPaymentsProfileStatus\n      instance._sent_params_.should == {\n        :ACTION => :Cancel,\n        :PROFILEID => 'profile_id'\n      }\n    end\n  end\n\n  describe '#cancel!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'ManageRecurringPaymentsProfileStatus/success'\n      response = instance.cancel! 'profile_id'\n      response.should be_instance_of(Paypal::Express::Response)\n    end\n\n    it 'should call ManageRecurringPaymentsProfileStatus' do\n      expect do\n        instance.cancel! 'profile_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :ManageRecurringPaymentsProfileStatus\n      instance._sent_params_.should == {\n        :ACTION => :Cancel,\n        :PROFILEID => 'profile_id'\n      }\n    end\n  end\n\n  describe '#suspend!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'ManageRecurringPaymentsProfileStatus/success'\n      response = instance.cancel! 'profile_id'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call ManageRecurringPaymentsProfileStatus' do\n      expect do\n        instance.suspend! 'profile_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :ManageRecurringPaymentsProfileStatus\n      instance._sent_params_.should == {\n        :ACTION => :Suspend,\n        :PROFILEID => 'profile_id'\n      }\n    end\n  end\n\n  describe '#reactivate!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'ManageRecurringPaymentsProfileStatus/success'\n      response = instance.cancel! 'profile_id'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call ManageRecurringPaymentsProfileStatus' do\n      expect do\n        instance.reactivate! 'profile_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :ManageRecurringPaymentsProfileStatus\n      instance._sent_params_.should == {\n        :ACTION => :Reactivate,\n        :PROFILEID => 'profile_id'\n      }\n    end\n  end\n\n  describe '#agree!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'CreateBillingAgreement/success'\n      response = instance.agree! 'token'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call CreateBillingAgreement' do\n      expect do\n        instance.agree! 'token'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :CreateBillingAgreement\n      instance._sent_params_.should == {\n        :TOKEN => 'token'\n      }\n    end\n  end\n\n  describe '#agreement' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'BillAgreementUpdate/fetch'\n      response = instance.agreement 'reference_id'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call BillAgreementUpdate' do\n      expect do\n        instance.agreement 'reference_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :BillAgreementUpdate\n      instance._sent_params_.should == {\n        :REFERENCEID => 'reference_id'\n      }\n    end\n  end\n\n  describe '#charge!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'DoReferenceTransaction/success'\n      response = instance.charge! 'billing_agreement_id', 1000\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call DoReferenceTransaction' do\n      expect do\n        instance.charge! 'billing_agreement_id', 1000, :currency_code => :JPY\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :DoReferenceTransaction\n      instance._sent_params_.should == {\n        :REFERENCEID => 'billing_agreement_id',\n        :AMT => '1000.00',\n        :PAYMENTACTION => :Sale,\n        :CURRENCYCODE => :JPY\n      }\n    end\n  end\n\n  describe '#revoke!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'BillAgreementUpdate/revoke'\n      response = instance.revoke! 'reference_id'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call BillAgreementUpdate' do\n      expect do\n        instance.revoke! 'reference_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :BillAgreementUpdate\n      instance._sent_params_.should == {\n        :REFERENCEID => 'reference_id',\n        :BillingAgreementStatus => :Canceled\n      }\n    end\n  end\n\n  describe '#refund!' do\n    it 'should return Paypal::Express::Response' do\n      fake_response 'RefundTransaction/full'\n      response = instance.refund! 'transaction_id'\n      response.should be_instance_of Paypal::Express::Response\n    end\n\n    it 'should call RefundTransaction' do\n      expect do\n        instance.refund! 'transaction_id'\n      end.to request_to nvp_endpoint, :post\n      instance._method_.should == :RefundTransaction\n      instance._sent_params_.should == {\n        :TRANSACTIONID => 'transaction_id',\n        :REFUNDTYPE => :Full\n      }\n    end\n  end\nend\n"
  },
  {
    "path": "spec/paypal/express/response_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Express::Response do\n  before { fake_response 'SetExpressCheckout/success' }\n\n  let(:return_url) { 'http://example.com/success' }\n  let(:cancel_url) { 'http://example.com/cancel' }\n  let :request do\n    Paypal::Express::Request.new(\n      :username => 'nov',\n      :password => 'password',\n      :signature => 'sig'\n    )\n  end\n  let :payment_request do\n    Paypal::Payment::Request.new( \n      :billing_type => :RecurringPayments,\n      :billing_agreement_description => 'Recurring Payment Request'\n    )\n  end\n  let(:response) { request.setup payment_request, return_url, cancel_url }\n\n  describe '#redirect_uri' do\n    subject { response.redirect_uri }\n    it { should include 'https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' }\n  end\n\n  describe '#popup_uri' do\n    subject { response.popup_uri }\n    it { should include 'https://www.paypal.com/incontext?token=' }\n  end\n\n  context 'when pay_on_paypal option is given' do\n    let(:response) { request.setup payment_request, return_url, cancel_url, :pay_on_paypal => true }\n\n    subject { response }\n    its(:pay_on_paypal) { should be_true }\n    its(:query) { should include(:useraction => 'commit') }\n\n    describe '#redirect_uri' do\n      subject { response.redirect_uri }\n      it { should include 'useraction=commit' }\n    end\n\n    describe '#popup_uri' do\n      subject { response.popup_uri }\n      it { should include 'useraction=commit' }\n    end\n  end\n\n  context 'when sandbox mode' do\n    before do\n      Paypal.sandbox!\n      fake_response 'SetExpressCheckout/success'\n    end\n    after { Paypal.sandbox = false }\n\n    describe '#redirect_uri' do\n      subject { response.redirect_uri }\n      it { should include 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' }\n    end\n\n    describe '#popup_uri' do\n      subject { response.popup_uri }\n      it { should include 'https://www.sandbox.paypal.com/incontext?token=' }\n    end\n  end\n\n  context 'when mobile option is given' do\n    let(:response) { request.setup payment_request, return_url, cancel_url, :mobile => true }\n\n    subject { response }\n\n    describe '#redirect_uri' do\n      subject { response.redirect_uri }\n      it { should include 'https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout-mobile&token=' }\n    end\n  end\n\nend"
  },
  {
    "path": "spec/paypal/ipn_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Paypal::IPN do\n  describe '.verify!' do\n    context 'when valid' do\n      before { fake_response 'IPN/valid', :IPN }\n      subject { Paypal::IPN.verify!('raw-post-body') }\n      it { should be_true }\n    end\n\n    context 'when invalid' do\n      before { fake_response 'IPN/invalid', :IPN }\n      subject {}\n      it do\n        expect { Paypal::IPN.verify!('raw-post-body') }.to raise_error(Paypal::Exception::APIError)\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/nvp/request_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::NVP::Request do\n  let :attributes do\n    {\n      :username => 'nov',\n      :password => 'password',\n      :signature => 'sig'\n    }\n  end\n\n  let :instance do\n    Paypal::NVP::Request.new attributes\n  end\n\n  describe '.new' do\n    context 'when any required parameters are missing' do\n      it 'should raise AttrRequired::AttrMissing' do\n        attributes.keys.each do |missing_key|\n          insufficient_attributes = attributes.reject do |key, value|\n            key == missing_key\n          end\n          expect do\n            Paypal::NVP::Request.new insufficient_attributes\n          end.to raise_error AttrRequired::AttrMissing\n        end\n      end\n    end\n\n    context 'when all required parameters are given' do\n      it 'should succeed' do\n        expect do\n          Paypal::NVP::Request.new attributes\n        end.not_to raise_error AttrRequired::AttrMissing\n      end\n\n      it 'should setup endpoint and version' do\n        client = Paypal::NVP::Request.new attributes\n        client.class.endpoint.should == Paypal::NVP::Request::ENDPOINT[:production]\n      end\n\n      it 'should support sandbox mode' do\n        sandbox_mode do\n          client = Paypal::NVP::Request.new attributes\n          client.class.endpoint.should == Paypal::NVP::Request::ENDPOINT[:sandbox]\n        end\n      end\n    end\n\n    context 'when optional parameters are given' do\n      let(:optional_attributes) do\n        { :subject => 'user@example.com' }\n      end\n\n      it 'should setup subject' do\n        client = Paypal::NVP::Request.new attributes.merge(optional_attributes)\n        client.subject.should == 'user@example.com'\n      end\n    end\n  end\n\n  describe '#common_params' do\n    {\n      :username => :USER,\n      :password => :PWD,\n      :signature => :SIGNATURE,\n      :subject => :SUBJECT,\n      :version => :VERSION\n    }.each do |option_key, param_key|\n      it \"should include :#{param_key}\" do\n        instance.common_params.should include(param_key)\n      end\n\n      it \"should set :#{param_key} as #{option_key}\" do\n        instance.common_params[param_key].should == instance.send(option_key)\n      end\n    end\n  end\n\n  describe '#request' do\n    it 'should POST to NPV endpoint' do\n      expect do\n        instance.request :RPCMethod\n      end.to request_to Paypal::NVP::Request::ENDPOINT[:production], :post\n    end\n\n    context 'when got API error response' do\n      before do\n        fake_response 'SetExpressCheckout/failure'\n      end\n\n      it 'should raise Paypal::Exception::APIError' do\n        expect do\n          instance.request :SetExpressCheckout\n        end.to raise_error(Paypal::Exception::APIError)\n      end\n    end\n\n    context 'when got HTTP error response' do\n      before do\n        FakeWeb.register_uri(\n          :post,\n          Paypal::NVP::Request::ENDPOINT[:production],\n          :body => \"Invalid Request\",\n          :status => [\"400\", \"Bad Request\"]\n        )\n      end\n\n      it 'should raise Paypal::Exception::HttpError' do\n        expect do\n          instance.request :SetExpressCheckout\n        end.to raise_error(Paypal::Exception::HttpError)\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/nvp/response_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::NVP::Response do\n  let(:return_url) { 'http://example.com/success' }\n  let(:cancel_url) { 'http://example.com/cancel' }\n  let :request do\n    Paypal::Express::Request.new(\n      :username => 'nov',\n      :password => 'password',\n      :signature => 'sig'\n    )\n  end\n\n  let :payment_request do\n    Paypal::Payment::Request.new(\n      :amount => 1000,\n      :description => 'Instant Payment Request'\n    )\n  end\n\n  let :recurring_profile do\n    Paypal::Payment::Recurring.new(\n      :start_date => Time.utc(2011, 2, 8, 9, 0, 0),\n      :description => 'Recurring Profile',\n      :billing => {\n        :period => :Month,\n        :frequency => 1,\n        :amount => 1000\n      }\n    )\n  end\n\n  describe '.new' do\n    context 'when non-supported attributes are given' do\n      it 'should ignore them and warn' do\n        Paypal.logger.should_receive(:warn).with(\n          \"Ignored Parameter (Paypal::NVP::Response): ignored=Ignore me!\"\n        )\n        Paypal::NVP::Response.new(\n          :ignored => 'Ignore me!'\n        )\n      end\n    end\n\n    context 'when SetExpressCheckout response given' do\n      before do\n        fake_response 'SetExpressCheckout/success'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        response = request.setup payment_request, return_url, cancel_url\n        response.token.should == 'EC-5YJ90598G69065317'\n      end\n    end\n\n    context 'when GetExpressCheckoutDetails response given' do\n      before do\n        fake_response 'GetExpressCheckoutDetails/success'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        response = request.details 'token'\n        response.payer.identifier.should == '9RWDTMRKKHQ8S'\n        response.payment_responses.size.should == 1\n        response.payment_info.size.should == 0\n        response.payment_responses.first.should be_instance_of(Paypal::Payment::Response)\n      end\n\n      context 'when BILLINGAGREEMENTACCEPTEDSTATUS included' do\n        before do\n          fake_response 'GetExpressCheckoutDetails/with_billing_accepted_status'\n        end\n\n        it 'should handle all attributes' do\n          Paypal.logger.should_not_receive(:warn)\n          response = request.details 'token'\n        end\n      end\n    end\n\n    context 'when DoExpressCheckoutPayment response given' do\n      before do\n        fake_response 'DoExpressCheckoutPayment/success'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        response = request.checkout! 'token', 'payer_id', payment_request\n        response.payment_responses.size.should == 0\n        response.payment_info.size.should == 1\n        response.payment_info.first.should be_instance_of(Paypal::Payment::Response::Info)\n      end\n\n      context 'when billing_agreement is included' do\n        before do\n          fake_response 'DoExpressCheckoutPayment/success_with_billing_agreement'\n        end\n\n        it 'should have billing_agreement' do\n          Paypal.logger.should_not_receive(:warn)\n          response = request.checkout! 'token', 'payer_id', payment_request\n          response.billing_agreement.identifier.should == 'B-1XR87946TC504770W'\n        end\n      end\n    end\n\n    context 'when CreateRecurringPaymentsProfile response given' do\n      before do\n        fake_response 'CreateRecurringPaymentsProfile/success'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        response = request.subscribe! 'token', recurring_profile\n        response.recurring.identifier.should == 'I-L8N58XFUCET3'\n      end\n    end\n\n    context 'when GetRecurringPaymentsProfileDetails response given' do\n      before do\n        fake_response 'GetRecurringPaymentsProfileDetails/success'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        response = request.subscription 'profile_id'\n        response.recurring.billing.amount.total.should == 1000\n        response.recurring.regular_billing.paid.should == 1000\n        response.recurring.summary.next_billing_date.should == '2011-03-04T10:00:00Z'\n      end\n    end\n\n    context 'when ManageRecurringPaymentsProfileStatus response given' do\n      before do\n        fake_response 'ManageRecurringPaymentsProfileStatus/success'\n      end\n\n      it 'should handle all attributes' do\n        Paypal.logger.should_not_receive(:warn)\n        request.renew! 'profile_id', :Cancel\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/common/amount_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Common::Amount do\n  let :keys do\n    Paypal::Payment::Common::Amount.optional_attributes\n  end\n\n  describe '.new' do\n    it 'should not allow nil for attributes' do\n      amount = Paypal::Payment::Common::Amount.new\n      keys.each do |key|\n        amount.send(key).should == 0\n      end\n    end\n\n    it 'should treat all attributes as Numeric' do\n      # Integer\n      attributes = keys.inject({}) do |attributes, key|\n        attributes.merge!(key => \"100\")\n      end\n      amount = Paypal::Payment::Common::Amount.new attributes\n      keys.each do |key|\n        amount.send(key).should == 100\n      end\n\n      # Float\n      attributes = keys.inject({}) do |attributes, key|\n        attributes.merge!(key => \"10.25\")\n      end\n      amount = Paypal::Payment::Common::Amount.new attributes\n      keys.each do |key|\n        amount.send(key).should == 10.25\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/recurring/activation_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Paypal::Payment::Recurring::Activation do\n  let :instance do\n    Paypal::Payment::Recurring::Activation.new(\n      :initial_amount => 100,\n      :failed_action => 'ContinueOnFailure'\n    )\n  end\n\n  describe '#to_params' do\n    it 'should handle Recurring Profile activation parameters' do\n      instance.to_params.should == {\n        :INITAMT => '100.00',\n        :FAILEDINITAMTACTION => 'ContinueOnFailure'\n      }\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/recurring_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Recurring do\n  let :keys do\n    Paypal::Payment::Recurring.optional_attributes\n  end\n\n  let :trial_attributes do\n    {}\n  end\n\n  let :attributes do\n    {\n      :identifier => '12345',\n      :description => 'Subscription Payment Profile',\n      :status => 'Active',\n      :start_date => '2011-02-03T15:00:00Z',\n      :name => 'Nov Matake',\n      :auto_bill => 'NoAutoBill',\n      :max_fails => '0',\n      :aggregate_amount => '1000',\n      :aggregate_optional_amount => '0',\n      :final_payment_date => '1970-01-01T00:00:00Z',\n      :billing => {\n        :amount => Paypal::Payment::Common::Amount.new(\n          :total => '1000',\n          :shipping => '0',\n          :tax => '0'\n        ),\n        :currency_code => 'JPY',\n        :period => 'Month',\n        :frequency => '1',\n        :total_cycles => '0',\n        :trial => trial_attributes\n      },\n      :regular_billing => {\n        :amount => '1000',\n        :shipping_amount => '0',\n        :tax_amount => '0',\n        :currency_code => 'JPY',\n        :period => 'Month',\n        :frequency => '1',\n        :total_cycles => '0',\n        :paid => '1000'\n      },\n      :summary => {\n        :next_billing_date => '2011-03-04T10:00:00Z',\n        :cycles_completed => '1',\n        :cycles_remaining => '18446744073709551615',\n        :outstanding_balance => '0',\n        :failed_count => '0',\n        :last_payment_date => '2011-02-04T10:50:56Z',\n        :last_payment_amount => '1000'\n      }\n    }\n  end\n\n  let :instance do\n    Paypal::Payment::Recurring.new attributes\n  end\n\n  describe '.new' do\n    it 'should accept all supported attributes' do\n      instance.identifier.should == '12345'\n      instance.description.should == 'Subscription Payment Profile'\n      instance.status.should == 'Active'\n      instance.start_date.should == '2011-02-03T15:00:00Z'\n      instance.billing.trial.should be_nil\n    end\n\n    context 'when optional trial info given' do\n      let :trial_attributes do\n        {\n          :period => 'Month',\n          :frequency => '1',\n          :total_cycles => '0',\n          :currency_code => 'JPY',\n          :amount => '1000',\n          :shipping_amount => '0',\n          :tax_amount => '0'\n        }\n      end\n      it 'should setup trial billing info' do\n        instance.billing.trial.should == Paypal::Payment::Recurring::Billing.new(trial_attributes)\n      end\n    end\n  end\n\n  describe '#to_params' do\n    it 'should handle Recurring Profile parameters' do\n      instance.to_params.should == {\n        :AUTOBILLOUTAMT => 'NoAutoBill',\n        :BILLINGFREQUENCY => 1,\n        :SHIPPINGAMT => '0.00',\n        :DESC => 'Subscription Payment Profile',\n        :SUBSCRIBERNAME => 'Nov Matake',\n        :BILLINGPERIOD => 'Month',\n        :AMT => '1000.00',\n        :MAXFAILEDPAYMENTS => 0,\n        :TOTALBILLINGCYCLES => 0,\n        :TAXAMT => '0.00',\n        :PROFILESTARTDATE => '2011-02-03T15:00:00Z',\n        :CURRENCYCODE => 'JPY'\n      }\n    end\n\n    context 'when start_date is Time' do\n      it 'should be stringfy' do\n        instance = Paypal::Payment::Recurring.new attributes.merge(\n          :start_date => Time.utc(2011, 2, 8, 15, 0, 0)\n        )\n        instance.start_date.should be_instance_of(Time)\n        instance.to_params[:PROFILESTARTDATE].should == '2011-02-08 15:00:00'\n      end\n    end\n\n    context 'when optional trial setting given' do\n      let :trial_attributes do\n        {\n          :period => 'Month',\n          :frequency => '1',\n          :total_cycles => '0',\n          :currency_code => 'JPY',\n          :amount => '1000',\n          :shipping_amount => '0',\n          :tax_amount => '0'\n        }\n      end\n      it 'should setup trial billing info' do\n        instance.to_params.should == {\n          :TRIALBILLINGPERIOD => \"Month\",\n          :TRIALBILLINGFREQUENCY => 1,\n          :TRIALTOTALBILLINGCYCLES => 0,\n          :TRIALAMT => \"1000.00\",\n          :TRIALCURRENCYCODE => \"JPY\",\n          :TRIALSHIPPINGAMT => \"0.00\",\n          :TRIALTAXAMT => \"0.00\",\n          :BILLINGPERIOD => \"Month\",\n          :BILLINGFREQUENCY => 1,\n          :TOTALBILLINGCYCLES => 0,\n          :AMT => \"1000.00\",\n          :CURRENCYCODE => \"JPY\",\n          :SHIPPINGAMT => \"0.00\",\n          :TAXAMT => \"0.00\",\n          :DESC => \"Subscription Payment Profile\",\n          :MAXFAILEDPAYMENTS => 0,\n          :AUTOBILLOUTAMT => \"NoAutoBill\",\n          :PROFILESTARTDATE => \"2011-02-03T15:00:00Z\",\n          :SUBSCRIBERNAME => \"Nov Matake\"\n        }\n      end\n    end\n  end\n\n  describe '#numeric_attribute?' do\n    let :numeric_attributes do\n      [:aggregate_amount, :aggregate_optional_amount, :max_fails, :failed_count]\n    end\n\n    it 'should detect numeric attributes' do\n      numeric_attributes.each do |key|\n        instance.numeric_attribute?(key).should be_true\n      end\n      non_numeric_keys = keys - numeric_attributes\n      non_numeric_keys.each do |key|\n        instance.numeric_attribute?(key).should be_false\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/request/item_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Request::Item do\n  let :instance do\n    Paypal::Payment::Request::Item.new(\n      :name => 'Name',\n      :description => 'Description',\n      :amount => 10,\n      :quantity => 5,\n      :category => :Digital,\n      :number => '1'\n    )\n  end\n\n  describe '#to_params' do\n    it 'should handle Recurring Profile activation parameters' do\n      instance.to_params(1).should == {\n        :L_PAYMENTREQUEST_1_NAME0 => 'Name',\n        :L_PAYMENTREQUEST_1_DESC0 => 'Description',\n        :L_PAYMENTREQUEST_1_AMT0 => '10.00',\n        :L_PAYMENTREQUEST_1_QTY0 => 5,\n        :L_PAYMENTREQUEST_1_ITEMCATEGORY0 => :Digital,\n        :L_PAYMENTREQUEST_1_NUMBER0 => '1'\n      }\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/request_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Request do\n  let :instant_request do\n    Paypal::Payment::Request.new(\n      :amount => 25.7,\n      :tax_amount => 0.4,\n      :shipping_amount => 1.5,\n      :currency_code => :JPY,\n      :description => 'Instant Payment Request',\n      :notify_url => 'http://merchant.example.com/notify',\n      :invoice_number => 'ABC123',\n      :custom => 'Custom',\n      :items => [{\n        :quantity => 2,\n        :name => 'Item1',\n        :description => 'Awesome Item 1!',\n        :amount => 10.25\n      }, {\n        :quantity => 3,\n        :name => 'Item2',\n        :description => 'Awesome Item 2!',\n        :amount => 1.1\n      }],\n      :custom_fields => {\n        \"l_surveychoice{n}\" => 'abcd' # The '{n}' will be replaced with the index\n      }\n    )\n  end\n\n  let :recurring_request do\n    Paypal::Payment::Request.new(\n      :currency_code => :JPY,\n      :billing_type => :RecurringPayments,\n      :billing_agreement_description => 'Recurring Payment Request'\n    )\n  end\n\n  let :reference_transaction_request do\n    Paypal::Payment::Request.new(\n      :currency_code => :JPY,\n      :billing_type => :MerchantInitiatedBillingSingleAgreement,\n      :billing_agreement_description => 'Reference Transaction Request'\n    )\n  end\n\n  describe '.new' do\n    it 'should handle Instant Payment parameters' do\n      instant_request.amount.total.should == 25.7\n      instant_request.amount.tax.should == 0.4\n      instant_request.amount.shipping.should == 1.5\n      instant_request.currency_code.should == :JPY\n      instant_request.description.should == 'Instant Payment Request'\n      instant_request.notify_url.should == 'http://merchant.example.com/notify'\n    end\n\n    it 'should handle Recurring Payment parameters' do\n      recurring_request.currency_code.should == :JPY\n      recurring_request.billing_type.should == :RecurringPayments\n      recurring_request.billing_agreement_description.should == 'Recurring Payment Request'\n    end\n\n    it 'should handle Recurring Payment parameters' do\n      reference_transaction_request.currency_code.should == :JPY\n      reference_transaction_request.billing_type.should == :MerchantInitiatedBillingSingleAgreement\n      reference_transaction_request.billing_agreement_description.should == 'Reference Transaction Request'\n    end\n  end\n\n  describe '#to_params' do\n    it 'should handle Instant Payment parameters' do\n      instant_request.to_params.should == {\n        :PAYMENTREQUEST_0_AMT => \"25.70\",\n        :PAYMENTREQUEST_0_TAXAMT => \"0.40\",\n        :PAYMENTREQUEST_0_SHIPPINGAMT => \"1.50\",\n        :PAYMENTREQUEST_0_CURRENCYCODE => :JPY,\n        :PAYMENTREQUEST_0_DESC => \"Instant Payment Request\",\n        :PAYMENTREQUEST_0_NOTIFYURL => \"http://merchant.example.com/notify\",\n        :PAYMENTREQUEST_0_ITEMAMT => \"23.80\",\n        :PAYMENTREQUEST_0_INVNUM => \"ABC123\",\n        :PAYMENTREQUEST_0_CUSTOM => \"Custom\",\n        :L_PAYMENTREQUEST_0_NAME0 => \"Item1\",\n        :L_PAYMENTREQUEST_0_DESC0 => \"Awesome Item 1!\",\n        :L_PAYMENTREQUEST_0_AMT0 => \"10.25\",\n        :L_PAYMENTREQUEST_0_QTY0 => 2,\n        :L_PAYMENTREQUEST_0_NAME1 => \"Item2\",\n        :L_PAYMENTREQUEST_0_DESC1 => \"Awesome Item 2!\",\n        :L_PAYMENTREQUEST_0_AMT1 => \"1.10\",\n        :L_PAYMENTREQUEST_0_QTY1 => 3,\n        :L_SURVEYCHOICE0 => 'abcd' # Note the 'n' was replaced by the index\n      }\n    end\n\n    it 'should handle Recurring Payment parameters' do\n      recurring_request.to_params.should == {\n        :PAYMENTREQUEST_0_AMT => \"0.00\",\n        :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n        :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\",\n        :PAYMENTREQUEST_0_CURRENCYCODE => :JPY,\n        :L_BILLINGTYPE0 => :RecurringPayments,\n        :L_BILLINGAGREEMENTDESCRIPTION0 => \"Recurring Payment Request\"\n      }\n    end\n\n    it 'should handle Reference Transactions parameters' do\n      reference_transaction_request.to_params.should == {\n        :PAYMENTREQUEST_0_AMT => \"0.00\",\n        :PAYMENTREQUEST_0_TAXAMT => \"0.00\",\n        :PAYMENTREQUEST_0_SHIPPINGAMT => \"0.00\",\n        :PAYMENTREQUEST_0_CURRENCYCODE => :JPY,\n        :L_BILLINGTYPE0 => :MerchantInitiatedBillingSingleAgreement,\n        :L_BILLINGAGREEMENTDESCRIPTION0 => \"Reference Transaction Request\"\n      }\n    end\n  end\n\n  describe '#items_amount' do\n    context 'when BigDecimal'\n    let(:instance) do\n      Paypal::Payment::Request.new(\n        :items => [{\n          :quantity => 3,\n          :name => 'Item1',\n          :description => 'Awesome Item 1!',\n          :amount => 130.45\n        }]\n      )\n    end\n\n    # NOTE:\n    # 130.45 * 3 => 391.34999999999997 (in ruby 1.9)\n    it 'should calculate total amount correctly' do\n      instance.items_amount.should == 391.35\n    end\n  end\nend\n"
  },
  {
    "path": "spec/paypal/payment/response/address_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Response::Address do\n  let :keys do\n    Paypal::Payment::Response::Address.optional_attributes\n  end\n\n  describe '.new' do\n    it 'should allow nil for attributes' do\n      payer = Paypal::Payment::Response::Address.new\n      keys.each do |key|\n        payer.send(key).should be_nil\n      end\n    end\n\n    it 'should treat all attributes as String' do\n      attributes = keys.inject({}) do |attributes, key|\n        attributes.merge!(key => \"xyz\")\n      end\n      payer = Paypal::Payment::Response::Address.new attributes\n      keys.each do |key|\n        payer.send(key).should == \"xyz\"\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/response/info_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Response::Info do\n  let :attribute_mapping do\n    Paypal::Payment::Response::Info.attribute_mapping\n  end\n\n  let :attributes do\n    {\n      :ACK => 'Success',\n      :CURRENCYCODE => 'JPY',\n      :ERRORCODE => 0,\n      :ORDERTIME => '2011-02-08T03:23:54Z',\n      :PAYMENTSTATUS => 'Completed',\n      :PAYMENTTYPE => 'instant',\n      :PENDINGREASON => 'None',\n      :PROTECTIONELIGIBILITY => 'Ineligible',\n      :PROTECTIONELIGIBILITYTYPE => 'None',\n      :REASONCODE => 'None',\n      :TRANSACTIONID => '8NC65222871997739',\n      :TRANSACTIONTYPE => 'expresscheckout',\n      :AMT => '14.00',\n      :FEEAMT => '0.85',\n      :TAXAMT => '0.00',\n      :RECEIPTID => '12345',\n      :SECUREMERCHANTACCOUNTID => '123456789',\n      :PAYMENTREQUESTID => '12345',\n      :SELLERPAYPALACCOUNTID => 'seller@shop.example.com',\n      :EXCHANGERATE => '0.811965'\n    }\n  end\n\n  describe '.new' do\n    context 'when attribute keys are uppercase Symbol' do\n      it 'should accept all without any warning' do\n        Paypal.logger.should_not_receive(:warn)\n        from_symbol_uppercase = Paypal::Payment::Response::Info.new attributes\n        attribute_mapping.values.each do |key|\n          from_symbol_uppercase.send(key).should_not be_nil\n        end\n        from_symbol_uppercase.amount.should == Paypal::Payment::Common::Amount.new(\n          :total => 14,\n          :fee => 0.85\n        )\n      end\n    end\n\n    context 'when attribute keys are lowercase Symbol' do\n      it 'should ignore them and warn' do\n        _attrs_ = attributes.inject({}) do |_attrs_, (k, v)|\n          _attrs_.merge!(k.to_s.downcase.to_sym => v)\n        end\n        _attrs_.each do |key, value|\n          Paypal.logger.should_receive(:warn).with(\n            \"Ignored Parameter (Paypal::Payment::Response::Info): #{key}=#{value}\"\n          )\n        end\n        from_symbol_lowercase = Paypal::Payment::Response::Info.new _attrs_\n        attribute_mapping.values.each do |key|\n          from_symbol_lowercase.send(key).should be_nil\n        end\n        from_symbol_lowercase.amount.should == Paypal::Payment::Common::Amount.new\n      end\n    end\n\n    context 'when attribute keys are String' do\n      it 'should ignore them and warn' do\n        attributes.stringify_keys.each do |key, value|\n          Paypal.logger.should_receive(:warn).with(\n            \"Ignored Parameter (Paypal::Payment::Response::Info): #{key}=#{value}\"\n          )\n        end\n        from_string = Paypal::Payment::Response::Info.new attributes.stringify_keys\n        attribute_mapping.values.each do |key|\n          from_string.send(key).should be_nil\n        end\n        from_string.amount.should == Paypal::Payment::Common::Amount.new\n      end\n    end\n\n    context 'when non-supported attributes are given' do\n      it 'should ignore them and warn' do\n        _attr_ = attributes.merge(\n          :ignored => 'Ignore me!'\n        )\n        Paypal.logger.should_receive(:warn).with(\n          \"Ignored Parameter (Paypal::Payment::Response::Info): ignored=Ignore me!\"\n        )\n        Paypal::Payment::Response::Info.new _attr_\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/paypal/payment/response/item_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Response::Info do\n  let :attributes do\n    {\n      :NAME => 'Item Name',\n      :DESC => 'Item Description',\n      :QTY => '1',\n      :NUMBER => '1',\n      :ITEMCATEGORY => 'Digital',\n      :ITEMWIDTHVALUE => '1.0',\n      :ITEMHEIGHTVALUE => '2.0',\n      :ITEMLENGTHVALUE => '3.0',\n      :ITEMWEIGHTVALUE => '4.0'\n    }\n  end\n\n  describe '.new' do\n    subject { Paypal::Payment::Response::Item.new(attributes) }\n    its(:name) { should == 'Item Name' }\n    its(:description) { should == 'Item Description' }\n    its(:quantity) { should == 1 }\n    its(:category) { should == 'Digital' }\n    its(:width) { should == '1.0' }\n    its(:height) { should == '2.0' }\n    its(:length) { should == '3.0' }\n    its(:weight) { should == '4.0' }\n    its(:number) { should == '1' }\n\n    context 'when non-supported attributes are given' do\n      it 'should ignore them and warn' do\n        _attr_ = attributes.merge(\n          :ignored => 'Ignore me!'\n        )\n        Paypal.logger.should_receive(:warn).with(\n          \"Ignored Parameter (Paypal::Payment::Response::Item): ignored=Ignore me!\"\n        )\n        Paypal::Payment::Response::Item.new _attr_\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/response/payer_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Response::Payer do\n  let :keys do\n    Paypal::Payment::Response::Payer.optional_attributes\n  end\n\n  describe '.new' do\n    it 'should allow nil for attributes' do\n      payer = Paypal::Payment::Response::Payer.new\n      keys.each do |key|\n        payer.send(key).should be_nil\n      end\n    end\n\n    it 'should treat all attributes as String' do\n      attributes = keys.inject({}) do |attributes, key|\n        attributes.merge!(key => \"xyz\")\n      end\n      payer = Paypal::Payment::Response::Payer.new attributes\n      keys.each do |key|\n        payer.send(key).should == \"xyz\"\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/payment/response_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Payment::Response do\n  describe '.new' do\n    context 'when non-supported attributes are given' do\n      it 'should ignore them and warn' do\n        Paypal.logger.should_receive(:warn).with(\n          \"Ignored Parameter (Paypal::Payment::Response): ignored=Ignore me!\"\n        )\n        response = Paypal::Payment::Response.new(\n          :ignored => 'Ignore me!'\n        )\n      end\n    end\n  end\nend"
  },
  {
    "path": "spec/paypal/util_spec.rb",
    "content": "require 'spec_helper.rb'\n\ndescribe Paypal::Util do\n  describe '.formatted_amount' do\n    it 'should return String in \"xx.yy\" format' do\n      Paypal::Util.formatted_amount(nil).should == '0.00'\n      Paypal::Util.formatted_amount(10).should == '10.00'\n      Paypal::Util.formatted_amount(10.02).should == '10.02'\n      Paypal::Util.formatted_amount(10.2).should == '10.20'\n      Paypal::Util.formatted_amount(10.24).should == '10.24'\n      Paypal::Util.formatted_amount(10.255).should == '10.25'\n    end\n  end\n\n  describe '.to_numeric' do\n    it 'should return Numeric' do\n      Paypal::Util.to_numeric('10').should be_kind_of(Integer)\n      Paypal::Util.to_numeric('10.5').should be_kind_of(Float)\n      Paypal::Util.to_numeric('-1.5').should == -1.5\n      Paypal::Util.to_numeric('-1').should == -1\n      Paypal::Util.to_numeric('0').should == 0\n      Paypal::Util.to_numeric('0.00').should == 0\n      Paypal::Util.to_numeric('10').should == 10\n      Paypal::Util.to_numeric('10.00').should == 10\n      Paypal::Util.to_numeric('10.02').should == 10.02\n      Paypal::Util.to_numeric('10.2').should == 10.2\n      Paypal::Util.to_numeric('10.20').should == 10.2\n      Paypal::Util.to_numeric('10.24').should == 10.24\n      Paypal::Util.to_numeric('10.25').should == 10.25\n    end\n  end\nend"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "require 'simplecov'\n\nSimpleCov.start do\n  add_filter 'spec'\nend\n\nrequire 'paypal'\nrequire 'rspec'\nrequire 'helpers/fake_response_helper'\n\nRSpec.configure do |config|\n  config.before do\n    Paypal.logger = double(\"logger\")\n  end\n  config.after do\n    FakeWeb.clean_registry\n  end\nend\n\ndef sandbox_mode(&block)\n  Paypal.sandbox!\n  yield\nensure\n  Paypal.sandbox = false\nend"
  }
]