datatrans 1.0.0 → 2.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.
@@ -0,0 +1,68 @@
1
+ require 'datatrans/xml/transaction/request'
2
+ require 'datatrans/xml/transaction/response'
3
+
4
+ class Datatrans::XML::Transaction
5
+ class CaptureRequest < Request
6
+
7
+ def process
8
+ self.class.post(Datatrans.xml_settlement_url,
9
+ :headers => { 'Content-Type' => 'text/xml' },
10
+ :body => build_capture_request.to_s).parsed_response
11
+ end
12
+
13
+
14
+ private
15
+
16
+ def build_capture_request
17
+ build_xml_request(:payment) do |xml|
18
+ xml.amount params[:amount]
19
+ xml.currency params[:currency]
20
+ xml.uppTransactionId params[:transaction_id]
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ class CaptureResponse < Response
27
+
28
+ def successful?
29
+ response_code == '01' && response_message == 'settlement succeeded'
30
+ end
31
+
32
+ def response_code
33
+ params_root_node['response']['responseCode'] rescue nil
34
+ end
35
+
36
+ def response_message
37
+ params_root_node['response']['responseMessage'] rescue nil
38
+ end
39
+
40
+ def transaction_id
41
+ params_root_node['request']['uppTransactionId'] rescue nil
42
+ end
43
+
44
+ def reference_number
45
+ params_root_node['refno'] rescue nil
46
+ end
47
+
48
+ def error_code
49
+ params_root_node['error']['errorCode'] rescue nil
50
+ end
51
+
52
+ def error_message
53
+ params_root_node['error']['errorMessage'] rescue nil
54
+ end
55
+
56
+ def error_detail
57
+ params_root_node['error']['errorDetail'] rescue nil
58
+ end
59
+
60
+
61
+ private
62
+
63
+ def params_root_node
64
+ params['paymentService']['body']['transaction']
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,39 @@
1
+ require 'httparty'
2
+ require 'builder'
3
+
4
+ class Datatrans::XML::Transaction
5
+ class Request
6
+ include HTTParty
7
+
8
+ attr_accessor :params
9
+
10
+ def initialize(params)
11
+ @params = params
12
+ end
13
+
14
+ def process
15
+ raise 'overwrite in subclass!'
16
+ end
17
+
18
+
19
+ private
20
+
21
+ include Datatrans::Common
22
+
23
+ def build_xml_request(service)
24
+ xml = Builder::XmlMarkup.new
25
+ xml.instruct!
26
+ xml.tag! "#{service}Service", :version => 1 do
27
+ xml.body :merchantId => Datatrans.merchant_id do |body|
28
+ xml.transaction :refno => params[:refno] do
29
+ xml.request do
30
+ yield body
31
+ end
32
+ end
33
+ end
34
+ end
35
+ xml.target!
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ class Datatrans::XML::Transaction
2
+ class Response
3
+ attr_reader :params
4
+
5
+ def initialize(params)
6
+ @params = params
7
+ end
8
+
9
+ def successful?
10
+ raise 'overwrite in subclass!'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,69 @@
1
+ require 'datatrans/xml/transaction/request'
2
+ require 'datatrans/xml/transaction/response'
3
+
4
+ class Datatrans::XML::Transaction
5
+ class VoidRequest < Request
6
+
7
+ def process
8
+ self.class.post(Datatrans.xml_settlement_url,
9
+ :headers => { 'Content-Type' => 'text/xml' },
10
+ :body => build_void_request.to_s).parsed_response
11
+ end
12
+
13
+
14
+ private
15
+
16
+ def build_void_request
17
+ build_xml_request(:payment) do |xml|
18
+ xml.amount params[:amount]
19
+ xml.currency params[:currency]
20
+ xml.uppTransactionId params[:transaction_id]
21
+ xml.reqtype 'DOA'
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ class VoidResponse < Response
28
+
29
+ def successful?
30
+ response_code == '01' && response_message == 'cancellation succeeded'
31
+ end
32
+
33
+ def response_code
34
+ params_root_node['response']['responseCode'] rescue nil
35
+ end
36
+
37
+ def response_message
38
+ params_root_node['response']['responseMessage'] rescue nil
39
+ end
40
+
41
+ def transaction_id
42
+ params_root_node['request']['uppTransactionId'] rescue nil
43
+ end
44
+
45
+ def reference_number
46
+ params_root_node['refno'] rescue nil
47
+ end
48
+
49
+ def error_code
50
+ params_root_node['error']['errorCode'] rescue nil
51
+ end
52
+
53
+ def error_message
54
+ params_root_node['error']['errorMessage'] rescue nil
55
+ end
56
+
57
+ def error_detail
58
+ params_root_node['error']['errorDetail'] rescue nil
59
+ end
60
+
61
+
62
+ private
63
+
64
+ def params_root_node
65
+ params['paymentService']['body']['transaction']
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Datatrans::Common do
4
+
5
+ context "sign" do
6
+ before do
7
+ class Request; include Datatrans::Common; end
8
+ @request = Request.new
9
+ end
10
+
11
+ it "generates the correct sign" do
12
+ amount = 1000
13
+ currency = 'CHF'
14
+ reference_number = 'ABCEDF'
15
+
16
+ @request.sign(Datatrans.merchant_id, amount, currency, reference_number).should == '4e7d4d5bbde548c586f3b7f109635ffc'
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'datatrans'
5
+
6
+ RSpec.configure do |config|
7
+
8
+ config.before(:each) do
9
+ Datatrans.configure do |config|
10
+ config.merchant_id = '1100000000'
11
+ config.sign_key = 'd777c17ba2010282c2d2350a68b441ca07a799d294bfaa630b7c8442207c0b69703cc55775b0ca5a4e455b818a9bb10a43669c0c20ce31f4a43f10e0cabb9525'
12
+ config.environment = :development
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,128 @@
1
+ #encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Datatrans::Web::Transaction do
6
+ before do
7
+ @successful_response = {
8
+ :status => "success",
9
+ :returnCustomerCountry => "CHE",
10
+ :sign => "95f3111123e628eab6469c636e0d3f06",
11
+ :aliasCC => "70323122544311173",
12
+ :maskedCC => "520000xxxxxx0007",
13
+ :responseMessage => "Authorized",
14
+ :useAlias => "Yes",
15
+ :expm => "12",
16
+ :responseCode => "01",
17
+ :sign2 => "a9571428be4d9d37b88988656984bfbf",
18
+ :testOnly => "yes",
19
+ :currency => "CHF",
20
+ :amount => "1000",
21
+ :hiddenMode => "yes",
22
+ :expy => "15",
23
+ :merchantId => "1100000000",
24
+ :authorizationCode => "521029462",
25
+ :uppTransactionId => "110808173520119430",
26
+ :refno => "1",
27
+ :uppMsgType => "web",
28
+ :uppCustomerName => "",
29
+ :pmethod => "ECA",
30
+ :reqtype => "NOA",
31
+ :uppCustomerEmail => "customer@email.com",
32
+ :acqAuthorizationCode => "173520"
33
+ }
34
+
35
+ @failed_response = {
36
+ :status => "error",
37
+ :returnCustomerCountry => "CHE",
38
+ :sign => "95f3123246e628eab6469c636e0d3f06",
39
+ :aliasCC => "70323122544311173",
40
+ :maskedCC => "520000xxxxxx0007",
41
+ :errorMessage => "declined",
42
+ :useAlias => "Yes",
43
+ :expm => "12",
44
+ :errorCode => "1403",
45
+ :testOnly => "yes",
46
+ :currency => "CHF",
47
+ :amount => "1000",
48
+ :hiddenMode => "yes",
49
+ :expy => "14",
50
+ :merchantId => "1100000000",
51
+ :errorDetail => "Declined",
52
+ :uppTransactionId => "110808173951050102",
53
+ :refno => "1",
54
+ :uppMsgType => "web",
55
+ :uppCustomerName => "",
56
+ :pmethod => "ECA",
57
+ :reqtype => "NOA",
58
+ :uppCustomerEmail => "customer@email.com"
59
+ }
60
+
61
+ @valid_params = {
62
+ :refno => 'ABCDEF',
63
+ :amount => 1000,
64
+ :currency => 'CHF',
65
+ :uppCustomerEmail => 'customer@email.com'
66
+ # also params from view helper needed
67
+ }
68
+ end
69
+
70
+ context "rails form helper" do
71
+ before do
72
+ @transaction = Datatrans::Web::Transaction.new(@valid_params)
73
+ @view = ActionView::Base.new
74
+ end
75
+
76
+ it "should generate valid form field string" do
77
+ @view.datatrans_notification_request_hidden_fields(@transaction).should == "<input id=\"merchantId\" name=\"merchantId\" type=\"hidden\" value=\"1100000000\" /><input id=\"hiddenMode\" name=\"hiddenMode\" type=\"hidden\" value=\"Yes\" /><input id=\"reqtype\" name=\"reqtype\" type=\"hidden\" value=\"NOA\" /><input id=\"amount\" name=\"amount\" type=\"hidden\" value=\"1000\" /><input id=\"currency\" name=\"currency\" type=\"hidden\" value=\"CHF\" /><input id=\"useAlias\" name=\"useAlias\" type=\"hidden\" value=\"Yes\" /><input id=\"sign\" name=\"sign\" type=\"hidden\" value=\"0402fb3fba8c6fcb40df9b7756e7e637\" /><input id=\"refno\" name=\"refno\" type=\"hidden\" value=\"ABCDEF\" /><input id=\"uppCustomerName\" name=\"uppCustomerName\" type=\"hidden\" /><input id=\"uppCustomerEmail\" name=\"uppCustomerEmail\" type=\"hidden\" value=\"customer@email.com\" />"
78
+ end
79
+ end
80
+
81
+ context "successful response" do
82
+ before do
83
+ Datatrans::Web::Transaction::AuthorizeResponse.any_instance.stub(:params).and_return(@successful_response)
84
+ end
85
+
86
+ context "process" do
87
+ it "handles a valid datatrans authorize response" do
88
+ @transaction = Datatrans::Web::Transaction.new(@valid_params)
89
+ @transaction.authorize.should be_true
90
+ end
91
+ end
92
+ end
93
+
94
+ context "compromised response" do
95
+ before do
96
+ fake_response = @successful_response
97
+ fake_response[:sign2] = 'invalid'
98
+ Datatrans::Web::Transaction::AuthorizeResponse.any_instance.stub(:params).and_return(fake_response)
99
+ @transaction = Datatrans::Web::Transaction.new(@valid_params)
100
+ end
101
+
102
+ it "raises an exception if sign2 is invalid" do
103
+ expect {
104
+ @transaction.authorize
105
+ }.to raise_error(Datatrans::InvalidSignatureError)
106
+ end
107
+ end
108
+
109
+ context "failed response" do
110
+ before do
111
+ Datatrans::Web::Transaction::AuthorizeResponse.any_instance.stub(:params).and_return(@failed_response)
112
+ @transaction = Datatrans::Web::Transaction.new(@valid_params)
113
+ end
114
+
115
+ context "process" do
116
+ it "handles a failed datatrans authorize response" do
117
+ @transaction.authorize.should be_false
118
+ end
119
+
120
+ it "returns error details" do
121
+ @transaction.authorize
122
+ @transaction.error_code.length.should > 0
123
+ @transaction.error_message.length.should > 0
124
+ @transaction.error_detail.length.should > 0
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe Datatrans::XML::Transaction::AuthorizeRequest do
4
+ before do
5
+ @successful_response = {
6
+ "authorizationService" => {
7
+ "body" => {
8
+ "transaction" => {
9
+ "request" => {
10
+ "amount" => "1000",
11
+ "currency" => "CHF",
12
+ "aliasCC" => "70323122544311173",
13
+ "expm" => "12",
14
+ "expy" => "15",
15
+ "sign" => "1d236349b97fac15b267becb0792d185",
16
+ "reqtype" => "NOA"
17
+ },
18
+ "response" => {
19
+ "responseCode" => "01",
20
+ "responseMessage" => "Authorized",
21
+ "uppTransactionId" => "110808142256858007",
22
+ "authorizationCode" => "257128012",
23
+ "acqAuthorizationCode" => "142257",
24
+ "maskedCC" => "520000xxxxxx0007",
25
+ "returnCustomerCountry" => "CHE"
26
+ },
27
+ "refno" => "ABCDEF",
28
+ "trxStatus" => "response"
29
+ },
30
+ "merchantId" => "1100001872",
31
+ "status" => "accepted"
32
+ },
33
+ "version" => "1"
34
+ }
35
+ }
36
+
37
+ @failed_response = {
38
+ "authorizationService" => {
39
+ "body" => {
40
+ "transaction" => {
41
+ "request" => {
42
+ "amount" => "1000",
43
+ "currency" => "CHF",
44
+ "aliasCC" => "70323122544311173",
45
+ "expm" => "12",
46
+ "expy" => "15",
47
+ "sign" => "1d236349b97fac15b267becb0792d185",
48
+ "reqtype" => "NOA"
49
+ },
50
+ "error" => {
51
+ "errorCode" => "2021",
52
+ "errorMessage" => "missing value",
53
+ "errorDetail" => "CC-alias"
54
+ },
55
+ "refno" => "ABCDEF",
56
+ "trxStatus" => "response"
57
+ },
58
+ "merchantId" => "1100001872",
59
+ "status" => "accepted"
60
+ },
61
+ "version" => "1"
62
+ }
63
+ }
64
+
65
+ @valid_params = {
66
+ :refno => 'ABCDEF',
67
+ :amount => 1000,
68
+ :currency => 'CHF',
69
+ :aliasCC => '3784982984234',
70
+ :expm => 12,
71
+ :expy => 15
72
+ }
73
+ end
74
+
75
+ context "successful response" do
76
+ before do
77
+ Datatrans::XML::Transaction::AuthorizeRequest.any_instance.stub(:process).and_return(@successful_response)
78
+ end
79
+
80
+ context "build_authorize_request" do
81
+ it "generates a valid datatrans authorize xml" do
82
+ @request = Datatrans::XML::Transaction::AuthorizeRequest.new(@valid_params)
83
+ @request.send(:build_authorize_request).should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?><authorizationService version=\"1\"><body merchantId=\"1100000000\"><transaction refno=\"ABCDEF\"><request><amount>1000</amount><currency>CHF</currency><aliasCC>3784982984234</aliasCC><expm>12</expm><expy>15</expy><sign>0402fb3fba8c6fcb40df9b7756e7e637</sign></request></transaction></body></authorizationService>"
84
+ end
85
+ end
86
+
87
+ context "process" do
88
+ it "handles a valid datatrans authorize response" do
89
+ @transaction = Datatrans::XML::Transaction.new(@valid_params)
90
+ @transaction.authorize.should be_true
91
+ end
92
+ end
93
+ end
94
+
95
+ context "failed response" do
96
+ before do
97
+ Datatrans::XML::Transaction::AuthorizeRequest.any_instance.stub(:process).and_return(@failed_response)
98
+ @transaction = Datatrans::XML::Transaction.new(@valid_params)
99
+ end
100
+
101
+ context "process" do
102
+ it "handles a failed datatrans authorize response" do
103
+ @transaction.authorize.should be_false
104
+ end
105
+
106
+ it "returns error details" do
107
+ @transaction.authorize
108
+ @transaction.error_code.length.should > 0
109
+ @transaction.error_message.length.should > 0
110
+ @transaction.error_detail.length.should > 0
111
+ end
112
+ end
113
+ end
114
+ end