From be79e2b2503982976448e6aa1f48802f86a8c310 Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 11 Mar 2020 03:08:14 +1100 Subject: [PATCH] leanwork Out is implemented --- leanworkIn.go | 13 +++++- leanworkOut.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ rpnIn.go | 23 ++++++++++ rpnIn_test.go | 10 +++++ 4 files changed, 163 insertions(+), 2 deletions(-) diff --git a/leanworkIn.go b/leanworkIn.go index 64bebd7..a8dbfa1 100644 --- a/leanworkIn.go +++ b/leanworkIn.go @@ -26,12 +26,21 @@ func lrIsIdMatchSign(id string, sign string) bool { _, err := getRequestRowByIdAndSign(id, sign) return err == nil } +func getLeanworkInById(id int64) (row LeanworkIn, err error) { + db.conn(Config) + defer db.close() + err = db.h.QueryRow("SELECT * FROM leanworkIn WHERE id=? ", id).Scan( + &row.Id, &row.PickupUrl, &row.ReceiveUrl, &row.SignType, + &row.OrderNo, &row.OrderAmount, &row.OrderCurrency, &row.CustomerId, + &row.Sign, &row.Valid, &row.Ts, &row.Ip4, &row.Ip4Location) + return +} func getRequestRowByIdAndSign(id string, sign string) (row LeanworkIn, err error) { //retrieve form DB - row = LeanworkIn{} db.conn(Config) - selDB, err := db.h.Query("SELECT * FROM leanworkIN WHERE id=? and sign=?", id, sign) + defer db.close() + selDB, err := db.h.Query("SELECT * FROM leanworkIn WHERE id=? and sign=?", id, sign) if err != nil { return } diff --git a/leanworkOut.go b/leanworkOut.go index c9ecbf5..2bfa0bf 100644 --- a/leanworkOut.go +++ b/leanworkOut.go @@ -1,2 +1,121 @@ package main +import ( + "io/ioutil" + "log" + "net/http" + "net/url" + "strconv" + "strings" + "time" +) + +type LeanworkOut struct { + Id int64 + Leanwork int64 + OrderNo string + OrderAmount string + OrderCurrency string + TransactionId string + Status string + Sign string + Ts time.Time + LeanworkResp string +} + +//inform Leanwork of final result, retry 5 times if not successful +func (m *LeanworkOut) DoHttp() (retry bool, err error) { + retry = true + form := url.Values{} + form.Set("signType", "MD5") + form.Set("orderNo", m.OrderNo) + form.Set("orderAmount", m.OrderAmount) + form.Set("orderCurrency", m.OrderCurrency) + form.Set("transactionId", m.TransactionId) + form.Set("sign", m.Sign) + + lin, err := getLeanworkInById(m.Leanwork) //which is very unlikely + if err != nil { + log.Println("Fatal: Cannot get LeanworkIn by ID =" + strconv.FormatInt(m.Leanwork, 10) + "error " + err.Error()) + retry = false + } + resp, err := http.PostForm(lin.ReceiveUrl, form) + if err != nil { + log.Println("Leanwork Server Error, give bad response, " + err.Error()) + return + } + defer resp.Body.Close() + + if resp.StatusCode == http.StatusOK { + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Println("Fatal: Cannot read leanwork Http Response " + err.Error()) + } + bodyString := string(bodyBytes) + if strings.Contains(strings.ToLower(bodyString), "success") { + retry = false + } else { + log.Println("Leanwork response without success word : " + bodyString) + } + } + return +} + +func (m *LeanworkOut) startCallBack() { + for i := 1; i <= 5; i++ { + retry, err := m.DoHttp() + if !retry { + break + } + time.Sleep(5 * time.Minute) //sleep 5 minute and try again + log.Printf("Trying(%d) to report leanwork about transaction status %+v, encountered error %s \n", i, *m, err.Error()) + } +} + +func (m *LeanworkOut) add2db() (ret LeanworkOut, err error) { + if err = db.conn(Config); err != nil { + return + } + defer db.close() + + q := `INSERT INTO leanworkOut( + leanwork, orderNo, orderAmount, orderCurrency, + transactionId, status, sign, leanworkResp) + VALUES(?,?,?,?,?,?,?,?) + ` + insForm, err := db.h.Prepare(q) + if err != nil { + log.Printf("Failed to prepare SQL statment for insert leanworkOut" + err.Error()) + return + } + res, err := insForm.Exec( + m.Leanwork, m.OrderNo, m.OrderAmount, m.OrderCurrency, + m.TransactionId, m.Status, m.Sign, m.LeanworkResp) + + if err != nil { + log.Printf("Error inserting leanworkOut with orderNo =%s, %s \n", m.OrderNo, err.Error()) + return + } + id, err := res.LastInsertId() + if err != nil { + log.Printf("Cannot retrieve lastInsertId for orderID %s", m.OrderNo) + return + } + + ret, err = getLeanWorkOutById(id) + if err == nil { + *m = ret + } + + return +} + +func getLeanWorkOutById(id int64) (row LeanworkOut, err error) { + db.conn(Config) + defer db.close() + err = db.h.QueryRow("SELECT * FROM leanworkOut WHERE id=? ", id).Scan( + &row.Id, &row.Leanwork, &row.OrderNo, &row.OrderAmount, + &row.OrderCurrency, &row.TransactionId, &row.Status, &row.Sign, + &row.Ts, &row.LeanworkResp) + return +} diff --git a/rpnIn.go b/rpnIn.go index 0f0735a..07e5286 100644 --- a/rpnIn.go +++ b/rpnIn.go @@ -47,6 +47,29 @@ func getRpnInById(id int64) (ret RpnIn, err error) { return } +//get given RpnIn record based on ID +func getRpnInByLeanworkId(id int64) (ret RpnIn, err error) { + if err = db.conn(Config); err != nil { + return + } + defer db.close() + + q := "SELECT * FROM rpnIn WHERE leanwork = ? ORDER BY id DESC LIMIT 1" + err = db.h.QueryRow(q, id).Scan( + &ret.Id, &ret.Leanwork, &ret.Order_id, + &ret.Order_time, &ret.Order_amount, &ret.Deal_id, + &ret.Deal_time, &ret.Pay_amount, &ret.Pay_result, + &ret.Signature, &ret.Ts, &ret.Ip4) + if err != nil { + if err == sql.ErrNoRows { + log.Println("trying to retrieve rpnIn(" + strconv.FormatInt(id, 10) + ") but not found") + } else { + log.Println("Error retrieving rpnIn(" + strconv.FormatInt(id, 10) + ") encountered : " + err.Error()) + } + } + return +} + //add to database func (m *RpnIn) add2db() (ret RpnIn, err error) { if err = db.conn(Config); err != nil { diff --git a/rpnIn_test.go b/rpnIn_test.go index 9d877f2..eaa78b7 100644 --- a/rpnIn_test.go +++ b/rpnIn_test.go @@ -50,3 +50,13 @@ func TestRpnInCall(t *testing.T) { } } + +func TestGetRecByLeanworkID(t *testing.T) { + ri, err := getRpnInByLeanworkId(152) + if err != nil { + t.Error("we should not have error to get leanwork id 152 from rpnIn") + } + if ri.Id != 15 { + t.Error("Biggest leanwork id 152 should cap to rpnIn 15") + } +}