Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions lib/wirecard/base.rb
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
module Wirecard
class Base

attr_reader :request

attr_accessor :response, :params

def defaults
@defaults ||= {
customer_id: Wirecard.config.customer_id,
shop_id: Wirecard.config.shop_id
}
end

def initialize(params = {})
@request = Wirecard::Request.new(
params: defaults.merge(params),
implicit_fingerprint_order: implicit_fingerprint_order,
uri: uri
)
end

def post
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

self.response = Wirecard::Response.new(http.request(request.to_post)).to_hash
self
end

alias_method :save, :post

def method_missing(method_name, *args, &block)
if response && (response.key?(method_name.to_sym) || response.key?(method_name))
response[method_name.to_sym] || response[method_name]
else
super
end
end

def respond_to_missing?(method_name, include_private = false)
response && (response.key?(method_name.to_sym) || response.key?(method_name)) || super
end

def implicit_fingerprint_order
nil
end

def self.create(attributes = {})
object = new(attributes)
object.save
object
end

private

def uri
@uri ||= URI.parse(url)
end

def url
raise NotImplementedError, 'A URL must be given to make a call'
end

end
end
35 changes: 20 additions & 15 deletions lib/wirecard/callback.rb
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
module Wirecard
class Callback

attr_reader :params

def initialize(params)
@params = params
end

def to_hash
fingerprint_valid? ? params_to_ruby : nil
fingerprint_valid? ? params_to_ruby : {}
end

def fingerprint_valid?
!!response_fingerprint && !!response_fingerprint_order && !unfingerprinted_params? && (computed_fingerprint == response_fingerprint)
!suspicious_values? && !!response_fingerprint && !!response_fingerprint_order && !unfingerprinted_params? && (computed_fingerprint == response_fingerprint)
end

private

def response_fingerprint
@response_fingerprint ||= params['responseFingerprint']
end

def response_fingerprint_order
@response_fingerprint_order ||= params['responseFingerprintOrder']
end

def fingerprinted_params
@fingerprinted_params ||= response_fingerprint_order.split(',')
end

def unfingerprinted_params
@unfingerprinted_params ||= params.keys - fingerprinted_params - ['responseFingerprint']
end

def unfingerprinted_params?
unfingerprinted_params.size > 0
end


# scans all parameter values for bit sequence "10000000" (\x80), which indicates a length extension attack on the fingerprint
def suspicious_values?
params.values.select{ |value| !value.nil? && value.bytes.include?(128) }.compact.any?
end

def underscore(s)
s.gsub(/([A-Z])/) { |e| '_' + $1.downcase }
end

def params_to_ruby
@ruby_params ||= Hash[params.map{ |key, value| [underscore(key).to_sym, value] }]
end

def computed_fingerprint
@computed_fingerprint ||= Wirecard::Fingerprint::Sha512.new(params).fingerprint
end
Expand Down
14 changes: 14 additions & 0 deletions lib/wirecard/gem_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Wirecard
def self.gem_version
Gem::Version.new VERSION::STRING
end

module VERSION
MAJOR = 0
MINOR = 0
TINY = 3
PRE = nil

STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
end
8 changes: 4 additions & 4 deletions lib/wirecard/payment_process/init.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
module Wirecard
module PaymentProcess
class Init < Wirecard::Base

def order_number
@order_number ||= Wirecard::Backend::GenerateOrderNumber.create
end

def url
@url ||= [Wirecard.config.endpoint, :frontend, :init].join('/')
end

def redirect_url
response[:redirect_url]
end

def defaults
super.merge(
order_number: order_number,
Expand Down
26 changes: 13 additions & 13 deletions lib/wirecard/request.rb
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
module Wirecard
class Request
attr_reader :params, :implicit_fingerprint_order, :uri

def defaults
@defaults ||= {
params: nil,
implicit_fingerprint_order: nil,
uri: nil
}
end

def initialize(options)
options = defaults.merge(options)
raise ArgumentError 'Options must contain params: <parameters hash>' unless options[:params]
raise ArgumentError 'Options must contain uri: <wirecard API uri>' unless options[:uri]

@params = params_to_wirecard(options[:params])
@implicit_fingerprint_order = keys_to_wirecard(options[:implicit_fingerprint_order])
@uri = options[:uri]
end

def to_post
post = Net::HTTP::Post.new(uri.request_uri)

post.set_form_data(fingerprinted_params)

post["Host"] = Wirecard.config.host
post["User-Agent"] = Wirecard.config.user_agent
post["Content-Type"] = 'application/x-www-form-urlencoded'
post["Content-Length"] = post.body.bytesize.to_s
post["Connection"] = 'close'

post
end

private

def params_to_wirecard(params)
Hash[params.keys.map{ |key| [camelize(key), params[key]] }]
Hash[params.keys.reject{ |key| !params[key] }.map{ |key| [camelize(key), params[key]] }]
end

def keys_to_wirecard(keys)
keys.map{ |key| camelize(key) } if keys
end

def camelize(key)
key.to_s.gsub(/_(.)/) { |e| $1.upcase }
end

def fingerprinted_params
@fingerprinted_params ||= Wirecard::Fingerprint::Sha512.new(params, implicit_fingerprint_order).fingerprinted_params
end
Expand Down
6 changes: 5 additions & 1 deletion lib/wirecard/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
require_relative 'gem_version'

module Wirecard
VERSION = "0.0.2"
def self.version
gem_version
end
end
44 changes: 36 additions & 8 deletions spec/unit_tests/backend/approve_reversal_spec.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
require 'spec_helper'

RSpec.describe Wirecard::Backend::ApproveReversal do

let(:approve_reversal) { Wirecard::Backend::ApproveReversal.new(options) }
let(:options) { Hash.new.merge(order_number) }
let(:order_number) { { order_number: '23473341' } }

include_context 'configuration'

it { is_expected.to be_a_kind_of(Wirecard::Backend::ApproveReversal) }

describe '#implicit_fingerprint_order' do
subject { approve_reversal.implicit_fingerprint_order }

Expand All @@ -31,17 +31,45 @@

describe '#post' do
subject { approve_reversal.post.response }
include_context 'stub requests'


context 'when order number is 23473341' do
let(:order_number) { { order_number: '23473341' } }

#it { is_expected.to eq({ status: '0' }) }
before do
stub_request(:post, "https://checkout.wirecard.com/seamless/backend/approvereversal").
with(body: default_backend_request_hash.merge(
{
"orderNumber"=>'23473341',
"requestFingerprint"=>"4b5b4733bf2ec86456f180a75ed08eb7c0d3abbe8b3f834f313a5f35b8fe85fdf9568765f08cf8921be864764585d85a12357b9826e0f197255d69afc4155a45"
}
)).
to_return(
status: 200,
body: "status=0",
headers: {}
)
end

it { is_expected.to eq({ status: '0' }) }
end

context 'when order number is not given' do
let(:order_number) { { } }


before do
stub_request(:post, "https://checkout.wirecard.com/seamless/backend/approvereversal").
with(body: default_backend_request_hash.merge(
{
"requestFingerprint"=>"dfd315b6687aa1f213450008cb3932b29c23601097a0f1a120377938149c3be84e54dafd36e7cf75385e6f356cff79f1a084712d099bedeb2735e63df861b2c5"
}
)).
to_return(
status: 200,
body: "error.1.errorCode=11011&error.1.message=Order+number+is+missing.&error.1.consumerMessage=Order+number+is+missing.&errors=1&status=1",
headers: {}
)
end

it { is_expected.to eq({
:"error.1.consumer_message" => "Order number is missing.",
:"error.1.error_code" => "11011",
Expand Down
Loading