cic_payment 0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e7a9ab1ef67d2fa58b5d65ea218357c23309af5f
4
+ data.tar.gz: d6fa62f8539328b668989efa02990321301e1f99
5
+ SHA512:
6
+ metadata.gz: 90b86638090ab0a557fd21027e963ca72658475e01e42c34a659fd0a03399cd8059396cbc681b34e880e290d03b01fc03eaeb12b3146f67e5b4a439d33677688
7
+ data.tar.gz: 93bda4215ce221d1f59a429e37a1e48a252d9a791b01394fd6b8f96d3dc60b80558da008425d9a79aae37a55eaf5264e2742016e18a992670f29242c09e0e2c0
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/MIT-LICENSE ADDED
@@ -0,0 +1,84 @@
1
+ #encoding: utf-8
2
+ Copyright (c) 2009 Novelys
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ #==============================================================================
24
+ #
25
+ # "Open source" kit for P@iement CM-CIC(TM).
26
+ # Integration sample in a merchant site for Ruby
27
+ #
28
+ # Author : Euro-Information/e-Commerce (contact: centrecom@e-i.com)
29
+ # Version : 1.0
30
+ # Date : 01/01/2009
31
+ #
32
+ # Copyright: (c) 2009 Euro-Information. All rights reserved.
33
+ #
34
+ #==============================================================================
35
+
36
+ Redistribution and use in source and binary forms, with or without
37
+ modification, are permitted provided that the following conditions are
38
+ met:
39
+ - Redistributions of source code must retain the above copyright
40
+ notice and the following disclaimer.
41
+ - Redistributions in binary form must reproduce the above copyright
42
+ notice and the following disclaimer in the documentation and/or
43
+ other materials provided with the distribution.
44
+ - Neither the name of Euro-Information nor the names of its
45
+ contributors may be used to endorse or promote products derived
46
+ from this software without specific prior written permission.
47
+
48
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51
+ A PARTICULAR PURPOSE ARE DISCLAIMED.
52
+ IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
53
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
55
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
57
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
58
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60
+
61
+ Note: Euro-Information does not provide person-to-person technical
62
+ support for tryout of CM-CIC P@iement examples. We do however
63
+ welcome your feedback which can be sent to <centrecom@e-i.com>.
64
+
65
+ #------------------------------------------------------------------------------
66
+
67
+ This software uses RSA Data Security, Inc. MD5 Message-Digest Algorithm.
68
+
69
+ License to copy and use this software is granted provided that it is
70
+ identified as the "RSA Data Security, Inc. MD5 Message-Digest
71
+ Algorithm" in all material mentioning or referencing this software or
72
+ this function.
73
+ License is also granted to make and use derivative works provided that
74
+ such works are identified as "derived from the RSA Data Security,
75
+ Inc. MD5 Message-Digest Algorithm" in all material mentioning or
76
+ referencing the derived work.
77
+ RSA Data Security, Inc. makes no representations concerning either the
78
+ merchantability of this software or the suitability of this software
79
+ for any particular purpose. It is provided "as is" without express or
80
+ implied warranty of any kind.
81
+ These notices must be retained in any copies of any part of this
82
+ documentation and/or software.
83
+
84
+ #==============================================================================
data/README.markdown ADDED
@@ -0,0 +1,105 @@
1
+ # CIC Payment
2
+
3
+ CIC Payment is a plugin to ease credit card payment with the CIC / Credit Mutuel banks system version 3.0.
4
+ It's a Ruby on Rails port of the connexion kits published by the bank.
5
+
6
+ * The banks payment [site](http://www.cmcicpaiement.fr)
7
+
8
+
9
+ ## INSTALL
10
+
11
+ In your Gemfile
12
+
13
+ gem 'cic_payment'
14
+
15
+ ## USAGE
16
+
17
+ ### Setup
18
+
19
+ Create a `cic_payment.yml` config file in the `Rails.root/config` directory:
20
+
21
+ base: &base
22
+ # Hmac key calculated with the js calculator given by CIC
23
+ hmac_key: "AA123456AAAAAA789123BBBBBB123456CCCCCC12345678"
24
+
25
+ # TPE number
26
+ tpe: "010203"
27
+
28
+ # Version
29
+ version: "3.0"
30
+
31
+ # Merchant name
32
+ societe: "marchantname"
33
+
34
+ # Auto response URL
35
+ url_retour: 'http://return.fr'
36
+
37
+ # Success return path
38
+ url_retour_ok: 'http://return.ok'
39
+
40
+ # Error/cancel return path
41
+ url_retour_err: 'http://return.err'
42
+
43
+ target_url: "https://paiement.creditmutuel.fr/test/paiement.cgi"
44
+
45
+ production:
46
+ <<: *base
47
+ target_url: "https://paiement.creditmutuel.fr/paiement.cgi"
48
+
49
+ development:
50
+ <<: *base
51
+
52
+ test:
53
+ <<: *base
54
+
55
+ ***Note:*** this file _must_ be named _exactly_ `cic_payment.yml` or an exception would be raised
56
+
57
+ `target_url` needs to point to the controller method handling the bank response (e.g. see below `payments#create`)
58
+
59
+ ### In the controller :
60
+
61
+ class PaymentsController < ApplicationController
62
+
63
+ def index
64
+ # :montant and :reference are required, you can also add :texte_libre, :lgue and :mail arguements if needed
65
+ @request = CicPayment.new.request(:montant => '123', :reference => '456')
66
+ end
67
+
68
+ ### Then in the view, generate the form:
69
+
70
+ The form generated is populated with hidden fields that will be sent to the bank gateway
71
+
72
+ # :button_text and :button_class are optionnal, use them for style cutomization if needed
73
+ = cic_payment_form(@request, :button_text => 'Payer', :button_class => 'btn btn-pink')
74
+
75
+ ### Now, listen to the bank transaction result:
76
+
77
+ Just add a create action in your payment controller
78
+
79
+ class PaymentsController < ApplicationController
80
+
81
+ protect_from_forgery :except => [:create]
82
+
83
+ def index
84
+ # :montant and :reference are required, you can also add :texte_libre, :lgue and :mail arguements if needed
85
+ @request = CicPayment.new.request(:montant => '123', :reference => '456')
86
+ end
87
+
88
+ def create
89
+ @response = CicPayment.new.response(params)
90
+
91
+ # Save and/or process the order as you need it (or not)
92
+ end
93
+
94
+ ...
95
+
96
+ The @response variable contains all the regular rails params received from the bank, plus an extra :success boolean parameter.
97
+
98
+
99
+ ## Contributors
100
+ * Novelys Team : original gem and cryptographic stuff
101
+ * Guillaume Barillot : refactoring and usage simplification
102
+ * Michael Brung : configuration file refactoring.
103
+
104
+ ## Licence
105
+ released under the MIT license
@@ -0,0 +1,18 @@
1
+ #encoding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "cic_payment"
6
+ s.version = "0.4"
7
+ s.date = "2014-03-18"
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Novelys Team", 'Guillaume Barillot', 'Regis Millet (aka Kulgar)']
10
+ s.email = "kulgar@ct2c.fr"
11
+ s.homepage = "https://github.com/Kulgar/cic_payment"
12
+ s.summary = %q{CIC / Credit Mutuel credit card payment toolbox}
13
+ s.description = %q{CIC Payment is a gem to ease credit card payment with the CIC / Credit Mutuel banks system. It's a Ruby on Rails port of the connexion kits published by the bank.}
14
+ s.license = "MIT"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.require_paths = ["lib"]
18
+ end
@@ -0,0 +1,172 @@
1
+ #encoding: utf-8
2
+ require 'digest/sha1'
3
+ require 'openssl'
4
+ require 'payment_settings'
5
+ require "view_helpers/form_helpers"
6
+
7
+ ActionView::Base.send :include, FormHelpers
8
+
9
+ class CicPayment < PaymentSettings
10
+
11
+ cattr_accessor :target_url, :version, :hmac_key, :tpe, :societe, :url_retour, :url_retour_ok, :url_retour_err, :societe
12
+ attr_accessor :date, :montant, :reference, :texte_libre, :lgue, :mail
13
+
14
+ @@tpe = ""
15
+ @@version = ""
16
+ @@societe = ""
17
+ @@hmac_key = ""
18
+ @@target_url = ""
19
+ @@url_retour = ""
20
+ @@url_retour_ok = ""
21
+ @@url_retour_err = ""
22
+
23
+ def initialize
24
+
25
+ settings = self.load_settings
26
+
27
+ @@tpe = settings[:tpe]
28
+ @@version = settings[:version]
29
+ @@societe = settings[:societe]
30
+ @@hmac_key = settings[:hmac_key]
31
+ @@target_url = settings[:target_url]
32
+ @@url_retour = settings[:url_retour]
33
+ @@url_retour_ok = settings[:url_retour_ok]
34
+ @@url_retour_err = settings[:url_retour_err]
35
+
36
+ end
37
+
38
+ def request(payment)
39
+
40
+ params = self.load_params(payment)
41
+
42
+ @date = Time.now.strftime(self.date_format)
43
+ @montant = params[:montant]
44
+ @reference = params[:reference]
45
+
46
+ @texte_libre = params[:texte_libre]
47
+ @lgue = params[:lgue]
48
+ @mail = params[:mail]
49
+
50
+ return self
51
+ end
52
+
53
+ def response(params)
54
+
55
+ if verify_hmac(params)
56
+
57
+ if params['code-retour'] == "Annulation"
58
+ params.update(:success => false)
59
+
60
+ elsif params['code-retour'] == "payetest"
61
+ params.update(:success => true)
62
+
63
+ elsif params['code-retour'] == "paiement"
64
+ params.update(:success => true)
65
+ end
66
+
67
+ else
68
+ params.update(:success => false)
69
+ end
70
+
71
+ end
72
+
73
+ def self.mac_string params
74
+ hmac_key = CicPayment.new
75
+ mac_string = [hmac_key.tpe, params['date'], params['montant'], params['reference'], params['texte-libre'], hmac_key.version, params['code-retour'], params['cvx'], params['vld'], params['brand'], params['status3ds'], params['numauto'], params['motifrefus'], params['originecb'], params['bincb'], params['hpancb'], params['ipclient'], params['originetr'], params['veres'], params['pares']].join('*') + "*"
76
+ end
77
+
78
+ def verify_hmac params
79
+ mac_string = [self.tpe, params['date'], params['montant'], params['reference'], params['texte-libre'], self.version, params['code-retour'], params['cvx'], params['vld'], params['brand'], params['status3ds'], params['numauto'], params['motifrefus'], params['originecb'], params['bincb'], params['hpancb'], params['ipclient'], params['originetr'], params['veres'], params['pares']].join('*') + "*"
80
+
81
+ params['MAC'] ? hmac = params['MAC'] : hmac = ""
82
+ self.valid_hmac?(hmac)
83
+ end
84
+
85
+ # Check if the HMAC matches the HMAC of the data string
86
+ def valid_hmac?(sent_mac)
87
+ hmac_token == sent_mac.downcase
88
+ end
89
+
90
+ # Return the HMAC for a data string
91
+ def hmac_token
92
+ # This chain must contains:
93
+ # <TPE>*<date>*<montant>*<reference>*<texte-libre>*<version>*<lgue>*<societe>*<mail>*
94
+ # <nbrech>*<dateech1>*<montantech1>*<dateech2>*<montantech2>*<dateech3>*<montantech3>*
95
+ # <dateech4>*<montantech4>*<options>
96
+ # For a regular payment, it will be somthing like this:
97
+ # 1234567*05/12/2006:11:55:23*62.73EUR*ABERTYP00145*ExempleTexteLibre*3.0*FR*monSite1*internaute@sonemail.fr**********
98
+ #
99
+ # So the chain array must contains 9 filled elements + 9 unfilled elements + 1 final star
100
+ # <text-libre>, <lgue> and <mail> are optional, but don't forget to put them in the chain if you decide to add
101
+ # them to the form
102
+ #
103
+ # For a fragmented payment:
104
+ # 1234567*05/12/2006:11:55:23*62.73EUR*ABERTYP00145*ExempleTexteLibre*3.0*FR*monSite1*internaute@sonemail.fr*
105
+ # 4*05/12/2006*16.23EUR*05/01/2007*15.5EUR*05/02/2007*15.5EUR*05/03/2007*15.5EUR*
106
+ chain = [self.tpe,
107
+ self.date,
108
+ self.montant,
109
+ self.reference,
110
+ self.texte_libre,
111
+ self.version,
112
+ self.lgue,
113
+ self.societe,
114
+ self.mail,
115
+ "", "", "", "", "", "", "", "", "", "" # 10 stars: 9 for fragmented unfilled params + 1 final star
116
+ ].join("*")
117
+
118
+ hmac_sha1(usable_key(self.hmac_key), chain).downcase
119
+ end
120
+
121
+ protected
122
+ def date_format
123
+ "%d/%m/%Y:%H:%M:%S"
124
+ end
125
+
126
+ def hmac_sha1(key, data)
127
+ length = 64
128
+
129
+ if (key.length > length)
130
+ key = [Digest::SHA1.hexdigest(key)].pack("H*")
131
+ end
132
+
133
+ key = key.ljust(length, 0.chr)
134
+ ipad = ''.ljust(length, 54.chr)
135
+ opad = ''.ljust(length, 92.chr)
136
+
137
+ k_ipad = compute(key, ipad)
138
+ k_opad = compute(key, opad)
139
+
140
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new("sha1"), key, data)
141
+ end
142
+
143
+ private
144
+ # Return the key to be used in the hmac method
145
+ def usable_key(hmac_key)
146
+
147
+ hex_string_key = hmac_key[0..37]
148
+ hex_final = hmac_key[38..40] + "00";
149
+
150
+ cca0 = hex_final[0].ord
151
+
152
+ if cca0 > 70 && cca0 < 97
153
+ hex_string_key += (cca0 - 23).chr + hex_final[1..2]
154
+ elsif hex_final[1..2] == "M"
155
+ hex_string_key += hex_final[0..1] + "0"
156
+ else
157
+ hex_string_key += hex_final[0..2]
158
+ end
159
+
160
+ [hex_string_key].pack("H*")
161
+ end
162
+
163
+ def compute(key, pad)
164
+ raise ArgumentError, "Can't bitwise-XOR a String with a non-String" \
165
+ unless pad.kind_of? String
166
+ raise ArgumentError, "Can't bitwise-XOR strings of different length" \
167
+ unless key.length == pad.length
168
+
169
+ result = (0..key.length-1).collect { |i| key[i].ord ^ pad[i].ord }
170
+ result.pack("C*")
171
+ end
172
+ end
@@ -0,0 +1,90 @@
1
+ #encoding: utf-8
2
+
3
+ class PaymentSettings
4
+ def initialize
5
+ @settings = {}
6
+ end
7
+
8
+ def load_settings
9
+ load_yaml_config
10
+ end
11
+
12
+ def load_params(payment)
13
+ required_params(payment)
14
+ optionnal_params(payment)
15
+ end
16
+
17
+ private
18
+ def optionnal_params(payment)
19
+ @settings ||= {}
20
+ @settings.update(:texte_libre => (payment[:texte_libre] || ""))
21
+ @settings.update(:lgue => (payment[:lgue] || "FR"))
22
+ @settings.update(:mail => (payment[:mail] || ""))
23
+ end
24
+
25
+ def required_params(payment)
26
+
27
+ @settings ||= {}
28
+
29
+ if payment[:montant]
30
+ @settings.update(:montant => ("%.2f" % payment[:montant]) + "EUR")
31
+ else
32
+ raise "CicPayment error ! Missing required parameter :montant"
33
+ end
34
+
35
+ if payment[:reference]
36
+ @settings.update(:reference => payment[:reference])
37
+ else
38
+ raise "CicPayment error ! Missing required parameter :reference"
39
+ end
40
+
41
+ end
42
+
43
+ def load_yaml_config
44
+ @settings ||= {}
45
+
46
+ path = Rails.root.join('config', 'cic_payment.yml')
47
+
48
+ if File.exist?(path)
49
+ config = YAML::load(ERB.new(File.read(path)).result)
50
+ else
51
+ raise "File config/cic_payment.yml does not exist"
52
+ end
53
+
54
+ env = Rails.env
55
+
56
+ unless config[env]
57
+ raise "config/cic_payment.yml is missing a section for `#{env}`"
58
+ end
59
+
60
+ settings = {
61
+ :tpe => config[env]['tpe'],
62
+ :version => config[env]['version'],
63
+ :societe => config[env]['societe'],
64
+ :hmac_key => config[env]['hmac_key'],
65
+ :target_url => config[env]['target_url']
66
+ }
67
+
68
+ %i(url_retour url_retour_ok url_retour_err).each do |k|
69
+ provided_setting_for_key = config[env][k.to_s]
70
+
71
+ if provided_setting_for_key.is_a? Hash
72
+ merged_setting_for_key = provided_setting_for_key.merge!(Rails.application.config.payments.default_url_options)
73
+
74
+ settings[k] = Rails.application.routes.url_helpers.url_for(merged_setting_for_key)
75
+ else
76
+ settings[k] = provided_setting_for_key
77
+ end
78
+ end
79
+
80
+ settings.each do |key, value|
81
+ if value
82
+ @settings.update(key => value)
83
+ else
84
+ raise "CicPayment error ! Missing parameter :#{key} in /config/cic_payment.yml config file"
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module CicPayment
2
+ VERSION = "0.4.0".freeze
3
+ end
@@ -0,0 +1,32 @@
1
+ #encoding: utf-8
2
+ module FormHelpers
3
+
4
+ def cic_payment_form(payment, options = {})
5
+
6
+ options[:button_text] ||= 'Payer'
7
+ options[:button_class] ||= ''
8
+
9
+ html = "<form name='cic_payment_form' action='#{payment.target_url}' method='post'>\n"
10
+
11
+ html << " <input type='hidden' name='version' id='version' value='#{payment.version}' />\n"
12
+ html << " <input type='hidden' name='TPE' id='TPE' value='#{payment.tpe}' />\n"
13
+ html << " <input type='hidden' name='date' id='date' value='#{payment.date}' />\n"
14
+ html << " <input type='hidden' name='montant' id='montant' value='#{payment.montant}' />\n"
15
+ html << " <input type='hidden' name='reference' id='reference' value='#{payment.reference}' />\n"
16
+ html << " <input type='hidden' name='MAC' id='MAC' value='#{payment.hmac_token}' />\n"
17
+ html << " <input type='hidden' name='url_retour' id='url_retour' value='#{payment.url_retour}' />\n"
18
+ html << " <input type='hidden' name='url_retour_ok' id='url_retour_ok' value='#{payment.url_retour_ok}' />\n"
19
+ html << " <input type='hidden' name='url_retour_err' id='url_retour_err' value='#{payment.url_retour_err}' />\n"
20
+ html << " <input type='hidden' name='lgue' id='lgue' value='#{payment.lgue}' />\n"
21
+ html << " <input type='hidden' name='societe' id='societe' value='#{payment.societe}' />\n"
22
+ html << " <input type='hidden' name='texte-libre' id='texte-libre' value='#{payment.texte_libre}' />\n"
23
+ html << " <input type='hidden' name='mail' id='mail' value='#{payment.mail}' />\n"
24
+
25
+ html << " <input type='submit' name='submit_cic_payment_form' value='#{options[:button_text]}' class='#{options[:button_class]}' />\n"
26
+ html << "</form>\n"
27
+
28
+ html.respond_to?(:html_safe) ? html.html_safe : html
29
+
30
+ end
31
+
32
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cic_payment
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.4'
5
+ platform: ruby
6
+ authors:
7
+ - Novelys Team
8
+ - Guillaume Barillot
9
+ - Regis Millet (aka Kulgar)
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-03-18 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: CIC Payment is a gem to ease credit card payment with the CIC / Credit
16
+ Mutuel banks system. It's a Ruby on Rails port of the connexion kits published by
17
+ the bank.
18
+ email: kulgar@ct2c.fr
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - MIT-LICENSE
25
+ - README.markdown
26
+ - cic_payment.gemspec
27
+ - lib/cic_payment.rb
28
+ - lib/payment_settings.rb
29
+ - lib/version.rb
30
+ - lib/view_helpers/form_helpers.rb
31
+ homepage: https://github.com/Kulgar/cic_payment
32
+ licenses:
33
+ - MIT
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 2.2.2
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: CIC / Credit Mutuel credit card payment toolbox
55
+ test_files: []
56
+ has_rdoc: