Skip to content

Commit

Permalink
CommerceHub: Enabling multi-use public key encryption (#4771)
Browse files Browse the repository at this point in the history
Summary:
------------------------------
Changes the payment method so is possible to send an encrypted
credit card following the CommerceHub Multi-User public key
methodology.

SER-555

Note on failing test: You need the proper account permissions and
credentials to use the encrypted credit card.

Remote Test:
------------------------------
Finished in 288.325843 seconds.
25 tests, 63 assertions, 0 failures, 0 errors, 0 pendings,
0 omissions, 0 notifications
100% passed

Unit Tests:
------------------------------
Finished in 38.640945 seconds.
5506 tests, 77384 assertions, 0 failures, 0 errors,
0 pendings, 0 omissions, 0 notifications
100% passed

RuboCop:
------------------------------
760 files inspected, no offenses detected

Co-authored-by: cristian <Heavyblade@users.noreply.github.com>
Co-authored-by: Nick Ashton <nashton@gmail.com>
  • Loading branch information
3 people authored May 23, 2023
1 parent 9d6e204 commit 87f20dd
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
== HEAD
* Payu Latam - Update error code method to surface network code [yunnydang] #4773
* CyberSource: Handling Canadian bank accounts [heavyblade] #4764
* CommerceHub: Enabling multi-use public key encryption [jherreraa] #4771
* CyberSource Rest: Fixing currency detection [heavyblade] #4777
* CyberSource: Allow business rules for requests with network tokens [aenand] #4764
* Adyen: Update Mastercard error messaging [kylene-spreedly] #4770
* Authorize.net: Update mapping for billing address phone number [jcreiff] #4778
* Braintree: Update mapping for billing address phone number [jcreiff] #4779
* CommerceHub: Enabling multi-use public key encryption [jherreraa] #4771

== Version 1.129.0 (May 3rd, 2023)
* Adyen: Update selectedBrand mapping for Google Pay [jcreiff] #4763
Expand Down
9 changes: 7 additions & 2 deletions lib/active_merchant/billing/gateways/commerce_hub.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def add_transaction_interaction(post, options)
post[:transactionInteraction][:origin] = options[:origin] || 'ECOM'
post[:transactionInteraction][:eciIndicator] = options[:eci_indicator] || 'CHANNEL_ENCRYPTED'
post[:transactionInteraction][:posConditionCode] = options[:pos_condition_code] || 'CARD_NOT_PRESENT_ECOM'
post[:transactionInteraction][:posEntryMode] = options[:pos_entry_mode] || 'MANUAL'
post[:transactionInteraction][:posEntryMode] = (options[:pos_entry_mode] || 'MANUAL') unless options[:encryption_data].present?
post[:transactionInteraction][:additionalPosInformation] = {}
post[:transactionInteraction][:additionalPosInformation][:dataEntrySource] = options[:data_entry_source] || 'UNSPECIFIED'
end
Expand Down Expand Up @@ -256,7 +256,12 @@ def add_payment(post, payment, options = {})
when NetworkTokenizationCreditCard
add_decrypted_wallet(source, payment, options)
when CreditCard
add_credit_card(source, payment, options)
if options[:encryption_data].present?
source[:sourceType] = 'PaymentCard'
source[:encryptionData] = options[:encryption_data]
else
add_credit_card(source, payment, options)
end
when String
add_payment_token(source, payment, options)
end
Expand Down
20 changes: 17 additions & 3 deletions test/remote/gateways/remote_commerce_hub_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def test_successful_purchase_with_stored_credential_framework
def test_failed_purchase
response = @gateway.purchase(@amount, @declined_card, @options)
assert_failure response
assert_equal 'Unable to assign card to brand: Invalid.', response.message
assert_equal 'Unable to assign card to brand: Invalid', response.message
assert_equal '104', response.error_code
end

Expand All @@ -131,7 +131,7 @@ def test_successful_authorize
def test_failed_authorize
response = @gateway.authorize(@amount, @declined_card, @options)
assert_failure response
assert_equal 'Unable to assign card to brand: Invalid.', response.message
assert_equal 'Unable to assign card to brand: Invalid', response.message
end

def test_successful_authorize_and_void
Expand Down Expand Up @@ -235,7 +235,7 @@ def test_successful_purchase_with_apple_pay
def test_failed_purchase_with_declined_apple_pay
response = @gateway.purchase(@amount, @declined_apple_pay, @options)
assert_failure response
assert_equal 'Unable to assign card to brand: Invalid.', response.message
assert_equal 'Unable to assign card to brand: Invalid', response.message
end

def test_transcript_scrubbing
Expand All @@ -260,4 +260,18 @@ def test_transcript_scrubbing_apple_pay
assert_scrubbed(@gateway.options[:api_secret], transcript)
assert_scrubbed(@apple_pay.payment_cryptogram, transcript)
end

def test_successful_purchase_with_encrypted_credit_card
@options[:encryption_data] = {
keyId: '6d0b6b63-3658-4c90-b7a4-bffb8a928288',
encryptionType: 'RSA',
encryptionBlock: 'udJ89RebrHLVxa3ofdyiQ/RrF2Y4xKC/qw4NuV1JYrTDEpNeIq9ZimVffMjgkyKL8dlnB2R73XFtWA4klHrpn6LZrRumYCgoqAkBRJCrk09+pE5km2t2LvKtf/Bj2goYQNFA9WLCCvNGwhofp8bNfm2vfGsBr2BkgL+PH/M4SqyRHz0KGKW/NdQ4Mbdh4hLccFsPjtDnNidkMep0P02PH3Se6hp1f5GLkLTbIvDLPSuLa4eNgzb5/hBBxrq5M5+5n9a1PhQnVT1vPU0WbbWe1SGdGiVCeSYmmX7n+KkVmc1lw0dD7NXBjKmD6aGFAWGU/ls+7JVydedDiuz4E7HSDQ==',
encryptionBlockFields: 'card.cardData:16,card.nameOnCard:10,card.expirationMonth:2,card.expirationYear:4,card.securityCode:3',
encryptionTarget: 'MANUAL'
}

response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
assert_equal 'Approved', response.message
end
end
27 changes: 27 additions & 0 deletions test/unit/gateways/commerce_hub_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def test_successful_purchase
assert_equal request['amount']['total'], (@amount / 100.0).to_f
assert_equal request['source']['card']['cardData'], @credit_card.number
assert_equal request['source']['card']['securityCode'], @credit_card.verification_value
assert_equal request['transactionInteraction']['posEntryMode'], 'MANUAL'
assert_equal request['source']['card']['securityCodeIndicator'], 'PROVIDED'
end.respond_with(successful_purchase_response)

Expand Down Expand Up @@ -347,6 +348,32 @@ def test_add_reference_transaction_details_refund_reference_id
assert_equal 'CHARGES', @post[:referenceTransactionDetails][:referenceTransactionType]
end

def test_successful_purchase_when_encrypted_credit_card_present
@options[:order_id] = 'abc123'
@options[:encryption_data] = {
keyId: SecureRandom.uuid,
encryptionType: 'RSA',
encryptionBlock: SecureRandom.alphanumeric(20),
encryptionBlockFields: 'card.cardData:16,card.nameOnCard:8,card.expirationMonth:2,card.expirationYear:4,card.securityCode:3',
encryptionTarget: 'MANUAL'
}

response = stub_comms do
@gateway.purchase(@amount, @credit_card, @options)
end.check_request do |_endpoint, data, _headers|
request = JSON.parse(data)
refute_nil request['source']['encryptionData']
assert_equal request['source']['sourceType'], 'PaymentCard'
assert_equal request['source']['encryptionData']['keyId'], @options[:encryption_data][:keyId]
assert_equal request['source']['encryptionData']['encryptionType'], 'RSA'
assert_equal request['source']['encryptionData']['encryptionBlock'], @options[:encryption_data][:encryptionBlock]
assert_equal request['source']['encryptionData']['encryptionBlockFields'], @options[:encryption_data][:encryptionBlockFields]
assert_equal request['source']['encryptionData']['encryptionTarget'], 'MANUAL'
end.respond_with(successful_purchase_response)

assert_success response
end

private

def successful_purchase_response
Expand Down

0 comments on commit 87f20dd

Please sign in to comment.