recurly 0.4.16 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of recurly might be problematic. Click here for more details.
- data/README.markdown +118 -0
- data/bin/recurly +78 -0
- data/lib/rails/generators/recurly/config_generator.rb +16 -0
- data/lib/rails/recurly.rb +13 -0
- data/lib/recurly.rb +64 -139
- data/lib/recurly/account.rb +52 -111
- data/lib/recurly/add_on.rb +20 -0
- data/lib/recurly/adjustment.rb +51 -0
- data/lib/recurly/api.rb +73 -0
- data/lib/recurly/api/errors.rb +205 -0
- data/lib/recurly/api/net_http.rb +77 -0
- data/lib/recurly/billing_info.rb +45 -42
- data/lib/recurly/coupon.rb +63 -8
- data/lib/recurly/helper.rb +39 -0
- data/lib/recurly/invoice.rb +38 -16
- data/lib/recurly/js.rb +113 -0
- data/lib/recurly/money.rb +105 -0
- data/lib/recurly/plan.rb +26 -15
- data/lib/recurly/redemption.rb +34 -0
- data/lib/recurly/resource.rb +925 -0
- data/lib/recurly/resource/pager.rb +210 -0
- data/lib/recurly/subscription.rb +90 -67
- data/lib/recurly/subscription/add_ons.rb +73 -0
- data/lib/recurly/transaction.rb +65 -53
- data/lib/recurly/transaction/errors.rb +98 -0
- data/lib/recurly/version.rb +16 -2
- data/lib/recurly/xml.rb +85 -0
- data/lib/recurly/xml/nokogiri.rb +49 -0
- data/lib/recurly/xml/rexml.rb +50 -0
- metadata +76 -165
- data/LICENSE +0 -21
- data/README.md +0 -104
- data/init.rb +0 -1
- data/lib/patches/rails2/active_resource/base.rb +0 -35
- data/lib/patches/rails2/active_resource/connection.rb +0 -10
- data/lib/patches/rails3/active_model/serializers/xml.rb +0 -28
- data/lib/patches/rails3/active_resource/connection.rb +0 -10
- data/lib/recurly/account_base.rb +0 -35
- data/lib/recurly/base.rb +0 -195
- data/lib/recurly/charge.rb +0 -39
- data/lib/recurly/config_parser.rb +0 -31
- data/lib/recurly/credit.rb +0 -28
- data/lib/recurly/exceptions.rb +0 -32
- data/lib/recurly/formats/xml_with_errors.rb +0 -132
- data/lib/recurly/formats/xml_with_pagination.rb +0 -47
- data/lib/recurly/rails2/compatibility.rb +0 -8
- data/lib/recurly/rails3/railtie.rb +0 -21
- data/lib/recurly/rails3/recurly.rake +0 -28
- data/lib/recurly/transparent.rb +0 -148
- data/lib/recurly/verification.rb +0 -83
- data/spec/config/recurly.yml +0 -6
- data/spec/config/test1.yml +0 -4
- data/spec/config/test2.yml +0 -7
- data/spec/integration/account_spec.rb +0 -286
- data/spec/integration/add_on_spec.rb +0 -84
- data/spec/integration/billing_info_spec.rb +0 -148
- data/spec/integration/charge_spec.rb +0 -176
- data/spec/integration/coupon_spec.rb +0 -49
- data/spec/integration/credit_spec.rb +0 -106
- data/spec/integration/invoice_spec.rb +0 -86
- data/spec/integration/plan_spec.rb +0 -87
- data/spec/integration/subscription_spec.rb +0 -221
- data/spec/integration/transaction_spec.rb +0 -154
- data/spec/integration/transparent_spec.rb +0 -99
- data/spec/spec_helper.rb +0 -34
- data/spec/support/factory.rb +0 -211
- data/spec/support/vcr.rb +0 -11
- data/spec/unit/account_spec.rb +0 -19
- data/spec/unit/billing_info_spec.rb +0 -39
- data/spec/unit/charge_spec.rb +0 -20
- data/spec/unit/config_spec.rb +0 -42
- data/spec/unit/coupon_spec.rb +0 -13
- data/spec/unit/credit_spec.rb +0 -20
- data/spec/unit/plan_spec.rb +0 -18
- data/spec/unit/subscription_spec.rb +0 -25
- data/spec/unit/transaction_spec.rb +0 -32
- data/spec/unit/transparent_spec.rb +0 -152
- data/spec/unit/verification_spec.rb +0 -82
data/lib/recurly/charge.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Recurly
|
2
|
-
class Charge < Base
|
3
|
-
self.element_name = "charge"
|
4
|
-
self.prefix = "/accounts/:account_code/"
|
5
|
-
|
6
|
-
def self.known_attributes
|
7
|
-
[
|
8
|
-
"account_code",
|
9
|
-
"quantity",
|
10
|
-
"unit_amount_in_cents",
|
11
|
-
"amount_in_cents", # quantity * unit_amount_in_cents
|
12
|
-
"start_date",
|
13
|
-
"end_date",
|
14
|
-
"description",
|
15
|
-
"created_at"
|
16
|
-
]
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.list(account_code, status = :all)
|
20
|
-
params = {:account_code => account_code}
|
21
|
-
|
22
|
-
if status != :all
|
23
|
-
params[:show] = status.to_s
|
24
|
-
end
|
25
|
-
|
26
|
-
find(:all, :params => params)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.lookup(account_code, id)
|
30
|
-
find(id, :params => { :account_code => account_code })
|
31
|
-
end
|
32
|
-
|
33
|
-
# def destroy
|
34
|
-
# reload
|
35
|
-
# return false if respond_to?(:invoice_id) and invoice_id.present?
|
36
|
-
# super
|
37
|
-
# end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
module Recurly
|
6
|
-
module ConfigParser
|
7
|
-
class << self
|
8
|
-
|
9
|
-
def parse(path = nil)
|
10
|
-
path ||= Recurly.settings_path
|
11
|
-
settings = {}
|
12
|
-
if File.exists?(path)
|
13
|
-
settings = YAML::load(ERB.new(File.read(path)).result) || {}
|
14
|
-
else
|
15
|
-
puts "\n#{path} file not found. Run rake recurly:setup to create one\n\n"
|
16
|
-
end
|
17
|
-
|
18
|
-
settings
|
19
|
-
end
|
20
|
-
|
21
|
-
def save(settings = {}, path = nil)
|
22
|
-
path ||= Recurly.settings_path
|
23
|
-
FileUtils.mkdir_p(File.dirname(path))
|
24
|
-
File.open(path, 'w' ) do |out|
|
25
|
-
YAML.dump(settings, out)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
data/lib/recurly/credit.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module Recurly
|
2
|
-
class Credit < Base
|
3
|
-
self.element_name = "credit"
|
4
|
-
self.prefix = "/accounts/:account_code/"
|
5
|
-
|
6
|
-
def self.known_attributes
|
7
|
-
[
|
8
|
-
"account_code",
|
9
|
-
"quantity",
|
10
|
-
"unit_amount_in_cents",
|
11
|
-
"amount_in_cents", # quantity * unit_amount_in_cents
|
12
|
-
"start_date",
|
13
|
-
"end_date",
|
14
|
-
"description",
|
15
|
-
"created_at"
|
16
|
-
]
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.list(account_code)
|
20
|
-
find(:all, :params => { :account_code => account_code })
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.lookup(account_code, id)
|
24
|
-
find(id, :params => { :account_code => account_code })
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
data/lib/recurly/exceptions.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'active_resource/exceptions'
|
2
|
-
require 'active_resource/validations'
|
3
|
-
|
4
|
-
module Recurly
|
5
|
-
class RecurlyError < StandardError; end
|
6
|
-
|
7
|
-
class ConfigurationError < RecurlyError; end
|
8
|
-
|
9
|
-
# Query string has been tampered with and cannot be trusted.
|
10
|
-
class ForgedQueryString < RecurlyError; end
|
11
|
-
|
12
|
-
# Transparent Post -- validations failed or transaction failed. See the {model} for errors.
|
13
|
-
class ValidationsFailed < RecurlyError
|
14
|
-
attr_reader :model
|
15
|
-
|
16
|
-
def initialize(model)
|
17
|
-
@model = model
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
class ResourceInvalid < ::ActiveResource::ResourceInvalid
|
23
|
-
# Overridden to print the actual error message
|
24
|
-
def to_s
|
25
|
-
message = "Failed."
|
26
|
-
message << " Response code = #{response.code}." if response.respond_to?(:code)
|
27
|
-
message << " Response message = #{@message}." if @message
|
28
|
-
message
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
@@ -1,132 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
module Recurly
|
4
|
-
module Formats
|
5
|
-
class XmlWithErrorsFormat
|
6
|
-
include ActiveResource::Formats::XmlFormat
|
7
|
-
|
8
|
-
def decode(xml)
|
9
|
-
doc = Nokogiri::XML(xml)
|
10
|
-
data = xml_node_to_hash(doc.root)
|
11
|
-
|
12
|
-
if data.is_a?(Hash) and data["type"] == 'collection' and data["current_page"]
|
13
|
-
data = paginate_data(data)
|
14
|
-
end
|
15
|
-
|
16
|
-
data
|
17
|
-
end
|
18
|
-
|
19
|
-
def xml_node_to_hash(node)
|
20
|
-
return node.content.to_s.strip unless node.element?
|
21
|
-
|
22
|
-
node_type = xml_node_type(node)
|
23
|
-
if node.children.size == 1 && node.children[0].text?
|
24
|
-
return [] if node_type == 'array'
|
25
|
-
return xml_node_value(node)
|
26
|
-
end
|
27
|
-
|
28
|
-
if node.name == 'errors'
|
29
|
-
return node.children.collect do |child|
|
30
|
-
error_xml_node_to_hash(child) if child.name == 'error'
|
31
|
-
end.reject { |n| n.nil? }
|
32
|
-
elsif node_type == 'array'
|
33
|
-
return node.children.collect do |child|
|
34
|
-
xml_node_to_hash(child)
|
35
|
-
end.reject { |n| n.nil? || (n.is_a?(String) && n.blank?) }
|
36
|
-
end
|
37
|
-
|
38
|
-
return nil if node.children.empty?
|
39
|
-
|
40
|
-
result_hash = {}
|
41
|
-
result_hash['type'] = node_type unless node_type.nil?
|
42
|
-
|
43
|
-
node.children.each do |child|
|
44
|
-
child_name = child.name
|
45
|
-
result = xml_node_to_hash(child)
|
46
|
-
|
47
|
-
next if child_name == 'text' && result == ''
|
48
|
-
|
49
|
-
if result_hash[child_name]
|
50
|
-
next if result == ''
|
51
|
-
if result_hash[child_name].is_a?(Array)
|
52
|
-
result_hash[child_name] << result
|
53
|
-
else
|
54
|
-
result_hash[child_name] = [result_hash[child_name]] << result
|
55
|
-
end
|
56
|
-
else
|
57
|
-
result_hash[child_name] = result
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
result_hash
|
62
|
-
end
|
63
|
-
|
64
|
-
def error_xml_node_to_hash(node)
|
65
|
-
xml_attributes(node).merge('message' => node.children[0].content.to_s)
|
66
|
-
end
|
67
|
-
|
68
|
-
def xml_node_value(node)
|
69
|
-
return nil if xml_node_nil?(node)
|
70
|
-
|
71
|
-
case xml_node_type(node)
|
72
|
-
when 'integer'
|
73
|
-
node.content.to_i
|
74
|
-
when 'boolean'
|
75
|
-
['true','1'].include?(node.content.downcase)
|
76
|
-
when 'datetime'
|
77
|
-
Time.parse(node.content)
|
78
|
-
else
|
79
|
-
node.content.to_s.strip
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def xml_node_nil?(node)
|
84
|
-
return true if node.nil?
|
85
|
-
attr_node = node.attribute('nil')
|
86
|
-
attr_node.nil? ? false : true
|
87
|
-
end
|
88
|
-
|
89
|
-
def xml_node_type(node)
|
90
|
-
attr_node = node.attribute('type')
|
91
|
-
attr_node.nil? ? nil : attr_node.value
|
92
|
-
end
|
93
|
-
|
94
|
-
def xml_attributes(node)
|
95
|
-
return {} if node.attribute_nodes.empty?
|
96
|
-
values = {}
|
97
|
-
node.attribute_nodes.each do |attribute|
|
98
|
-
values[attribute.name] = attribute.value
|
99
|
-
end
|
100
|
-
values
|
101
|
-
end
|
102
|
-
|
103
|
-
# convert the data into a paginated resultset (array with singleton methods)
|
104
|
-
def paginate_data(data)
|
105
|
-
per_page = data["per_page"] || 0
|
106
|
-
current_page = data["current_page"] || 0
|
107
|
-
total_entries = data["total_entries"] || 0
|
108
|
-
|
109
|
-
# find the first array and use that as the resultset (lame workaround)
|
110
|
-
results = data.values.select{|v| v.is_a?(Array)}.first || []
|
111
|
-
if results.empty?
|
112
|
-
data.delete("per_page")
|
113
|
-
data.delete("current_page")
|
114
|
-
data.delete("total_entries")
|
115
|
-
data.delete("type")
|
116
|
-
results = [data.values.first].compact
|
117
|
-
end
|
118
|
-
|
119
|
-
# define total_entries accessor on result object
|
120
|
-
results.instance_eval "def total_entries; #{total_entries.to_i}; end"
|
121
|
-
|
122
|
-
# define current_page accessor on result object
|
123
|
-
results.instance_eval "def current_page; #{current_page.to_i}; end"
|
124
|
-
|
125
|
-
# define per_page accessor on result object
|
126
|
-
results.instance_eval "def per_page; #{per_page.to_i}; end"
|
127
|
-
|
128
|
-
results
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Recurly
|
2
|
-
module Formats
|
3
|
-
class XmlWithPaginationFormat
|
4
|
-
include ActiveResource::Formats::XmlFormat
|
5
|
-
|
6
|
-
def decode(xml)
|
7
|
-
data = super
|
8
|
-
|
9
|
-
if data.is_a?(Hash) and data["type"] == "collection" and data["current_page"]
|
10
|
-
data = paginate_data(data)
|
11
|
-
end
|
12
|
-
|
13
|
-
data
|
14
|
-
end
|
15
|
-
|
16
|
-
# convert the data into a paginated resultset (array with singleton methods)
|
17
|
-
def paginate_data(data)
|
18
|
-
|
19
|
-
per_page = data["per_page"] || 0
|
20
|
-
current_page = data["current_page"] || 0
|
21
|
-
total_entries = data["total_entries"] || 0
|
22
|
-
|
23
|
-
# find the first array and use that as the resultset (lame workaround)
|
24
|
-
results = data.values.select{|v| v.is_a?(Array)}.first || []
|
25
|
-
if results.empty?
|
26
|
-
data.delete("per_page")
|
27
|
-
data.delete("current_page")
|
28
|
-
data.delete("total_entries")
|
29
|
-
data.delete("type")
|
30
|
-
results = [data.values.first].compact
|
31
|
-
end
|
32
|
-
|
33
|
-
# define total_entries accessor on result object
|
34
|
-
results.instance_eval "def total_entries; #{total_entries.to_i}; end"
|
35
|
-
|
36
|
-
# define current_page accessor on result object
|
37
|
-
results.instance_eval "def current_page; #{current_page.to_i}; end"
|
38
|
-
|
39
|
-
# define per_page accessor on result object
|
40
|
-
results.instance_eval "def per_page; #{per_page.to_i}; end"
|
41
|
-
|
42
|
-
results
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Recurly
|
2
|
-
class Railtie < ::Rails::Railtie
|
3
|
-
rake_tasks do
|
4
|
-
load 'recurly/rails3/recurly.rake'
|
5
|
-
end
|
6
|
-
|
7
|
-
config.after_initialize do
|
8
|
-
Recurly.configure unless Recurly.configured?
|
9
|
-
end
|
10
|
-
|
11
|
-
initializer :recurly_set_accept_language do
|
12
|
-
ActionController::Base.class_eval do
|
13
|
-
prepend_before_filter do
|
14
|
-
# used to default the current accept language to the latest request
|
15
|
-
Recurly.current_accept_language = request.env["HTTP_ACCEPT_LANGUAGE"]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
namespace :recurly do
|
2
|
-
|
3
|
-
# loads settings
|
4
|
-
task :load_settings => :environment do
|
5
|
-
# load the recurly.yml file
|
6
|
-
@recurly_config = Recurly::ConfigParser.parse
|
7
|
-
end
|
8
|
-
|
9
|
-
def setup_static
|
10
|
-
@recurly_config["api_key"] ||= "my_api_key"
|
11
|
-
@recurly_config["private_key"] ||= "my_private_key"
|
12
|
-
@recurly_config["subdomain"] ||= "mysite"
|
13
|
-
end
|
14
|
-
|
15
|
-
desc "Creates a recurly.yml config file"
|
16
|
-
task :setup => :environment do
|
17
|
-
|
18
|
-
# load the recurly.yml file
|
19
|
-
Rake::Task["recurly:load_settings"].invoke
|
20
|
-
|
21
|
-
setup_static
|
22
|
-
puts "Settings file generated at:\n#{Recurly.settings_path}\n"
|
23
|
-
puts "Edit this file to configure your Recurly settings.\n"
|
24
|
-
|
25
|
-
# saves the yml file
|
26
|
-
Recurly::ConfigParser.save(@recurly_config)
|
27
|
-
end
|
28
|
-
end
|
data/lib/recurly/transparent.rb
DELETED
@@ -1,148 +0,0 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
|
-
module Recurly
|
4
|
-
|
5
|
-
module Action
|
6
|
-
CreateSubscription = "subscription"
|
7
|
-
UpdateBilling = "billing_info"
|
8
|
-
CreateTransaction = "transaction"
|
9
|
-
end
|
10
|
-
|
11
|
-
class Transparent
|
12
|
-
attr_accessor :data
|
13
|
-
|
14
|
-
def initialize(data = {})
|
15
|
-
@data = data || {}
|
16
|
-
end
|
17
|
-
|
18
|
-
# output the transparent data as a hidden field
|
19
|
-
def hidden_field
|
20
|
-
html = %{<input type="hidden" name="data" value="#{ERB::Util.html_escape(encoded_data)}" />}
|
21
|
-
|
22
|
-
if html.respond_to?(:html_safe)
|
23
|
-
html.html_safe
|
24
|
-
else
|
25
|
-
html
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# output transparent data along with a verification string to prevent tampering of data
|
30
|
-
def encoded_data
|
31
|
-
verify_required_fields
|
32
|
-
|
33
|
-
# convert data to a query string
|
34
|
-
query_data = self.class.query_string(data)
|
35
|
-
|
36
|
-
# generate a validation string by encrypting the string using the private key
|
37
|
-
validation_string = self.class.encrypt_string(query_data)
|
38
|
-
|
39
|
-
# return the validation and query data
|
40
|
-
"#{validation_string}|#{query_data}"
|
41
|
-
end
|
42
|
-
|
43
|
-
# verify that certain fields are present (or else the transparent post wont work)
|
44
|
-
def verify_required_fields
|
45
|
-
# make sure there's a redirect_url defined
|
46
|
-
unless @data.has_key?(:redirect_url)
|
47
|
-
raise "A :redirect_url key must be defined for Transparent posts"
|
48
|
-
end
|
49
|
-
unless @data.has_key?(:account)
|
50
|
-
raise "An :account key must be defined for Transparent posts"
|
51
|
-
end
|
52
|
-
unless @data[:account].has_key?(:account_code)
|
53
|
-
raise "An :account[:account_code] key must be defined for Transparent posts"
|
54
|
-
end
|
55
|
-
|
56
|
-
return true
|
57
|
-
end
|
58
|
-
|
59
|
-
# convert data into query string
|
60
|
-
def self.query_string(data = {})
|
61
|
-
# process data
|
62
|
-
data = process_data(data.dup)
|
63
|
-
data[:time] = Time.now.utc.strftime("%d/%b/%Y %H:%M:%S %Z")
|
64
|
-
|
65
|
-
address = Addressable::URI.new
|
66
|
-
address.query_values = data
|
67
|
-
address.query
|
68
|
-
end
|
69
|
-
|
70
|
-
# returns the url to post to
|
71
|
-
def self.url(action = nil)
|
72
|
-
raise Recurly::ConfigurationError.new("Recurly gem not configured. run `rake recurly:setup`") unless Recurly.configured?
|
73
|
-
raise Recurly::ConfigurationError.new("Recurly gem not configured. 'private_key' missing.") if Recurly.private_key.blank?
|
74
|
-
raise Recurly::ConfigurationError.new("Recurly gem not configured. 'subdomain' missing.") if Recurly.subdomain.blank?
|
75
|
-
|
76
|
-
# default action to create new subscription
|
77
|
-
action ||= Action::CreateSubscription
|
78
|
-
|
79
|
-
URI.parse("#{Recurly::Base.site}/").merge("/transparent/#{Recurly.subdomain}/#{action}").to_s
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.create_subscription_url
|
83
|
-
url(Action::CreateSubscription)
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.create_transaction_url
|
87
|
-
url(Action::CreateTransaction)
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.update_billing_url
|
91
|
-
url(Action::UpdateBilling)
|
92
|
-
end
|
93
|
-
|
94
|
-
# returns the results via a code
|
95
|
-
def self.results(params)
|
96
|
-
# pull out the result key and status
|
97
|
-
type = params["type"]
|
98
|
-
result_key = params["result"]
|
99
|
-
status = params["status"]
|
100
|
-
|
101
|
-
# verify confirmation matches the passed in querystring
|
102
|
-
address = Addressable::URI.new
|
103
|
-
address.query_values = {:type => type.to_s, :status => status.to_s, :result => result_key.to_s}
|
104
|
-
raise Recurly::ForgedQueryString.new if params["confirm"] != encrypt_string(address.query)
|
105
|
-
|
106
|
-
# pull the class name
|
107
|
-
model = Recurly.const_get(type.to_s.classify)
|
108
|
-
|
109
|
-
response = nil
|
110
|
-
begin
|
111
|
-
# rebuild the ActiveResource object from the xml results
|
112
|
-
response = Recurly::Base.connection.get_raw("/transparent/results/#{result_key}", model.headers)
|
113
|
-
return model.new.from_transparent_results(response)
|
114
|
-
|
115
|
-
rescue ActiveResource::ResourceInvalid => ex
|
116
|
-
model_result = model.new.from_transparent_results(ex.response)
|
117
|
-
raise Recurly::ValidationsFailed.new(model_result)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
# encode a string using the configured private key
|
122
|
-
def self.encrypt_string(input_string)
|
123
|
-
raise Recurly::ConfigurationError.new("Recurly gem not configured. To use transparent redirects, set your private_key within config/recurly.yml to the private_key provided by recurly.com") unless Recurly.private_key.present?
|
124
|
-
digest_key = ::Digest::SHA1.digest(Recurly.private_key)
|
125
|
-
sha1_hash = ::OpenSSL::Digest::Digest.new("sha1")
|
126
|
-
::OpenSSL::HMAC.hexdigest(sha1_hash, digest_key, input_string.to_s)
|
127
|
-
end
|
128
|
-
|
129
|
-
# recursively process the query data (running to_s on values)
|
130
|
-
def self.process_data(data = {})
|
131
|
-
return data unless data.is_a?(Hash)
|
132
|
-
data.each do |key, val|
|
133
|
-
if val.is_a?(Hash)
|
134
|
-
data[key] = process_data(val)
|
135
|
-
elsif val.is_a?(String)
|
136
|
-
data[key] = val.to_s
|
137
|
-
elsif val.is_a?(Enumerable)
|
138
|
-
values = Hash.new
|
139
|
-
val.each_with_index{ |item, index| values[index] = process_data(item) }
|
140
|
-
data[key] = values
|
141
|
-
else
|
142
|
-
data[key] = val.to_s
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|