-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e6eb288
commit 2e6aa17
Showing
16 changed files
with
880 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# EditorConfig coding styles definitions. For more information about the | ||
# properties used in this file, please see the EditorConfig documentation: | ||
# http://editorconfig.org/ | ||
|
||
# indicate this is the root of the project | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
indent_style = space | ||
indent_size = 4 | ||
|
||
[Makefile] | ||
indent_style = tab | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.idea/ | ||
.vscode/ | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright 2021 Bhinneka.com | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.PHONY: test cover | ||
|
||
test: | ||
go test -race | ||
|
||
cover: | ||
go test -race -coverprofile=coverage.txt -covermode=atomic |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
package cicil | ||
|
||
import ( | ||
"bytes" | ||
"crypto/hmac" | ||
"crypto/sha256" | ||
b64 "encoding/base64" | ||
"encoding/hex" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"strings" | ||
"time" | ||
) | ||
|
||
// cicil entry struick for cicil | ||
type cicil struct { | ||
MerchantID string | ||
APIKey string | ||
MerchantSecret string | ||
BaseURL string | ||
client *cicilHttpClient | ||
*logger | ||
} | ||
|
||
/*New Function, create cicil pointer | ||
Required parameter : | ||
1. Your MerchantID (this from Team cicil) | ||
2. Your MerchantSecret (this from Team cicil) | ||
3. Your APIKey (this from Team cicil) | ||
3. BaseURL (hit to endpoint ex: https://sandbox-api.cicil.dev/v1 for sandbox. | ||
this value based on https://docs.cicil.app/#introduction) | ||
*/ | ||
func New(baseUrl string, apiKey string, merchantId string, merchantSecret string, timeout time.Duration) *cicil { | ||
httpRequest := newRequest(timeout) | ||
return &cicil{ | ||
APIKey: apiKey, | ||
MerchantID: merchantId, | ||
MerchantSecret: merchantSecret, | ||
BaseURL: baseUrl, | ||
client: httpRequest, | ||
logger: newLogger(), | ||
} | ||
} | ||
|
||
func (c *cicil) call(method string, path string, body io.Reader, v interface{}, headers map[string]string) error { | ||
c.info().Println("Starting http call..") | ||
if !strings.HasPrefix(path, "/") { | ||
path = "/" + path | ||
} | ||
|
||
path = fmt.Sprintf("%s%s", c.BaseURL, path) | ||
return c.client.exec(method, path, body, v, headers) | ||
} | ||
|
||
func (c *cicil) GetToken() (digest string, dateNowReturn string) { | ||
dateNow := time.Now().Format(time.RFC1123) | ||
formattedMessage := fmt.Sprintf("%s%s", c.MerchantSecret, dateNow) | ||
// Create a new HMAC by defining the hash type and the key (as byte array) | ||
h := hmac.New(sha256.New, []byte(c.APIKey)) | ||
// Write Data to it | ||
h.Write([]byte(formattedMessage)) | ||
|
||
// Get result and encode as hexadecimal string | ||
digestData := hex.EncodeToString(h.Sum(nil)) | ||
basicData := fmt.Sprintf("%s:%s", c.MerchantID, digestData) | ||
output := b64.URLEncoding.EncodeToString([]byte(basicData)) | ||
return output, dateNow | ||
} | ||
|
||
func (c *cicil) GetCheckoutURL(param CheckoutRequest) (resp CheckoutResponse, err error) { | ||
c.info().Println("Starting Get Order URL Cicil") | ||
defer func() { | ||
if r := recover(); r != nil { | ||
err = fmt.Errorf("panic: %v", r) | ||
} | ||
if err != nil { | ||
c.error().Println(err.Error()) | ||
} | ||
}() | ||
var getCheckoutURLResponse CheckoutResponse | ||
|
||
// get auth data | ||
getDiggest, getDate := c.GetToken() | ||
|
||
// set header | ||
headers := make(map[string]string) | ||
headers["Content-Type"] = "application/json" | ||
headers["Date"] = getDate | ||
headers["Authorization"] = fmt.Sprintf("Basic %s", getDiggest) | ||
|
||
pathGetOrderURL := "po" | ||
//Marshal Order | ||
payload, errPayload := json.Marshal(param) | ||
if errPayload != nil { | ||
return getCheckoutURLResponse, err | ||
} | ||
|
||
err = c.call("POST", pathGetOrderURL, bytes.NewBuffer(payload), &getCheckoutURLResponse, headers) | ||
if err != nil { | ||
return getCheckoutURLResponse, err | ||
} | ||
if len(getCheckoutURLResponse.Message) > 0 { | ||
err = errors.New(getCheckoutURLResponse.Message) | ||
return getCheckoutURLResponse, err | ||
} | ||
|
||
return getCheckoutURLResponse, nil | ||
} | ||
|
||
func (c *cicil) SetCancelOrder (param CancelOrderRequest) (resp CancelOrderResponse, err error) { | ||
c.info().Println("Starting Set Cancel Order Cicil") | ||
defer func() { | ||
if r := recover(); r != nil { | ||
err = fmt.Errorf("panic: %v", r) | ||
} | ||
if err != nil { | ||
c.error().Println(err.Error()) | ||
} | ||
}() | ||
var setCancelOrderResponse CancelOrderResponse | ||
|
||
// get auth data | ||
getDiggest, getDate := c.GetToken() | ||
|
||
// set header | ||
headers := make(map[string]string) | ||
headers["Content-Type"] = "application/json" | ||
headers["Date"] = getDate | ||
headers["Authorization"] = fmt.Sprintf("Basic %s", getDiggest) | ||
|
||
pathGetOrderURL := "po/cancel" | ||
//Marshal Order | ||
payload, errPayload := json.Marshal(param) | ||
if errPayload != nil { | ||
return setCancelOrderResponse, err | ||
} | ||
|
||
err = c.call("POST", pathGetOrderURL, bytes.NewBuffer(payload), &setCancelOrderResponse, headers) | ||
if err != nil { | ||
return setCancelOrderResponse, err | ||
} | ||
if len(setCancelOrderResponse.Message) > 0 { | ||
err = errors.New(setCancelOrderResponse.Message) | ||
return setCancelOrderResponse, err | ||
} | ||
|
||
return setCancelOrderResponse, nil | ||
} | ||
|
||
func (c *cicil) UpdateStatus (param UpdateStatusRequest) (resp UpdateStatusResponse, err error) { | ||
c.info().Println("Starting Set Cancel Order Cicil") | ||
defer func() { | ||
if r := recover(); r != nil { | ||
err = fmt.Errorf("panic: %v", r) | ||
} | ||
if err != nil { | ||
c.error().Println(err.Error()) | ||
} | ||
}() | ||
var updateStatusResponse UpdateStatusResponse | ||
|
||
// get auth data | ||
getDiggest, getDate := c.GetToken() | ||
|
||
// set header | ||
headers := make(map[string]string) | ||
headers["Content-Type"] = "application/json" | ||
headers["Date"] = getDate | ||
headers["Authorization"] = fmt.Sprintf("Basic %s", getDiggest) | ||
|
||
pathGetOrderURL := "po/update" | ||
//Marshal Order | ||
payload, errPayload := json.Marshal(param) | ||
if errPayload != nil { | ||
return updateStatusResponse, err | ||
} | ||
|
||
err = c.call("POST", pathGetOrderURL, bytes.NewBuffer(payload), &updateStatusResponse, headers) | ||
if err != nil { | ||
return updateStatusResponse, err | ||
} | ||
if len(updateStatusResponse.Message) > 0 { | ||
err = errors.New(updateStatusResponse.Message) | ||
return updateStatusResponse, err | ||
} | ||
|
||
return updateStatusResponse, nil | ||
} |
Oops, something went wrong.