diff --git a/README.md b/README.md index 0f05aef..14e8532 100644 --- a/README.md +++ b/README.md @@ -345,6 +345,11 @@ else end ``` +### Epsilon Link Payment Void Transaction +```ruby +gateway.void('order_number') +``` + ### Error handling If epsilon server returns status excepted 200, `#purchase` method raise `ActiveMerchant::ResponseError`. diff --git a/lib/active_merchant/billing/gateways/epsilon_link_payment.rb b/lib/active_merchant/billing/gateways/epsilon_link_payment.rb index 013b352..d58a266 100644 --- a/lib/active_merchant/billing/gateways/epsilon_link_payment.rb +++ b/lib/active_merchant/billing/gateways/epsilon_link_payment.rb @@ -37,6 +37,15 @@ def purchase(amount, detail = {}) commit('receive_order3.cgi', params, RESPONSE_KEYS) end + + def void(order_number) + params = { + contract_code: self.contract_code, + order_number: order_number + } + + commit('cancel_payment.cgi', params) + end end end end diff --git a/test/fixtures/vcr_cassettes/epsilon_link_type_purchase_fail.yml b/test/fixtures/vcr_cassettes/epsilon_link_type_purchase_fail.yml new file mode 100644 index 0000000..712d5c2 --- /dev/null +++ b/test/fixtures/vcr_cassettes/epsilon_link_type_purchase_fail.yml @@ -0,0 +1,43 @@ +--- +http_interactions: +- request: + method: post + uri: https://beta.epsilon.jp/cgi-bin/order/receive_order3.cgi + body: + encoding: UTF-8 + string: contract_code=[CONTRACT_CODE]&user_id=U1594794779&user_name=%E5%B1%B1%E7%94%B0+%E5%A4%AA%E9%83%8E&user_mail_add=yamada-taro%40example.com&item_code=ITEM001&item_name=Greate+Product&order_number=O59578602&st_code=invalid_id&mission_code=1&item_price=10000&process_code=1&xml=1&delivery_code=99&consignee_postal=1000001&consignee_name=%E3%82%A4%E3%83%97%E3%82%B7%E3%83%AD%E3%83%B3%E3%82%BF%E3%83%AD%E3%82%A6&consignee_address=%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8D%83%E4%BB%A3%E7%94%B0%E5%8C%BA%E5%8D%83%E4%BB%A3%E7%94%B01%E7%95%AA1%E5%8F%B7&consignee_tel=0312345678&orderer_postal=1000001&orderer_name=YAMADA+Taro&orderer_address=%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8D%83%E4%BB%A3%E7%94%B0%E5%8C%BA%E5%8D%83%E4%BB%A3%E7%94%B01%E7%95%AA1%E5%8F%B7&orderer_tel=0312345678&memo1=memo1&memo2=memo2 + headers: + Content-Type: + - application/x-www-form-urlencoded + Connection: + - close + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Wed, 15 Jul 2020 06:32:59 GMT + Server: + - Apache + Connection: + - close + Transfer-Encoding: + - chunked + Content-Type: + - text/xml + body: + encoding: UTF-8 + string: "\r\n \r\n + \ \r\n \r\n \r\n \r\n \r\n + \ \r\n" + recorded_at: Wed, 15 Jul 2020 06:33:00 GMT +recorded_with: VCR 6.0.0 diff --git a/test/fixtures/vcr_cassettes/epsilon_link_type_purchase_successfull.yml b/test/fixtures/vcr_cassettes/epsilon_link_type_purchase_successfull.yml new file mode 100644 index 0000000..310e7f4 --- /dev/null +++ b/test/fixtures/vcr_cassettes/epsilon_link_type_purchase_successfull.yml @@ -0,0 +1,44 @@ +--- +http_interactions: +- request: + method: post + uri: https://beta.epsilon.jp/cgi-bin/order/receive_order3.cgi + body: + encoding: UTF-8 + string: contract_code=[CONTRACT_CODE]&user_id=U1594794223&user_name=%E5%B1%B1%E7%94%B0+%E5%A4%AA%E9%83%8E&user_mail_add=yamada-taro%40example.com&item_code=ITEM001&item_name=Greate+Product&order_number=O43585140&st_code=00000-0000-01000-00000-00000-00000-00000&mission_code=1&item_price=10000&process_code=1&xml=1&delivery_code=99&consignee_postal=1000001&consignee_name=%E3%82%A4%E3%83%97%E3%82%B7%E3%83%AD%E3%83%B3%E3%82%BF%E3%83%AD%E3%82%A6&consignee_address=%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8D%83%E4%BB%A3%E7%94%B0%E5%8C%BA%E5%8D%83%E4%BB%A3%E7%94%B01%E7%95%AA1%E5%8F%B7&consignee_tel=0312345678&orderer_postal=1000001&orderer_name=YAMADA+Taro&orderer_address=%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8D%83%E4%BB%A3%E7%94%B0%E5%8C%BA%E5%8D%83%E4%BB%A3%E7%94%B01%E7%95%AA1%E5%8F%B7&orderer_tel=0312345678&memo1=memo1&memo2=memo2 + headers: + Content-Type: + - application/x-www-form-urlencoded + Connection: + - close + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Wed, 15 Jul 2020 06:23:43 GMT + Server: + - Apache + Connection: + - close + Transfer-Encoding: + - chunked + Content-Type: + - text/xml + body: + encoding: UTF-8 + string: | + + + + + + recorded_at: Wed, 15 Jul 2020 06:23:44 GMT +recorded_with: VCR 6.0.0 diff --git a/test/fixtures/vcr_cassettes/epsilon_link_type_void_fail.yml b/test/fixtures/vcr_cassettes/epsilon_link_type_void_fail.yml new file mode 100644 index 0000000..09357c1 --- /dev/null +++ b/test/fixtures/vcr_cassettes/epsilon_link_type_void_fail.yml @@ -0,0 +1,45 @@ +--- +http_interactions: +- request: + method: post + uri: https://beta.epsilon.jp/cgi-bin/order/cancel_payment.cgi + body: + encoding: UTF-8 + string: contract_code=&order_number=invalid_order_number + headers: + Content-Type: + - application/x-www-form-urlencoded + Connection: + - close + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 20 Jul 2020 02:48:28 GMT + Server: + - Apache + Connection: + - close + Transfer-Encoding: + - chunked + Content-Type: + - text/xml; charset=CP932 + body: + encoding: UTF-8 + string: |- + + + + + + + recorded_at: Mon, 20 Jul 2020 02:48:29 GMT +recorded_with: VCR 6.0.0 diff --git a/test/fixtures/vcr_cassettes/epsilon_link_type_void_successfull.yml b/test/fixtures/vcr_cassettes/epsilon_link_type_void_successfull.yml new file mode 100644 index 0000000..e29e23c --- /dev/null +++ b/test/fixtures/vcr_cassettes/epsilon_link_type_void_successfull.yml @@ -0,0 +1,45 @@ +--- +http_interactions: +- request: + method: post + uri: https://beta.epsilon.jp/cgi-bin/order/cancel_payment.cgi + body: + encoding: UTF-8 + string: contract_code=[CONTRACT_CODE]&order_number=595213151 + headers: + Content-Type: + - application/x-www-form-urlencoded + Connection: + - close + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 20 Jul 2020 02:56:42 GMT + Server: + - Apache + Connection: + - close + Transfer-Encoding: + - chunked + Content-Type: + - text/xml; charset=CP932 + body: + encoding: UTF-8 + string: |- + + + + + + + recorded_at: Mon, 20 Jul 2020 02:56:43 GMT +recorded_with: VCR 6.0.0 diff --git a/test/remote/gateways/remote_epsilon_link_payment_test.rb b/test/remote/gateways/remote_epsilon_link_payment_test.rb new file mode 100644 index 0000000..510da15 --- /dev/null +++ b/test/remote/gateways/remote_epsilon_link_payment_test.rb @@ -0,0 +1,46 @@ +require 'test_helper' +class RemoteEpsilonLinkPaymentTest < MiniTest::Test + include SamplePaymentMethods + + def gateway + @gateway ||= ActiveMerchant::Billing::EpsilonLinkPaymentGateway.new + end + + def test_epsilon_link_type_purchase_successfull + VCR.use_cassette(:epsilon_link_type_purchase_successfull) do + response = gateway.purchase(10000, valid_epsilon_link_type_purchase_detail) + + assert_equal true, response.success? + assert_equal true, !response.params['redirect'].empty? + end + end + + def test_epsilon_link_type_purchase_fail + VCR.use_cassette(:epsilon_link_type_purchase_fail) do + response = gateway.purchase(10000, invalid_epsilon_link_type_purchase_detail) + + assert_equal false, response.success? + assert_equal true, response.params["error_detail"].valid_encoding? + end + end + + def test_epsilon_link_type_void_successfull + VCR.use_cassette(:epsilon_link_type_void_successfull) do + # あらかじめ課金済ステータスの受注がイプシロン側にないと取り消しができないため、課金済の受注をイプシロン側で作成しておいた。 + # ここでは void の引数として作成済の受注のorder_numberを渡している。 + # VCRのキャッシュを作成し直す場合は変更しないとエラーとなる。 + response = gateway.void('595213151') + + assert_equal true, response.success? + end + end + + def test_epsilon_link_type_void_fail + VCR.use_cassette(:epsilon_link_type_void_fail) do + response = gateway.void('invalid_order_number') + + assert_equal false, response.success? + assert_equal true, response.params["error_detail"].valid_encoding? + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index c2445fd..405fb4a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -230,6 +230,52 @@ def gmo_after_purchase_detail } end + def valid_epsilon_link_type_purchase_detail + now = Time.now + { + user_id: "U#{Time.now.to_i}", + user_name: '山田 太郎', + user_email: 'yamada-taro@example.com', + item_code: 'ITEM001', + item_name: 'Greate Product', + order_number: "O#{now.sec}#{now.usec}", + st_code: '00000-0000-01000-00000-00000-00000-00000', + memo1: 'memo1', + memo2: 'memo2', + consignee_postal: '1000001', + consignee_name: 'イプシロンタロウ', + consignee_address: '東京都千代田区千代田1番1号', + consignee_tel: '0312345678', + orderer_postal: '1000001', + orderer_name: 'YAMADA Taro', + orderer_address: '東京都千代田区千代田1番1号', + orderer_tel: '0312345678', + } + end + + def invalid_epsilon_link_type_purchase_detail + now = Time.now + { + user_id: "U#{Time.now.to_i}", + user_name: '山田 太郎', + user_email: 'yamada-taro@example.com', + item_code: 'ITEM001', + item_name: 'Greate Product', + order_number: "O#{now.sec}#{now.usec}", + st_code: 'invalid_id', + memo1: 'memo1', + memo2: 'memo2', + consignee_postal: '1000001', + consignee_name: 'イプシロンタロウ', + consignee_address: '東京都千代田区千代田1番1号', + consignee_tel: '0312345678', + orderer_postal: '1000001', + orderer_name: 'YAMADA Taro', + orderer_address: '東京都千代田区千代田1番1号', + orderer_tel: '0312345678', + } + end + def fixture_xml(filename, parse: true) xml = File.read("test/fixtures/#{filename}") parse ? Nokogiri.parse(xml.sub('x-sjis-cp932', 'CP932')) : xml