diff --git a/README.md b/README.md index fb77c55..b4accd8 100644 --- a/README.md +++ b/README.md @@ -631,6 +631,7 @@ There are: - [Core Api examples](example/simple/coreapi/sample.go) - [Snap examples](example/simple/snap/sample.go) - [Iris examples](example/simple/iris/sample.go) +- [Readme Example](example/README.md) Integration test are available - [CoreApi Sample Functional Test](coreapi/client_test.go) diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..60b0c50 --- /dev/null +++ b/example/README.md @@ -0,0 +1,11 @@ +# Sample App +This is a very simple, very minimalist example to demonstrate integrating Midtrans with Go + +## Run The app +1. Clone the repository, open terminal in this `/example/simple/coreapi-card-3ds` folder. +2. Run the web server using: `go run main.go` +3. The smple app will run at port 3000. Open `localhost:3000` from browser. + +## Run command line app +1. Clone the repository, open terminal in this `/example/simple/coreapi` folder. +2. Run the app using: `go run main.go` diff --git a/example/simple/coreapi-card-3ds/main.go b/example/simple/coreapi-card-3ds/main.go index 1451041..ab4484b 100644 --- a/example/simple/coreapi-card-3ds/main.go +++ b/example/simple/coreapi-card-3ds/main.go @@ -3,15 +3,16 @@ package main import ( + "encoding/json" + "fmt" + "github.com/midtrans/midtrans-go" + "github.com/midtrans/midtrans-go/coreapi" "html/template" - "net/http" "log" + "net/http" "path" - "time" "strconv" - "github.com/midtrans/midtrans-go" - "github.com/midtrans/midtrans-go/coreapi" - "encoding/json" + "time" ) // Set Your server key @@ -48,7 +49,7 @@ func HomeHandler(w http.ResponseWriter, r *http.Request) { } needCredential := false - if(len(SERVER_KEY) == 0 || len(CLIENT_KEY) == 0 ){ + if len(SERVER_KEY) == 0 || len(CLIENT_KEY) == 0 { needCredential = true } diff --git a/httpclient.go b/httpclient.go index c88191d..219ac5f 100644 --- a/httpclient.go +++ b/httpclient.go @@ -97,66 +97,78 @@ func (c *HttpClientImplementation) DoRequest(req *http.Request, result interface res, err := c.HttpClient.Do(req) if err != nil { c.Logger.Error("Cannot send request: %v", err.Error()) + var statusCode int + + if res != nil { + statusCode = res.StatusCode + } else if strings.Contains(err.Error(), "timeout") { + statusCode = 408 + } else { + statusCode = 0 + } + return &Error{ Message: fmt.Sprintf("Error when request via HttpClient, Cannot send request with error: %s", err.Error()), - StatusCode: res.StatusCode, + StatusCode: statusCode, RawError: err, } } - defer res.Body.Close() + if res != nil { + defer res.Body.Close() - c.Logger.Info("================== END ==================") - c.Logger.Info("Request completed in %v ", time.Since(start)) + c.Logger.Info("================== END ==================") + c.Logger.Info("Request completed in %v ", time.Since(start)) - resBody, err := ioutil.ReadAll(res.Body) - if err != nil { - c.Logger.Error("Request failed: %v", err) - return &Error{ - Message: "Cannot read response body: " + err.Error(), - StatusCode: res.StatusCode, + resBody, err := ioutil.ReadAll(res.Body) + if err != nil { + c.Logger.Error("Request failed: %v", err) + return &Error{ + Message: "Cannot read response body: " + err.Error(), + StatusCode: res.StatusCode, + RawError: err, + } } - } - rawResponse := newHTTPResponse(res, resBody) - c.Logger.Debug("=============== Response ===============") - // Loop through headers to perform log - logHttpHeaders(c.Logger, rawResponse.Header, false) - c.Logger.Debug("Response Body: %v", string(rawResponse.RawBody)) + rawResponse := newHTTPResponse(res, resBody) + c.Logger.Debug("=============== Response ===============") + // Loop through headers to perform log + logHttpHeaders(c.Logger, rawResponse.Header, false) + c.Logger.Debug("Response Body: %v", string(rawResponse.RawBody)) + + if result != nil { + if err = json.Unmarshal(resBody, &result); err != nil { + return &Error{ + Message: fmt.Sprintf("Invalid body response, parse error during API request to Midtrans with message: %s", err.Error()), + StatusCode: res.StatusCode, + RawError: err, + RawApiResponse: rawResponse, + } + } + } - if result != nil { - if err = json.Unmarshal(resBody, &result); err != nil { - return &Error{ - Message: fmt.Sprintf("Invalid body response, parse error during API request to Midtrans with message: %s", err.Error()), - StatusCode: res.StatusCode, - RawError: err, - RawApiResponse: rawResponse, + // Check status_code from Midtrans response body + if found, data := HasOwnProperty("status_code", resBody); found { + statusCode, _ := strconv.Atoi(data["status_code"].(string)) + if statusCode >= 401 && statusCode != 407 { + return &Error{ + Message: fmt.Sprintf("Midtrans API is returning API error. HTTP status code: %s API response: %s", strconv.Itoa(statusCode), string(resBody)), + StatusCode: statusCode, + RawApiResponse: rawResponse, + } } } - } - // Check status_code from Midtrans response body - if found, data := HasOwnProperty("status_code", resBody); found { - statusCode, _ := strconv.Atoi(data["status_code"].(string)) - if statusCode >= 401 && statusCode != 407 { + // Check StatusCode from Midtrans HTTP response api StatusCode + if res.StatusCode >= 400 { return &Error{ - Message: fmt.Sprintf("Midtrans API is returning API error. HTTP status code: %s API response: %s", strconv.Itoa(statusCode), string(resBody)), - StatusCode: statusCode, + Message: fmt.Sprintf("Midtrans API is returning API error. HTTP status code: %s API response: %s", strconv.Itoa(res.StatusCode), string(resBody)), + StatusCode: res.StatusCode, RawApiResponse: rawResponse, + RawError: err, } } } - - // Check StatusCode from Midtrans HTTP response api StatusCode - if res.StatusCode >= 400 { - return &Error{ - Message: fmt.Sprintf("Midtrans API is returning API error. HTTP status code: %s API response: %s", strconv.Itoa(res.StatusCode), string(resBody)), - StatusCode: res.StatusCode, - RawApiResponse: rawResponse, - RawError: err, - } - } - return nil } diff --git a/iris/client_test.go b/iris/client_test.go index 60d7238..f21502d 100644 --- a/iris/client_test.go +++ b/iris/client_test.go @@ -178,7 +178,38 @@ func TestGetListBeneficiaryBank(t *testing.T) { func TestValidateBankAccount(t *testing.T) { iris := Client{} iris.New(irisApproverKeySandbox, midtrans.Sandbox) - resp, err := iris.ValidateBankAccount("danamon", "000001137298") + resp, err := iris.ValidateBankAccount("mandiri", "1111222233333") assert.Nil(t, err) - assert.Equal(t, resp.AccountNo, "000001137298") + assert.Equal(t, resp.AccountNo, "1111222233333") +} + +func TestCreatePayoutFail(t *testing.T) { + iris := Client{} + iris.New(irisCreatorKeySandbox, midtrans.Sandbox) + + p1 := CreatePayoutDetailReq{ + BeneficiaryAccount: "1380011819286", + BeneficiaryBank: "mandiri", + BeneficiaryEmail: "tony.stark@mail.com", + Amount: random(), + Notes: "MidGoUnitTest", + } + + p2 := CreatePayoutDetailReq{ + BeneficiaryAccount: "1380011819286", + BeneficiaryBank: "mandiri", + BeneficiaryEmail: "jon.snow@mail.com", + Amount: random(), + Notes: "MidGoUnitTest", + } + var payouts []CreatePayoutDetailReq + payouts = append(payouts, p1) + payouts = append(payouts, p2) + + + cp := CreatePayoutReq{Payouts: payouts} + payoutReps, err := iris.CreatePayout(cp) + assert.NotNil(t, payoutReps) + assert.NotNil(t, err) + assert.Equal(t, "An error occurred when creating payouts", payoutReps.ErrorMessage) } diff --git a/iris/response.go b/iris/response.go index e9329a1..fb54a22 100644 --- a/iris/response.go +++ b/iris/response.go @@ -29,7 +29,7 @@ type BeneficiaryBankResponse struct { type CreatePayoutResponse struct { Payouts []CreatePayoutDetailResponse `json:"payouts"` ErrorMessage string `json:"error_message"` - Errors []string `json:"errors"` + Errors interface{} `json:"errors"` } // CreatePayoutDetailResponse : Represent Create payout detail response payload diff --git a/midtrans.go b/midtrans.go index 1d01a7e..b4a4705 100644 --- a/midtrans.go +++ b/midtrans.go @@ -20,7 +20,7 @@ const ( Production //libraryVersion : midtrans go library version - libraryVersion = "v1.2.1" + libraryVersion = "v1.2.2" ) //ServerKey is config payment API key for global use