paygate-ruby 0.1.6 → 0.1.11
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -28
- data/LICENSE.txt +21 -21
- data/README.md +327 -316
- data/Rakefile +3 -2
- data/data/card_bin_20191001.xlsx +0 -0
- data/data/config.yml +2744 -2686
- data/lib/paygate/aes.rb +150 -150
- data/lib/paygate/aes_ctr.rb +133 -133
- data/lib/paygate/configuration.rb +16 -16
- data/lib/paygate/helpers/form_helper.rb +155 -80
- data/lib/paygate/member.rb +21 -21
- data/lib/paygate/profile.rb +30 -30
- data/lib/paygate/response.rb +25 -25
- data/lib/paygate/transaction.rb +58 -47
- data/lib/paygate/version.rb +3 -3
- data/lib/paygate-ruby.rb +48 -48
- data/spec/integration/paygate_spec.rb +9 -0
- data/spec/spec_helper.rb +10 -0
- data/vendor/assets/javascripts/paygate.js +86 -81
- metadata +38 -26
- data/.gitignore +0 -9
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -4
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/data/card_bin_20190201.xlsx +0 -0
- data/paygate-ruby.gemspec +0 -24
@@ -1,80 +1,155 @@
|
|
1
|
-
module Paygate
|
2
|
-
module FormHelper
|
3
|
-
|
4
|
-
|
5
|
-
'
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
1
|
+
module Paygate
|
2
|
+
module FormHelper
|
3
|
+
FORM_TEXT_FIELDS = {
|
4
|
+
mid: {
|
5
|
+
placeholder: 'Member ID'
|
6
|
+
},
|
7
|
+
|
8
|
+
locale: {
|
9
|
+
name: 'langcode',
|
10
|
+
default: 'KR',
|
11
|
+
placeholder: 'Language'
|
12
|
+
},
|
13
|
+
|
14
|
+
charset: {
|
15
|
+
default: 'UTF-8',
|
16
|
+
placeholder: 'Charset'
|
17
|
+
},
|
18
|
+
|
19
|
+
title: {
|
20
|
+
name: 'goodname',
|
21
|
+
placeholder: 'Title'
|
22
|
+
},
|
23
|
+
|
24
|
+
currency: {
|
25
|
+
name: 'goodcurrency',
|
26
|
+
default: 'WON',
|
27
|
+
placeholder: 'Currency'
|
28
|
+
},
|
29
|
+
|
30
|
+
amount: {
|
31
|
+
name: 'unitprice',
|
32
|
+
placeholder: 'Amount'
|
33
|
+
},
|
34
|
+
|
35
|
+
meta1: {
|
36
|
+
name: 'goodoption1',
|
37
|
+
placeholder: 'Good Option 1'
|
38
|
+
},
|
39
|
+
|
40
|
+
meta2: {
|
41
|
+
name: 'goodoption2',
|
42
|
+
placeholder: 'Good Option 2'
|
43
|
+
},
|
44
|
+
|
45
|
+
meta3: {
|
46
|
+
name: 'goodoption3',
|
47
|
+
placeholder: 'Good Option 3'
|
48
|
+
},
|
49
|
+
|
50
|
+
meta4: {
|
51
|
+
name: 'goodoption4',
|
52
|
+
placeholder: 'Good Option 4'
|
53
|
+
},
|
54
|
+
|
55
|
+
meta5: {
|
56
|
+
name: 'goodoption5',
|
57
|
+
placeholder: 'Good Option 5'
|
58
|
+
},
|
59
|
+
|
60
|
+
pay_method: {
|
61
|
+
name: 'paymethod',
|
62
|
+
default: 'card',
|
63
|
+
placeholder: 'Pay Method'
|
64
|
+
},
|
65
|
+
|
66
|
+
customer_name: {
|
67
|
+
name: 'receipttoname',
|
68
|
+
placeholder: 'Customer Name'
|
69
|
+
},
|
70
|
+
|
71
|
+
customer_email: {
|
72
|
+
name: 'receipttoemail',
|
73
|
+
placeholder: 'Customer Email'
|
74
|
+
},
|
75
|
+
|
76
|
+
card_number: {
|
77
|
+
name: 'cardnumber',
|
78
|
+
placeholder: 'Card Number'
|
79
|
+
},
|
80
|
+
|
81
|
+
expiry_year: {
|
82
|
+
name: 'cardexpireyear',
|
83
|
+
placeholder: 'Expiry Year'
|
84
|
+
},
|
85
|
+
|
86
|
+
expiry_month: {
|
87
|
+
name: 'cardexpiremonth',
|
88
|
+
placeholder: 'Expiry Month'
|
89
|
+
},
|
90
|
+
|
91
|
+
cvv: {
|
92
|
+
name: 'cardsecretnumber',
|
93
|
+
placeholder: 'CVV'
|
94
|
+
},
|
95
|
+
|
96
|
+
card_auth_code: {
|
97
|
+
name: 'cardauthcode',
|
98
|
+
placeholder: 'Card Auth Code'
|
99
|
+
},
|
100
|
+
|
101
|
+
response_code: {
|
102
|
+
name: 'replycode',
|
103
|
+
placeholder: 'Response Code'
|
104
|
+
},
|
105
|
+
|
106
|
+
response_message: {
|
107
|
+
name: 'replyMsg',
|
108
|
+
placeholder: 'Response Message'
|
109
|
+
},
|
110
|
+
|
111
|
+
tid: {
|
112
|
+
placeholder: 'TID'
|
113
|
+
},
|
114
|
+
|
115
|
+
profile_no: {
|
116
|
+
placeholder: 'Profile No'
|
117
|
+
},
|
118
|
+
|
119
|
+
hash_result: {
|
120
|
+
name: 'hashresult',
|
121
|
+
placeholder: 'Hash Result'
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
def paygate_open_pay_api_js_url
|
126
|
+
(Paygate.configuration.mode == :live) ?
|
127
|
+
'https://api.paygate.net/ajax/common/OpenPayAPI.js'.freeze :
|
128
|
+
'https://stgapi.paygate.net/ajax/common/OpenPayAPI.js'.freeze
|
129
|
+
end
|
130
|
+
|
131
|
+
def paygate_open_pay_api_form(options = {})
|
132
|
+
form_tag({}, name: 'PGIOForm') do
|
133
|
+
fields = []
|
134
|
+
|
135
|
+
FORM_TEXT_FIELDS.each do |key, opts|
|
136
|
+
arg_opts = options[key] || {}
|
137
|
+
fields << text_field_tag(
|
138
|
+
key,
|
139
|
+
arg_opts[:value] || opts[:default],
|
140
|
+
name: opts[:name] || key.to_s,
|
141
|
+
placeholder: arg_opts[:placeholder] || opts[:placeholder]
|
142
|
+
).html_safe
|
143
|
+
end
|
144
|
+
|
145
|
+
fields.join.html_safe
|
146
|
+
end.html_safe
|
147
|
+
end
|
148
|
+
|
149
|
+
def paygate_open_pay_api_screen
|
150
|
+
content_tag(:div, nil, id: 'PGIOscreen')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
ActionView::Base.send :include, Paygate::FormHelper
|
data/lib/paygate/member.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
module Paygate
|
2
|
-
class Member
|
3
|
-
attr_reader :mid, :secret
|
4
|
-
|
5
|
-
def initialize(mid, secret)
|
6
|
-
@mid, @secret = mid, secret
|
7
|
-
end
|
8
|
-
|
9
|
-
def refund_transaction(txn_id, options = {})
|
10
|
-
txn = Transaction.new(txn_id)
|
11
|
-
txn.member = self
|
12
|
-
txn.refund(options)
|
13
|
-
end
|
14
|
-
|
15
|
-
def profile_pay(profile_no, currency, amount)
|
16
|
-
profile = Profile.new(profile_no)
|
17
|
-
profile.member = self
|
18
|
-
profile.purchase(currency, amount)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
1
|
+
module Paygate
|
2
|
+
class Member
|
3
|
+
attr_reader :mid, :secret
|
4
|
+
|
5
|
+
def initialize(mid, secret)
|
6
|
+
@mid, @secret = mid, secret
|
7
|
+
end
|
8
|
+
|
9
|
+
def refund_transaction(txn_id, options = {})
|
10
|
+
txn = Transaction.new(txn_id)
|
11
|
+
txn.member = self
|
12
|
+
txn.refund(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def profile_pay(profile_no, currency, amount)
|
16
|
+
profile = Profile.new(profile_no)
|
17
|
+
profile.member = self
|
18
|
+
profile.purchase(currency, amount)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/paygate/profile.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'net/http'
|
3
|
-
|
4
|
-
module Paygate
|
5
|
-
class Profile
|
6
|
-
PURCHASE_URL = 'https://service.paygate.net/INTL/pgtlProcess3.jsp'.freeze
|
7
|
-
|
8
|
-
attr_reader :profile_no
|
9
|
-
attr_accessor :member
|
10
|
-
|
11
|
-
def initialize(profile_no)
|
12
|
-
@profile_no = profile_no
|
13
|
-
end
|
14
|
-
|
15
|
-
def purchase(currency, amount)
|
16
|
-
# Prepare params
|
17
|
-
params = { profile_no: profile_no,
|
18
|
-
mid: member.mid,
|
19
|
-
goodcurrency: currency,
|
20
|
-
unitprice: amount }.delete_if { |_, v| v.blank? }
|
21
|
-
|
22
|
-
# Make request
|
23
|
-
uri = URI(PURCHASE_URL)
|
24
|
-
uri.query = ::URI.encode_www_form(params)
|
25
|
-
response = ::Net::HTTP.get_response(uri)
|
26
|
-
|
27
|
-
Response.build_from_net_http_response(:profile_pay, response)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module Paygate
|
5
|
+
class Profile
|
6
|
+
PURCHASE_URL = 'https://service.paygate.net/INTL/pgtlProcess3.jsp'.freeze
|
7
|
+
|
8
|
+
attr_reader :profile_no
|
9
|
+
attr_accessor :member
|
10
|
+
|
11
|
+
def initialize(profile_no)
|
12
|
+
@profile_no = profile_no
|
13
|
+
end
|
14
|
+
|
15
|
+
def purchase(currency, amount)
|
16
|
+
# Prepare params
|
17
|
+
params = { profile_no: profile_no,
|
18
|
+
mid: member.mid,
|
19
|
+
goodcurrency: currency,
|
20
|
+
unitprice: amount }.delete_if { |_, v| v.blank? }
|
21
|
+
|
22
|
+
# Make request
|
23
|
+
uri = URI(PURCHASE_URL)
|
24
|
+
uri.query = ::URI.encode_www_form(params)
|
25
|
+
response = ::Net::HTTP.get_response(uri)
|
26
|
+
|
27
|
+
Response.build_from_net_http_response(:profile_pay, response)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/paygate/response.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
module Paygate
|
2
|
-
class Response
|
3
|
-
attr_accessor :transaction_type, :http_code, :message, :body, :raw_info, :json
|
4
|
-
|
5
|
-
def self.build_from_net_http_response(txn_type, response)
|
6
|
-
r = new
|
7
|
-
r.transaction_type = txn_type
|
8
|
-
r.http_code = response.code
|
9
|
-
r.message = response.message
|
10
|
-
r.body = response.body
|
11
|
-
|
12
|
-
case txn_type
|
13
|
-
when :refund
|
14
|
-
r.json = JSON.parse response.body.gsub(/^callback\((.*)\)$/, '\1') if response.code.to_i == 200
|
15
|
-
when :profile_pay
|
16
|
-
r.json = {}
|
17
|
-
response.body.split('&').each do |key_value_pair|
|
18
|
-
key_value_ary = key_value_pair.split('=')
|
19
|
-
r.json[key_value_ary[0]] = key_value_ary[1]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
r
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
module Paygate
|
2
|
+
class Response
|
3
|
+
attr_accessor :transaction_type, :http_code, :message, :body, :raw_info, :json
|
4
|
+
|
5
|
+
def self.build_from_net_http_response(txn_type, response)
|
6
|
+
r = new
|
7
|
+
r.transaction_type = txn_type
|
8
|
+
r.http_code = response.code
|
9
|
+
r.message = response.message
|
10
|
+
r.body = response.body
|
11
|
+
|
12
|
+
case txn_type
|
13
|
+
when :refund
|
14
|
+
r.json = JSON.parse response.body.gsub(/^callback\((.*)\)$/, '\1') if response.code.to_i == 200
|
15
|
+
when :profile_pay
|
16
|
+
r.json = {}
|
17
|
+
response.body.split('&').each do |key_value_pair|
|
18
|
+
key_value_ary = key_value_pair.split('=')
|
19
|
+
r.json[key_value_ary[0]] = key_value_ary[1]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
r
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/paygate/transaction.rb
CHANGED
@@ -1,47 +1,58 @@
|
|
1
|
-
require 'digest'
|
2
|
-
require 'uri'
|
3
|
-
require 'net/http'
|
4
|
-
|
5
|
-
module Paygate
|
6
|
-
class Transaction
|
7
|
-
FULL_AMOUNT_IDENTIFIER = 'F'.freeze
|
8
|
-
|
9
|
-
attr_reader :tid
|
10
|
-
attr_accessor :member
|
11
|
-
|
12
|
-
def initialize(tid)
|
13
|
-
@tid = tid
|
14
|
-
end
|
15
|
-
|
16
|
-
def refund(options = {})
|
17
|
-
# Encrypt data
|
18
|
-
api_key_256 = ::Digest::SHA256.hexdigest(member.secret)
|
19
|
-
aes_ctr = AesCtr.encrypt(tid, api_key_256, 256)
|
20
|
-
tid_enc = "AES256#{aes_ctr}"
|
21
|
-
|
22
|
-
# Prepare params
|
23
|
-
params = { callback: 'callback', mid: member.mid, tid: tid_enc }
|
24
|
-
params.merge!(options.slice(:amount))
|
25
|
-
params[:amount] ||= FULL_AMOUNT_IDENTIFIER
|
26
|
-
params[:mb_serial_no] = options[:order_id]
|
27
|
-
params.delete_if { |_, v| v.blank? }
|
28
|
-
|
29
|
-
# Make request
|
30
|
-
uri = URI(self.class.refund_api_url)
|
31
|
-
uri.query = ::URI.encode_www_form(params)
|
32
|
-
response = ::Net::HTTP.get_response(uri)
|
33
|
-
|
34
|
-
r = Response.build_from_net_http_response(:refund, response)
|
35
|
-
r.raw_info = OpenStruct.new(tid: tid, tid_enc: tid_enc, request_url: uri.to_s)
|
36
|
-
r
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
1
|
+
require 'digest'
|
2
|
+
require 'uri'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module Paygate
|
6
|
+
class Transaction
|
7
|
+
FULL_AMOUNT_IDENTIFIER = 'F'.freeze
|
8
|
+
|
9
|
+
attr_reader :tid
|
10
|
+
attr_accessor :member
|
11
|
+
|
12
|
+
def initialize(tid)
|
13
|
+
@tid = tid
|
14
|
+
end
|
15
|
+
|
16
|
+
def refund(options = {})
|
17
|
+
# Encrypt data
|
18
|
+
api_key_256 = ::Digest::SHA256.hexdigest(member.secret)
|
19
|
+
aes_ctr = AesCtr.encrypt(tid, api_key_256, 256)
|
20
|
+
tid_enc = "AES256#{aes_ctr}"
|
21
|
+
|
22
|
+
# Prepare params
|
23
|
+
params = { callback: 'callback', mid: member.mid, tid: tid_enc }
|
24
|
+
params.merge!(options.slice(:amount))
|
25
|
+
params[:amount] ||= FULL_AMOUNT_IDENTIFIER
|
26
|
+
params[:mb_serial_no] = options[:order_id]
|
27
|
+
params.delete_if { |_, v| v.blank? }
|
28
|
+
|
29
|
+
# Make request
|
30
|
+
uri = URI(self.class.refund_api_url)
|
31
|
+
uri.query = ::URI.encode_www_form(params)
|
32
|
+
response = ::Net::HTTP.get_response(uri)
|
33
|
+
|
34
|
+
r = Response.build_from_net_http_response(:refund, response)
|
35
|
+
r.raw_info = OpenStruct.new(tid: tid, tid_enc: tid_enc, request_url: uri.to_s)
|
36
|
+
r
|
37
|
+
end
|
38
|
+
|
39
|
+
# Doc: https://km.paygate.net/pages/viewpage.action?pageId=9207875
|
40
|
+
def verify
|
41
|
+
params = { tid: tid, verifyNum: 100 }
|
42
|
+
|
43
|
+
uri = URI('https://service.paygate.net/djemals/settle/verifyReceived.jsp')
|
44
|
+
uri.query = ::URI.encode_www_form(params)
|
45
|
+
response = ::Net::HTTP.get_response(uri)
|
46
|
+
|
47
|
+
Response.build_from_net_http_response(:verify, response)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.refund_api_url
|
53
|
+
(Paygate.configuration.mode == :live) ?
|
54
|
+
'https://service.paygate.net/service/cancelAPI.json' :
|
55
|
+
'https://stgsvc.paygate.net/service/cancelAPI.json'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/paygate/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Paygate
|
2
|
-
VERSION = '0.1.
|
3
|
-
end
|
1
|
+
module Paygate
|
2
|
+
VERSION = '0.1.11'
|
3
|
+
end
|
data/lib/paygate-ruby.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
require 'paygate/configuration'
|
4
|
-
require 'paygate/aes'
|
5
|
-
require 'paygate/aes_ctr'
|
6
|
-
|
7
|
-
require 'paygate/
|
8
|
-
require 'paygate/
|
9
|
-
require 'paygate/
|
10
|
-
require 'paygate/
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
CONFIG = YAML.load(File.read(File.expand_path('../data/config.yml', File.dirname(__FILE__)))).freeze
|
18
|
-
LOCALES_MAP = CONFIG[:locales].freeze
|
19
|
-
INTL_BRANDS_MAP = CONFIG[:intl][:brands].freeze
|
20
|
-
KOREA_BIN_NUMBERS = CONFIG[:korea][:bin_numbers].freeze
|
21
|
-
|
22
|
-
DEFAULT_CURRENCY = 'WON'.freeze
|
23
|
-
DEFAULT_LOCALE = 'US'.freeze
|
24
|
-
|
25
|
-
def mapped_currency(currency)
|
26
|
-
return DEFAULT_CURRENCY unless currency.present?
|
27
|
-
|
28
|
-
currency.to_s == 'KRW' ? 'WON' : currency.to_s
|
29
|
-
end
|
30
|
-
module_function :mapped_currency
|
31
|
-
|
32
|
-
def mapped_locale(locale)
|
33
|
-
locale.present? ? LOCALES_MAP[locale.to_s] : DEFAULT_LOCALE
|
34
|
-
end
|
35
|
-
module_function :mapped_locale
|
36
|
-
|
37
|
-
class << self
|
38
|
-
attr_writer :configuration
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.configuration
|
42
|
-
@configuration ||= Configuration.new
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.configure
|
46
|
-
yield configuration
|
47
|
-
end
|
48
|
-
end
|
1
|
+
require 'yaml'
|
2
|
+
require 'paygate/version'
|
3
|
+
require 'paygate/configuration'
|
4
|
+
require 'paygate/aes'
|
5
|
+
require 'paygate/aes_ctr'
|
6
|
+
require 'paygate/member'
|
7
|
+
require 'paygate/response'
|
8
|
+
require 'paygate/transaction'
|
9
|
+
require 'paygate/profile'
|
10
|
+
require 'paygate/helpers/form_helper' if defined?(ActionView)
|
11
|
+
|
12
|
+
module Paygate
|
13
|
+
if defined?(Rails)
|
14
|
+
class Engine < ::Rails::Engine; end
|
15
|
+
end
|
16
|
+
|
17
|
+
CONFIG = YAML.load(File.read(File.expand_path('../data/config.yml', File.dirname(__FILE__)))).freeze
|
18
|
+
LOCALES_MAP = CONFIG[:locales].freeze
|
19
|
+
INTL_BRANDS_MAP = CONFIG[:intl][:brands].freeze
|
20
|
+
KOREA_BIN_NUMBERS = CONFIG[:korea][:bin_numbers].freeze
|
21
|
+
|
22
|
+
DEFAULT_CURRENCY = 'WON'.freeze
|
23
|
+
DEFAULT_LOCALE = 'US'.freeze
|
24
|
+
|
25
|
+
def mapped_currency(currency)
|
26
|
+
return DEFAULT_CURRENCY unless currency.present?
|
27
|
+
|
28
|
+
currency.to_s == 'KRW' ? 'WON' : currency.to_s
|
29
|
+
end
|
30
|
+
module_function :mapped_currency
|
31
|
+
|
32
|
+
def mapped_locale(locale)
|
33
|
+
locale.present? ? LOCALES_MAP[locale.to_s] : DEFAULT_LOCALE
|
34
|
+
end
|
35
|
+
module_function :mapped_locale
|
36
|
+
|
37
|
+
class << self
|
38
|
+
attr_writer :configuration
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.configuration
|
42
|
+
@configuration ||= Configuration.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.configure
|
46
|
+
yield configuration
|
47
|
+
end
|
48
|
+
end
|