Skip to content
Open
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
14 changes: 8 additions & 6 deletions src/main/java/com/razorpay/ApiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,20 +221,22 @@ private String getEntity(JSONObject jsonObj, HttpUrl url) {
}

private void throwException(int statusCode, JSONObject responseJson) throws RazorpayException {
if (responseJson.has(ERROR)) {
if (responseJson != null && responseJson.has(ERROR)) {
JSONObject errorResponse = responseJson.getJSONObject(ERROR);
String code = errorResponse.getString(STATUS_CODE);
String description = errorResponse.getString(DESCRIPTION);
throw new RazorpayException(code + ":" + description);
String code = errorResponse.optString(STATUS_CODE, null);
String description = errorResponse.optString(DESCRIPTION, null);
String message = (code != null && description != null) ? code + ":" + description
: (description != null) ? description : "API request failed";
throw new RazorpayException(message, statusCode, code, description);
}
throwServerException(statusCode, responseJson.toString());
throwServerException(statusCode, responseJson != null ? responseJson.toString() : "");
}

private void throwServerException(int statusCode, String responseBody) throws RazorpayException {
StringBuilder sb = new StringBuilder();
sb.append("Status Code: ").append(statusCode).append("\n");
sb.append("Server response: ").append(responseBody);
throw new RazorpayException(sb.toString());
throw new RazorpayException(sb.toString(), statusCode);
}

private Class getClass(String entity) {
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/com/razorpay/RazorpayException.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,79 @@

public class RazorpayException extends Exception {

private static final long serialVersionUID = 1L;

private final Integer statusCode;
private final String code;
private final String description;

public RazorpayException(String message) {
super(message);
this.statusCode = null;
this.code = null;
this.description = null;
}

public RazorpayException(String message, int statusCode) {
super(message);
this.statusCode = statusCode;
this.code = null;
this.description = null;
}

public RazorpayException(String message, int statusCode, String code, String description) {
super(message);
this.statusCode = statusCode;
this.code = code;
this.description = description;
}

public RazorpayException(String message, Throwable cause) {
super(message, cause);
this.statusCode = null;
this.code = null;
this.description = null;
}

public RazorpayException(Throwable cause) {
super(cause);
this.statusCode = null;
this.code = null;
this.description = null;
}

public RazorpayException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
this.statusCode = null;
this.code = null;
this.description = null;
}

/**
* Returns the HTTP status code when the exception was caused by an API error response.
*
* @return the HTTP status code, or null if not available
*/
public Integer getStatusCode() {
return statusCode;
}

/**
* Returns the API error code (e.g. BAD_REQUEST_ERROR) when present in the error response.
*
* @return the error code, or null if not available
*/
public String getCode() {
return code;
}

/**
* Returns the API error description when present in the error response.
*
* @return the error description, or null if not available
*/
public String getDescription() {
return description;
}
}
19 changes: 19 additions & 0 deletions src/test/java/com/razorpay/PaymentClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.mockito.InjectMocks;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.*;
Expand Down Expand Up @@ -1000,6 +1001,24 @@ public void expandedDetails() throws RazorpayException {
}
}

@Test
public void fetchThrowsExceptionWithStatusCodeAndErrorCode() throws IOException {
String errorResponse = "{\"error\":{\"code\":\"BAD_REQUEST_ERROR\","
+ "\"description\":\"Payment not found\"}}";
mockResponseFromExternalClient(errorResponse);
mockResponseHTTPCodeFromExternalClient(400);
mockURL(Arrays.asList("v1", "payments", PAYMENT_ID));

try {
paymentClient.fetch(PAYMENT_ID);
assertTrue("Expected RazorpayException", false);
} catch (RazorpayException e) {
assertEquals(Integer.valueOf(400), e.getStatusCode());
assertEquals("BAD_REQUEST_ERROR", e.getCode());
assertEquals("Payment not found", e.getDescription());
}
}

@Test
public void fetchPaymentMethods() throws RazorpayException {
String mockedResponseJson = "{\n" +
Expand Down
48 changes: 48 additions & 0 deletions src/test/java/com/razorpay/RazorpayExceptionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.razorpay;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

public class RazorpayExceptionTest {

@Test
public void constructorWithMessage_SetsMessageOnly() {
RazorpayException ex = new RazorpayException("test message");
assertEquals("test message", ex.getMessage());
assertNull(ex.getStatusCode());
assertNull(ex.getCode());
assertNull(ex.getDescription());
}

@Test
public void constructorWithMessageAndStatusCode_SetsBoth() {
RazorpayException ex = new RazorpayException("Server error", 500);
assertEquals("Server error", ex.getMessage());
assertEquals(Integer.valueOf(500), ex.getStatusCode());
assertNull(ex.getCode());
assertNull(ex.getDescription());
}

@Test
public void constructorWithFullParams_SetsAllFields() {
RazorpayException ex = new RazorpayException("BAD_REQUEST_ERROR:Invalid payment id",
400, "BAD_REQUEST_ERROR", "Invalid payment id");
assertEquals("BAD_REQUEST_ERROR:Invalid payment id", ex.getMessage());
assertEquals(Integer.valueOf(400), ex.getStatusCode());
assertEquals("BAD_REQUEST_ERROR", ex.getCode());
assertEquals("Invalid payment id", ex.getDescription());
}

@Test
public void constructorWithCause_PreservesLegacyBehavior() {
Exception cause = new RuntimeException("underlying");
RazorpayException ex = new RazorpayException("wrapped", cause);
assertEquals("wrapped", ex.getMessage());
assertEquals(cause, ex.getCause());
assertNull(ex.getStatusCode());
assertNull(ex.getCode());
assertNull(ex.getDescription());
}
}