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.

227 lines
4.5 KiB

3 years ago
3 years ago
3 years ago
  1. package coupon
  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. var coupon_rpc_url string = "127.0.0.1:7972"
  40. if len(url) > 0 && url[0] != "" {
  41. coupon_rpc_url = url[0]
  42. }
  43. conn, _, err := DialCouponService("tcp", coupon_rpc_url)
  44. if err != nil {
  45. return nil, err
  46. }
  47. defer conn.Close()
  48. arg := AvailableReqArg{dbname, user_coupon_id, user_id, product_id}
  49. data_json, err := json.Marshal(arg)
  50. if err != nil {
  51. return nil, err
  52. }
  53. now_int64 := time.Now().Unix()
  54. encryData := crypter.DesEn(string(data_json), "conaapon")
  55. now := strconv.FormatInt(now_int64, 10)
  56. sign := Sign(encryData, now)
  57. req := &CouponRequest{proto.String(encryData), proto.String(now), proto.String(sign), nil}
  58. res := &CouponResponse{}
  59. err = conn.IsAvailable(req, res)
  60. if err != nil {
  61. log.Println("coupon rpc error:", err)
  62. return nil, err
  63. }
  64. res_data := res.GetData()
  65. if res_data != "" {
  66. time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64)
  67. if err != nil {
  68. return nil, err
  69. }
  70. now_int64 = time.Now().Unix()
  71. if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 {
  72. //时间误差前后10秒,返回
  73. return nil, errors.New("返回时间错误")
  74. }
  75. check_sign := CheckSign(res.GetSign(), res_data, res.GetTime())
  76. if !check_sign {
  77. return nil, errors.New("返回数据签名错误")
  78. }
  79. //解密
  80. res_data_de := crypter.DesDe(res_data, "conaapon")
  81. var res_arr AvailableRes
  82. err = json.Unmarshal([]byte(res_data_de), &res_arr)
  83. if err != nil {
  84. return nil, err
  85. }
  86. return &res_arr, nil
  87. }
  88. return nil, nil
  89. }
  90. /**
  91. * 使用优惠券
  92. * @param data {"user_coupon_id":"","order_sn":""}
  93. * @param return is_available,name,money,error
  94. */
  95. func Use(dbname, user_coupon_id, order_sn string, url ...string) (*UseRes, error) {
  96. var coupon_rpc_url string = "127.0.0.1:7972"
  97. if len(url) > 0 && url[0] != "" {
  98. coupon_rpc_url = url[0]
  99. }
  100. conn, _, err := DialCouponService("tcp", coupon_rpc_url)
  101. if err != nil {
  102. return nil, err
  103. }
  104. defer conn.Close()
  105. arg := UseReqArg{dbname, user_coupon_id, order_sn}
  106. data_json, err := json.Marshal(arg)
  107. if err != nil {
  108. return nil, err
  109. }
  110. now_int64 := time.Now().Unix()
  111. encryData := crypter.DesEn(string(data_json), "conaapon")
  112. now := strconv.FormatInt(now_int64, 10)
  113. sign := Sign(encryData, now)
  114. req := &CouponRequest{proto.String(encryData), proto.String(now), proto.String(sign), nil}
  115. res := &CouponResponse{}
  116. err = conn.Use(req, res)
  117. if err != nil {
  118. log.Println("coupon rpc error:", err)
  119. return nil, err
  120. }
  121. res_data := res.GetData()
  122. if res_data != "" {
  123. time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64)
  124. if err != nil {
  125. return nil, err
  126. }
  127. now_int64 = time.Now().Unix()
  128. if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 {
  129. //时间误差前后10秒,返回
  130. return nil, errors.New("返回时间错误")
  131. }
  132. check_sign := CheckSign(res.GetSign(), res_data, res.GetTime())
  133. if !check_sign {
  134. return nil, errors.New("返回数据签名错误")
  135. }
  136. //解密
  137. res_data_de := crypter.DesDe(res_data, "conaapon")
  138. var res_arr UseRes
  139. err = json.Unmarshal([]byte(res_data_de), &res_arr)
  140. if err != nil {
  141. return nil, err
  142. }
  143. return &res_arr, nil
  144. }
  145. return nil, nil
  146. }
  147. /**
  148. * 签名
  149. */
  150. func Sign(data string, salt string) string {
  151. var build strings.Builder
  152. build.WriteString(data)
  153. build.WriteString(salt)
  154. build.WriteString("cou$%po87n")
  155. data_str := build.String()
  156. h := md5.New()
  157. h.Write([]byte(data_str)) // 需要加密的字符串
  158. return hex.EncodeToString(h.Sum(nil)) // 输出加密结果
  159. }
  160. /**
  161. * 验证签名
  162. */
  163. func CheckSign(sign_str, data, salt string) bool {
  164. sign := Sign(data, salt)
  165. if strings.Compare(sign_str, sign) > -1 {
  166. return true
  167. }
  168. return false
  169. }