lolita-first-data 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.
- data/.rspec +2 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +140 -0
- data/LICENSE.txt +20 -0
- data/README.md +89 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/app/controllers/lolita/first_data/common_controller.rb +25 -0
- data/app/controllers/lolita/first_data/test_controller.rb +78 -0
- data/app/controllers/lolita/first_data/transaction_controller.rb +49 -0
- data/app/models/lolita/first_data/transaction.rb +55 -0
- data/config/locales/en.yml +109 -0
- data/config/locales/lv.yml +109 -0
- data/config/routes.rb +5 -0
- data/lib/generators/lolita_first_data/install_generator.rb +14 -0
- data/lib/generators/lolita_first_data/templates/migration.rb +21 -0
- data/lib/lolita-first-data.rb +6 -0
- data/lib/lolita-first-data/billing.rb +37 -0
- data/lib/lolita-first-data/custom_logger.rb +10 -0
- data/lib/lolita-first-data/gateway.rb +160 -0
- data/lib/lolita-first-data/rails.rb +6 -0
- data/lib/tasks/first_data_tasks.rake +78 -0
- data/lolita-first-data.gemspec +95 -0
- data/spec/cert.pem +63 -0
- data/spec/fabricators/reservation_fabricator.rb +4 -0
- data/spec/fabricators/transaction_fabricator.rb +7 -0
- data/spec/first_data_spec.rb +67 -0
- data/spec/spec_helper.rb +101 -0
- data/spec/support/rails.rb +16 -0
- metadata +189 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
namespace :first_data do
|
4
|
+
desc "Generate certificates"
|
5
|
+
task :generate_certificate do
|
6
|
+
fdcg = FirstDataCertGenerator.new
|
7
|
+
fdcg.start
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class FirstDataCertGenerator
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@cert_type = prompt(%^\nCertificate type?
|
15
|
+
1. test
|
16
|
+
2. production^) == '2' ? 'production' : 'test'
|
17
|
+
@destination = File.join(Rails.root, "config", "first-data", @cert_type)
|
18
|
+
FileUtils.mkdir_p(@destination) unless File.exists?(@destination)
|
19
|
+
@domain = prompt("Your domain:")
|
20
|
+
@merchantId = prompt("Your merchantId:")
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
unless File.exists?("#{@destination}/ECOMM.pem")
|
25
|
+
gen_cert
|
26
|
+
end
|
27
|
+
sign_cert
|
28
|
+
end
|
29
|
+
|
30
|
+
def gen_cert
|
31
|
+
`openssl req -newkey rsa:1024 -keyout #{@destination}/#{@merchantId}_key.pem -out #{@destination}/#{@merchantId}_req.pem -subj "/C=lv/O=#{@domain}/CN=#{@merchantId}" -outform PEM`
|
32
|
+
if @cert_type == 'test'
|
33
|
+
puts "Open https://secureshop-test.firstdata.lv/report/keystore_.do and enter your email address and copy this into \"Cert Request (PEM)\""
|
34
|
+
puts File.open("#{@destination}/#{@merchantId}_req.pem", 'r').read.split("\n").collect{|line| line unless line =~ /^-/}.join("\n")
|
35
|
+
else
|
36
|
+
puts "Send \"#{@destination}/#{@merchantId}_req.pem\" to FirstData support email."
|
37
|
+
end
|
38
|
+
puts "\nAfter receiving email, download all attachments into #{@destination}"
|
39
|
+
prompt("To continue press [return]")
|
40
|
+
end
|
41
|
+
|
42
|
+
def sign_cert
|
43
|
+
puts "For PEM pass enter the same as in the first step, for import and export pass type new password."
|
44
|
+
`openssl pkcs12 -export -in #{@destination}/#{@merchantId}.pem -out #{@destination}/#{@merchantId}_keystore.p12 -certfile #{@destination}/ECOMM.pem -inkey #{@destination}/#{@merchantId}_key.pem`
|
45
|
+
`openssl pkcs12 -in #{@destination}/#{@merchantId}_keystore.p12 > #{@destination}/cert.pem`
|
46
|
+
puts "\nNow update your environment configuration files with constants:"
|
47
|
+
puts "\nFD_PEM = File.join(Rails.root, \"config\", \"first-data\", \"#{@cert_type}\", \"cert.pem\")"
|
48
|
+
puts "FD_PASS = '<Enter PEM pass phrase>'"
|
49
|
+
if @cert_type == 'test'
|
50
|
+
puts "\nAnd change mode to :test"
|
51
|
+
puts %^
|
52
|
+
config.after_initialize do
|
53
|
+
ActiveMerchant::Billing::Base.mode = :test
|
54
|
+
end
|
55
|
+
|
56
|
+
IMPORTANT
|
57
|
+
|
58
|
+
After you have test certificate you should run all FirstData tests https://secureshop-test.firstdata.lv/report/common/testplan/test.jsp
|
59
|
+
To do sou you need to update your merchant information https://secureshop-test.firstdata.lv/report/merchantlist.do
|
60
|
+
- change IP to your current IP
|
61
|
+
- change returnOkUrl and returnFailUrl to http://localhost:3000/first_data_test/test
|
62
|
+
- save
|
63
|
+
|
64
|
+
Now run server and start testing http://localhost:3000/first_data_test/test?nr=1
|
65
|
+
In transaction details you specify all data from response and amount as 1.00 LVL.
|
66
|
+
^
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def prompt q
|
73
|
+
puts "#{q}"
|
74
|
+
$stdout.flush
|
75
|
+
$stdin.gets.strip
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "lolita-first-data"
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["ITHouse, Gatis Tomsons"]
|
12
|
+
s.date = "2011-09-07"
|
13
|
+
s.description = "FirstData Payment plugin for Lolita using ActiveMerchant"
|
14
|
+
s.email = "gatis@ithouse.cc"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".rspec",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"app/controllers/lolita/first_data/common_controller.rb",
|
28
|
+
"app/controllers/lolita/first_data/test_controller.rb",
|
29
|
+
"app/controllers/lolita/first_data/transaction_controller.rb",
|
30
|
+
"app/models/lolita/first_data/transaction.rb",
|
31
|
+
"config/locales/en.yml",
|
32
|
+
"config/locales/lv.yml",
|
33
|
+
"config/routes.rb",
|
34
|
+
"lib/generators/lolita_first_data/install_generator.rb",
|
35
|
+
"lib/generators/lolita_first_data/templates/migration.rb",
|
36
|
+
"lib/lolita-first-data.rb",
|
37
|
+
"lib/lolita-first-data/billing.rb",
|
38
|
+
"lib/lolita-first-data/custom_logger.rb",
|
39
|
+
"lib/lolita-first-data/gateway.rb",
|
40
|
+
"lib/lolita-first-data/rails.rb",
|
41
|
+
"lib/tasks/first_data_tasks.rake",
|
42
|
+
"lolita-first-data.gemspec",
|
43
|
+
"spec/cert.pem",
|
44
|
+
"spec/fabricators/reservation_fabricator.rb",
|
45
|
+
"spec/fabricators/transaction_fabricator.rb",
|
46
|
+
"spec/first_data_spec.rb",
|
47
|
+
"spec/spec_helper.rb",
|
48
|
+
"spec/support/rails.rb"
|
49
|
+
]
|
50
|
+
s.homepage = "http://github.com/ithouse/lolita-first-data"
|
51
|
+
s.licenses = ["MIT"]
|
52
|
+
s.require_paths = ["lib"]
|
53
|
+
s.rubygems_version = "1.8.10"
|
54
|
+
s.summary = "FirstData Payment plugin for Lolita"
|
55
|
+
|
56
|
+
if s.respond_to? :specification_version then
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
60
|
+
s.add_runtime_dependency(%q<rails>, [">= 3.0.0"])
|
61
|
+
s.add_runtime_dependency(%q<activemerchant>, ["~> 1.17.0"])
|
62
|
+
s.add_development_dependency(%q<sqlite3>, ["~> 1.3.4"])
|
63
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
|
64
|
+
s.add_development_dependency(%q<webmock>, ["~> 1.7.6"])
|
65
|
+
s.add_development_dependency(%q<ruby-debug19>, ["~> 0.11.6"])
|
66
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
67
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
68
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
69
|
+
s.add_development_dependency(%q<fabrication>, ["~> 1.1.0"])
|
70
|
+
else
|
71
|
+
s.add_dependency(%q<rails>, [">= 3.0.0"])
|
72
|
+
s.add_dependency(%q<activemerchant>, ["~> 1.17.0"])
|
73
|
+
s.add_dependency(%q<sqlite3>, ["~> 1.3.4"])
|
74
|
+
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
75
|
+
s.add_dependency(%q<webmock>, ["~> 1.7.6"])
|
76
|
+
s.add_dependency(%q<ruby-debug19>, ["~> 0.11.6"])
|
77
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
78
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
79
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
80
|
+
s.add_dependency(%q<fabrication>, ["~> 1.1.0"])
|
81
|
+
end
|
82
|
+
else
|
83
|
+
s.add_dependency(%q<rails>, [">= 3.0.0"])
|
84
|
+
s.add_dependency(%q<activemerchant>, ["~> 1.17.0"])
|
85
|
+
s.add_dependency(%q<sqlite3>, ["~> 1.3.4"])
|
86
|
+
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
87
|
+
s.add_dependency(%q<webmock>, ["~> 1.7.6"])
|
88
|
+
s.add_dependency(%q<ruby-debug19>, ["~> 0.11.6"])
|
89
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
90
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
91
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
92
|
+
s.add_dependency(%q<fabrication>, ["~> 1.1.0"])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
data/spec/cert.pem
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
Bag Attributes
|
2
|
+
localKeyID: 43 9C BD D3 7A E2 0F AF 0B CD FE 3C DC 0D 1C F2 7B 31 01 3C
|
3
|
+
subject=/C=lv/O=rentmama.com/CN=1205715
|
4
|
+
issuer=/C=LV/ST=Riga/L=Riga/O=BSC/OU=BSC/CN=ECOMM/emailAddress=gatisa@bsc.lv
|
5
|
+
-----BEGIN CERTIFICATE-----
|
6
|
+
MIICaDCCAdGgAwIBAgIGASx+2FQ/MA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNVBAYT
|
7
|
+
AkxWMQ0wCwYDVQQIEwRSaWdhMQ0wCwYDVQQHEwRSaWdhMQwwCgYDVQQKEwNCU0Mx
|
8
|
+
DDAKBgNVBAsTA0JTQzEOMAwGA1UEAxMFRUNPTU0xHDAaBgkqhkiG9w0BCQEWDWdh
|
9
|
+
dGlzYUBic2MubHYwHhcNMTAxMTI0MTcwNDU1WhcNMTExMTI0MTcwNDU1WjA2MQsw
|
10
|
+
CQYDVQQGEwJsdjEVMBMGA1UEChMMcmVudG1hbWEuY29tMRAwDgYDVQQDEwcxMjA1
|
11
|
+
NzE1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDD1qUrW+wQWirKgO8TEmNY
|
12
|
+
0HQVMsX7KI7dnYDxZbmRrVJnphtfsPkSlG94mnJVVhfPMHZarR1jjBGegEyfvmND
|
13
|
+
A/gkqP+jb7Ab4F/YiD4mcBQPlraLFNH/SR1I6LT/s5lIzwHeAAeGcdm589MvPB5w
|
14
|
+
SRrwrtk8uaCBI2qB6h2qaQIDAQABo0IwQDAdBgNVHQ4EFgQUkYZ8CFxL1omXWfjs
|
15
|
+
Qi1R2mIhEsswHwYDVR0jBBgwFoAUeMx7hKHipDRx8VQVqW3Zd/Q/iu0wDQYJKoZI
|
16
|
+
hvcNAQEFBQADgYEAER2D3mDAAObaaxMLlFCexyasCAx3XlZslQ9Im1BDM6Do1rIW
|
17
|
+
OQJi8mmmGLqmFHNA1Swnw0g5gDjHb0e+uvFJoMQOp9AL/dhshDimShBklu3O476D
|
18
|
+
ehuGv2rS8ERB01fYrz1UT6jIGMpLPR6ewxZUtLwjPERVNDYXg/gIdc7LwmA=
|
19
|
+
-----END CERTIFICATE-----
|
20
|
+
Bag Attributes: <No Attributes>
|
21
|
+
subject=/C=LV/ST=Riga/L=Riga/O=BSC/OU=BSC/CN=ECOMM/emailAddress=gatisa@bsc.lv
|
22
|
+
issuer=/C=LV/ST=Riga/L=Riga/O=BSC/OU=BSC/CN=ECOMM/emailAddress=gatisa@bsc.lv
|
23
|
+
-----BEGIN CERTIFICATE-----
|
24
|
+
MIIDMzCCApygAwIBAgIBADANBgkqhkiG9w0BAQQFADB1MQswCQYDVQQGEwJMVjEN
|
25
|
+
MAsGA1UECBMEUmlnYTENMAsGA1UEBxMEUmlnYTEMMAoGA1UEChMDQlNDMQwwCgYD
|
26
|
+
VQQLEwNCU0MxDjAMBgNVBAMTBUVDT01NMRwwGgYJKoZIhvcNAQkBFg1nYXRpc2FA
|
27
|
+
YnNjLmx2MB4XDTA0MDQwODAxMzcwOFoXDTE0MDQwNjAxMzcwOFowdTELMAkGA1UE
|
28
|
+
BhMCTFYxDTALBgNVBAgTBFJpZ2ExDTALBgNVBAcTBFJpZ2ExDDAKBgNVBAoTA0JT
|
29
|
+
QzEMMAoGA1UECxMDQlNDMQ4wDAYDVQQDEwVFQ09NTTEcMBoGCSqGSIb3DQEJARYN
|
30
|
+
Z2F0aXNhQGJzYy5sdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzuhGdZxj
|
31
|
+
+SisIrvbbCbqE9zYFKzzm9EpYD1RB95FuKHTXDJvFzZ4BPigxHVKeFK+I6ok/pdw
|
32
|
+
0RC1v6SVQWCrFYhD4YaBnyZP/QhXvCsiWuqqYf+MTW+1qrTSiW18e+bVqZIVwEYi
|
33
|
+
7UF7Eo45ldqq1F5Sqja0rtYhuvqesaCF7H8CAwEAAaOB0jCBzzAdBgNVHQ4EFgQU
|
34
|
+
eMx7hKHipDRx8VQVqW3Zd/Q/iu0wgZ8GA1UdIwSBlzCBlIAUeMx7hKHipDRx8VQV
|
35
|
+
qW3Zd/Q/iu2heaR3MHUxCzAJBgNVBAYTAkxWMQ0wCwYDVQQIEwRSaWdhMQ0wCwYD
|
36
|
+
VQQHEwRSaWdhMQwwCgYDVQQKEwNCU0MxDDAKBgNVBAsTA0JTQzEOMAwGA1UEAxMF
|
37
|
+
RUNPTU0xHDAaBgkqhkiG9w0BCQEWDWdhdGlzYUBic2MubHaCAQAwDAYDVR0TBAUw
|
38
|
+
AwEB/zANBgkqhkiG9w0BAQQFAAOBgQCz+f3UFP3qHde5nXC5az0ypDJJbCbpo3p1
|
39
|
+
T82Zu1Gz0DEF4EOj1oPyt7RnIid3FLWQ42xCBmIcSYXwdfg6eUDLYbW8W4FWsTmP
|
40
|
+
h2WYdD7LSF6yZb4OmsfQdY1ITDwoQu4LDflA34zW3yEd2cA+OZp5DllVbpu2CUaG
|
41
|
+
M2Pi8ijiEA==
|
42
|
+
-----END CERTIFICATE-----
|
43
|
+
Bag Attributes
|
44
|
+
localKeyID: 43 9C BD D3 7A E2 0F AF 0B CD FE 3C DC 0D 1C F2 7B 31 01 3C
|
45
|
+
Key Attributes: <No Attributes>
|
46
|
+
-----BEGIN RSA PRIVATE KEY-----
|
47
|
+
Proc-Type: 4,ENCRYPTED
|
48
|
+
DEK-Info: DES-EDE3-CBC,4BFFF89B175212F9
|
49
|
+
|
50
|
+
Kj6qk3u2SqeowQUZEKY4HePMfbTUsvcHpACMUPuXLGMSMlHsGkd6L3tZU/qCtx8G
|
51
|
+
lBdF+eRHzrirYOAfawjbe4P6B7zcH4zsg1vFm3jKARgsG6PYFwhIyrjjHCFkiSM1
|
52
|
+
0fwIjCVu55EyVhEZQtjYIvfXQiI8kimF6sB6Ayru3ZTyA1U2P3FuHb24whocdAPn
|
53
|
+
l2LiRezYO0dx9PjvZDSRFszbImJiHgEUtMx0FeQsP1xBtH86X4OgmygOXtAnqOeU
|
54
|
+
CAvXJiB5wf8x7EEsFNf2mlRofQ0nDFfs2WV1GN+xxoBE6wKFuTpYZBGPwJyonDci
|
55
|
+
7s+51NYZoGXBImk+7zptr3NEEXSRDP2AeRaKXe6JfhvZuCSgvM4Q+wR1uYTixozp
|
56
|
+
kPMjQHDyneZDRfqL3x+dpcxjbBhXIjjGm3Pt1zUqhcUmCXwe7CLc67mxNNMc89Vh
|
57
|
+
4RJagkG14JT9Qphgko2X6+OtBRKFfxC6g/aVxcuaxiYnB6m5UPp36hmnb0iaqoQi
|
58
|
+
FFRDEHJmgZUVMQBM6x94h6CSvrNxeMCRD2s3XKS9b+Jy/GAiHv8+w/TJF4OL52fG
|
59
|
+
FiFkCob5/1gyn7pjXk2QelPg7v625ppO1reQQKj472wG79C3cNF8zBo72R8NXiTM
|
60
|
+
/zo6mxAv2r8kfJ9vSPjBjxLxrVsJcjclaPAzADnCWhXbec/K0nb9jszTRFqpWI8x
|
61
|
+
3NiXipaV7M96slcz7MiOkdm5DvgfBbjtFxyirRnQUC6HoGm4BKjwxB3BoOQZh2MW
|
62
|
+
nKQju6pJxleyABQpmEwrtRdy1hf3XUrcu2v3ucTaFmA7MpAv0987uA==
|
63
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
3
|
+
|
4
|
+
describe Lolita::FirstData::Transaction do
|
5
|
+
|
6
|
+
let(:trx){ Fabricate(:transaction) }
|
7
|
+
let(:gateway) {
|
8
|
+
ActiveMerchant::Billing::FirstDataGateway.new(
|
9
|
+
:pem => File.open(FD_PEM).read,
|
10
|
+
:pem_password => FD_PASS,
|
11
|
+
:payment => trx.paymentable
|
12
|
+
)
|
13
|
+
}
|
14
|
+
|
15
|
+
it "should create transaction" do
|
16
|
+
trx.transaction_id.should == "D6zNpp/BJnC1y2wZntm4D8XrB2g="
|
17
|
+
trx.status.should == 'processing'
|
18
|
+
trx.paymentable.full_price.should == 250
|
19
|
+
trx.ip.should == "100.100.100.100"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should process answer and save transaction" do
|
23
|
+
rs = gateway.get_trans_result("127.0.0.1", trx.transaction_id)
|
24
|
+
request = double('request')
|
25
|
+
request.stub(:env).and_return({})
|
26
|
+
trx.process_answer(rs, gateway, request).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should process completed payment" do
|
30
|
+
stub_request(:post, "https://secureshop.firstdata.lv:8443/ecomm/MerchantHandler").
|
31
|
+
with(:body => {"client_ip_addr"=>"127.0.0.1", "command"=>"c", "trans_id"=>"D6zNpp/BJnC1y2wZntm4D8XrB2g="},
|
32
|
+
:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
|
33
|
+
to_return(:status => 200, :body => "RESULT: OK RESULT_CODE: 000", :headers => {})
|
34
|
+
|
35
|
+
rs = gateway.get_trans_result("127.0.0.1", trx.transaction_id)
|
36
|
+
request = double('request')
|
37
|
+
request.stub(:env).and_return({})
|
38
|
+
trx.process_answer(rs, gateway, request).should be_true
|
39
|
+
trx.status.should == 'completed'
|
40
|
+
trx.paymentable.status.should == 'completed'
|
41
|
+
trx.paymentable.paid?.should be_true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should process rejected payment" do
|
45
|
+
stub_request(:post, "https://secureshop.firstdata.lv:8443/ecomm/MerchantHandler").
|
46
|
+
with(:body => {"client_ip_addr"=>"127.0.0.1", "command"=>"c", "trans_id"=>"D6zNpp/BJnC1y2wZntm4D8XrB2g="},
|
47
|
+
:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
|
48
|
+
to_return(:status => 200, :body => "RESULT: FAILED RESULT_CODE: 102", :headers => {})
|
49
|
+
|
50
|
+
rs = gateway.get_trans_result("127.0.0.1", trx.transaction_id)
|
51
|
+
request = double('request')
|
52
|
+
request.stub(:env).and_return({})
|
53
|
+
trx.process_answer(rs, gateway, request).should be_true
|
54
|
+
trx.status.should == 'rejected'
|
55
|
+
trx.transaction_code.should == "102"
|
56
|
+
trx.paymentable.status.should == 'rejected'
|
57
|
+
trx.paymentable.fd_error_message.should == "Rejected, possible fraud detected"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should process close day" do
|
61
|
+
stub_request(:post, "https://secureshop.firstdata.lv:8443/ecomm/MerchantHandler").
|
62
|
+
with(:body => {"command"=>"b"},:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
|
63
|
+
to_return(:status => 200, :body => "RESULT: OK", :headers => {})
|
64
|
+
|
65
|
+
Reservation.close_business_day.should be_true
|
66
|
+
end
|
67
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'active_record'
|
12
|
+
require 'rspec'
|
13
|
+
require 'webmock/rspec'
|
14
|
+
require 'fabrication'
|
15
|
+
require 'logger'
|
16
|
+
require 'ruby-debug'
|
17
|
+
require 'lolita-first-data'
|
18
|
+
require 'support/rails'
|
19
|
+
|
20
|
+
FD_PEM = File.dirname(__FILE__) + "/cert.pem"
|
21
|
+
FD_PASS = "1234"
|
22
|
+
|
23
|
+
# load transaction module
|
24
|
+
require File.dirname(__FILE__)+'/../app/models/lolita/first_data/transaction.rb'
|
25
|
+
|
26
|
+
ActiveRecord::Base.logger = Logger.new(File.open("#{File.dirname(__FILE__)}/database.log", 'w+'))
|
27
|
+
ActiveRecord::Base.establish_connection({ :database => ":memory:", :adapter => 'sqlite3', :timeout => 500 })
|
28
|
+
|
29
|
+
# setup I18n
|
30
|
+
I18n.load_path += Dir[File.join(File.dirname(__FILE__), '..', 'config', 'locales', '*.{rb,yml}').to_s]
|
31
|
+
I18n.available_locales = [:en,:lv]
|
32
|
+
I18n.default_locale = :en
|
33
|
+
I18n.locale = :en
|
34
|
+
|
35
|
+
# load transaction module
|
36
|
+
require File.dirname(__FILE__)+'/../app/models/lolita/first_data/transaction.rb'
|
37
|
+
|
38
|
+
# Add models
|
39
|
+
ActiveRecord::Schema.define do
|
40
|
+
create_table :first_data_transactions do |t|
|
41
|
+
t.string :transaction_id, :length => 28
|
42
|
+
t.string :transaction_code, :length => 3
|
43
|
+
t.string :status, :default => 'processing'
|
44
|
+
t.references :paymentable, :polymorphic => true
|
45
|
+
t.string :ip, :length => 10
|
46
|
+
|
47
|
+
t.timestamps
|
48
|
+
end
|
49
|
+
|
50
|
+
create_table :reservations do |t|
|
51
|
+
t.integer :full_price
|
52
|
+
t.string :status
|
53
|
+
|
54
|
+
t.timestamps
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Reservation < ActiveRecord::Base
|
59
|
+
include Lolita::FirstData::Billing
|
60
|
+
|
61
|
+
# Methods for FirstData
|
62
|
+
#-----------------------
|
63
|
+
def price
|
64
|
+
full_price
|
65
|
+
end
|
66
|
+
|
67
|
+
# string up to 125 symbols
|
68
|
+
def description
|
69
|
+
"testing"
|
70
|
+
end
|
71
|
+
|
72
|
+
# returns 3 digit string according to http://en.wikipedia.org/wiki/ISO_4217
|
73
|
+
def currency
|
74
|
+
"840"
|
75
|
+
end
|
76
|
+
|
77
|
+
# this is called when FirstData merchant is taking some actions
|
78
|
+
# there you can save the log message other than the default log file
|
79
|
+
def log severity, message
|
80
|
+
end
|
81
|
+
|
82
|
+
def fd_trx_saved trx
|
83
|
+
case trx.status
|
84
|
+
when 'processing'
|
85
|
+
update_attribute(:status, 'payment')
|
86
|
+
when 'completed'
|
87
|
+
update_attribute(:status, 'completed')
|
88
|
+
when 'rejected'
|
89
|
+
update_attribute(:status, 'rejected')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
#-----------------------
|
93
|
+
end
|
94
|
+
|
95
|
+
RSpec.configure do |config|
|
96
|
+
config.mock_with :rspec
|
97
|
+
config.before(:each) do
|
98
|
+
ActiveRecord::Base.connection.execute "DELETE from first_data_transactions"
|
99
|
+
ActiveRecord::Base.connection.execute "DELETE from reservations"
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext/object/to_param'
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the
|
5
|
+
# param name.
|
6
|
+
#
|
7
|
+
# Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
|
8
|
+
def to_query(key)
|
9
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
10
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Hash
|
15
|
+
alias_method :to_query, :to_param
|
16
|
+
end
|