payment gateway for rpn cn
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
4.5KB

  1. package main
  2. import (
  3. "io/ioutil"
  4. "log"
  5. "net/http"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. "time"
  10. )
  11. type LeanworkOut struct {
  12. Id int64
  13. Leanwork int64
  14. SignType string
  15. OrderNo string
  16. OrderAmount string
  17. OrderCurrency string
  18. TransactionId string
  19. Status string
  20. Sign string
  21. Ts time.Time
  22. LeanworkResp string
  23. }
  24. //inform Leanwork of final result, retry 5 times if not successful
  25. func (m *LeanworkOut) DoHttp() (retry bool, err error) {
  26. retry = true
  27. form := url.Values{}
  28. form.Set("signType", "MD5")
  29. form.Set("orderNo", m.OrderNo)
  30. form.Set("orderAmount", m.OrderAmount)
  31. form.Set("orderCurrency", m.OrderCurrency)
  32. form.Set("transactionId", m.TransactionId)
  33. form.Set("status", m.Status)
  34. form.Set("sign", m.Sign)
  35. lin, err := getLeanworkInById(m.Leanwork) //which is very unlikely
  36. if err != nil {
  37. log.Println("Fatal: Cannot get LeanworkIn by ID =" + strconv.FormatInt(m.Leanwork, 10) + "error " + err.Error())
  38. retry = false
  39. }
  40. resp, err := http.PostForm(lin.ReceiveUrl, form)
  41. if err != nil {
  42. log.Println("Leanwork Server Error, give bad response, " + err.Error())
  43. m.LeanworkResp = "Http Error: " + err.Error()
  44. m.add2db()
  45. return
  46. }
  47. defer resp.Body.Close()
  48. if resp.StatusCode == http.StatusOK {
  49. bodyBytes, err := ioutil.ReadAll(resp.Body)
  50. if err != nil {
  51. log.Println("Fatal: Cannot read leanwork Http Response " + err.Error())
  52. }
  53. bodyString := string(bodyBytes)
  54. m.LeanworkResp = bodyString
  55. m.add2db()
  56. if strings.Contains(strings.ToLower(bodyString), "success") {
  57. retry = false
  58. } else {
  59. log.Println("Leanwork response without success word : " + bodyString)
  60. }
  61. retry = false
  62. }
  63. return
  64. }
  65. func startLeanworkCallBack(ri RpnIn) {
  66. lo, err := buildLeanworkOutByRpnIn(ri)
  67. if err != nil {
  68. log.Printf("Fatal: cannot inform Leanwork %+v , \n\t%s\n", ri, err.Error())
  69. return
  70. }
  71. if ri.Pay_result != "3" {
  72. log.Printf("Warning: RpnIn is processing not informing leanwork %+v", ri)
  73. return
  74. }
  75. for i := 1; i <= 5; i++ {
  76. retry, err := lo.DoHttp()
  77. if !retry {
  78. break
  79. }
  80. time.Sleep(5 * time.Minute) //sleep 5 minute and try again
  81. log.Printf("Trying(%d) to report leanwork about transaction status %+v, encountered error %s \n", i, lo, err.Error())
  82. }
  83. }
  84. func buildLeanworkOutByRpnIn(ri RpnIn) (ret LeanworkOut, err error) {
  85. li, err := getLeanworkInById(ri.Leanwork)
  86. if err != nil {
  87. return
  88. }
  89. ret.Leanwork = ri.Leanwork
  90. ret.SignType = "MD5"
  91. ret.OrderNo = li.OrderNo
  92. ret.OrderAmount = li.OrderAmount
  93. ret.OrderCurrency = li.OrderCurrency
  94. ret.TransactionId = ri.Deal_id
  95. if ri.Pay_result == "3" {
  96. ret.Status = "success"
  97. } else if ri.Pay_result == "1" {
  98. ret.Status = "processing"
  99. }
  100. ret.UpdateSignature()
  101. return
  102. }
  103. func (m *LeanworkOut) UpdateSignature() {
  104. s := m.SignType + m.OrderNo + m.OrderAmount + m.OrderCurrency + m.TransactionId + m.Status + Config.LeanWork.MD5Key
  105. m.Sign = md5str(s)
  106. }
  107. func (m *LeanworkOut) add2db() (ret LeanworkOut, err error) {
  108. if err = db.conn(Config); err != nil {
  109. return
  110. }
  111. defer db.close()
  112. q := `INSERT INTO leanworkOut(
  113. leanwork, signType, orderNo, orderAmount, orderCurrency,
  114. transactionId, status, sign, leanworkResp)
  115. VALUES(?,?,?,?,?,?,?,?,?)
  116. `
  117. insForm, err := db.h.Prepare(q)
  118. if err != nil {
  119. log.Printf("Failed to prepare SQL statment for insert leanworkOut" + err.Error())
  120. return
  121. }
  122. res, err := insForm.Exec(
  123. m.Leanwork, m.SignType, m.OrderNo, m.OrderAmount, m.OrderCurrency,
  124. m.TransactionId, m.Status, m.Sign, m.LeanworkResp)
  125. if err != nil {
  126. log.Printf("Error inserting leanworkOut with orderNo =%s, %s \n", m.OrderNo, err.Error())
  127. return
  128. }
  129. id, err := res.LastInsertId()
  130. if err != nil {
  131. log.Printf("Cannot retrieve lastInsertId for orderID %s", m.OrderNo)
  132. return
  133. }
  134. ret, err = getLeanWorkOutById(id)
  135. if err == nil {
  136. *m = ret
  137. }
  138. return
  139. }
  140. func getLeanWorkOutById(id int64) (row LeanworkOut, err error) {
  141. db.conn(Config)
  142. defer db.close()
  143. err = db.h.QueryRow("SELECT * FROM leanworkOut WHERE id=? ", id).Scan(
  144. &row.Id, &row.Leanwork, &row.SignType, &row.OrderNo, &row.OrderAmount,
  145. &row.OrderCurrency, &row.TransactionId, &row.Status, &row.Sign,
  146. &row.Ts, &row.LeanworkResp)
  147. return
  148. }
  149. func getLeanWorkOutByLeanworkId(id int64) (row LeanworkOut, err error) {
  150. db.conn(Config)
  151. defer db.close()
  152. err = db.h.QueryRow("SELECT * FROM leanworkOut WHERE leanwork=? ORDER BY id DESC LIMIT 1", id).Scan(
  153. &row.Id, &row.Leanwork, &row.SignType, &row.OrderNo, &row.OrderAmount,
  154. &row.OrderCurrency, &row.TransactionId, &row.Status, &row.Sign,
  155. &row.Ts, &row.LeanworkResp)
  156. return
  157. }