Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,6 @@
<tabs>true</tabs>
<spacesPerTab>4</spacesPerTab>
</indent>
<googleJavaFormat>
<version>1.22.0</version>
<style>AOSP</style>
<reflowLongStrings>true</reflowLongStrings>
</googleJavaFormat>
</java>
</configuration>
<executions>
Expand Down
226 changes: 115 additions & 111 deletions src/main/java/com/phonepe/sdk/pg/common/http/HttpCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,121 +48,125 @@
@Slf4j
public class HttpCommand<T, R> {

private final OkHttpClient client;
@NotNull private final String hostURL;
@NotNull private String url;
private List<HttpHeaderPair> headers;
private final ObjectMapper objectMapper;
private final TypeReference<T> responseTypeReference;
private final R requestData;
private final String encodingType;
@NotBlank private final HttpMethodType methodName;
private Map<String, String> queryParams;
private final OkHttpClient client;
@NotNull private final String hostURL;
@NotNull private String url;
private List<HttpHeaderPair> headers;
private final ObjectMapper objectMapper;
private final TypeReference<T> responseTypeReference;
private final R requestData;
private final String encodingType;
@NotBlank
private final HttpMethodType methodName;
private Map<String, String> queryParams;

/**
* Returns the request body containing the serialized data.
*
* @return the request body as a RequestBody object
*/
@SneakyThrows
private RequestBody prepareRequestBody() {
if (Objects.equals(encodingType, APPLICATION_JSON)) {
return RequestBody.create(
objectMapper.writeValueAsBytes(requestData), MediaType.parse(encodingType));
}
/**
* Returns the request body containing the serialized data.
*
* @return the request body as a RequestBody object
*/
@SneakyThrows
private RequestBody prepareRequestBody() {
if (Objects.equals(encodingType, APPLICATION_JSON)) {
return RequestBody.create(
objectMapper.writeValueAsBytes(requestData), MediaType.parse(encodingType));
}

if (Objects.equals(encodingType, APPLICATION_FORM_URLENCODED)) {
return (RequestBody) requestData;
}
return (RequestBody) requestData;
}
if (Objects.equals(encodingType, APPLICATION_FORM_URLENCODED)) {
return (RequestBody) requestData;
}
return (RequestBody) requestData;
}

/**
* Constructs an HTTP URL by appending the provided URL to the base host URL.
*
* @param url the URL to append to the base host URL
* @return the constructed HttpUrl object
* @throws IllegalArgumentException if the base host URL or the provided URL is invalid
*/
private HttpUrl prepareHttpURL(String url) {
HttpUrl.Builder urlBuilder =
Objects.requireNonNull(HttpUrl.parse(String.format("%s%s", this.hostURL, url)))
.newBuilder();
if (!Objects.isNull(queryParams)) {
for (Map.Entry<String, String> param : queryParams.entrySet()) {
urlBuilder.addQueryParameter(param.getKey(), param.getValue());
}
}
return HttpUrl.get(urlBuilder.build().toString());
}
/**
* Constructs an HTTP URL by appending the provided URL to the base host URL.
*
* @param url the URL to append to the base host URL
* @return the constructed HttpUrl object
* @throws IllegalArgumentException if the base host URL or the provided URL is invalid
*/
private HttpUrl prepareHttpURL(String url) {
HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(String.format("%s%s", this.hostURL, url)))
.newBuilder();
if (!Objects.isNull(queryParams)) {
for (Map.Entry<String, String> param : queryParams.entrySet()) {
urlBuilder.addQueryParameter(param.getKey(), param.getValue());
}
}
return HttpUrl.get(urlBuilder.build()
.toString());
}

/**
* Executes the HTTP request and returns the response.
*
* @return the response object
*/
@SneakyThrows
public T execute() {
log.info("Calling {} : {}{}", methodName, hostURL, url);
final HttpUrl httpUrl = prepareHttpURL(this.url);
final Request httpRequest = prepareRequest(httpUrl);
final Response response = client.newCall(httpRequest).execute();
return handleResponse(response);
}
/**
* Executes the HTTP request and returns the response.
*
* @return the response object
*/
@SneakyThrows
public T execute() {
log.info("Calling {} : {}{}", methodName, hostURL, url);
final HttpUrl httpUrl = prepareHttpURL(this.url);
final Request httpRequest = prepareRequest(httpUrl);
final Response response = client.newCall(httpRequest)
.execute();
return handleResponse(response);
}

@SneakyThrows
public T handleResponse(Response response) {
int responseCode = response.code();
final byte[] responseBody =
Objects.nonNull(response.body()) ? response.body().bytes() : null;
@SneakyThrows
public T handleResponse(Response response) {
int responseCode = response.code();
final byte[] responseBody = Objects.nonNull(response.body()) ? response.body()
.bytes() : null;
if (responseCode == 204) {
return null;
}
if (responseCode >= 200 && responseCode <= 299) {
return objectMapper.readValue(responseBody, responseTypeReference);
}
try {
PhonePeResponse phonePeResponse = objectMapper.readValue(responseBody, PhonePeResponse.class);
if (ExceptionMapper.codeToException.containsKey(responseCode)) {
ExceptionMapper.prepareCodeToException(
responseCode, response.message(), phonePeResponse);
} else if (responseCode >= 400 && responseCode <= 499) {
throw new ClientError(responseCode, response.message(), phonePeResponse);
} else if (responseCode >= 500 && responseCode <= 599) {
throw new ServerError(responseCode, response.message(), phonePeResponse);
}
throw new PhonePeException(responseCode, response.message(), phonePeResponse);
} catch (JsonProcessingException jsonProcessingException) {
throw new PhonePeException(responseCode, response.message());
}
}

if (responseCode >= 200 && responseCode <= 299) {
return objectMapper.readValue(responseBody, responseTypeReference);
}
try {
PhonePeResponse phonePeResponse =
objectMapper.readValue(responseBody, PhonePeResponse.class);
if (ExceptionMapper.codeToException.containsKey(responseCode)) {
ExceptionMapper.prepareCodeToException(
responseCode, response.message(), phonePeResponse);
} else if (responseCode >= 400 && responseCode <= 499) {
throw new ClientError(responseCode, response.message(), phonePeResponse);
} else if (responseCode >= 500 && responseCode <= 599) {
throw new ServerError(responseCode, response.message(), phonePeResponse);
}
throw new PhonePeException(responseCode, response.message(), phonePeResponse);
} catch (JsonProcessingException jsonProcessingException) {
throw new PhonePeException(responseCode, response.message());
}
}

/**
* Constructs an HTTP request based on the provided HTTP URL, method name, and headers.
*
* @param httpUrl the HTTP URL for the request
* @return the constructed Request object
* @throws PhonePeException if the method name is not supported
*/
public Request prepareRequest(final HttpUrl httpUrl) {
if (methodName == HttpMethodType.POST) {
final Request.Builder requestBuilder =
new Request.Builder().url(httpUrl).post(prepareRequestBody());
if (!Objects.isNull(headers)) {
for (HttpHeaderPair httpHeader : headers) {
requestBuilder.header(httpHeader.getKey(), httpHeader.getValue());
}
}
return requestBuilder.build();
} else if (methodName == HttpMethodType.GET) {
final Request.Builder requestBuilder = new Request.Builder().url(httpUrl).get();
if (!Objects.isNull(headers)) {
for (HttpHeaderPair httpHeader : headers) {
requestBuilder.header(httpHeader.getKey(), httpHeader.getValue());
}
}
return requestBuilder.build();
} else {
throw new PhonePeException(405, "Method Not Supported");
}
}
/**
* Constructs an HTTP request based on the provided HTTP URL, method name, and headers.
*
* @param httpUrl the HTTP URL for the request
* @return the constructed Request object
* @throws PhonePeException if the method name is not supported
*/
public Request prepareRequest(final HttpUrl httpUrl) {
if (methodName == HttpMethodType.POST) {
final Request.Builder requestBuilder = new Request.Builder().url(httpUrl)
.post(prepareRequestBody());
if (!Objects.isNull(headers)) {
for (HttpHeaderPair httpHeader : headers) {
requestBuilder.header(httpHeader.getKey(), httpHeader.getValue());
}
}
return requestBuilder.build();
} else if (methodName == HttpMethodType.GET) {
final Request.Builder requestBuilder = new Request.Builder().url(httpUrl)
.get();
if (!Objects.isNull(headers)) {
for (HttpHeaderPair httpHeader : headers) {
requestBuilder.header(httpHeader.getKey(), httpHeader.getValue());
}
}
return requestBuilder.build();
} else {
throw new PhonePeException(405, "Method Not Supported");
}
}
}
15 changes: 15 additions & 0 deletions src/test/CancelSubscriptionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,19 @@ void testCancelSubscriptionIfResponseReceived() {

wireMockServer.verify(exactly(1), postRequestedFor(urlPathMatching(url)));
}

@Test
void testCancelSubscriptionIfNoContentResponseReceived() {
wireMockServer.resetRequests();
String merchantSubscriptionId = "c61d7378-a081-44ab-9559-ad8563a24b49";
String url = String.format(SubscriptionConstants.CANCEL_API, merchantSubscriptionId);

Map<String, String> headers = getHeadersForSubscription();

addStubForPostRequest(url, headers, null, HttpStatus.SC_NO_CONTENT, Maps.newHashMap(), "");

subscriptionClient.cancelSubscription(merchantSubscriptionId);

wireMockServer.verify(exactly(1), postRequestedFor(urlPathMatching(url)));
}
}
23 changes: 23 additions & 0 deletions src/test/HttpCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.junit.jupiter.api.Assertions.assertThrows;

import com.fasterxml.jackson.core.type.TypeReference;
Expand All @@ -22,6 +23,8 @@
import com.phonepe.sdk.pg.common.http.HttpMethodType;
import com.phonepe.sdk.pg.common.http.PhonePeResponse;
import java.util.Map;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import wiremock.org.apache.http.HttpStatus;
Expand Down Expand Up @@ -74,4 +77,24 @@ void testIfPhonePeResponseNull() {
Assertions.assertEquals(404, phonePeException.getHttpStatusCode());
Assertions.assertEquals("Not Found", phonePeException.getMessage());
}

@Test
void testHttpCommand204() {
String sampleJson = "{\"state\":\"PENDING\"}";
RequestBody requestBody = RequestBody.create(
sampleJson.getBytes(), MediaType.parse(APPLICATION_JSON));
HttpCommand<Void, RequestBody> httpCommand =
HttpCommand.<Void, RequestBody>builder()
.hostURL("http://localhost:30419")
.client(okHttpClient)
.requestData(requestBody)
.objectMapper(mapper)
.responseTypeReference(new TypeReference<>() {})
.url("/testing")
.methodName(HttpMethodType.POST)
.build();
addStubForPostRequest("/testing", sampleJson, HttpStatus.SC_NO_CONTENT, "");
Void result = httpCommand.execute();
Assertions.assertNull(result);
}
}