-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Shift4_v2: Inherit securionPay API to enable Shift4v2
Description ------------------------- [SER-653](https://spreedly.atlassian.net/browse/SER-653) [SER-654](https://spreedly.atlassian.net/browse/SER-654) [SER-655](https://spreedly.atlassian.net/browse/SER-655) [SER-662](https://spreedly.atlassian.net/browse/SER-662) Shift4 purchased Securion Pay and is now using their API, that's why this commit enable a new shift4_v2 gateway Unit test ------------------------- Finished in 0.150258 seconds. 34 tests, 191 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed Remote test ------------------------- Finished in 28.137188 seconds. 30 tests, 103 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed Rubocop ------------------------- 760 files inspected, no offenses detected
- Loading branch information
1 parent
d8af5bf
commit d6c61de
Showing
5 changed files
with
227 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
module ActiveMerchant #:nodoc: | ||
module Billing #:nodoc: | ||
class Shift4V2Gateway < SecurionPayGateway | ||
# same endpont for testing | ||
self.live_url = 'https://api.shift4.com/' | ||
self.display_name = 'Shift4 V2' | ||
self.homepage_url = 'https://dev.shift4.com/us/' | ||
|
||
def credit(money, payment, options = {}) | ||
post = create_post_for_auth_or_purchase(money, payment, options) | ||
commit('credits', post, options) | ||
end | ||
|
||
def create_post_for_auth_or_purchase(money, payment, options) | ||
super.tap do |post| | ||
add_stored_credentials(post, options) | ||
end | ||
end | ||
|
||
def add_stored_credentials(post, options) | ||
return unless options[:stored_credential].present? | ||
|
||
initiator = options.dig(:stored_credential, :initiator) | ||
reason_type = options.dig(:stored_credential, :reason_type) | ||
|
||
post_type = { | ||
['cardholder', 'recurring'] => 'first_recurring', | ||
['merchant', 'recurring'] => 'subsequent_recurring', | ||
['cardholder', 'unscheduled'] => 'customer_initiated', | ||
['merchant', 'installment'] => 'merchant_initiated' | ||
}[[initiator, reason_type]] | ||
post[:type] = post_type if post_type | ||
end | ||
|
||
def headers(options = {}) | ||
super.tap do |headers| | ||
headers['User-Agent'] = "Shift4/v2 ActiveMerchantBindings/#{ActiveMerchant::VERSION}" | ||
end | ||
end | ||
|
||
def scrub(transcript) | ||
super. | ||
gsub(%r((card\[expMonth\]=)\d+), '\1[FILTERED]'). | ||
gsub(%r((card\[expYear\]=)\d+), '\1[FILTERED]'). | ||
gsub(%r((card\[cardholderName\]=)\w+[^ ]\w+), '\1[FILTERED]') | ||
end | ||
|
||
def json_error(raw_response) | ||
super(raw_response, 'Shift4 V2') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
require 'test_helper' | ||
require_relative 'remote_securion_pay_test' | ||
|
||
class RemoteShift4V2Test < RemoteSecurionPayTest | ||
def setup | ||
super | ||
@gateway = Shift4V2Gateway.new(fixtures(:shift4_v2)) | ||
end | ||
|
||
def test_successful_purchase_third_party_token | ||
auth = @gateway.store(@credit_card, @options) | ||
token = auth.params['defaultCardId'] | ||
customer_id = auth.params['id'] | ||
response = @gateway.purchase(@amount, token, @options.merge!(customer_id: customer_id)) | ||
assert_success response | ||
assert_equal 'Transaction approved', response.message | ||
assert_equal 'foo@example.com', response.params['metadata']['email'] | ||
assert_match CHARGE_ID_REGEX, response.authorization | ||
end | ||
|
||
def test_unsuccessful_purchase_third_party_token | ||
auth = @gateway.store(@credit_card, @options) | ||
customer_id = auth.params['id'] | ||
response = @gateway.purchase(@amount, @invalid_token, @options.merge!(customer_id: customer_id)) | ||
assert_failure response | ||
assert_equal "Token 'tok_invalid' does not exist", response.message | ||
end | ||
|
||
def test_successful_stored_credentials_first_recurring | ||
stored_credentials = { | ||
initiator: 'cardholder', | ||
reason_type: 'recurring' | ||
} | ||
@options.merge!(stored_credential: stored_credentials) | ||
response = @gateway.purchase(@amount, @credit_card, @options) | ||
assert_success response | ||
assert_equal 'Transaction approved', response.message | ||
assert_equal 'first_recurring', response.params['type'] | ||
assert_match CHARGE_ID_REGEX, response.authorization | ||
end | ||
|
||
def test_successful_stored_credentials_subsequent_recurring | ||
stored_credentials = { | ||
initiator: 'merchant', | ||
reason_type: 'recurring' | ||
} | ||
@options.merge!(stored_credential: stored_credentials) | ||
response = @gateway.purchase(@amount, @credit_card, @options) | ||
assert_success response | ||
assert_equal 'Transaction approved', response.message | ||
assert_equal 'subsequent_recurring', response.params['type'] | ||
assert_match CHARGE_ID_REGEX, response.authorization | ||
end | ||
|
||
def test_successful_stored_credentials_customer_initiated | ||
stored_credentials = { | ||
initiator: 'cardholder', | ||
reason_type: 'unscheduled' | ||
} | ||
@options.merge!(stored_credential: stored_credentials) | ||
response = @gateway.purchase(@amount, @credit_card, @options) | ||
assert_success response | ||
assert_equal 'Transaction approved', response.message | ||
assert_equal 'customer_initiated', response.params['type'] | ||
assert_match CHARGE_ID_REGEX, response.authorization | ||
end | ||
|
||
def test_successful_stored_credentials_merchant_initiated | ||
stored_credentials = { | ||
initiator: 'merchant', | ||
reason_type: 'installment' | ||
} | ||
@options.merge!(stored_credential: stored_credentials) | ||
response = @gateway.purchase(@amount, @credit_card, @options) | ||
assert_success response | ||
assert_equal 'Transaction approved', response.message | ||
assert_equal 'merchant_initiated', response.params['type'] | ||
assert_match CHARGE_ID_REGEX, response.authorization | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
require 'test_helper' | ||
require_relative 'securion_pay_test' | ||
|
||
class Shift4V2Test < SecurionPayTest | ||
include CommStub | ||
|
||
def setup | ||
super | ||
@gateway = Shift4V2Gateway.new( | ||
secret_key: 'pr_test_random_key' | ||
) | ||
end | ||
|
||
def test_invalid_raw_response | ||
@gateway.expects(:ssl_request).returns(invalid_json_response) | ||
|
||
response = @gateway.purchase(@amount, @credit_card, @options) | ||
assert_failure response | ||
assert_match(/^Invalid response received from the Shift4 V2 API/, response.message) | ||
end | ||
|
||
def test_ensure_does_not_respond_to_credit; end | ||
|
||
private | ||
|
||
def pre_scrubbed | ||
<<-PRE_SCRUBBED | ||
opening connection to api.shift4.com:443... | ||
opened | ||
starting SSL for api.shift4.com:443... | ||
SSL established | ||
<- "POST /charges HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nAuthorization: Basic cHJfdGVzdF9xWk40VlZJS0N5U2ZDZVhDQm9ITzlEQmU6\r\nUser-Agent: SecurionPay/v1 ActiveMerchantBindings/1.47.0\r\nAccept-Encoding: gzip;q=0,deflate;q=0.6\r\nAccept: */*\r\nConnection: close\r\nHost: api.shift4.com\r\nContent-Length: 214\r\n\r\n" | ||
<- "amount=2000¤cy=usd&card[number]=4242424242424242&card[expMonth]=9&card[expYear]=2016&card[cvc]=123&card[cardholderName]=Longbob+Longsen&description=ActiveMerchant+test+charge&metadata[email]=foo%40example.com" | ||
-> "HTTP/1.1 200 OK\r\n" | ||
-> "Server: cloudflare-nginx\r\n" | ||
-> "Date: Fri, 12 Jun 2015 21:36:39 GMT\r\n" | ||
-> "Content-Type: application/json;charset=UTF-8\r\n" | ||
-> "Transfer-Encoding: chunked\r\n" | ||
-> "Connection: close\r\n" | ||
-> "Set-Cookie: __cfduid=d5da73266c61acce6307176d45e2672b41434144998; expires=Sat, 11-Jun-16 21:36:38 GMT; path=/; domain=.securionpay.com; HttpOnly\r\n" | ||
-> "CF-RAY: 1f58b1414ca00af6-WAW\r\n" | ||
-> "\r\n" | ||
-> "1f4\r\n" | ||
reading 500 bytes... | ||
-> "{\"id\":\"char_TOnen0ZcDMYzECNS4fItK9P4\",\"created\":1434144998,\"objectType\":\"charge\",\"amount\":2000,\"currency\":\"USD\",\"description\":\"ActiveMerchant test charge\",\"card\":{\"id\":\"card_yJ4JNcp6P4sG8UrtZ62VWb5e\",\"created\":1434144998,\"objectType\":\"card\",\"first6\":\"424242\",\"last4\":\"4242\",\"fingerprint\":\"ecAKhFD1dmDAMKD9\",\"expMonth\":\"9\",\"expYear\":\"2016\",\"cardholderName\":\"Longbob Longsen\",\"brand\":\"Visa\",\"type\":\"Credit Card\"},\"captured\":true,\"refunded\":false,\"disputed\":false,\"metadata\":{\"email\":\"foo@example.com\"}}" | ||
read 500 bytes | ||
reading 2 bytes... | ||
-> "\r\n" | ||
read 2 bytes | ||
-> "0\r\n" | ||
-> "\r\n" | ||
Conn close | ||
PRE_SCRUBBED | ||
end | ||
|
||
def post_scrubbed | ||
<<-POST_SCRUBBED | ||
opening connection to api.shift4.com:443... | ||
opened | ||
starting SSL for api.shift4.com:443... | ||
SSL established | ||
<- "POST /charges HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nAuthorization: Basic [FILTERED]\r\nUser-Agent: SecurionPay/v1 ActiveMerchantBindings/1.47.0\r\nAccept-Encoding: gzip;q=0,deflate;q=0.6\r\nAccept: */*\r\nConnection: close\r\nHost: api.shift4.com\r\nContent-Length: 214\r\n\r\n" | ||
<- "amount=2000¤cy=usd&card[number]=[FILTERED]&card[expMonth]=[FILTERED]&card[expYear]=[FILTERED]&card[cvc]=[FILTERED]&card[cardholderName]=[FILTERED]&description=ActiveMerchant+test+charge&metadata[email]=foo%40example.com" | ||
-> "HTTP/1.1 200 OK\r\n" | ||
-> "Server: cloudflare-nginx\r\n" | ||
-> "Date: Fri, 12 Jun 2015 21:36:39 GMT\r\n" | ||
-> "Content-Type: application/json;charset=UTF-8\r\n" | ||
-> "Transfer-Encoding: chunked\r\n" | ||
-> "Connection: close\r\n" | ||
-> "Set-Cookie: __cfduid=d5da73266c61acce6307176d45e2672b41434144998; expires=Sat, 11-Jun-16 21:36:38 GMT; path=/; domain=.securionpay.com; HttpOnly\r\n" | ||
-> "CF-RAY: 1f58b1414ca00af6-WAW\r\n" | ||
-> "\r\n" | ||
-> "1f4\r\n" | ||
reading 500 bytes... | ||
-> "{\"id\":\"char_TOnen0ZcDMYzECNS4fItK9P4\",\"created\":1434144998,\"objectType\":\"charge\",\"amount\":2000,\"currency\":\"USD\",\"description\":\"ActiveMerchant test charge\",\"card\":{\"id\":\"card_yJ4JNcp6P4sG8UrtZ62VWb5e\",\"created\":1434144998,\"objectType\":\"card\",\"first6\":\"424242\",\"last4\":\"4242\",\"fingerprint\":\"ecAKhFD1dmDAMKD9\",\"expMonth\":\"9\",\"expYear\":\"2016\",\"cardholderName\":\"Longbob Longsen\",\"brand\":\"Visa\",\"type\":\"Credit Card\"},\"captured\":true,\"refunded\":false,\"disputed\":false,\"metadata\":{\"email\":\"foo@example.com\"}}" | ||
read 500 bytes | ||
reading 2 bytes... | ||
-> "\r\n" | ||
read 2 bytes | ||
-> "0\r\n" | ||
-> "\r\n" | ||
Conn close | ||
POST_SCRUBBED | ||
end | ||
end |