From e35f2571c31bf95c2896b248aa793e485c7b1b8d Mon Sep 17 00:00:00 2001 From: Mellyza Rismawan Date: Wed, 6 Apr 2022 18:40:51 +0700 Subject: [PATCH] added dana inquiry user info function --- client.go | 14 +++++++-- core.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ request.go | 5 ++++ responses.go | 28 +++++++++++++++--- 4 files changed, 121 insertions(+), 7 deletions(-) diff --git a/client.go b/client.go index 3f82ef3..2de6847 100755 --- a/client.go +++ b/client.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "moul.io/http2curl" "net/http" + "strings" "time" ) @@ -40,8 +41,8 @@ func NewClient() Client { // 1: Errors only // 2: Errors + informational (default) // 3: Errors + informational + debug - LogLevel: 2, - Logger: logger, + LogLevel: 2, + Logger: logger, SignatureEnabled: true, } } @@ -94,15 +95,23 @@ func (c *Client) ExecuteRequest(req *http.Request, v interface{}) error { if v != nil && res.StatusCode == 200 { if err = json.Unmarshal(resBody, v); err != nil { + c.Logger.Error("Failed unmarshal body: %v ", err) return err } + // Dana endpoint V1 doesn't return signature in response, so we don't need to verify signature again + if strings.Contains(req.URL.String(), "/v1/") { + c.Logger.Info("Req URL Contains Dana endpoint V1") + return nil + } + if c.SignatureEnabled { response := gjson.Get(string(resBody), "response") signature := gjson.Get(string(resBody), "signature") err = verifySignature(response.String(), signature.String(), c.PublicKey) if err != nil { + c.Logger.Error("verifySignature failed: %v ", err) return err } } @@ -124,4 +133,3 @@ func (c *Client) Call(method, path string, header map[string]string, body io.Rea } // ===================== END HTTP CLIENT ================================================ - diff --git a/core.go b/core.go index 4b7dd7e..a26a714 100755 --- a/core.go +++ b/core.go @@ -23,12 +23,14 @@ const ( USER_PROFILE_PATH = "alipayplus/member/query/queryUserProfile.htm" DANA_TIME_LAYOUT = "2006-01-02T15:04:05-07:00" CURRENCY_IDR = "IDR" + INQUIRY_USER_INFO_PATH = "v1/customers/user/inquiryUserInfoByAccessToken.htm" FUNCTION_CREATE_ORDER = "dana.acquiring.order.createOrder" FUNCTION_QUERY_ORDER = "dana.acquiring.order.query" FUNCTION_REFUND = "dana.acquiring.refund.refund" FUNCTION_APPLY_ACCESS_TOKEN = "dana.oauth.auth.applyToken" FUNCTION_USER_PROFILE = "dana.member.query.queryUserProfile" + FUNCTION_INQUIRY_USER_INFO = "customers.openapi.user.inquiryUserInfoByAccessToken" ) // CoreGateway struct @@ -155,6 +157,27 @@ func (gateway *CoreGateway) UserProfile(reqBody *UserProfileRequestData, accessT return } +func (gateway *CoreGateway) InquiryUserInfo(reqBody *InquiryUserInfoRequest, accessToken string) (res InquiryUserInfoResponse, err error) { + var response interface{} + response, err = gateway.requestToDanaV1(reqBody, accessToken, FUNCTION_INQUIRY_USER_INFO, INQUIRY_USER_INFO_PATH) + if err != nil { + return + } + + var responseByte []byte + responseByte, err = json.Marshal(response) + if err != nil { + return + } + + err = json.Unmarshal(responseByte, &res) + if err != nil { + return + } + + return +} + func (gateway *CoreGateway) requestToDana(reqBody interface{}, accessToken string, headerFunction string, path string) (res ResponseBody, err error) { now := time.Now() @@ -211,3 +234,61 @@ func (gateway *CoreGateway) requestToDana(reqBody interface{}, accessToken strin return } + +func (gateway *CoreGateway) requestToDanaV1(reqBody interface{}, accessToken string, headerFunction string, path string) (res interface{}, err error) { + now := time.Now() + + head := RequestHeader{} + head.Version = gateway.Client.Version + head.Function = headerFunction + head.ClientID = gateway.Client.ClientId + head.ReqTime = now.Format(DANA_TIME_LAYOUT) + head.ClientSecret = gateway.Client.ClientSecret + + if accessToken != "" { + head.AccessToken = accessToken + } + + var id uuid.UUID + id, err = uuid.NewUUID() + if err != nil { + return + } + + head.ReqMsgID = id.String() + + req := Request{ + Head: head, + Body: reqBody, + } + + sig, err := generateSignature(req, gateway.Client.PrivateKey) + if err != nil { + err = fmt.Errorf("failed to generate signature: %v", err) + log.Println("generateSignature Failed: ", err) + return + } + + reqJson, err := json.Marshal(reqBody) + if err != nil { + return + } + + log.Println("Dana request: ", string(reqJson)) + + headers := map[string]string{ + "Content-Type": "application/json", + "Client-Id": gateway.Client.ClientId, + "Request-Time": now.Format(DANA_TIME_LAYOUT), + "Signature": sig, + } + + bodyReq := bytes.NewBuffer(reqJson) + err = gateway.Call("POST", path, headers, bodyReq, &res) + if err != nil { + log.Println("Failed call dana endpoint: ", err) + return + } + + return +} diff --git a/request.go b/request.go index 2768905..d3d88ed 100755 --- a/request.go +++ b/request.go @@ -170,3 +170,8 @@ type RequestApplyAccessToken struct { type UserProfileRequestData struct { UserResources []string `json:"userResources" valid:"required"` } + +type InquiryUserInfoRequest struct { + AccessToken string `json:"accessToken" valid:"required"` + ExtendInfo string `json:"extendInfo,omitempty" valid:"optional"` +} diff --git a/responses.go b/responses.go index 7b5d339..b696b99 100755 --- a/responses.go +++ b/responses.go @@ -49,10 +49,11 @@ type RefundResponseData struct { } type ResultInfo struct { - ResultStatus string `json:"resultStatus" valid:"optional"` - ResultCodeID string `json:"resultCodeId" valid:"optional"` - ResultMsg string `json:"resultMsg" valid:"optional"` - ResultCode string `json:"resultCode" valid:"optional"` + ResultStatus string `json:"resultStatus" valid:"optional"` + ResultCodeID string `json:"resultCodeId" valid:"optional"` + ResultMsg string `json:"resultMsg" valid:"optional"` + ResultCode string `json:"resultCode" valid:"optional"` + ResultMessage string `json:"resultMessage" valid:"optional"` } type PayFinishResponse struct { @@ -142,3 +143,22 @@ type UserProfileResponseData struct { ResultInfo ResultInfo `json:"resultInfo" valid:"required"` UserResourceInfos []UserResourceInfos `json:"userResourceInfos" valid:"required"` } + +type InquiryUserInfoResponse struct { + Result ResultInfo `json:"result" valid:"required"` + UserInfo ResultUserInfo `json:"userInfo" valid:"required"` +} + +type ResultUserInfo struct { + UserContactInfoEmail string `json:"USER_CONTACTINFO_EMAIL" valid:"optional"` + UserName string `json:"USER_NAME" valid:"optional"` + UserAddress []UserAddress `json:"USER_ADDRESS" valid:"optional"` + UserContactInfo string `json:"USER_CONTACTINFO" valid:"optional"` +} + +type UserAddress struct { + Area string `json:"area" valid:"optional"` + Province string `json:"province" valid:"optional"` + City string `json:"city" valid:"optional"` + Address1 string `json:"address1" valid:"optional"` +}