diff --git a/lib/midtrans_api/api/merchant/get.rb b/lib/midtrans_api/api/merchant/get.rb new file mode 100644 index 0000000..d02c9bc --- /dev/null +++ b/lib/midtrans_api/api/merchant/get.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module MidtransApi + module Api + module Merchant + class Get < MidtransApi::Api::Base + PATH = 'merchants' + + def get(params, partner_id) + response = client.get(PATH, params, { + 'X-PARTNER-ID': partner_id + }) + + MidtransApi::Model::Merchant::Get.new(response) + end + end + end + end +end diff --git a/lib/midtrans_api/client.rb b/lib/midtrans_api/client.rb index 5d0d688..2e28944 100644 --- a/lib/midtrans_api/client.rb +++ b/lib/midtrans_api/client.rb @@ -14,6 +14,7 @@ require 'midtrans_api/api/check/balance' require 'midtrans_api/api/disbursement/payout' require 'midtrans_api/api/merchant/create' +require 'midtrans_api/api/merchant/get' require 'midtrans_api/api/channel/list' require 'midtrans_api/middleware/handle_response_exception' @@ -30,6 +31,7 @@ require 'midtrans_api/model/check/balance' require 'midtrans_api/model/disbursement/payout' require 'midtrans_api/model/merchant/create' +require 'midtrans_api/model/merchant/get' module MidtransApi class Client @@ -104,6 +106,10 @@ def merchant @merchant ||= MidtransApi::Api::Merchant::Create.new(self) end + def get_merchant + @merchant_get ||= MidtransApi::Api::Merchant::Get.new(self) + end + def channel @channel ||= MidtransApi::Api::Channel::List.new(self) end diff --git a/lib/midtrans_api/model/merchant/get.rb b/lib/midtrans_api/model/merchant/get.rb new file mode 100644 index 0000000..8f4cbac --- /dev/null +++ b/lib/midtrans_api/model/merchant/get.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require_relative 'item' + +module MidtransApi + module Model + module Merchant + class Get < MidtransApi::Model::Base + resource_attributes :merchants + + def resolve_params_attr(attr) + attr.to_s + end + + def merchant_list + return [] unless merchants + + merchants.map do |merchant_data| + Item.new(merchant_data) + end + end + end + end + end +end diff --git a/lib/midtrans_api/model/merchant/item.rb b/lib/midtrans_api/model/merchant/item.rb new file mode 100644 index 0000000..3d06e76 --- /dev/null +++ b/lib/midtrans_api/model/merchant/item.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module MidtransApi + module Model + module Merchant + class Item < MidtransApi::Model::Base + attr_reader :merchant_id, :merchant_name, :merchant_phone_number, :email + + def initialize(merchant_data) + @merchant_id = merchant_data['merchant_id'] + @merchant_name = merchant_data['merchant_name'] + @merchant_phone_number = merchant_data['merchant_phone_number'] + @email = merchant_data['email'] + end + + def to_h + { + merchant_id: merchant_id, + merchant_name: merchant_name, + merchant_phone_number: merchant_phone_number, + email: email + } + end + end + end + end +end diff --git a/spec/lib/midtrans_api/api/merchant/get_spec.rb b/spec/lib/midtrans_api/api/merchant/get_spec.rb new file mode 100644 index 0000000..8a2634b --- /dev/null +++ b/spec/lib/midtrans_api/api/merchant/get_spec.rb @@ -0,0 +1,314 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe MidtransApi::Api::Merchant::Get do + let(:client) do + MidtransApi::Client.new( + client_key: 'secret_key', + server_key: 'secret_key', + sandbox: true, + api_version: :v1 + ) + end + + let(:success_response) do + { + "status_code": "200", + "status_message": "Merchants have been successfully retrieved.", + "merchants": [ + { + "merchant_id": "G221991147", + "merchant_name": "MSN KAP Agus Ubaidillah dan Rekan01", + "merchant_phone_number": "+621000000000", + "email": "dhany+39457_79@mekari.com" + }, + { + "merchant_id": "G539217527", + "merchant_name": "MSN KAP Agus Ubaidillah dan Rekan01", + "merchant_phone_number": "+621000000000", + "email": "dhany+39457_80@mekari.com" + } + ] + } + end + + let(:empty_merchants_response) do + { + "status_code": "200", + "status_message": "No merchants found.", + "merchants": [] + } + end + + let(:missing_merchants_response) do + { + "status_code": "200", + "status_message": "No merchants found." + } + end + + let(:merchants_with_empty_fields_response) do + { + "status_code": "200", + "status_message": "Merchants have been successfully retrieved.", + "merchants": [ + { + "merchant_id": "G221991147", + "merchant_name": "", + "merchant_phone_number": nil, + "email": "dhany+39457_79@mekari.com" + }, + { + "merchant_id": "", + "merchant_name": "Test Merchant", + "merchant_phone_number": "+621000000000", + "email": "" + } + ] + } + end + + let(:merchants_with_missing_fields_response) do + { + "status_code": "200", + "status_message": "Merchants have been successfully retrieved.", + "merchants": [ + { + "merchant_id": "G221991147", + "email": "dhany+39457_79@mekari.com" + }, + { + "merchant_name": "Test Merchant", + "merchant_phone_number": "+621000000000" + } + ] + } + end + + let(:merchants_with_unexpected_fields_response) do + { + "status_code": "200", + "status_message": "Merchants have been successfully retrieved.", + "unexpected_root_field": "some_value", + "merchants": [ + { + "merchant_id": "G221991147", + "merchant_name": "MSN KAP Agus Ubaidillah dan Rekan01", + "merchant_phone_number": "+621000000000", + "email": "dhany+39457_79@mekari.com", + "unexpected_field": "unexpected_value", + "another_unexpected_field": { + "nested": "data" + } + }, + { + "merchant_id": "G539217527", + "merchant_name": "MSN KAP Agus Ubaidillah dan Rekan01", + "merchant_phone_number": "+621000000000", + "email": "dhany+39457_80@mekari.com", + "extra_field": 12345, + "boolean_field": true + } + ] + } + end + + describe '#get' do + context 'with keyword parameter' do + it 'returns expected response' do + partner_id = '739' + params = { keyword: 'MSN KAP Agus Ubaidillah dan Rekan01' } + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .with(query: params) + .to_return(status: 200, body: success_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_an(Array) + expect(response.merchants.length).to eq(2) + + # Test merchant_list method + merchant_list = response.merchant_list + expect(merchant_list).to be_an(Array) + expect(merchant_list.length).to eq(2) + + first_merchant = merchant_list.first + expect(first_merchant.merchant_id).to eq('G221991147') + expect(first_merchant.merchant_name).to eq('MSN KAP Agus Ubaidillah dan Rekan01') + expect(first_merchant.merchant_phone_number).to eq('+621000000000') + expect(first_merchant.email).to eq('dhany+39457_79@mekari.com') + end + end + + context 'without keyword parameter' do + it 'returns expected response' do + partner_id = '739' + params = {} + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .to_return(status: 200, body: success_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_an(Array) + end + end + + context 'when merchants array is empty' do + it 'returns empty merchant list' do + partner_id = '739' + params = {} + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .to_return(status: 200, body: empty_merchants_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_an(Array) + expect(response.merchants).to be_empty + expect(response.merchant_list).to be_an(Array) + expect(response.merchant_list).to be_empty + end + end + + context 'when merchants field is missing from response' do + it 'handles missing merchants field gracefully' do + partner_id = '739' + params = {} + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .to_return(status: 200, body: missing_merchants_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_nil + expect(response.merchant_list).to be_an(Array) + expect(response.merchant_list).to be_empty + end + end + + context 'when merchant fields are empty or nil' do + it 'handles empty and nil field values gracefully' do + partner_id = '739' + params = {} + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .to_return(status: 200, body: merchants_with_empty_fields_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_an(Array) + expect(response.merchants.length).to eq(2) + + merchant_list = response.merchant_list + expect(merchant_list.length).to eq(2) + + first_merchant = merchant_list.first + expect(first_merchant.merchant_id).to eq('G221991147') + expect(first_merchant.merchant_name).to eq('') + expect(first_merchant.merchant_phone_number).to be_nil + expect(first_merchant.email).to eq('dhany+39457_79@mekari.com') + + second_merchant = merchant_list.last + expect(second_merchant.merchant_id).to eq('') + expect(second_merchant.merchant_name).to eq('Test Merchant') + expect(second_merchant.merchant_phone_number).to eq('+621000000000') + expect(second_merchant.email).to eq('') + end + end + + context 'when merchant fields are missing' do + it 'handles missing field values gracefully' do + partner_id = '739' + params = {} + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .to_return(status: 200, body: merchants_with_missing_fields_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_an(Array) + expect(response.merchants.length).to eq(2) + + merchant_list = response.merchant_list + expect(merchant_list.length).to eq(2) + + first_merchant = merchant_list.first + expect(first_merchant.merchant_id).to eq('G221991147') + expect(first_merchant.merchant_name).to be_nil + expect(first_merchant.merchant_phone_number).to be_nil + expect(first_merchant.email).to eq('dhany+39457_79@mekari.com') + + second_merchant = merchant_list.last + expect(second_merchant.merchant_id).to be_nil + expect(second_merchant.merchant_name).to eq('Test Merchant') + expect(second_merchant.merchant_phone_number).to eq('+621000000000') + expect(second_merchant.email).to be_nil + end + end + + context 'when response contains unexpected fields' do + it 'ignores unexpected fields and processes only expected ones' do + partner_id = '739' + params = {} + + stub_request(:get, "#{client.config.api_url}/#{client.config.api_version}/merchants") + .to_return(status: 200, body: merchants_with_unexpected_fields_response.to_json) + + merchant_api = described_class.new(client) + response = merchant_api.get(params, partner_id) + + expect(response).to be_instance_of MidtransApi::Model::Merchant::Get + expect(response.merchants).to be_an(Array) + expect(response.merchants.length).to eq(2) + + # Verify that unexpected root-level fields are ignored + expect(response).not_to respond_to(:unexpected_root_field) + + merchant_list = response.merchant_list + expect(merchant_list.length).to eq(2) + + # Test first merchant - should only have expected fields + first_merchant = merchant_list.first + expect(first_merchant.merchant_id).to eq('G221991147') + expect(first_merchant.merchant_name).to eq('MSN KAP Agus Ubaidillah dan Rekan01') + expect(first_merchant.merchant_phone_number).to eq('+621000000000') + expect(first_merchant.email).to eq('dhany+39457_79@mekari.com') + + # Verify that unexpected merchant fields are ignored + expect(first_merchant).not_to respond_to(:unexpected_field) + expect(first_merchant).not_to respond_to(:another_unexpected_field) + + # Test second merchant - should only have expected fields + second_merchant = merchant_list.last + expect(second_merchant.merchant_id).to eq('G539217527') + expect(second_merchant.merchant_name).to eq('MSN KAP Agus Ubaidillah dan Rekan01') + expect(second_merchant.merchant_phone_number).to eq('+621000000000') + expect(second_merchant.email).to eq('dhany+39457_80@mekari.com') + + # Verify that unexpected merchant fields are ignored + expect(second_merchant).not_to respond_to(:extra_field) + expect(second_merchant).not_to respond_to(:boolean_field) + + # Verify to_h method only returns expected fields + first_merchant_hash = first_merchant.to_h + expect(first_merchant_hash.keys).to contain_exactly(:merchant_id, :merchant_name, :merchant_phone_number, :email) + expect(first_merchant_hash[:merchant_id]).to eq('G221991147') + end + end + end +end