package main import ( "io/ioutil" "log" "net/http" "net/url" "strconv" "strings" "time" ) type LeanworkOut struct { Id int64 Leanwork int64 SignType string 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("status", m.Status) 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()) m.LeanworkResp = "Http Error: " + err.Error() m.add2db() 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) m.LeanworkResp = bodyString m.add2db() if strings.Contains(strings.ToLower(bodyString), "success") { retry = false } else { log.Println("Leanwork response without success word : " + bodyString) } retry = false } return } func startLeanworkCallBack(ri RpnIn) { lo, err := buildLeanworkOutByRpnIn(ri) if err != nil { log.Printf("Fatal: cannot inform Leanwork %+v , \n\t%s\n", ri, err.Error()) return } if ri.Pay_result != "3" { log.Printf("Warning: RpnIn is processing not informing leanwork %+v", ri) return } for i := 1; i <= 5; i++ { retry, err := lo.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, lo, err.Error()) } } func buildLeanworkOutByRpnIn(ri RpnIn) (ret LeanworkOut, err error) { li, err := getLeanworkInById(ri.Leanwork) if err != nil { return } ret.Leanwork = ri.Leanwork ret.SignType = "MD5" ret.OrderNo = li.OrderNo ret.OrderAmount = li.OrderAmount ret.OrderCurrency = li.OrderCurrency ret.TransactionId = ri.Deal_id if ri.Pay_result == "3" { ret.Status = "success" } else if ri.Pay_result == "1" { ret.Status = "processing" } ret.UpdateSignature() return } func (m *LeanworkOut) UpdateSignature() { s := m.SignType + m.OrderNo + m.OrderAmount + m.OrderCurrency + m.TransactionId + m.Status + Config.LeanWork.MD5Key m.Sign = md5str(s) } func (m *LeanworkOut) add2db() (ret LeanworkOut, err error) { if err = db.conn(Config); err != nil { return } defer db.close() q := `INSERT INTO leanworkOut( leanwork, signType, 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.SignType, 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.SignType, &row.OrderNo, &row.OrderAmount, &row.OrderCurrency, &row.TransactionId, &row.Status, &row.Sign, &row.Ts, &row.LeanworkResp) return } func getLeanWorkOutByLeanworkId(id int64) (row LeanworkOut, err error) { db.conn(Config) defer db.close() err = db.h.QueryRow("SELECT * FROM leanworkOut WHERE leanwork=? ORDER BY id DESC LIMIT 1", id).Scan( &row.Id, &row.Leanwork, &row.SignType, &row.OrderNo, &row.OrderAmount, &row.OrderCurrency, &row.TransactionId, &row.Status, &row.Sign, &row.Ts, &row.LeanworkResp) return }