优惠券rpc数据结构及方法
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.

223 lines
4.4 KiB

  1. package couponrpc
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "encoding/json"
  6. "errors"
  7. "log"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "git.tetele.net/tgo/crypter"
  12. "github.com/golang/protobuf/proto"
  13. )
  14. type AvailableReqArg struct {
  15. Dbname string `json:"dbname"`
  16. UserCouponId string `json:"user_coupon_id"`
  17. UserId string `json:"user_id"`
  18. ProductId string `json:"product_id"`
  19. }
  20. type AvailableRes struct {
  21. Available bool `json:"available"`
  22. Money string `json:"money"`
  23. Name string `json:"name"`
  24. }
  25. type UseReqArg struct {
  26. Dbname string `json:"dbname"`
  27. UserCouponId string `json:"user_coupon_id"`
  28. OrderSn string `json:"order_sn"`
  29. }
  30. type UseRes struct {
  31. Success bool
  32. }
  33. /**
  34. * 优惠券是否可用
  35. * @param data {"user_id":"","product_id":"","coupon_id":""}
  36. * @param return is_available,name,money,error
  37. */
  38. func IsAvailable(dbname, user_id, product_id, user_coupon_id string, url ...string) (*AvailableRes, error) {
  39. conn, err := rpc_server_conn(url...)
  40. if err != nil {
  41. return nil, err
  42. }
  43. defer conn.Close()
  44. arg := AvailableReqArg{dbname, user_coupon_id, user_id, product_id}
  45. data_json, err := json.Marshal(arg)
  46. if err != nil {
  47. return nil, err
  48. }
  49. now_int64 := time.Now().Unix()
  50. encryData := crypter.DesEn(string(data_json), "conaapon")
  51. now := strconv.FormatInt(now_int64, 10)
  52. sign := Sign(encryData, now)
  53. req := &CouponRequest{proto.String(encryData), proto.String(now), proto.String(sign), nil}
  54. res := &CouponResponse{}
  55. err = conn.IsAvailable(req, res)
  56. if err != nil {
  57. log.Println("coupon rpc error:", err)
  58. return nil, err
  59. }
  60. res_data := res.GetData()
  61. if res_data != "" {
  62. time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64)
  63. if err != nil {
  64. return nil, err
  65. }
  66. now_int64 = time.Now().Unix()
  67. if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 {
  68. //时间误差前后10秒,返回
  69. return nil, errors.New("返回时间错误")
  70. }
  71. check_sign := CheckSign(res.GetSign(), res_data, res.GetTime())
  72. if !check_sign {
  73. return nil, errors.New("返回数据签名错误")
  74. }
  75. //解密
  76. res_data_de := crypter.DesDe(res_data, "conaapon")
  77. var res_arr AvailableRes
  78. err = json.Unmarshal([]byte(res_data_de), &res_arr)
  79. if err != nil {
  80. return nil, err
  81. }
  82. return &res_arr, nil
  83. }
  84. return nil, nil
  85. }
  86. /**
  87. * 使用优惠券
  88. * @param data {"user_coupon_id":"","order_sn":""}
  89. * @param return is_available,name,money,error
  90. */
  91. func Use(dbname, user_coupon_id, order_sn string, url ...string) (*UseRes, error) {
  92. var coupon_rpc_url string = "127.0.0.1:7972"
  93. if len(url) > 0 && url[0] != "" {
  94. coupon_rpc_url = url[0]
  95. }
  96. conn, _, err := DialCouponService("tcp", coupon_rpc_url)
  97. if err != nil {
  98. return nil, err
  99. }
  100. defer conn.Close()
  101. arg := UseReqArg{dbname, user_coupon_id, order_sn}
  102. data_json, err := json.Marshal(arg)
  103. if err != nil {
  104. return nil, err
  105. }
  106. now_int64 := time.Now().Unix()
  107. encryData := crypter.DesEn(string(data_json), "conaapon")
  108. now := strconv.FormatInt(now_int64, 10)
  109. sign := Sign(encryData, now)
  110. req := &CouponRequest{proto.String(encryData), proto.String(now), proto.String(sign), nil}
  111. res := &CouponResponse{}
  112. err = conn.Use(req, res)
  113. if err != nil {
  114. log.Println("coupon rpc error:", err)
  115. return nil, err
  116. }
  117. res_data := res.GetData()
  118. if res_data != "" {
  119. time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64)
  120. if err != nil {
  121. return nil, err
  122. }
  123. now_int64 = time.Now().Unix()
  124. if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 {
  125. //时间误差前后10秒,返回
  126. return nil, errors.New("返回时间错误")
  127. }
  128. check_sign := CheckSign(res.GetSign(), res_data, res.GetTime())
  129. if !check_sign {
  130. return nil, errors.New("返回数据签名错误")
  131. }
  132. //解密
  133. res_data_de := crypter.DesDe(res_data, "conaapon")
  134. var res_arr UseRes
  135. err = json.Unmarshal([]byte(res_data_de), &res_arr)
  136. if err != nil {
  137. return nil, err
  138. }
  139. return &res_arr, nil
  140. }
  141. return nil, nil
  142. }
  143. /**
  144. * 签名
  145. */
  146. func Sign(data string, salt string) string {
  147. var build strings.Builder
  148. build.WriteString(data)
  149. build.WriteString(salt)
  150. build.WriteString("cou$%po87n")
  151. data_str := build.String()
  152. h := md5.New()
  153. h.Write([]byte(data_str)) // 需要加密的字符串
  154. return hex.EncodeToString(h.Sum(nil)) // 输出加密结果
  155. }
  156. /**
  157. * 验证签名
  158. */
  159. func CheckSign(sign_str, data, salt string) bool {
  160. sign := Sign(data, salt)
  161. if strings.Compare(sign_str, sign) > -1 {
  162. return true
  163. }
  164. return false
  165. }