aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-01-20 17:16:29 +0700
committerShulhan <ms@kilabit.info>2023-01-20 18:33:08 +0700
commit616ed53618f7df87f1b13c3f3c9e3821121872c2 (patch)
treee57060b3845985bf7df391272d3a43e2a5008fd9
parent94f3139e32b16008e239b708f31366dc8d57bc48 (diff)
downloadduitku-616ed53618f7df87f1b13c3f3c9e3821121872c2.tar.xz
all: implement client API for InquiryStatus
The InquiryStatus get the status of previous Transfer. Ref: https://docs.duitku.com/disbursement/en/#inquiry-status
-rw-r--r--client.go41
-rw-r--r--client_test.go81
-rw-r--r--inquiry_status.go31
-rw-r--r--inquiry_status_response.go26
-rw-r--r--testdata/disbursement/inquirystatus_test.txt52
5 files changed, 231 insertions, 0 deletions
diff --git a/client.go b/client.go
index ae63ba4..1adecaf 100644
--- a/client.go
+++ b/client.go
@@ -22,6 +22,10 @@ const (
PathInquiry = `/webapi/api/disbursement/inquiry`
PathInquirySandbox = `/webapi/api/disbursement/inquirysandbox` // Used for testing.
+ // Endpoints to check transfer status.
+ PathInquiryStatus = `/webapi/api/disbursement/inquirystatus`
+ PathInquiryStatusSandbox = `/webapi/api/disbursement/inquirystatus` // Used for testing.
+
PathTransfer = `/webapi/api/disbursement/transfer`
PathTransferSandbox = `/webapi/api/disbursement/transfersandbox` // Used for testing.
@@ -165,6 +169,43 @@ func (cl *Client) ClearingTransfer(req *ClearingTransfer) (res *ClearingTransfer
return res, nil
}
+// InquiryStatus get the transfer status of ClearingTransfer or RtolTransfer.
+func (cl *Client) InquiryStatus(disburseID int64) (res *InquiryStatusResponse, err error) {
+ var (
+ logp = `InquiryStatus`
+ path = PathInquiryStatus
+ req = InquiryStatus{
+ DisburseID: disburseID,
+ }
+
+ resHttp *http.Response
+ resBody []byte
+ )
+
+ // Since the path is different in test environment, we check the host
+ // here to set it.
+ if cl.opts.host != hostLive {
+ path = PathInquiryStatusSandbox
+ }
+
+ req.Sign(cl.opts)
+
+ resHttp, resBody, err = cl.PostJSON(path, nil, req)
+ if err != nil {
+ return nil, fmt.Errorf(`%s: %w`, logp, err)
+ }
+ if resHttp.StatusCode >= 500 {
+ return nil, fmt.Errorf(`%s: %s`, logp, resHttp.Status)
+ }
+
+ err = json.Unmarshal(resBody, &res)
+ if err != nil {
+ return nil, fmt.Errorf(`%s: %w`, logp, err)
+ }
+
+ return res, nil
+}
+
// tListBank fetch list of banks for disbursement.
func (cl *Client) ListBank() (banks []Bank, err error) {
var (
diff --git a/client_test.go b/client_test.go
index fc6ba03..3db7dd2 100644
--- a/client_test.go
+++ b/client_test.go
@@ -120,6 +120,87 @@ func TestClient_ClearingTransfer_sandbox(t *testing.T) {
test.Assert(t, `AccountName`, `Test Account`, transferRes.AccountName)
}
+func TestClient_InquiryStatus_sandbox(t *testing.T) {
+ t.Skip(`This test require external call to server`)
+
+ var (
+ tdata *test.Data
+
+ reqInquiry *RtolInquiry
+ resInquiry *RtolInquiryResponse
+ expInquiry *RtolInquiryResponse
+
+ reqTransfer *RtolTransfer
+ resTransfer *RtolTransferResponse
+ expTransfer *RtolTransferResponse
+
+ resInqueryStatus *InquiryStatusResponse
+ expInquiryStatus *InquiryStatusResponse
+
+ err error
+ exp []byte
+ )
+
+ tdata, err = test.LoadData(`testdata/disbursement/inquirystatus_test.txt`)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = json.Unmarshal(tdata.Input[`inquiry_request.json`], &reqInquiry)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Do inquiry bank account ...
+
+ resInquiry, err = testClient.RtolInquiry(reqInquiry)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ exp = tdata.Output[`inquiry_response.json`]
+ err = json.Unmarshal(exp, &expInquiry)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expInquiry.CustRefNumber = resInquiry.CustRefNumber
+ expInquiry.DisburseID = resInquiry.DisburseID
+ test.Assert(t, `RtolInquiry`, expInquiry, resInquiry)
+
+ // Do the transfer ...
+
+ reqTransfer = NewRtolTransfer(reqInquiry, resInquiry)
+
+ resTransfer, err = testClient.RtolTransfer(reqTransfer)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ exp = tdata.Output[`transfer_response.json`]
+ err = json.Unmarshal(exp, &expTransfer)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expTransfer.CustRefNumber = resTransfer.CustRefNumber
+ expTransfer.DisburseID = resTransfer.DisburseID
+ test.Assert(t, `RtolTransfer`, expTransfer, resTransfer)
+
+ // Inquiry transfer status ...
+
+ resInqueryStatus, err = testClient.InquiryStatus(resTransfer.DisburseID)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ exp = tdata.Output[`inquirystatus_response.json`]
+ err = json.Unmarshal(exp, &expInquiryStatus)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expInquiryStatus.CustRefNumber = resInqueryStatus.CustRefNumber
+ test.Assert(t, `InquiryStatus`, expInquiryStatus, resInqueryStatus)
+}
+
func TestClient_RtolInquiry_sandbox(t *testing.T) {
t.Skip(`This test require external call to server`)
diff --git a/inquiry_status.go b/inquiry_status.go
new file mode 100644
index 0000000..66797bf
--- /dev/null
+++ b/inquiry_status.go
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: 2022 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package duitku
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "time"
+)
+
+// InquiryStatus request for transfer status.
+type InquiryStatus struct {
+ Request
+
+ DisburseID int64 `json:"disburseId"`
+}
+
+// Sign the request, fill the UserID, Email, Timestamp, and generate the
+// Signature.
+func (inq *InquiryStatus) Sign(opts ClientOptions) {
+ inq.UserID = opts.UserID
+ inq.Email = opts.Email
+ inq.Timestamp = time.Now().UnixMilli()
+
+ var plain string = fmt.Sprintf(`%s%d%d%s`, inq.Email, inq.Timestamp, inq.DisburseID, opts.ApiKey)
+ var plainHash [sha256.Size]byte = sha256.Sum256([]byte(plain))
+
+ inq.Signature = hex.EncodeToString(plainHash[:])
+}
diff --git a/inquiry_status_response.go b/inquiry_status_response.go
new file mode 100644
index 0000000..ced3f0e
--- /dev/null
+++ b/inquiry_status_response.go
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: 2022 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package duitku
+
+import "github.com/shuLhan/share/lib/math/big"
+
+type InquiryStatusResponse struct {
+ Response
+
+ // Destination Bank Code.
+ BankCode string `json:"bankCode"`
+
+ // Destination account number.
+ BankAccount string `json:"bankAccount"`
+
+ // Disbursement transfer amount.
+ Amount *big.Rat `json:"amountTransfer"`
+
+ // Bank Account owner.
+ AccountName string `json:"accountName"`
+
+ // 9 Digit Customer reference number that will be printed when the
+ // transaction is successful.
+ CustRefNumber string `json:"custRefNumber"`
+}
diff --git a/testdata/disbursement/inquirystatus_test.txt b/testdata/disbursement/inquirystatus_test.txt
new file mode 100644
index 0000000..9596cc3
--- /dev/null
+++ b/testdata/disbursement/inquirystatus_test.txt
@@ -0,0 +1,52 @@
+Test InquiryStatus.
+
+All of the custRefNumber and disburseId will be replaced, since its dynamic on
+each request.
+
+>>> inquiry_request.json
+{
+ "amountTransfer": 10000,
+ "bankAccount": "8760673566",
+ "bankCode": "002",
+ "purpose": "Test Transfer Online Inquiry with duitku.",
+ "senderId": 123456789,
+ "senderName": "John Doe"
+}
+
+<<< inquiry_response.json
+{
+ "responseCode": "00",
+ "responseDesc": "Success",
+ "email": "test@chakratechnology.com",
+ "bankCode": "002",
+ "bankAccount": "8760673566",
+ "amountTransfer": "10000",
+ "accountName": "Test Account",
+ "custRefNumber": "<replaced>",
+ "disburseId": 0
+}
+
+<<< transfer_response.json
+{
+ "purpose": "",
+ "responseCode": "00",
+ "responseDesc": "Success",
+ "email": "test@chakratechnology.com",
+ "bankCode": "002",
+ "bankAccount": "8760673566",
+ "amountTransfer": "10000",
+ "accountName": "Test Account",
+ "custRefNumber": "<replaced>",
+ "userId": 0
+}
+
+<<< inquirystatus_response.json
+{
+ "responseCode": "00",
+ "responseDesc": "Success",
+ "bankCode": "002",
+ "bankAccount": "8760673566",
+ "amountTransfer": "10000",
+ "accountName": "Test Account",
+ "custRefNumber": "<replaced>"
+}