package couponrpc import ( "crypto/md5" "encoding/hex" "encoding/json" "errors" "log" "strconv" "strings" "time" "git.tetele.net/tgo/crypter" "github.com/golang/protobuf/proto" ) type AvailableReqArg struct { Dbname string `json:"dbname"` UserCouponId string `json:"user_coupon_id"` UserId string `json:"user_id"` ProductId string `json:"product_id"` } type AvailableRes struct { Available bool `json:"available"` Money string `json:"money"` Name string `json:"name"` } type UseReqArg struct { Dbname string `json:"dbname"` UserCouponId string `json:"user_coupon_id"` OrderSn string `json:"order_sn"` } type UseRes struct { Success bool } /** * 优惠券是否可用 * @param data {"user_id":"","product_id":"","coupon_id":""} * @param return is_available,name,money,error */ func IsAvailable(dbname, user_id, product_id, user_coupon_id string, url ...string) (*AvailableRes, error) { conn, err := rpc_server_conn(url...) if err != nil { return nil, err } defer conn.Close() arg := AvailableReqArg{dbname, user_coupon_id, user_id, product_id} data_json, err := json.Marshal(arg) if err != nil { return nil, err } now_int64 := time.Now().Unix() encryData := crypter.DesEn(string(data_json), "conaapon") now := strconv.FormatInt(now_int64, 10) sign := Sign(encryData, now) req := &CouponRequest{proto.String(encryData), proto.String(now), proto.String(sign), nil} res := &CouponResponse{} err = conn.IsAvailable(req, res) if err != nil { log.Println("coupon rpc error:", err) return nil, err } res_data := res.GetData() if res_data != "" { time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64) if err != nil { return nil, err } now_int64 = time.Now().Unix() if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 { //时间误差前后10秒,返回 return nil, errors.New("返回时间错误") } check_sign := CheckSign(res.GetSign(), res_data, res.GetTime()) if !check_sign { return nil, errors.New("返回数据签名错误") } //解密 res_data_de := crypter.DesDe(res_data, "conaapon") var res_arr AvailableRes err = json.Unmarshal([]byte(res_data_de), &res_arr) if err != nil { return nil, err } return &res_arr, nil } return nil, nil } /** * 使用优惠券 * @param data {"user_coupon_id":"","order_sn":""} * @param return is_available,name,money,error */ func Use(dbname, user_coupon_id, order_sn string, url ...string) (*UseRes, error) { var coupon_rpc_url string = "127.0.0.1:7972" if len(url) > 0 && url[0] != "" { coupon_rpc_url = url[0] } conn, _, err := DialCouponService("tcp", coupon_rpc_url) if err != nil { return nil, err } defer conn.Close() arg := UseReqArg{dbname, user_coupon_id, order_sn} data_json, err := json.Marshal(arg) if err != nil { return nil, err } now_int64 := time.Now().Unix() encryData := crypter.DesEn(string(data_json), "conaapon") now := strconv.FormatInt(now_int64, 10) sign := Sign(encryData, now) req := &CouponRequest{proto.String(encryData), proto.String(now), proto.String(sign), nil} res := &CouponResponse{} err = conn.Use(req, res) if err != nil { log.Println("coupon rpc error:", err) return nil, err } res_data := res.GetData() if res_data != "" { time_int64, err := strconv.ParseInt(res.GetTime(), 10, 64) if err != nil { return nil, err } now_int64 = time.Now().Unix() if now_int64-time_int64 > 10 || time_int64-now_int64 > 10 { //时间误差前后10秒,返回 return nil, errors.New("返回时间错误") } check_sign := CheckSign(res.GetSign(), res_data, res.GetTime()) if !check_sign { return nil, errors.New("返回数据签名错误") } //解密 res_data_de := crypter.DesDe(res_data, "conaapon") var res_arr UseRes err = json.Unmarshal([]byte(res_data_de), &res_arr) if err != nil { return nil, err } return &res_arr, nil } return nil, nil } /** * 签名 */ func Sign(data string, salt string) string { var build strings.Builder build.WriteString(data) build.WriteString(salt) build.WriteString("cou$%po87n") data_str := build.String() h := md5.New() h.Write([]byte(data_str)) // 需要加密的字符串 return hex.EncodeToString(h.Sum(nil)) // 输出加密结果 } /** * 验证签名 */ func CheckSign(sign_str, data, salt string) bool { sign := Sign(data, salt) if strings.Compare(sign_str, sign) > -1 { return true } return false }