├── go.mod ├── .DS_Store ├── callback.go ├── production.go ├── sandbox.go ├── readme.md └── main.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Findryankp/snapMidtransGo 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findryankp/snapMidtransGo/HEAD/.DS_Store -------------------------------------------------------------------------------- /callback.go: -------------------------------------------------------------------------------- 1 | package snapMidtransGo 2 | 3 | import ( 4 | "crypto/sha512" 5 | "encoding/hex" 6 | ) 7 | 8 | type ResponseFromCallbackMidtrans struct { 9 | TransactionId string `json:"transaction_id"` 10 | TransactionStatus string `json:"transaction_status"` 11 | OrderId string `json:"order_id"` 12 | StatusCode string `json:"status_code"` 13 | SignatureKey string `json:"signature_key"` 14 | GrossAmount string `json:"gross_amount"` 15 | } 16 | 17 | func ValidateSignatureKey(response ResponseFromCallbackMidtrans, orderId, ServerKey string) bool { 18 | str := orderId + response.StatusCode + ServerKey 19 | hash := sha512.Sum512([]byte(str)) 20 | hashStr := hex.EncodeToString(hash[:]) 21 | return string(hashStr) == response.SignatureKey 22 | } 23 | -------------------------------------------------------------------------------- /production.go: -------------------------------------------------------------------------------- 1 | package snapMidtransGo 2 | 3 | import ( 4 | "encoding/base64" 5 | ) 6 | 7 | func RequestSnapMidtrans(postData DataPostMidtrans) (string, error) { 8 | stringBody, errBody := stringBody(postData) 9 | if errBody != nil { 10 | return "", errBody 11 | } 12 | 13 | link := "https://app.midtrans.com/snap/v1/transactions" 14 | encodedString := base64.StdEncoding.EncodeToString([]byte(postData.ServerKey)) 15 | dataBody := []byte(stringBody) 16 | 17 | return postDataTransaction(link, encodedString, dataBody) 18 | } 19 | 20 | func GetTransaction(postData DataPostMidtrans) (map[string]any, error) { 21 | baseUrl := "https://api.midtrans.com/v2" 22 | link := baseUrl + "/" + postData.OrderId + "/status" 23 | encodedString := base64.StdEncoding.EncodeToString([]byte(postData.ServerKey)) 24 | 25 | return getDataTransaction(link, encodedString) 26 | } 27 | -------------------------------------------------------------------------------- /sandbox.go: -------------------------------------------------------------------------------- 1 | package snapMidtransGo 2 | 3 | import ( 4 | "encoding/base64" 5 | ) 6 | 7 | func SandboxRequestSnapMidtrans(postData DataPostMidtrans) (string, error) { 8 | stringBody, errBody := stringBody(postData) 9 | if errBody != nil { 10 | return "", errBody 11 | } 12 | 13 | link := "https://app.sandbox.midtrans.com/snap/v1/transactions" 14 | encodedString := base64.StdEncoding.EncodeToString([]byte(postData.ServerKey)) 15 | dataBody := []byte(stringBody) 16 | 17 | return postDataTransaction(link, encodedString, dataBody) 18 | } 19 | 20 | func SandboxGetTransaction(postData DataPostMidtrans) (map[string]any, error) { 21 | baseUrl := "https://api.sandbox.midtrans.com/v2" 22 | link := baseUrl + "/" + postData.OrderId + "/status" 23 | encodedString := base64.StdEncoding.EncodeToString([]byte(postData.ServerKey)) 24 | return getDataTransaction(link, encodedString) 25 | } 26 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Simple Snap Midtrans - Golang 2 | 3 | ## 💫 About 4 | Simple package to connect your golang app with midtrans. 5 | 6 | ## 🚀 Import 7 | ```shell 8 | go get -u github.com/findryankp/snapMidtransGo@latest 9 | ``` 10 | 11 | ## 👨🏽‍💻 Example 12 | ```go 13 | import ( 14 | "fmt" 15 | 16 | "github.com/Findryankp/snapMidtransGo" 17 | ) 18 | 19 | func main() { 20 | var postData = snapMidtransGo.DataPostMidtrans{ 21 | OrderId: "order-001", 22 | Nominal: 1000, 23 | FirstName: "findryan", 24 | LastName: "kurnia", 25 | Email: "findryankp@gmail.com", 26 | Phone: "081*******", 27 | ServerKey: "key server from midtrans", 28 | } 29 | 30 | //send your transaction 31 | paymenLink, err1 := snapMidtransGo.SandboxRequestSnapMidtrans(postData) 32 | if err1 != nil { 33 | panic(err1.Error()) 34 | } 35 | 36 | fmt.Println(paymenLink) 37 | 38 | //get data from your transaction 39 | dataPayment, err2 := snapMidtransGo.SandboxGetTransaction(postData) 40 | if err2 != nil { 41 | panic(err2.Error()) 42 | } 43 | 44 | fmt.Println(dataPayment) 45 | } 46 | ``` 47 | 48 | ## 🎯 Post your data 49 | all data must be required 50 | 51 | ```go 52 | var postData = snapMidtransGo.DataPostMidtrans{ 53 | OrderId: "order-001", 54 | Nominal: 1000, 55 | FirstName: "findryan", 56 | LastName: "kurnia", 57 | Email: "findryankp@gmail.com", 58 | Phone: "081*******", 59 | ServerKey: "key server from midtrans", 60 | } 61 | ``` 62 | 63 | to call function request transaction 64 | - Production 65 | ```go 66 | //request transaction 67 | snapMidtransGo.RequestSnapMidtrans(postData) 68 | 69 | //get status transaction 70 | snapMidtransGo.GetTransaction(postData) 71 | ``` 72 | 73 | - Sandbox 74 | ```go 75 | //request transaction 76 | snapMidtransGo.SandboxRequestSnapMidtrans(postData) 77 | 78 | //get status transaction 79 | snapMidtransGo.SandboxGetTransaction(postData) 80 | ``` 81 | 82 | 83 | ## 🚀 Return data 84 | success 85 | ```json 86 | { 87 | "response_data" 88 | } 89 | ``` 90 | bad request 91 | ```json 92 | { 93 | "error message" 94 | } 95 | ``` 96 | ## 👨🏽‍💻 Get your server key from Midtrans 97 | 1. Login 98 | 2. Setting 99 | 3. Access Key 100 | 4. Server Key 101 | - if you use sandbox, choose sandbox server key 102 | - likewise if you choose production choose server key production 103 | 104 | ## 😎 Development by 105 | [![Findryankp](https://img.shields.io/badge/Findryankp-grey?style=for-the-badge&logo=github&logoColor=white)](https://github.com/findryankp) 106 | [![findryankp](https://img.shields.io/badge/findryankp-blue?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/Findryankp/) 107 | 108 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package snapMidtransGo 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "net/http" 9 | ) 10 | 11 | type DataPostMidtrans struct { 12 | OrderId string 13 | Nominal int 14 | FirstName string 15 | LastName string 16 | Email string 17 | Phone string 18 | ServerKey string 19 | } 20 | 21 | func checkRequirement(postData DataPostMidtrans) error { 22 | if postData.Email == "" || postData.FirstName == "" || postData.LastName == "" || postData.Nominal == 0 || postData.OrderId == "" || postData.ServerKey == "" || postData.Phone == "" { 23 | return errors.New("all requirement must be fill") 24 | } 25 | 26 | if postData.Nominal < 1000 { 27 | return errors.New("minimun transfer is Rp. 1.000") 28 | } 29 | 30 | return nil 31 | } 32 | 33 | func stringBody(postData DataPostMidtrans) (string, error) { 34 | if err := checkRequirement(postData); err != nil { 35 | return err.Error(), err 36 | } 37 | 38 | text := fmt.Sprintf(`{ 39 | "transaction_details": { 40 | "order_id": "%s", 41 | "gross_amount": %d 42 | }, 43 | "customer_details": { 44 | "first_name": "%s", 45 | "last_name": "%s", 46 | "email": "%s", 47 | "phone": "%s" 48 | } 49 | }`, postData.OrderId, postData.Nominal, postData.FirstName, postData.LastName, postData.Email, postData.Phone) 50 | 51 | return text, nil 52 | } 53 | 54 | func postDataTransaction(link, encodedString string, dataBody []byte) (string, error) { 55 | req, err := http.NewRequest("POST", link, bytes.NewBuffer(dataBody)) 56 | if err != nil { 57 | return "", err 58 | } 59 | 60 | req.Header.Add("Authorization", "Basic "+encodedString) 61 | req.Header.Add("Content-Type", "application/json") 62 | 63 | client := &http.Client{} 64 | resp, err := client.Do(req) 65 | if err != nil { 66 | return "", err 67 | } 68 | 69 | defer resp.Body.Close() 70 | buf := new(bytes.Buffer) 71 | buf.ReadFrom(resp.Body) 72 | body := buf.String() 73 | 74 | response := map[string]any{} 75 | json.Unmarshal([]byte(body), &response) 76 | 77 | _, ok := response["redirect_url"] 78 | if ok { 79 | return response["redirect_url"].(string), nil 80 | } 81 | 82 | return "", errors.New("unautorized token") 83 | } 84 | 85 | func getDataTransaction(link, encodedString string) (map[string]any, error) { 86 | req, err := http.NewRequest("GET", link, nil) 87 | if err != nil { 88 | return map[string]any{}, err 89 | } 90 | 91 | req.Header.Add("Authorization", "Basic "+encodedString) 92 | req.Header.Add("Content-Type", "application/json") 93 | 94 | client := &http.Client{} 95 | resp, err := client.Do(req) 96 | if err != nil { 97 | return map[string]any{}, err 98 | } 99 | 100 | defer resp.Body.Close() 101 | buf := new(bytes.Buffer) 102 | buf.ReadFrom(resp.Body) 103 | body := buf.String() 104 | 105 | response := map[string]any{} 106 | json.Unmarshal([]byte(body), &response) 107 | return response, err 108 | } 109 | --------------------------------------------------------------------------------