Skip to content

Commit fd2f965

Browse files
author
glondhe
committed
Adding client
1 parent 479c211 commit fd2f965

File tree

766 files changed

+86081
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

766 files changed

+86081
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
require_relative '../../util/Constants.rb'
2+
require_relative '.././payloadDigest/digest.rb'
3+
require 'openssl'
4+
# This function returns value for paramter Signature which is then passed to Signature header
5+
# paramter 'Signature' is calucated based on below key values and then signed with SECRET KEY -
6+
# host: Sandbox (apitest.cybersource.com) or Production (api.cybersource.com) hostname
7+
# date: "HTTP-date" format as defined by RFC7231.
8+
# (request-target): Should be in format of httpMethod: path
9+
# Example: "post /pts/v2/payments"
10+
# Digest: Only needed for POST calls.
11+
# digestString = BASE64( HMAC-SHA256 ( Payload ));
12+
# Digest: “SHA-256=“ + digestString;
13+
# v-c-merchant-id: set value to Cybersource Merchant ID
14+
# This ID can be found on EBC portal*/
15+
class SignatureParameter
16+
def generateSignatureParameter(merchantconfig_obj, gmtdatetime, log_obj)
17+
request_type = merchantconfig_obj.requestType.upcase
18+
merchantSecretKey = merchantconfig_obj.merchantSecretKey
19+
signatureString = Constants::HOST + ': ' + merchantconfig_obj.requestHost
20+
signatureString << "\n"+ Constants::DATE + ': ' + gmtdatetime
21+
signatureString << "\n(request-target): "
22+
if request_type == Constants::GET_REQUEST_TYPE || request_type == Constants::DELETE_REQUEST_TYPE
23+
targetUrl=gettargetUrlForGetDelete(request_type,merchantconfig_obj)
24+
signatureString << targetUrl + "\n"
25+
elsif request_type == Constants::POST_REQUEST_TYPE || request_type == Constants::PUT_REQUEST_TYPE
26+
targetUrl=gettargetUrlForPutPost(request_type,merchantconfig_obj)
27+
signatureString << targetUrl + "\n"
28+
payload = merchantconfig_obj.requestJsonData
29+
digest = DigestGeneration.new.generateDigest(payload, log_obj)
30+
digest_payload = Constants::SHA256 + digest
31+
signatureString << Constants::DIGEST + ': ' + digest_payload + "\n"
32+
end
33+
signatureString << Constants::V_C_MERCHANT_ID + ': ' + merchantconfig_obj.merchantId
34+
encodedSignatureString = signatureString.force_encoding(Encoding::UTF_8)
35+
decodedKey = Base64.decode64(merchantSecretKey)
36+
base64EncodedSignature = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', decodedKey, encodedSignatureString))
37+
return base64EncodedSignature
38+
rescue StandardError => err
39+
log_obj.logger.error(err.message)
40+
log_obj.logger.error(err.backtrace)
41+
puts 'Check log for more details.'
42+
exit!
43+
end
44+
def gettargetUrlForGetDelete(request_type, merchantconfig_obj)
45+
targetUrlForGetDelete = ''
46+
if request_type == Constants::DELETE_REQUEST_TYPE
47+
targetUrlForGetDelete = Constants::DELETE_REQUEST_TYPE_LOWER + ' ' + merchantconfig_obj.requestTarget
48+
elsif request_type == Constants::GET_REQUEST_TYPE
49+
targetUrlForGetDelete = Constants::GET_REQUEST_TYPE_LOWER + ' ' + merchantconfig_obj.requestTarget
50+
end
51+
return targetUrlForGetDelete
52+
end
53+
def gettargetUrlForPutPost(request_type, merchantconfig_obj)
54+
targetUrlForPutPost = ''
55+
if request_type == Constants::POST_REQUEST_TYPE
56+
targetUrlForPutPost = Constants::POST_REQUEST_TYPE_LOWER + ' ' + merchantconfig_obj.requestTarget
57+
elsif request_type == Constants::PUT_REQUEST_TYPE
58+
targetUrlForPutPost = Constants::PUT_REQUEST_TYPE_LOWER + ' ' + merchantconfig_obj.requestTarget
59+
end
60+
return targetUrlForPutPost
61+
end
62+
end
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
require 'base64'
2+
require_relative '../../core/ITokenGeneration.rb'
3+
require_relative '../../util/Constants.rb'
4+
require_relative '../../util/ApiException.rb'
5+
require_relative '.././payloadDigest/digest.rb'
6+
require_relative '.././http/GetSignatureParameter.rb'
7+
public
8+
# SignatureHeader return SignatureHeader Value that contains following paramters
9+
# * keyid -- Merchant ID obtained from EBC portal
10+
# * algorithm -- Should have value as "HmacSHA256"
11+
# * headers -- List of all header name passed in the Signature paramter below
12+
# String getHeaders = "host date (request-target)" + " " + "v-c-merchant-id";
13+
# String postHeaders = "host date (request-target) digest v-c-merchant-id";
14+
# Note: Digest is not passed for GET calls
15+
# * signature -- Signature header has paramter called signature
16+
# Paramter 'Signature' must contain all the paramters mentioned in header above in given order
17+
class GenerateHttpSignature
18+
# Generates Signature based on the requestType
19+
def getToken(merchantconfig_obj, gmtdatetime, log_obj)
20+
request_type = merchantconfig_obj.requestType.upcase
21+
signatureHeaderValue =''
22+
signatureHeaderValue << Constants::KEY_ID + merchantconfig_obj.merchantKeyId + "\""
23+
# Algorithm should be always HmacSHA256 for http signature
24+
signatureHeaderValue << ', ' + Constants::ALGORITHM + Constants::SIGNATURE_ALGORITHM + "\""
25+
# Headers - list is choosen based on HTTP method
26+
signatureheader=getsignatureHeader(request_type)
27+
signatureHeaderValue << ', ' + Constants::HEADERS_PARAM + signatureheader + "\""
28+
# Get Value for parameter 'Signature' to be passed to Signature Header
29+
signature_value = SignatureParameter.new.generateSignatureParameter(merchantconfig_obj, gmtdatetime, log_obj)
30+
signatureHeaderValue << ', ' + Constants::SIGNATURE_PARAM + signature_value + "\""
31+
return signatureHeaderValue
32+
rescue StandardError => err
33+
ApiException.new.apiexception(err,log_obj)
34+
exit!
35+
end
36+
def getsignatureHeader(request_type)
37+
headers = ''
38+
if request_type == Constants::POST_REQUEST_TYPE
39+
headers = 'host date (request-target) digest ' + Constants::V_C_MERCHANT_ID
40+
elsif request_type == Constants::GET_REQUEST_TYPE || request_type == Constants::DELETE_REQUEST_TYPE
41+
headers = 'host date (request-target)' + ' ' + Constants::V_C_MERCHANT_ID
42+
elsif request_type == Constants::PUT_REQUEST_TYPE
43+
headers = 'host date (request-target) digest ' + Constants::V_C_MERCHANT_ID
44+
else
45+
raise StandardError.new(Constants::ERROR_PREFIX + Constants::INVALID_REQUEST_TYPE_METHOD)
46+
end
47+
return headers
48+
end
49+
implements TokenInterface
50+
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
require 'base64'
2+
require 'openssl'
3+
require 'jwt'
4+
require 'json'
5+
require 'active_support'
6+
require_relative '../../core/ITokenGeneration.rb'
7+
require_relative '../../util/Constants.rb'
8+
require_relative '../../util/ApiException.rb'
9+
require_relative '../../util/Cache.rb'
10+
require_relative '../../authentication/payloadDigest/digest.rb'
11+
public
12+
#JWT Token-generated based on the Request type
13+
class GenerateJwtToken
14+
def getToken(merchantconfig_obj,gmtDatetime,log_obj)
15+
jwtBody = ''
16+
request_type = merchantconfig_obj.requestType.upcase
17+
filePath = merchantconfig_obj.keysDirectory + '/' + merchantconfig_obj.keyFilename + '.p12'
18+
if (!File.exist?(filePath))
19+
raise Constants::ERROR_PREFIX + Constants::FILE_NOT_FOUND + filePath
20+
end
21+
p12File = File.binread(filePath)
22+
jwtBody=getJwtBody(request_type, gmtDatetime, merchantconfig_obj, log_obj)
23+
claimSet = JSON.parse(jwtBody)
24+
p12FilePath = OpenSSL::PKCS12.new(p12File, merchantconfig_obj.keyPass)
25+
# Generating certificate.
26+
cacheObj = ActiveSupport::Cache::MemoryStore.new
27+
x5Cert = Cache.new.fetchCachedCertificate(filePath, p12File, merchantconfig_obj.keyPass, cacheObj)
28+
# Generating Public key.
29+
publicKey = OpenSSL::PKey::RSA.new(p12FilePath.key.public_key)
30+
#Generating Private Key
31+
privateKey = OpenSSL::PKey::RSA.new(p12FilePath.key)
32+
# JWT token-Generates using RS256 algorithm only
33+
x5clist = [x5Cert]
34+
customHeaders = {}
35+
customHeaders['v-c-merchant-id'] = merchantconfig_obj.keyAlias
36+
customHeaders['x5c'] = x5clist
37+
# Generating JWT token
38+
token = JWT.encode(claimSet, privateKey, 'RS256', customHeaders)
39+
return token
40+
rescue StandardError => err
41+
if err.message.include? 'PKCS12_parse: mac verify failure'
42+
ApiException.new.customerror(Constants::ERROR_PREFIX + Constants::INCORRECT_KEY_PASS,log_obj)
43+
exit!
44+
else
45+
ApiException.new.apiexception(err,log_obj)
46+
exit!
47+
end
48+
end
49+
def getJwtBody(request_type, gmtDatetime, merchantconfig_obj,log_obj)
50+
if request_type == Constants::POST_REQUEST_TYPE || request_type == Constants::PUT_REQUEST_TYPE
51+
payload = merchantconfig_obj.requestJsonData
52+
# Note: Digest is not passed for GET calls
53+
digest = DigestGeneration.new.generateDigest(payload, log_obj)
54+
jwtBody = "{\n \"digest\":\"" + digest + "\", \"digestAlgorithm\":\"SHA-256\", \"iat\":\"" + gmtDatetime + "\"}"
55+
elsif request_type == Constants::GET_REQUEST_TYPE || request_type == Constants::DELETE_REQUEST_TYPE
56+
jwtBody = "{\n \"iat\":\"" + gmtDatetime + "\"\n} \n\n"
57+
else
58+
raise StandardError.new(Constants::ERROR_PREFIX + Constants::INVALID_REQUEST_TYPE_METHOD)
59+
end
60+
end
61+
implements TokenInterface
62+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
require 'digest'
2+
public
3+
# This method return Digest value which is SHA-256
4+
# hash of payload that is BASE64 encoded
5+
class DigestGeneration
6+
def generateDigest(payload, log_obj)
7+
digest = Digest::SHA256.base64digest(payload)
8+
return digest
9+
end
10+
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require_relative '../authentication/http/HttpSignatureHeader.rb'
2+
require_relative '../authentication/jwt/JwtToken.rb'
3+
require_relative '../util/Constants.rb'
4+
require_relative '../util/ApiException.rb'
5+
public
6+
# This function calls for the generation of Signature message depending on the authentication type.
7+
class Authorization
8+
def getToken(merchantconfig_obj, gmtdatetime, log_obj)
9+
authenticationType = merchantconfig_obj.authenticationType.upcase
10+
if merchantconfig_obj.requestType.to_s.empty?
11+
raise StandardError.new(Constants::ERROR_PREFIX + Constants::REQUEST_TYPE_EMPTY)
12+
end
13+
if authenticationType == Constants::AUTH_TYPE_HTTP
14+
token = GenerateHttpSignature.new.getToken(merchantconfig_obj, gmtdatetime, log_obj)
15+
elsif authenticationType == Constants::AUTH_TYPE_JWT
16+
token = GenerateJwtToken.new.getToken(merchantconfig_obj, gmtdatetime, log_obj)
17+
elsif authenticationType != Constants::AUTH_TYPE_HTTP || authenticationType != Constants::AUTH_TYPE_JWT
18+
raise StandardError.ner(Constants::ERROR_PREFIX + Constants::AUTH_ERROR)
19+
end
20+
rescue StandardError => err
21+
ApiException.new.apiexception(err,log_obj)
22+
exit!
23+
end
24+
end
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
require 'interface'
2+
TokenInterface = interface {
3+
required_methods :getToken
4+
}

AuthenticationSDK/core/Logger.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require_relative '../util/ApiException.rb'
2+
require 'logger'
3+
public
4+
# Logger Class
5+
class Log
6+
def initialize(logDirectory, logFilename, logSize, enableLog)
7+
#log
8+
if enableLog == true
9+
filename = logDirectory + '/' + logFilename + '.log'
10+
datetime = DateTime.now
11+
if File.exist?(filename) && File.size(filename) >= logSize
12+
updatedFileName = logDirectory + '/' + logFilename + '_' + datetime.strftime('%Y%m%d%H%M%S') + '.log'
13+
File.rename(filename, updatedFileName)
14+
end
15+
@logger = Logger.new(STDOUT)
16+
@logger = Logger.new(filename, logSize)
17+
@logger.datetime_format = datetime.strftime('%Y-%m-%d %H:%M:%S')
18+
else
19+
@logger = Logger.new(false)
20+
end
21+
rescue StandardError => err
22+
puts err
23+
exit!
24+
end
25+
attr_accessor :logger
26+
end

0 commit comments

Comments
 (0)