activemerchant 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/CHANGELOG +40 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +93 -0
  4. data/lib/active_merchant.rb +59 -0
  5. data/lib/active_merchant/billing/base.rb +52 -0
  6. data/lib/active_merchant/billing/credit_card.rb +217 -0
  7. data/lib/active_merchant/billing/gateway.rb +100 -0
  8. data/lib/active_merchant/billing/gateways.rb +15 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +236 -0
  10. data/lib/active_merchant/billing/gateways/bogus.rb +92 -0
  11. data/lib/active_merchant/billing/gateways/eway.rb +235 -0
  12. data/lib/active_merchant/billing/gateways/linkpoint.rb +445 -0
  13. data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
  14. data/lib/active_merchant/billing/gateways/payflow.rb +84 -0
  15. data/lib/active_merchant/billing/gateways/payflow/f73e89fd.0 +17 -0
  16. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +190 -0
  17. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +30 -0
  18. data/lib/active_merchant/billing/gateways/payflow_express.rb +123 -0
  19. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +9 -0
  20. data/lib/active_merchant/billing/gateways/payflow_uk.rb +17 -0
  21. data/lib/active_merchant/billing/gateways/paypal.rb +90 -0
  22. data/lib/active_merchant/billing/gateways/paypal/api_cert_chain.crt +35 -0
  23. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +208 -0
  24. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +30 -0
  25. data/lib/active_merchant/billing/gateways/paypal_express.rb +115 -0
  26. data/lib/active_merchant/billing/gateways/psigate.rb +265 -0
  27. data/lib/active_merchant/billing/gateways/trust_commerce.rb +330 -0
  28. data/lib/active_merchant/billing/gateways/usa_epay.rb +189 -0
  29. data/lib/active_merchant/billing/integrations.rb +12 -0
  30. data/lib/active_merchant/billing/integrations/action_view_helper.rb +65 -0
  31. data/lib/active_merchant/billing/integrations/bogus.rb +17 -0
  32. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  33. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  34. data/lib/active_merchant/billing/integrations/chronopay.rb +17 -0
  35. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +81 -0
  36. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +156 -0
  37. data/lib/active_merchant/billing/integrations/gestpay.rb +21 -0
  38. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  39. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +72 -0
  40. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +83 -0
  41. data/lib/active_merchant/billing/integrations/helper.rb +79 -0
  42. data/lib/active_merchant/billing/integrations/nochex.rb +21 -0
  43. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  44. data/lib/active_merchant/billing/integrations/nochex/notification.rb +101 -0
  45. data/lib/active_merchant/billing/integrations/notification.rb +52 -0
  46. data/lib/active_merchant/billing/integrations/paypal.rb +35 -0
  47. data/lib/active_merchant/billing/integrations/paypal/helper.rb +103 -0
  48. data/lib/active_merchant/billing/integrations/paypal/notification.rb +187 -0
  49. data/lib/active_merchant/billing/response.rb +28 -0
  50. data/lib/active_merchant/lib/country.rb +297 -0
  51. data/lib/active_merchant/lib/posts_data.rb +21 -0
  52. data/lib/active_merchant/lib/requires_parameters.rb +17 -0
  53. data/lib/active_merchant/lib/validateable.rb +76 -0
  54. data/lib/tasks/cia.rb +90 -0
  55. metadata +129 -0
@@ -0,0 +1,52 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ class Notification
5
+ attr_accessor :params
6
+ attr_accessor :raw
7
+
8
+ def initialize(post)
9
+ empty!
10
+ parse(post)
11
+ end
12
+
13
+ def status
14
+ raise NotImplementedError, "Must implement this method in the subclass"
15
+ end
16
+
17
+ # the money amount we received in X.2 decimal.
18
+ def gross
19
+ raise NotImplementedError, "Must implement this method in the subclass"
20
+ end
21
+
22
+ def gross_cents
23
+ (gross.to_f * 100.0).round
24
+ end
25
+
26
+ # This combines the gross and currency and returns a proper Money object.
27
+ # this requires the money library located at http://dist.leetsoft.com/api/money
28
+ def amount
29
+ return Money.new(gross_cents, currency) rescue ArgumentError
30
+ return Money.new(gross_cents) # maybe you have an own money object which doesn't take a currency?
31
+ end
32
+
33
+ # reset the notification.
34
+ def empty!
35
+ @params = Hash.new
36
+ @raw = ""
37
+ end
38
+
39
+ private
40
+
41
+ # Take the posted data and move the relevant data into a hash
42
+ def parse(post)
43
+ @raw = post.to_s
44
+ for line in @raw.split('&')
45
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
46
+ params[key] = CGI.unescape(value)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,35 @@
1
+ require 'active_merchant/billing/integrations/paypal/helper.rb'
2
+ require 'active_merchant/billing/integrations/paypal/notification.rb'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ module Integrations #:nodoc:
7
+ module Paypal
8
+
9
+ # Overwrite this if you want to change the Paypal test url
10
+ mattr_accessor :test_url
11
+ self.test_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
12
+
13
+ # Overwrite this if you want to change the Paypal production url
14
+ mattr_accessor :production_url
15
+ self.production_url = 'https://www.paypal.com/cgi-bin/webscr'
16
+
17
+ def self.service_url
18
+ mode = ActiveMerchant::Billing::Base.integration_mode
19
+ case mode
20
+ when :production
21
+ self.production_url
22
+ when :test
23
+ self.test_url
24
+ else
25
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
26
+ end
27
+ end
28
+
29
+ def self.notification(post)
30
+ Notification.new(post)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,103 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Paypal
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+ CANADIAN_PROVINCES = { 'AB' => 'Alberta',
7
+ 'BC' => 'British Columbia',
8
+ 'MB' => 'Manitoba',
9
+ 'NB' => 'New Brunswick',
10
+ 'NL' => 'Newfoundland',
11
+ 'NS' => 'Nova Scotia',
12
+ 'NU' => 'Nunavut',
13
+ 'NT' => 'Northwest Territories',
14
+ 'ON' => 'Ontario',
15
+ 'PE' => 'Prince Edward Island',
16
+ 'QC' => 'Quebec',
17
+ 'SK' => 'Saskatchewan',
18
+ 'YT' => 'Yukon'
19
+ }
20
+ # See https://www.paypal.com/IntegrationCenter/ic_std-variable-reference.html for details on the following options.
21
+ mapping :order, [ 'item_number', 'custom' ]
22
+
23
+ def initialize(order, account, options = {})
24
+ super
25
+ add_field('cmd', '_ext-enter')
26
+ add_field('redirect_cmd', '_xclick')
27
+ add_field('quantity', 1)
28
+ add_field('item_name', 'Store purchase')
29
+ add_field('no_shipping', '1')
30
+ add_field('no_note', '1')
31
+ add_field('charset', 'utf-8')
32
+ end
33
+
34
+ mapping :amount, 'amount'
35
+ mapping :account, 'business'
36
+ mapping :currency, 'currency_code'
37
+ mapping :notify_url, 'notify_url'
38
+ mapping :return_url, 'return'
39
+ mapping :cancel_return_url, 'cancel_return'
40
+ mapping :invoice, 'invoice'
41
+ mapping :item_name, 'item_name'
42
+ mapping :quantity, 'quantity'
43
+ mapping :no_shipping, 'no_shipping'
44
+ mapping :no_note, 'no_note'
45
+
46
+ mapping :customer, :first_name => 'first_name',
47
+ :last_name => 'last_name',
48
+ :email => 'email',
49
+ :phone => 'night_phone_a'
50
+
51
+ mapping :billing_address, :city => 'city',
52
+ :address1 => 'address1',
53
+ :address2 => 'address2',
54
+ :state => 'state',
55
+ :zip => 'zip',
56
+ :country => 'country',
57
+ :phone_a => "night_phone_a",
58
+ :phone_b => "night_phone_b",
59
+ :phone_c => "night_phone_c"
60
+
61
+ def billing_address(params = {})
62
+
63
+ if params.has_key?(:phone)
64
+ phone = params.delete(:phone).to_s
65
+
66
+ # Whipe all non digits
67
+ phone.gsub!(/\D+/, '')
68
+
69
+ # Parse in the us style (555 555 5555) which seems to be the only format paypal supports. Ignore anything before this.
70
+ if phone =~ /(\d{3})(\d{3})(\d{4})$/
71
+ add_field(mappings[:billing_address][:phone_a], $1)
72
+ add_field(mappings[:billing_address][:phone_b], $2)
73
+ add_field(mappings[:billing_address][:phone_c], $3)
74
+ end
75
+ end
76
+
77
+ # Get the country code in the correct format
78
+ # Use what we were given if we can't find anything
79
+ country_code = lookup_country_code(params.delete(:country))
80
+ add_field(mappings[:billing_address][:country], country_code)
81
+ # Fix Canadian province if required
82
+ if country_code == 'CA'
83
+ province_code = params.delete(:state)
84
+ add_field(mappings[:billing_address][:state], CANADIAN_PROVINCES[province_code.upcase]) unless province_code.nil?
85
+ end
86
+
87
+ # Everything else
88
+ params.each do |k, v|
89
+ field = mappings[:billing_address][k]
90
+ add_field(field, v) unless field.nil?
91
+ end
92
+ end
93
+
94
+
95
+ mapping :tax, 'tax'
96
+ mapping :shipping, 'shipping'
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+
@@ -0,0 +1,187 @@
1
+ require 'net/http'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module Paypal
7
+ # Parser and handler for incoming Instant payment notifications from paypal.
8
+ # The Example shows a typical handler in a rails application. Note that this
9
+ # is an example, please read the Paypal API documentation for all the details
10
+ # on creating a safe payment controller.
11
+ #
12
+ # Example
13
+ #
14
+ # class BackendController < ApplicationController
15
+ # include ActiveMerchant::Billing::Integrations
16
+ #
17
+ # def paypal_ipn
18
+ # notify = Paypal::Notification.new(request.raw_post)
19
+ #
20
+ # order = Order.find(notify.item_id)
21
+ #
22
+ # if notify.acknowledge
23
+ # begin
24
+ #
25
+ # if notify.complete? and order.total == notify.amount
26
+ # order.status = 'success'
27
+ #
28
+ # shop.ship(order)
29
+ # else
30
+ # logger.error("Failed to verify Paypal's notification, please investigate")
31
+ # end
32
+ #
33
+ # rescue => e
34
+ # order.status = 'failed'
35
+ # raise
36
+ # ensure
37
+ # order.save
38
+ # end
39
+ # end
40
+ #
41
+ # render :nothing
42
+ # end
43
+ # end
44
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
45
+ # Overwrite this certificate. It contains the Paypal sandbox certificate by default.
46
+ #
47
+ # Example:
48
+ # Paypal::Notification.paypal_cert = File::read("paypal_cert.pem")
49
+ cattr_accessor :paypal_cert
50
+ @@paypal_cert = """
51
+ -----BEGIN CERTIFICATE-----
52
+ MIIDoTCCAwqgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBmDELMAkGA1UEBhMCVVMx
53
+ EzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCFNhbiBKb3NlMRUwEwYDVQQK
54
+ EwxQYXlQYWwsIEluYy4xFjAUBgNVBAsUDXNhbmRib3hfY2VydHMxFDASBgNVBAMU
55
+ C3NhbmRib3hfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0
56
+ MDQxOTA3MDI1NFoXDTM1MDQxOTA3MDI1NFowgZgxCzAJBgNVBAYTAlVTMRMwEQYD
57
+ VQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEVMBMGA1UEChMMUGF5
58
+ UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQwEgYDVQQDFAtzYW5k
59
+ Ym94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG
60
+ 9w0BAQEFAAOBjQAwgYkCgYEAt5bjv/0N0qN3TiBL+1+L/EjpO1jeqPaJC1fDi+cC
61
+ 6t6tTbQ55Od4poT8xjSzNH5S48iHdZh0C7EqfE1MPCc2coJqCSpDqxmOrO+9QXsj
62
+ HWAnx6sb6foHHpsPm7WgQyUmDsNwTWT3OGR398ERmBzzcoL5owf3zBSpRP0NlTWo
63
+ nPMCAwEAAaOB+DCB9TAdBgNVHQ4EFgQUgy4i2asqiC1rp5Ms81Dx8nfVqdIwgcUG
64
+ A1UdIwSBvTCBuoAUgy4i2asqiC1rp5Ms81Dx8nfVqdKhgZ6kgZswgZgxCzAJBgNV
65
+ BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEV
66
+ MBMGA1UEChMMUGF5UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQw
67
+ EgYDVQQDFAtzYW5kYm94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNv
68
+ bYIBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFc288DYGX+GX2+W
69
+ P/dwdXwficf+rlG+0V9GBPJZYKZJQ069W/ZRkUuWFQ+Opd2yhPpneGezmw3aU222
70
+ CGrdKhOrBJRRcpoO3FjHHmXWkqgbQqDWdG7S+/l8n1QfDPp+jpULOrcnGEUY41Im
71
+ jZJTylbJQ1b5PBBjGiP0PpK48cdF
72
+ -----END CERTIFICATE-----
73
+ """
74
+
75
+ # Was the transaction complete?
76
+ def complete?
77
+ status == "Completed"
78
+ end
79
+
80
+ # When was this payment received by the client.
81
+ # sometimes it can happen that we get the notification much later.
82
+ # One possible scenario is that our web application was down. In this case paypal tries several
83
+ # times an hour to inform us about the notification
84
+ def received_at
85
+ Time.parse params['payment_date']
86
+ end
87
+
88
+ # Status of transaction. List of possible values:
89
+ # <tt>Canceled-Reversal</tt>::
90
+ # <tt>Completed</tt>::
91
+ # <tt>Denied</tt>::
92
+ # <tt>Expired</tt>::
93
+ # <tt>Failed</tt>::
94
+ # <tt>In-Progress</tt>::
95
+ # <tt>Partially-Refunded</tt>::
96
+ # <tt>Pending</tt>::
97
+ # <tt>Processed</tt>::
98
+ # <tt>Refunded</tt>::
99
+ # <tt>Reversed</tt>::
100
+ # <tt>Voided</tt>::
101
+ def status
102
+ params['payment_status']
103
+ end
104
+
105
+ # Id of this transaction (paypal number)
106
+ def transaction_id
107
+ params['txn_id']
108
+ end
109
+
110
+ # What type of transaction are we dealing with?
111
+ # "cart" "send_money" "web_accept" are possible here.
112
+ def type
113
+ params['txn_type']
114
+ end
115
+
116
+ # the money amount we received in X.2 decimal.
117
+ def gross
118
+ params['mc_gross']
119
+ end
120
+
121
+ # the markup paypal charges for the transaction
122
+ def fee
123
+ params['mc_fee']
124
+ end
125
+
126
+ # What currency have we been dealing with
127
+ def currency
128
+ params['mc_currency']
129
+ end
130
+
131
+ # This is the item number which we submitted to paypal
132
+ # The custom field is also mapped to item_id because PayPal
133
+ # doesn't return item_number in dispute notifications
134
+ def item_id
135
+ params['item_number'] || params['custom']
136
+ end
137
+
138
+ # This is the invoice which you passed to paypal
139
+ def invoice
140
+ params['invoice']
141
+ end
142
+
143
+ # Was this a test transaction?
144
+ def test?
145
+ params['test_ipn'] == '1'
146
+ end
147
+
148
+ # Acknowledge the transaction to paypal. This method has to be called after a new
149
+ # ipn arrives. Paypal will verify that all the information we received are correct and will return a
150
+ # ok or a fail.
151
+ #
152
+ # Example:
153
+ #
154
+ # def paypal_ipn
155
+ # notify = PaypalNotification.new(request.raw_post)
156
+ #
157
+ # if notify.acknowledge
158
+ # ... process order ... if notify.complete?
159
+ # else
160
+ # ... log possible hacking attempt ...
161
+ # end
162
+ def acknowledge
163
+ payload = raw
164
+
165
+ uri = URI.parse(Paypal.service_url)
166
+ request_path = "#{uri.path}?cmd=_notify-validate"
167
+
168
+ request = Net::HTTP::Post.new(request_path)
169
+ request['Content-Length'] = "#{payload.size}"
170
+ request['User-Agent'] = "Active Merchant -- http://home.leetsoft.com/am"
171
+
172
+ http = Net::HTTP.new(uri.host, uri.port)
173
+
174
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @ssl_strict
175
+ http.use_ssl = true
176
+
177
+ request = http.request(request, payload)
178
+
179
+ raise StandardError.new("Faulty paypal result: #{request.body}") unless ["VERIFIED", "INVALID"].include?(request.body)
180
+
181
+ request.body == "VERIFIED"
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+
4
+ class Error < StandardError #:nodoc:
5
+ end
6
+
7
+ class Response
8
+ attr_reader :params
9
+ attr_reader :message
10
+ attr_reader :test
11
+ attr_reader :authorization
12
+
13
+ def success?
14
+ @success
15
+ end
16
+
17
+ def test?
18
+ @test
19
+ end
20
+
21
+ def initialize(success, message, params = {}, options = {})
22
+ @success, @message, @params = success, message, params.stringify_keys
23
+ @test = options[:test] || false
24
+ @authorization = options[:authorization]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,297 @@
1
+ module ActiveMerchant #:nodoc:
2
+ class InvalidCountryCodeError < StandardError
3
+ end
4
+
5
+ class CountryCodeFormatError < StandardError
6
+ end
7
+
8
+ class CountryCode
9
+ attr_reader :value, :format
10
+ def initialize(value)
11
+ @value = value.to_s.upcase
12
+ detect_format
13
+ end
14
+
15
+ def to_s
16
+ value
17
+ end
18
+
19
+ private
20
+
21
+ def detect_format
22
+ case @value
23
+ when /^[[:alpha:]]{2}$/
24
+ @format = :alpha2
25
+ when /^[[:alpha:]]{3}$/
26
+ @format = :alpha3
27
+ when /^[[:digit:]]{3}$/
28
+ @format = :numeric
29
+ else
30
+ raise CountryCodeFormatError, "The country code is not formatted correctly #{@value}"
31
+ end
32
+ end
33
+ end
34
+
35
+ class Country
36
+ include RequiresParameters
37
+ attr_reader :name
38
+
39
+ def initialize(options = {})
40
+ requires!(options, :name, :alpha2, :alpha3, :numeric)
41
+ @name = options.delete(:name)
42
+ @codes = options.collect{|k,v| CountryCode.new(v)}
43
+ end
44
+
45
+ def code(format)
46
+ @codes.select{|c| c.format == format}
47
+ end
48
+
49
+ def to_s
50
+ @name
51
+ end
52
+
53
+ COUNTRIES = [
54
+ { :alpha2 => 'AF', :name => 'Afghanistan', :alpha3 => 'AFG', :numeric => '004' },
55
+ { :alpha2 => 'AL', :name => 'Albania', :alpha3 => 'ALB', :numeric => '008' },
56
+ { :alpha2 => 'DZ', :name => 'Algeria', :alpha3 => 'DZA', :numeric => '012' },
57
+ { :alpha2 => 'AS', :name => 'American Samoa', :alpha3 => 'ASM', :numeric => '016' },
58
+ { :alpha2 => 'AD', :name => 'Andorra', :alpha3 => 'AND', :numeric => '020' },
59
+ { :alpha2 => 'AO', :name => 'Angola', :alpha3 => 'AGO', :numeric => '024' },
60
+ { :alpha2 => 'AI', :name => 'Anguilla', :alpha3 => 'AIA', :numeric => '660' },
61
+ { :alpha2 => 'AG', :name => 'Antigua and Barbuda', :alpha3 => 'ATG', :numeric => '028' },
62
+ { :alpha2 => 'AR', :name => 'Argentina', :alpha3 => 'ARG', :numeric => '032' },
63
+ { :alpha2 => 'AM', :name => 'Armenia', :alpha3 => 'ARM', :numeric => '051' },
64
+ { :alpha2 => 'AW', :name => 'Aruba', :alpha3 => 'ABW', :numeric => '533' },
65
+ { :alpha2 => 'AU', :name => 'Australia', :alpha3 => 'AUS', :numeric => '036' },
66
+ { :alpha2 => 'AT', :name => 'Austria', :alpha3 => 'AUT', :numeric => '040' },
67
+ { :alpha2 => 'AZ', :name => 'Azerbaijan', :alpha3 => 'AZE', :numeric => '031' },
68
+ { :alpha2 => 'BS', :name => 'Bahamas', :alpha3 => 'BHS', :numeric => '044' },
69
+ { :alpha2 => 'BH', :name => 'Bahrain', :alpha3 => 'BHR', :numeric => '048' },
70
+ { :alpha2 => 'BD', :name => 'Bangladesh', :alpha3 => 'BGD', :numeric => '050' },
71
+ { :alpha2 => 'BB', :name => 'Barbados', :alpha3 => 'BRB', :numeric => '052' },
72
+ { :alpha2 => 'BY', :name => 'Belarus', :alpha3 => 'BLR', :numeric => '112' },
73
+ { :alpha2 => 'BE', :name => 'Belgium', :alpha3 => 'BEL', :numeric => '056' },
74
+ { :alpha2 => 'BZ', :name => 'Belize', :alpha3 => 'BLZ', :numeric => '084' },
75
+ { :alpha2 => 'BJ', :name => 'Benin', :alpha3 => 'BEN', :numeric => '204' },
76
+ { :alpha2 => 'BM', :name => 'Bermuda', :alpha3 => 'BMU', :numeric => '060' },
77
+ { :alpha2 => 'BT', :name => 'Bhutan', :alpha3 => 'BTN', :numeric => '064' },
78
+ { :alpha2 => 'BO', :name => 'Bolivia', :alpha3 => 'BOL', :numeric => '068' },
79
+ { :alpha2 => 'BA', :name => 'Bosnia and Herzegovina', :alpha3 => 'BIH', :numeric => '070' },
80
+ { :alpha2 => 'BW', :name => 'Botswana', :alpha3 => 'BWA', :numeric => '072' },
81
+ { :alpha2 => 'BR', :name => 'Brazil', :alpha3 => 'BRA', :numeric => '076' },
82
+ { :alpha2 => 'BN', :name => 'Brunei Darussalam', :alpha3 => 'BRN', :numeric => '096' },
83
+ { :alpha2 => 'BG', :name => 'Bulgaria', :alpha3 => 'BGR', :numeric => '100' },
84
+ { :alpha2 => 'BF', :name => 'Burkina Faso', :alpha3 => 'BFA', :numeric => '854' },
85
+ { :alpha2 => 'BI', :name => 'Burundi', :alpha3 => 'BDI', :numeric => '108' },
86
+ { :alpha2 => 'KH', :name => 'Cambodia', :alpha3 => 'KHM', :numeric => '116' },
87
+ { :alpha2 => 'CM', :name => 'Cameroon', :alpha3 => 'CMR', :numeric => '120' },
88
+ { :alpha2 => 'CA', :name => 'Canada', :alpha3 => 'CAN', :numeric => '124' },
89
+ { :alpha2 => 'CV', :name => 'Cape Verde', :alpha3 => 'CPV', :numeric => '132' },
90
+ { :alpha2 => 'KY', :name => 'Cayman Islands', :alpha3 => 'CYM', :numeric => '136' },
91
+ { :alpha2 => 'CF', :name => 'Central African Republic', :alpha3 => 'CAF', :numeric => '140' },
92
+ { :alpha2 => 'TD', :name => 'Chad', :alpha3 => 'TCD', :numeric => '148' },
93
+ { :alpha2 => 'CL', :name => 'Chile', :alpha3 => 'CHL', :numeric => '152' },
94
+ { :alpha2 => 'CN', :name => 'China', :alpha3 => 'CHN', :numeric => '156' },
95
+ { :alpha2 => 'CO', :name => 'Colombia', :alpha3 => 'COL', :numeric => '170' },
96
+ { :alpha2 => 'KM', :name => 'Comoros', :alpha3 => 'COM', :numeric => '174' },
97
+ { :alpha2 => 'CG', :name => 'Congo', :alpha3 => 'COG', :numeric => '178' },
98
+ { :alpha2 => 'CD', :name => 'Congo, the Democratic Republic of the', :alpha3 => 'COD', :numeric => '180' },
99
+ { :alpha2 => 'CK', :name => 'Cook Islands', :alpha3 => 'COK', :numeric => '184' },
100
+ { :alpha2 => 'CR', :name => 'Costa Rica', :alpha3 => 'CRI', :numeric => '188' },
101
+ { :alpha2 => 'CI', :name => 'Cote D\'Ivoire', :alpha3 => 'CIV', :numeric => '384' },
102
+ { :alpha2 => 'HR', :name => 'Croatia', :alpha3 => 'HRV', :numeric => '191' },
103
+ { :alpha2 => 'CU', :name => 'Cuba', :alpha3 => 'CUB', :numeric => '192' },
104
+ { :alpha2 => 'CY', :name => 'Cyprus', :alpha3 => 'CYP', :numeric => '196' },
105
+ { :alpha2 => 'CZ', :name => 'Czech Republic', :alpha3 => 'CZE', :numeric => '203' },
106
+ { :alpha2 => 'DK', :name => 'Denmark', :alpha3 => 'DNK', :numeric => '208' },
107
+ { :alpha2 => 'DJ', :name => 'Djibouti', :alpha3 => 'DJI', :numeric => '262' },
108
+ { :alpha2 => 'DM', :name => 'Dominica', :alpha3 => 'DMA', :numeric => '212' },
109
+ { :alpha2 => 'DO', :name => 'Dominican Republic', :alpha3 => 'DOM', :numeric => '214' },
110
+ { :alpha2 => 'EC', :name => 'Ecuador', :alpha3 => 'ECU', :numeric => '218' },
111
+ { :alpha2 => 'EG', :name => 'Egypt', :alpha3 => 'EGY', :numeric => '818' },
112
+ { :alpha2 => 'SV', :name => 'El Salvador', :alpha3 => 'SLV', :numeric => '222' },
113
+ { :alpha2 => 'GQ', :name => 'Equatorial Guinea', :alpha3 => 'GNQ', :numeric => '226' },
114
+ { :alpha2 => 'ER', :name => 'Eritrea', :alpha3 => 'ERI', :numeric => '232' },
115
+ { :alpha2 => 'EE', :name => 'Estonia', :alpha3 => 'EST', :numeric => '233' },
116
+ { :alpha2 => 'ET', :name => 'Ethiopia', :alpha3 => 'ETH', :numeric => '231' },
117
+ { :alpha2 => 'FK', :name => 'Falkland Islands (Malvinas)', :alpha3 => 'FLK', :numeric => '238' },
118
+ { :alpha2 => 'FO', :name => 'Faroe Islands', :alpha3 => 'FRO', :numeric => '234' },
119
+ { :alpha2 => 'FJ', :name => 'Fiji', :alpha3 => 'FJI', :numeric => '242' },
120
+ { :alpha2 => 'FI', :name => 'Finland', :alpha3 => 'FIN', :numeric => '246' },
121
+ { :alpha2 => 'FR', :name => 'France', :alpha3 => 'FRA', :numeric => '250' },
122
+ { :alpha2 => 'GF', :name => 'French Guiana', :alpha3 => 'GUF', :numeric => '254' },
123
+ { :alpha2 => 'PF', :name => 'French Polynesia', :alpha3 => 'PYF', :numeric => '258' },
124
+ { :alpha2 => 'GA', :name => 'Gabon', :alpha3 => 'GAB', :numeric => '266' },
125
+ { :alpha2 => 'GM', :name => 'Gambia', :alpha3 => 'GMB', :numeric => '270' },
126
+ { :alpha2 => 'GE', :name => 'Georgia', :alpha3 => 'GEO', :numeric => '268' },
127
+ { :alpha2 => 'DE', :name => 'Germany', :alpha3 => 'DEU', :numeric => '276' },
128
+ { :alpha2 => 'GH', :name => 'Ghana', :alpha3 => 'GHA', :numeric => '288' },
129
+ { :alpha2 => 'GI', :name => 'Gibraltar', :alpha3 => 'GIB', :numeric => '292' },
130
+ { :alpha2 => 'GR', :name => 'Greece', :alpha3 => 'GRC', :numeric => '300' },
131
+ { :alpha2 => 'GL', :name => 'Greenland', :alpha3 => 'GRL', :numeric => '304' },
132
+ { :alpha2 => 'GD', :name => 'Grenada', :alpha3 => 'GRD', :numeric => '308' },
133
+ { :alpha2 => 'GP', :name => 'Guadeloupe', :alpha3 => 'GLP', :numeric => '312' },
134
+ { :alpha2 => 'GU', :name => 'Guam', :alpha3 => 'GUM', :numeric => '316' },
135
+ { :alpha2 => 'GT', :name => 'Guatemala', :alpha3 => 'GTM', :numeric => '320' },
136
+ { :alpha2 => 'GN', :name => 'Guinea', :alpha3 => 'GIN', :numeric => '324' },
137
+ { :alpha2 => 'GW', :name => 'Guinea-Bissau', :alpha3 => 'GNB', :numeric => '624' },
138
+ { :alpha2 => 'GY', :name => 'Guyana', :alpha3 => 'GUY', :numeric => '328' },
139
+ { :alpha2 => 'HT', :name => 'Haiti', :alpha3 => 'HTI', :numeric => '332' },
140
+ { :alpha2 => 'VA', :name => 'Holy See (Vatican City State)', :alpha3 => 'VAT', :numeric => '336' },
141
+ { :alpha2 => 'HN', :name => 'Honduras', :alpha3 => 'HND', :numeric => '340' },
142
+ { :alpha2 => 'HK', :name => 'Hong Kong', :alpha3 => 'HKG', :numeric => '344' },
143
+ { :alpha2 => 'HU', :name => 'Hungary', :alpha3 => 'HUN', :numeric => '348' },
144
+ { :alpha2 => 'IS', :name => 'Iceland', :alpha3 => 'ISL', :numeric => '352' },
145
+ { :alpha2 => 'IN', :name => 'India', :alpha3 => 'IND', :numeric => '356' },
146
+ { :alpha2 => 'ID', :name => 'Indonesia', :alpha3 => 'IDN', :numeric => '360' },
147
+ { :alpha2 => 'IR', :name => 'Iran, Islamic Republic of', :alpha3 => 'IRN', :numeric => '364' },
148
+ { :alpha2 => 'IQ', :name => 'Iraq', :alpha3 => 'IRQ', :numeric => '368' },
149
+ { :alpha2 => 'IE', :name => 'Ireland', :alpha3 => 'IRL', :numeric => '372' },
150
+ { :alpha2 => 'IL', :name => 'Israel', :alpha3 => 'ISR', :numeric => '376' },
151
+ { :alpha2 => 'IT', :name => 'Italy', :alpha3 => 'ITA', :numeric => '380' },
152
+ { :alpha2 => 'JM', :name => 'Jamaica', :alpha3 => 'JAM', :numeric => '388' },
153
+ { :alpha2 => 'JP', :name => 'Japan', :alpha3 => 'JPN', :numeric => '392' },
154
+ { :alpha2 => 'JO', :name => 'Jordan', :alpha3 => 'JOR', :numeric => '400' },
155
+ { :alpha2 => 'KZ', :name => 'Kazakhstan', :alpha3 => 'KAZ', :numeric => '398' },
156
+ { :alpha2 => 'KE', :name => 'Kenya', :alpha3 => 'KEN', :numeric => '404' },
157
+ { :alpha2 => 'KI', :name => 'Kiribati', :alpha3 => 'KIR', :numeric => '296' },
158
+ { :alpha2 => 'KP', :name => 'Korea, Democratic People\'s Republic of', :alpha3 => 'PRK', :numeric => '408' },
159
+ { :alpha2 => 'KR', :name => 'Korea, Republic of', :alpha3 => 'KOR', :numeric => '410' },
160
+ { :alpha2 => 'KW', :name => 'Kuwait', :alpha3 => 'KWT', :numeric => '414' },
161
+ { :alpha2 => 'KG', :name => 'Kyrgyzstan', :alpha3 => 'KGZ', :numeric => '417' },
162
+ { :alpha2 => 'LA', :name => 'Lao People\'s Democratic Republic', :alpha3 => 'LAO', :numeric => '418' },
163
+ { :alpha2 => 'LV', :name => 'Latvia', :alpha3 => 'LVA', :numeric => '428' },
164
+ { :alpha2 => 'LB', :name => 'Lebanon', :alpha3 => 'LBN', :numeric => '422' },
165
+ { :alpha2 => 'LS', :name => 'Lesotho', :alpha3 => 'LSO', :numeric => '426' },
166
+ { :alpha2 => 'LR', :name => 'Liberia', :alpha3 => 'LBR', :numeric => '430' },
167
+ { :alpha2 => 'LY', :name => 'Libyan Arab Jamahiriya', :alpha3 => 'LBY', :numeric => '434' },
168
+ { :alpha2 => 'LI', :name => 'Liechtenstein', :alpha3 => 'LIE', :numeric => '438' },
169
+ { :alpha2 => 'LT', :name => 'Lithuania', :alpha3 => 'LTU', :numeric => '440' },
170
+ { :alpha2 => 'LU', :name => 'Luxembourg', :alpha3 => 'LUX', :numeric => '442' },
171
+ { :alpha2 => 'MO', :name => 'Macao', :alpha3 => 'MAC', :numeric => '446' },
172
+ { :alpha2 => 'MK', :name => 'Macedonia, the Former Yugoslav Republic of', :alpha3 => 'MKD', :numeric => '807' },
173
+ { :alpha2 => 'MG', :name => 'Madagascar', :alpha3 => 'MDG', :numeric => '450' },
174
+ { :alpha2 => 'MW', :name => 'Malawi', :alpha3 => 'MWI', :numeric => '454' },
175
+ { :alpha2 => 'MY', :name => 'Malaysia', :alpha3 => 'MYS', :numeric => '458' },
176
+ { :alpha2 => 'MV', :name => 'Maldives', :alpha3 => 'MDV', :numeric => '462' },
177
+ { :alpha2 => 'ML', :name => 'Mali', :alpha3 => 'MLI', :numeric => '466' },
178
+ { :alpha2 => 'MT', :name => 'Malta', :alpha3 => 'MLT', :numeric => '470' },
179
+ { :alpha2 => 'MH', :name => 'Marshall Islands', :alpha3 => 'MHL', :numeric => '584' },
180
+ { :alpha2 => 'MQ', :name => 'Martinique', :alpha3 => 'MTQ', :numeric => '474' },
181
+ { :alpha2 => 'MR', :name => 'Mauritania', :alpha3 => 'MRT', :numeric => '478' },
182
+ { :alpha2 => 'MU', :name => 'Mauritius', :alpha3 => 'MUS', :numeric => '480' },
183
+ { :alpha2 => 'MX', :name => 'Mexico', :alpha3 => 'MEX', :numeric => '484' },
184
+ { :alpha2 => 'FM', :name => 'Micronesia, Federated States of', :alpha3 => 'FSM', :numeric => '583' },
185
+ { :alpha2 => 'MD', :name => 'Moldova, Republic of', :alpha3 => 'MDA', :numeric => '498' },
186
+ { :alpha2 => 'MC', :name => 'Monaco', :alpha3 => 'MCO', :numeric => '492' },
187
+ { :alpha2 => 'MN', :name => 'Mongolia', :alpha3 => 'MNG', :numeric => '496' },
188
+ { :alpha2 => 'MS', :name => 'Montserrat', :alpha3 => 'MSR', :numeric => '500' },
189
+ { :alpha2 => 'MA', :name => 'Morocco', :alpha3 => 'MAR', :numeric => '504' },
190
+ { :alpha2 => 'MZ', :name => 'Mozambique', :alpha3 => 'MOZ', :numeric => '508' },
191
+ { :alpha2 => 'MM', :name => 'Myanmar', :alpha3 => 'MMR', :numeric => '104' },
192
+ { :alpha2 => 'NA', :name => 'Namibia', :alpha3 => 'NAM', :numeric => '516' },
193
+ { :alpha2 => 'NR', :name => 'Nauru', :alpha3 => 'NRU', :numeric => '520' },
194
+ { :alpha2 => 'NP', :name => 'Nepal', :alpha3 => 'NPL', :numeric => '524' },
195
+ { :alpha2 => 'NL', :name => 'Netherlands', :alpha3 => 'NLD', :numeric => '528' },
196
+ { :alpha2 => 'AN', :name => 'Netherlands Antilles', :alpha3 => 'ANT', :numeric => '530' },
197
+ { :alpha2 => 'NC', :name => 'New Caledonia', :alpha3 => 'NCL', :numeric => '540' },
198
+ { :alpha2 => 'NZ', :name => 'New Zealand', :alpha3 => 'NZL', :numeric => '554' },
199
+ { :alpha2 => 'NI', :name => 'Nicaragua', :alpha3 => 'NIC', :numeric => '558' },
200
+ { :alpha2 => 'NE', :name => 'Niger', :alpha3 => 'NER', :numeric => '562' },
201
+ { :alpha2 => 'NG', :name => 'Nigeria', :alpha3 => 'NGA', :numeric => '566' },
202
+ { :alpha2 => 'NU', :name => 'Niue', :alpha3 => 'NIU', :numeric => '570' },
203
+ { :alpha2 => 'NF', :name => 'Norfolk Island', :alpha3 => 'NFK', :numeric => '574' },
204
+ { :alpha2 => 'MP', :name => 'Northern Mariana Islands', :alpha3 => 'MNP', :numeric => '580' },
205
+ { :alpha2 => 'NO', :name => 'Norway', :alpha3 => 'NOR', :numeric => '578' },
206
+ { :alpha2 => 'OM', :name => 'Oman', :alpha3 => 'OMN', :numeric => '512' },
207
+ { :alpha2 => 'PK', :name => 'Pakistan', :alpha3 => 'PAK', :numeric => '586' },
208
+ { :alpha2 => 'PW', :name => 'Palau', :alpha3 => 'PLW', :numeric => '585' },
209
+ { :alpha2 => 'PA', :name => 'Panama', :alpha3 => 'PAN', :numeric => '591' },
210
+ { :alpha2 => 'PG', :name => 'Papua New Guinea', :alpha3 => 'PNG', :numeric => '598' },
211
+ { :alpha2 => 'PY', :name => 'Paraguay', :alpha3 => 'PRY', :numeric => '600' },
212
+ { :alpha2 => 'PE', :name => 'Peru', :alpha3 => 'PER', :numeric => '604' },
213
+ { :alpha2 => 'PH', :name => 'Philippines', :alpha3 => 'PHL', :numeric => '608' },
214
+ { :alpha2 => 'PN', :name => 'Pitcairn', :alpha3 => 'PCN', :numeric => '612' },
215
+ { :alpha2 => 'PL', :name => 'Poland', :alpha3 => 'POL', :numeric => '616' },
216
+ { :alpha2 => 'PT', :name => 'Portugal', :alpha3 => 'PRT', :numeric => '620' },
217
+ { :alpha2 => 'PR', :name => 'Puerto Rico', :alpha3 => 'PRI', :numeric => '630' },
218
+ { :alpha2 => 'QA', :name => 'Qatar', :alpha3 => 'QAT', :numeric => '634' },
219
+ { :alpha2 => 'RE', :name => 'Reunion', :alpha3 => 'REU', :numeric => '638' },
220
+ { :alpha2 => 'RO', :name => 'Romania', :alpha3 => 'ROM', :numeric => '642' },
221
+ { :alpha2 => 'RU', :name => 'Russian Federation', :alpha3 => 'RUS', :numeric => '643' },
222
+ { :alpha2 => 'RW', :name => 'Rwanda', :alpha3 => 'RWA', :numeric => '646' },
223
+ { :alpha2 => 'SH', :name => 'Saint Helena', :alpha3 => 'SHN', :numeric => '654' },
224
+ { :alpha2 => 'KN', :name => 'Saint Kitts and Nevis', :alpha3 => 'KNA', :numeric => '659' },
225
+ { :alpha2 => 'LC', :name => 'Saint Lucia', :alpha3 => 'LCA', :numeric => '662' },
226
+ { :alpha2 => 'PM', :name => 'Saint Pierre and Miquelon', :alpha3 => 'SPM', :numeric => '666' },
227
+ { :alpha2 => 'VC', :name => 'Saint Vincent and the Grenadines', :alpha3 => 'VCT', :numeric => '670' },
228
+ { :alpha2 => 'WS', :name => 'Samoa', :alpha3 => 'WSM', :numeric => '882' },
229
+ { :alpha2 => 'SM', :name => 'San Marino', :alpha3 => 'SMR', :numeric => '674' },
230
+ { :alpha2 => 'ST', :name => 'Sao Tome and Principe', :alpha3 => 'STP', :numeric => '678' },
231
+ { :alpha2 => 'SA', :name => 'Saudi Arabia', :alpha3 => 'SAU', :numeric => '682' },
232
+ { :alpha2 => 'SN', :name => 'Senegal', :alpha3 => 'SEN', :numeric => '686' },
233
+ { :alpha2 => 'SC', :name => 'Seychelles', :alpha3 => 'SYC', :numeric => '690' },
234
+ { :alpha2 => 'SL', :name => 'Sierra Leone', :alpha3 => 'SLE', :numeric => '694' },
235
+ { :alpha2 => 'SG', :name => 'Singapore', :alpha3 => 'SGP', :numeric => '702' },
236
+ { :alpha2 => 'SK', :name => 'Slovakia', :alpha3 => 'SVK', :numeric => '703' },
237
+ { :alpha2 => 'SI', :name => 'Slovenia', :alpha3 => 'SVN', :numeric => '705' },
238
+ { :alpha2 => 'SB', :name => 'Solomon Islands', :alpha3 => 'SLB', :numeric => '090' },
239
+ { :alpha2 => 'SO', :name => 'Somalia', :alpha3 => 'SOM', :numeric => '706' },
240
+ { :alpha2 => 'ZA', :name => 'South Africa', :alpha3 => 'ZAF', :numeric => '710' },
241
+ { :alpha2 => 'ES', :name => 'Spain', :alpha3 => 'ESP', :numeric => '724' },
242
+ { :alpha2 => 'LK', :name => 'Sri Lanka', :alpha3 => 'LKA', :numeric => '144' },
243
+ { :alpha2 => 'SD', :name => 'Sudan', :alpha3 => 'SDN', :numeric => '736' },
244
+ { :alpha2 => 'SR', :name => 'Suriname', :alpha3 => 'SUR', :numeric => '740' },
245
+ { :alpha2 => 'SJ', :name => 'Svalbard and Jan Mayen', :alpha3 => 'SJM', :numeric => '744' },
246
+ { :alpha2 => 'SZ', :name => 'Swaziland', :alpha3 => 'SWZ', :numeric => '748' },
247
+ { :alpha2 => 'SE', :name => 'Sweden', :alpha3 => 'SWE', :numeric => '752' },
248
+ { :alpha2 => 'CH', :name => 'Switzerland', :alpha3 => 'CHE', :numeric => '756' },
249
+ { :alpha2 => 'SY', :name => 'Syrian Arab Republic', :alpha3 => 'SYR', :numeric => '760' },
250
+ { :alpha2 => 'TW', :name => 'Taiwan, Province of China', :alpha3 => 'TWN', :numeric => '158' },
251
+ { :alpha2 => 'TJ', :name => 'Tajikistan', :alpha3 => 'TJK', :numeric => '762' },
252
+ { :alpha2 => 'TZ', :name => 'Tanzania, United Republic of', :alpha3 => 'TZA', :numeric => '834' },
253
+ { :alpha2 => 'TH', :name => 'Thailand', :alpha3 => 'THA', :numeric => '764' },
254
+ { :alpha2 => 'TG', :name => 'Togo', :alpha3 => 'TGO', :numeric => '768' },
255
+ { :alpha2 => 'TK', :name => 'Tokelau', :alpha3 => 'TKL', :numeric => '772' },
256
+ { :alpha2 => 'TO', :name => 'Tonga', :alpha3 => 'TON', :numeric => '776' },
257
+ { :alpha2 => 'TT', :name => 'Trinidad and Tobago', :alpha3 => 'TTO', :numeric => '780' },
258
+ { :alpha2 => 'TN', :name => 'Tunisia', :alpha3 => 'TUN', :numeric => '788' },
259
+ { :alpha2 => 'TR', :name => 'Turkey', :alpha3 => 'TUR', :numeric => '792' },
260
+ { :alpha2 => 'TM', :name => 'Turkmenistan', :alpha3 => 'TKM', :numeric => '795' },
261
+ { :alpha2 => 'TC', :name => 'Turks and Caicos Islands', :alpha3 => 'TCA', :numeric => '796' },
262
+ { :alpha2 => 'TV', :name => 'Tuvalu', :alpha3 => 'TUV', :numeric => '798' },
263
+ { :alpha2 => 'UG', :name => 'Uganda', :alpha3 => 'UGA', :numeric => '800' },
264
+ { :alpha2 => 'UA', :name => 'Ukraine', :alpha3 => 'UKR', :numeric => '804' },
265
+ { :alpha2 => 'AE', :name => 'United Arab Emirates', :alpha3 => 'ARE', :numeric => '784' },
266
+ { :alpha2 => 'GB', :name => 'United Kingdom', :alpha3 => 'GBR', :numeric => '826' },
267
+ { :alpha2 => 'US', :name => 'United States', :alpha3 => 'USA', :numeric => '840' },
268
+ { :alpha2 => 'UY', :name => 'Uruguay', :alpha3 => 'URY', :numeric => '858' },
269
+ { :alpha2 => 'UZ', :name => 'Uzbekistan', :alpha3 => 'UZB', :numeric => '860' },
270
+ { :alpha2 => 'VU', :name => 'Vanuatu', :alpha3 => 'VUT', :numeric => '548' },
271
+ { :alpha2 => 'VE', :name => 'Venezuela', :alpha3 => 'VEN', :numeric => '862' },
272
+ { :alpha2 => 'VN', :name => 'Viet Nam', :alpha3 => 'VNM', :numeric => '704' },
273
+ { :alpha2 => 'VG', :name => 'Virgin Islands, British', :alpha3 => 'VGB', :numeric => '092' },
274
+ { :alpha2 => 'VI', :name => 'Virgin Islands, U.S.', :alpha3 => 'VIR', :numeric => '850' },
275
+ { :alpha2 => 'WF', :name => 'Wallis and Futuna', :alpha3 => 'WLF', :numeric => '876' },
276
+ { :alpha2 => 'EH', :name => 'Western Sahara', :alpha3 => 'ESH', :numeric => '732' },
277
+ { :alpha2 => 'YE', :name => 'Yemen', :alpha3 => 'YEM', :numeric => '887' },
278
+ { :alpha2 => 'ZM', :name => 'Zambia', :alpha3 => 'ZMB', :numeric => '894' },
279
+ { :alpha2 => 'ZW', :name => 'Zimbabwe', :alpha3 => 'ZWE', :numeric => '716' }
280
+ ]
281
+
282
+ def self.find(name)
283
+ raise InvalidCountryCodeError, "Cannot lookup country for an empty name" if name.blank?
284
+
285
+ case name.length
286
+ when 2, 3
287
+ upcase_name = name.upcase
288
+ country_code = CountryCode.new(name)
289
+ country = COUNTRIES.detect{|c| c[country_code.format] == upcase_name }
290
+ else
291
+ country = COUNTRIES.detect{|c| c[:name] == name }
292
+ end
293
+ raise InvalidCountryCodeError, "No country could be found for the country #{name}" if country.nil?
294
+ Country.new(country.dup)
295
+ end
296
+ end
297
+ end