diff --git a/.gitignore b/.gitignore index 5bc661e..2866229 100644 --- a/.gitignore +++ b/.gitignore @@ -105,4 +105,7 @@ bin/ ############################## .DS_Store -*.gpg \ No newline at end of file +*.gpg +.settings/org.eclipse.buildship.core.prefs +.project +*.prefs diff --git a/README.md b/README.md index e7e4f05..0fc643e 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ This library is the abstraction of Xendit API for access from applications writt - [Get Paylater Charge by ID](#get-paylater-charge-by-id) - [Refund Paylater Charge](#refund-paylater-charge) - [Get Refund by Refund ID](#get-refund-by-refund-id) + - [How to get Request Id](#how-to-get-request-id) - [Contributing](#contributing) - [Lint](#lint) - [Tests](#tests) @@ -1886,6 +1887,28 @@ PaylaterRefund paylaterRefund = PaylaterRefund.getPaylaterRefundStatus("charge-i PaylaterRefund paylaterRefund = xenditclient.paylater.getPaylaterRefundStatus("charge-id", "refund-id"); ``` +### How to get Request ID + +Each API request has an asssociated request identifier. You can find this value in the response headers, under Request-ID. You can use Request-ID to find logs in [API Logs](https://dashboard.xendit.co/api-logs) in Dashboard. Learn more about Searching API Logs using Request-ID in [API Logs Docs](https://docs.xendit.co/api-integration/api-logs). + +If you need to contact us about a specific request, providing the Request ID will ensure the fastest possible resolution. + +The following example will show how to obtain Request-ID when creating QRCode + +```java +/* Without client */ +QRCode qrCode = QRCode.createQRCode("12", QRCode.QRCodeType.DYNAMIC, "IDR", 10000); +/* Xendit.getResponseHeaders() will contain all response headers after your request is completed, hence you can obtain Request-Id from header by doing the following:*/ +System.out.println(Xendit.getResponseHeaders().get("Request-Id")); + +/* With client */ +QRCode qrCode = xenditClient.qrCode.createQRCode("external_id", QRCode.QRCodeType.DYNAMIC, "IDR", 10000); +/* Xendit.getResponseHeaders() will contain all response headers after your request is completed, hence you can obtain Request-Id from header by doing the following:*/ +System.out.println(Xendit.getResponseHeaders().get("Request-Id")); +``` +Full Example can be found [here](https://github.com/xendit/xendit-java/blob/9bd69bd6f4061307a5dee30287a1f7712d060527/xendit-java-library-example/src/main/java/ExampleWithClient/ExampleCreateQRCode.java) + + ## Contributing You can go to the [contributing guidelines](https://github.com/xendit/xendit-java/blob/master/CONTRIBUTING.md) to learn on how to contribute this project. diff --git a/xendit-java-lib/build.gradle b/xendit-java-lib/build.gradle index f9eb283..2e17e40 100644 --- a/xendit-java-lib/build.gradle +++ b/xendit-java-lib/build.gradle @@ -8,7 +8,7 @@ plugins { } group 'com.xendit' -version '1.21.0' +version '1.22.0' sourceCompatibility = 1.8 diff --git a/xendit-java-lib/src/main/java/com/xendit/Xendit.java b/xendit-java-lib/src/main/java/com/xendit/Xendit.java index f59fe96..6bd2f2b 100644 --- a/xendit-java-lib/src/main/java/com/xendit/Xendit.java +++ b/xendit-java-lib/src/main/java/com/xendit/Xendit.java @@ -2,6 +2,7 @@ import com.xendit.network.BaseRequest; import com.xendit.network.NetworkClient; +import java.util.Map; public class Xendit { @@ -19,6 +20,16 @@ public static void setRequestClient(NetworkClient requestClient) { Xendit.requestClient = requestClient; } + protected static Map responseHeaders; + + public static Map getResponseHeaders() { + return responseHeaders; + } + + public static void setResponseHeaders(Map headers) { + Xendit.responseHeaders = headers; + } + public static class Option { private String apiKey; @@ -37,7 +48,7 @@ public String getXenditURL() { } public String getVersion() { - return "1.21.0"; + return "1.22.0"; } } } diff --git a/xendit-java-lib/src/main/java/com/xendit/network/BaseRequest.java b/xendit-java-lib/src/main/java/com/xendit/network/BaseRequest.java index da1ce35..f44eb76 100644 --- a/xendit-java-lib/src/main/java/com/xendit/network/BaseRequest.java +++ b/xendit-java-lib/src/main/java/com/xendit/network/BaseRequest.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Scanner; +import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; @@ -198,6 +199,14 @@ private static XenditResponse httpPatchXenditConnection( int responseCode = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity()); + Header[] allHeaders = response.getAllHeaders(); + Map responseHeaders = new HashMap<>(); + for (Header respHeader : allHeaders) { + responseHeaders.put(respHeader.getName(), respHeader.getValue()); + } + + Xendit.setResponseHeaders(responseHeaders); + return new XenditResponse(responseCode, responseBody); } catch (IOException e) { throw new XenditException("Connection error : " + e.getMessage()); @@ -233,6 +242,12 @@ private static XenditResponse defaultHttpXenditConnection( responseBody = getResponseBody(connection.getErrorStream()); } + Map responseHeaders = new HashMap<>(); + for (Map.Entry> headerResponse : + connection.getHeaderFields().entrySet()) { + responseHeaders.put(headerResponse.getKey(), headerResponse.getValue().get(0)); + } + Xendit.setResponseHeaders(responseHeaders); return new XenditResponse(responseCode, responseBody); } catch (IOException e) { @@ -268,12 +283,14 @@ private static String encodeBase64(String key) throws XenditException { } } - private static String getResponseBody(InputStream responseStream) throws IOException { + private static String getResponseBody(InputStream responseStream) throws XenditException { try (final Scanner scanner = new Scanner(responseStream, RequestResource.CHARSET)) { // \A is the beginning of the stream boundary final String responseBody = scanner.useDelimiter("\\A").next(); responseStream.close(); return responseBody; + } catch (Exception e) { + throw new XenditException("Failed to get response, Please check your connection"); } } diff --git a/xendit-java-lib/src/test/java/com/xenditclient/BalanceTest.java b/xendit-java-lib/src/test/java/com/xenditclient/BalanceTest.java index 31dcff2..eded92d 100644 --- a/xendit-java-lib/src/test/java/com/xenditclient/BalanceTest.java +++ b/xendit-java-lib/src/test/java/com/xenditclient/BalanceTest.java @@ -1,6 +1,7 @@ package com.xenditclient; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -23,12 +24,30 @@ public class BalanceTest { NetworkClient requestClient = mock(BaseRequest.class); Xendit.Option opt = mock(Xendit.Option.class); BalanceClient balanceClient = mock(BalanceClient.class); + private static Map responseHeaders = + new HashMap() { + { + put("Request-Id", "test_request_id"); + } + }; @Before public void initMocks() { Xendit.Opt.setApiKey( "xnd_development_Z568GecuIH66011GIILkDFNJOoR1wFZdGqOOMFBrRVeX64DISB1o7hnNKB"); Xendit.setRequestClient(requestClient); + Xendit.setResponseHeaders(responseHeaders); + } + + @Test + public void get_Success_With_RequestId() throws XenditException { + when(this.requestClient.request( + RequestResource.Method.GET, URL, HEADERS, null, opt.getApiKey(), Balance.class)) + .thenReturn(VALID_BALANCE); + when(balanceClient.get()).thenReturn(VALID_BALANCE); + Balance balance = balanceClient.get(); + assertEquals(balance, VALID_BALANCE); + assertNotNull(Xendit.getResponseHeaders().get("Request-Id")); } @Test diff --git a/xendit-java-lib/src/test/java/com/xenditclient/QRCodeTest.java b/xendit-java-lib/src/test/java/com/xenditclient/QRCodeTest.java index 94a76ee..d305cfa 100644 --- a/xendit-java-lib/src/test/java/com/xenditclient/QRCodeTest.java +++ b/xendit-java-lib/src/test/java/com/xenditclient/QRCodeTest.java @@ -1,6 +1,7 @@ package com.xenditclient; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -26,6 +27,12 @@ public class QRCodeTest { private static String TEST_QR_CURRENCY = "IDR"; private static Map PARAMS = new HashMap<>(); private static Map HEADERS = new HashMap<>(); + private static Map responseHeaders = + new HashMap() { + { + put("Request-Id", "test_request_id"); + } + }; private static QRCode VALID_PAYMENT = QRCode.builder() .id(TEST_ID) @@ -46,6 +53,7 @@ public void initMocks() { Xendit.setRequestClient(requestClient); PARAMS.clear(); + Xendit.setResponseHeaders(responseHeaders); } private void initCreateParams() { @@ -72,6 +80,24 @@ public void createQRCode_Success_IfMethodCalledCorrectly() throws XenditExceptio assertEquals(qrCode, VALID_PAYMENT); } + @Test + public void createQRCode_And_RequestId_Not_Null() throws XenditException { + initCreateParams(); + + when(this.requestClient.request( + RequestResource.Method.POST, URL, HEADERS, PARAMS, opt.getApiKey(), QRCode.class)) + .thenReturn(VALID_PAYMENT); + when(qrCodeClient.createQRCode( + TEST_REFERENCE_ID, QRCode.QRCodeType.DYNAMIC, TEST_QR_CURRENCY, 10000)) + .thenReturn(VALID_PAYMENT); + QRCode qrCode = + qrCodeClient.createQRCode( + TEST_REFERENCE_ID, QRCode.QRCodeType.DYNAMIC, TEST_QR_CURRENCY, 10000); + + assertEquals(qrCode, VALID_PAYMENT); + assertNotNull(Xendit.getResponseHeaders().get("Request-Id")); + } + @Test public void createQRCode_Success_IfParamsIsValid() throws XenditException { initCreateParams(); diff --git a/xendit-java-library-example/src/main/java/ExampleWithClient/ExampleCreateQRCode.java b/xendit-java-library-example/src/main/java/ExampleWithClient/ExampleCreateQRCode.java index ef14c39..bf70357 100644 --- a/xendit-java-library-example/src/main/java/ExampleWithClient/ExampleCreateQRCode.java +++ b/xendit-java-library-example/src/main/java/ExampleWithClient/ExampleCreateQRCode.java @@ -1,6 +1,7 @@ package ExampleWithClient; import com.xendit.exception.XenditException; +import com.xendit.Xendit; import com.xendit.XenditClient; import com.xendit.model.QRCode; @@ -11,8 +12,11 @@ public static void main(String[] args) { .setApikey("xnd_development_...") .build(); try { - QRCode qrCode = xenditClient.qrCode.createQRCode("external_id", QRCode.QRCodeType.DYNAMIC, "https://webhook.site", 10000); + QRCode qrCode = xenditClient.qrCode.createQRCode("external_id", QRCode.QRCodeType.DYNAMIC, "IDR", 10000); System.out.println(qrCode.getId()); + + //You can find this value in the response headers, under Request-ID. You can use Request-ID to find logs in API Logs in Dashboard (https://dashboard.xendit.co/api-logs). + System.out.println(Xendit.getResponseHeaders().get("Request-Id")); } catch (XenditException e) { e.printStackTrace(); } diff --git a/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateClosedVA.java b/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateClosedVA.java index 6ea8684..f0c248d 100644 --- a/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateClosedVA.java +++ b/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateClosedVA.java @@ -41,7 +41,7 @@ public static void main(String[] args) { FixedVirtualAccount virtualAccount3 = FixedVirtualAccount.createClosed("my_external_id", BankCode.MANDIRI.getText(), "John Doe", 100000L, closedVAMap); - System.out.println(virtualAccount); + System.out.println(virtualAccount.getId()); } catch (XenditException e) { e.printStackTrace(); } diff --git a/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateQRCode.java b/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateQRCode.java index 81ad83a..1f02859 100644 --- a/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateQRCode.java +++ b/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleCreateQRCode.java @@ -13,8 +13,13 @@ public static void main(String[] args) { // Xendit.apiKey = "xnd_development_..."; try { - QRCode qrCode = QRCode.createQRCode("12", QRCode.QRCodeType.DYNAMIC, "https://webhook.site", 10000); + QRCode qrCode = QRCode.createQRCode("12", QRCode.QRCodeType.DYNAMIC, "IDR", 10000); System.out.println(qrCode.getId()); + + // You can find this value in the response headers, under Request-ID. You can + // use Request-ID to find logs in API Logs in Dashboard + // (https://dashboard.xendit.co/api-logs). + System.out.println(Xendit.getResponseHeaders().get("Request-Id")); } catch (XenditException e) { e.printStackTrace(); } diff --git a/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleUpdateVA.java b/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleUpdateVA.java index c6e9750..651be53 100644 --- a/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleUpdateVA.java +++ b/xendit-java-library-example/src/main/java/ExampleWithoutClient/ExampleUpdateVA.java @@ -9,18 +9,23 @@ public class ExampleUpdateVA { public static void main(String[] args) { - //access key with Option - Xendit.Opt.setApiKey("xnd_development_..."); + // access key with Option + Xendit.Opt.setApiKey("xnd_development..."); - //access static variable (same as old code ) - //Xendit.apiKey = "xnd_development_..."; + // access static variable (same as old code ) + // Xendit.apiKey = "xnd_development_..."; try { Map params = new HashMap<>(); params.put("is_single_use", true); - FixedVirtualAccount fixedVirtualAccount = FixedVirtualAccount.update("614dbfea41de115d0d338602", params); + FixedVirtualAccount fixedVirtualAccount = FixedVirtualAccount.update("6413cdfaca7651511ae7f604", params); System.out.println(fixedVirtualAccount.getIsSingleUse()); + + // You can find this value in the response headers, under Request-ID. You can + // use Request-ID to find logs in API Logs in Dashboard + // (https://dashboard.xendit.co/api-logs). + System.out.println(Xendit.getResponseHeaders().get("Request-Id")); } catch (XenditException e) { e.printStackTrace(); }