abiao 4 gadi atpakaļ
vecāks
revīzija
ba592ac60a
30 mainītis faili ar 710 papildinājumiem un 893 dzēšanām
  1. 1 1
      go/gopath/src/fohow.com/apps/controllers/ad_controller/ad_controller.go
  2. 2 2
      go/gopath/src/fohow.com/apps/controllers/order_controller/init.go
  3. 2 2
      go/gopath/src/fohow.com/apps/controllers/order_controller/order_controller.go
  4. 2 2
      go/gopath/src/fohow.com/apps/controllers/pay_controller/init.go
  5. 2 2
      go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_controller.go
  6. 42 7
      go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_exchange_controller.go
  7. 156 490
      go/gopath/src/fohow.com/apps/controllers/permit_controller/permit_controller.go
  8. 9 3
      go/gopath/src/fohow.com/apps/controllers/product_controller/product_controller.go
  9. 18 2
      go/gopath/src/fohow.com/apps/controllers/test_controller/test_controller.go
  10. 6 109
      go/gopath/src/fohow.com/apps/controllers/user_controller/binding_wx_phone_controller.go
  11. 89 144
      go/gopath/src/fohow.com/apps/init.go
  12. 2 0
      go/gopath/src/fohow.com/apps/models/order_model/order.go
  13. 72 18
      go/gopath/src/fohow.com/apps/models/product_model/product.go
  14. 1 1
      go/gopath/src/fohow.com/apps/models/promotion_model/order_promotion.go
  15. 14 0
      go/gopath/src/fohow.com/apps/models/token_model/init.go
  16. 107 0
      go/gopath/src/fohow.com/apps/models/token_model/token.go
  17. 3 2
      go/gopath/src/fohow.com/apps/models/user_model/user.go
  18. 9 10
      go/gopath/src/fohow.com/apps/models/user_model/wx_user.go
  19. 23 5
      go/gopath/src/fohow.com/conf/app.conf
  20. BIN
      go/gopath/src/fohow.com/fohowmall.com
  21. 5 0
      go/gopath/src/fohow.com/libs/lib_redis/redis.go
  22. 0 34
      go/gopath/src/fohow.com/libs/tool/token.go
  23. 83 3
      go/gopath/src/fohow.com/libs/wx_mp/pay.go
  24. 5 0
      go/gopath/src/fohow.com/nginx/ngx_prod_config
  25. 2 2
      go/gopath/src/fohow.com/nginx/ngx_test_config
  26. 4 0
      go/gopath/src/fohow.com/routers/routes.go
  27. 0 27
      go/gopath/src/fohow.com/static/tapi/5539910_tfohowapi.hiwavo.com.key
  28. 27 0
      go/gopath/src/fohow.com/static/tapi/5754763_tfohowapi.hiwavo.com.key
  29. 24 25
      go/gopath/src/fohow.com/static/tapi/5539910_tfohowapi.hiwavo.com.pem
  30. 0 2
      go/gopath/src/github.com/chanxuehong/wechat/mch/sign.go

+ 1 - 1
go/gopath/src/fohow.com/apps/controllers/ad_controller/ad_controller.go

@@ -91,7 +91,7 @@ func (self *AdController) GetItems() {
 	default:
 		self.Data["json"] = ads
 	}
-	self.ServeJSON()
+	self.ServeResultJSON()
 }
 
 //根据广告位id,获取广告图

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/order_controller/init.go

@@ -16,8 +16,8 @@ import (
 
 var (
 	//需要校验用户登录的Action
-	exceptCheckUserLoginAction   = []string{"Create", "Detail", "List", "Operate", "GetExpressNo", "MultChangeItemState", "GetCartList"}
-	exceptCheckWxUserLoginAction = []string{"GetExpressNo", "MultChangeItemState", "GetCartList"}
+	exceptCheckUserLoginAction   = []string{}
+	exceptCheckWxUserLoginAction = []string{}
 )
 
 type OrderController struct {

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/order_controller/order_controller.go

@@ -528,7 +528,7 @@ func (self *OrderController) Detail() {
 	}
 	o.WxUser = wxUser
 	self.Data["json"] = o
-	self.ServeJSON()
+	self.ServeResultJSON()
 }
 
 //获取用户待评价订单列表
@@ -671,7 +671,7 @@ func (self *OrderController) List() {
 		ListCount int64                `json:"list_count"`
 	}
 	self.Data["json"] = &Ret{ListCount: count, List: latestOrders}
-	self.ServeJSON()
+	self.ServeResultJSON()
 }
 
 //用户更改订单状态

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/pay_controller/init.go

@@ -28,8 +28,8 @@ import (
 
 var (
 	//不需要校验用户登录的Action
-	exceptCheckUserLoginAction   = []string{"Pay", "PayAsync"}
-	exceptCheckWxUserLoginAction = []string{"Pay", "PayAsync"}
+	exceptCheckUserLoginAction   = []string{"PayAsync"}
+	exceptCheckWxUserLoginAction = []string{"PayAsync"}
 )
 
 type PayController struct {

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_controller.go

@@ -29,9 +29,9 @@ func (self *PayController) Pay() {
 	remark := self.GetString("remark")
 
 	source := self.GetString("s")
-	useCoupon, _ := self.GetBool("use_coupon", true)
+	useCoupon, _ := self.GetBool("use_coupon", false)
 
-	beego.BeeLogger.Debug("pay.oId(%s).payway(%s).(%v)", oId, payWay, payWay == balance_model.PAY_WAY_TYPE_RECHARGE_WXPAY)
+	beego.BeeLogger.Debug("pay.oId(%s).payway(%s).(%v).use_coupon(%t)", oId, payWay, payWay == balance_model.PAY_WAY_TYPE_RECHARGE_WXPAY, useCoupon)
 	if oId == "" || payWay == "" {
 		self.ReturnError(500, apps.ParamsError, "", nil)
 	}

+ 42 - 7
go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_exchange_controller.go

@@ -67,15 +67,14 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source,
 		if pick_dept == nil || pick_address == nil || pick_address.WxUserId != wxUId {
 			self.ReturnError(403, apps.AddressNotMatch, "", nil)
 		}
-
 		concat = pick_address.Contact
 		tel = pick_address.Tel
 		addr = pick_dept.PickAddress
 	}
-
-	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_GZH {
+	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_APP {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
+
 	wxUser := user_model.GetWxUserById(wxUId, false)
 	if wxUser == nil {
 		self.ReturnError(403, apps.UserNeedLogin, "", nil)
@@ -237,7 +236,7 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source,
 			order.PaiedPrice = total_weixin
 			order.Source = source
 			order.Save()
-			if order.Source == order_model.SOURCE_XCX { //小程序微信支付
+			if source == order_model.SOURCE_XCX { //小程序微信支付
 				freight := sys_config.GetFreight()
 				if order.TotalPrice >= sys_config.GetOrderLimit() {
 					freight = int64(0)
@@ -246,7 +245,9 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source,
 				notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
 				body := fmt.Sprintf("凤凰菁选-购买商品")
 				//获取paycode
-				payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+				payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, false)
+
+				beego.BeeLogger.Warn("payCode--%s", payCode)
 				payData := wx_mp.GetPayData(wxUser.Openid, order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
 
 				//返回数据
@@ -256,6 +257,25 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source,
 				}
 				self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
 
+			} else if source == order_model.SOURCE_APP {
+				freight := sys_config.GetFreight()
+				if order.TotalPrice >= sys_config.GetOrderLimit() {
+					freight = int64(0)
+				}
+				order.TotalPrice += freight
+				notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
+				body := fmt.Sprintf("FOHOW玖玖-购买商品")
+				//获取paycode
+				payCode := "app" //sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+				payData := wx_mp.GetAppPayData(order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
+				beego.BeeLogger.Warn("pay_data --%v", payData)
+				//返回数据
+				type PayData struct {
+					NeedWx  bool              `json:"need_wx"`
+					PayData map[string]string `json:"pay_data"`
+				}
+				self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
+
 			} else { //公众号微信支付
 
 				notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
@@ -279,7 +299,7 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source,
 		}
 	} else {
 		//如果是第二次支付
-		if order.Source == order_model.SOURCE_XCX { //小程序微信支付
+		if source == order_model.SOURCE_XCX { //小程序微信支付
 
 			notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
 			body := fmt.Sprintf("凤凰菁选-购买商品")
@@ -293,6 +313,21 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source,
 			}
 			self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
 
+		} else if source == order_model.SOURCE_APP {
+			notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
+			body := fmt.Sprintf("FOHOW玖玖-购买商品")
+			//payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+			payCode := "app" //sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+
+			payData := wx_mp.GetAppPayData(order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
+
+			//返回数据
+			type PayData struct {
+				NeedWx  bool              `json:"need_wx"`
+				PayData map[string]string `json:"pay_data"`
+			}
+			self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
+
 		} else { //公众号微信支付
 
 			notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
@@ -331,7 +366,7 @@ func (self *PayController) payCentExchange(oId, returnUrl, source, remark string
 		self.ReturnError(403, apps.AddressNotMatch, "", nil)
 	}
 
-	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_GZH {
+	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_APP {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
 	wxUser := user_model.GetWxUserById(wxUId, false)

+ 156 - 490
go/gopath/src/fohow.com/apps/controllers/permit_controller/permit_controller.go

@@ -1,9 +1,12 @@
 package permit_controller
 
 import (
+	"crypto/md5"
+	"encoding/hex"
 	"fmt"
+	"fohow.com/apps/models/token_model"
 	"fohow.com/libs/lib_redis"
-	"strconv"
+	"fohow.com/libs/tool"
 
 	// "math/rand"
 	// "crypto/md5"
@@ -24,14 +27,12 @@ import (
 	// "fohow.com/apps/models/order_model"
 	// "fohow.com/apps/models/product_model"
 	// "fohow.com/apps/models/shop_model"
-	// "fohow.com/apps/models/sms_model"
+	"fohow.com/apps/models/sms_model"
 	"fohow.com/apps/models/user_model"
 	// "fohow.com/apps/models/wx_gongzhonghao_model"
 	"fohow.com/cache"
 	// "fohow.com/libs/tool"
 	"fohow.com/libs/wx_mp"
-	// "fohow.com/libs/wx_open"
-	"fohow.com/libs/tool"
 )
 
 var (
@@ -53,11 +54,7 @@ func (self *PermitController) Init(ctx *context.Context, controllerName, actionN
 //小程序授权
 func (self *PermitController) XcxAuthorize() {
 	params := self.GetString("userinfo")
-
-	channel, _ := self.GetInt64("channel", 0)
-	//beego.BeeLogger.Warn("XcxAuthorize userinfo: %s", params)
-	inviteId, _ := self.GetInt64("invite_id", 0)
-	first := false
+	cache, _ := self.GetBool("cache", false)
 	//beego.BeeLogger.Warn("XcxAuthorize inviteId: %d", inviteId)
 	type UserInfo struct {
 		NickName  string `json:"nickName"`  // 用户的昵称
@@ -85,58 +82,70 @@ func (self *PermitController) XcxAuthorize() {
 		beego.BeeLogger.Error("XcxAuthorize err: %s, info:%s", err, info)
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
-	//beego.BeeLogger.Warn("XcxAuthorize code: %s", info.Wxlogincode)
-
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
-	//beego.BeeLogger.Warn("sessionKey:%s", sessionKey)
-	type EncryptedData struct {
-		UnionId  string `json:"unionId"`
-		OpenId   string `json:"openId"`
-		NickName string `json:"nickName"`
-	}
-
-	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
-	}
-	encryptedData := &EncryptedData{}
-	encryptedData.OpenId, encryptedData.UnionId = GetXcxLoginInfo(info.Wxlogincode)
-	/*
-		pc := helpers.WxBizDataCrypt{AppID: beego.AppConfig.String("WxFohowXcxAppId"), SessionKey: sessionKey}
-		beego.BeeLogger.Warn("EncryptedData:%s", info.EncryptedData)
-		beego.BeeLogger.Warn("Iv:%s", info.Iv)
-		result, err := pc.Decrypt(info.EncryptedData, info.Iv, true) //第三个参数解释: 需要返回 JSON 数据类型时 使用 true, 需要返回 map 数据类型时 使用 false
-		if err != nil {
-			beego.BeeLogger.Error("xcx XcxAuthorize descrypt failed, err:%s", err)
-			self.ReturnError(403, apps.XcxAuthorizeError, "", nil)
-		}
-		beego.BeeLogger.Warn("result:%v", result)
-		encryptedData := &EncryptedData{}
+	wxUser := self.GetCurrentWxUser(cache)
+	user := self.GetCurrentUser(cache)
+	if wxUser == nil {
+		self.ReturnError(401, apps.WxUserNotExist, "", nil)
+	}
+	//更新用户信息
+	wxUser.Nickname = info.UserInfo.NickName
+	wxUser.Sex = info.UserInfo.Gender
+	wxUser.City = info.UserInfo.City
+	wxUser.Province = info.UserInfo.Province
+	wxUser.Country = info.UserInfo.Country
+	wxUser.Save()
+	user.Nickname = wxUser.Nickname
+	user.Country = wxUser.Country
+	user.Province = wxUser.Province
+	user.City = wxUser.City
+	user.Sex = wxUser.Sex
+	user.Save()
 
-		json.Unmarshal([]byte(result.(string)), encryptedData)*/
+	beego.BeeLogger.Warn("XcxAuthorize wxUser after save() Nickname:%s, Sex:%s, City:%s, Province:%s, Country:%s ", wxUser.Nickname, wxUser.Sex, wxUser.City, wxUser.Province, wxUser.Country)
 
-	if encryptedData.UnionId == "" || encryptedData.OpenId == "" {
-		beego.BeeLogger.Error("encryptedData:%v", encryptedData)
-		self.ReturnError(403, apps.UserAuthorizeFailed, "", nil)
-	}
-	wxUser := user_model.GetWxUserByUnionid(encryptedData.UnionId, false)
-	ip := self.Ctx.Input.IP()
-	var user *user_model.User
-	if wxUser != nil && wxUser.UserId > 0 {
-		//查找已注册会员
-		user = user_model.GetUserById(wxUser.UserId, false)
-	} else {
-		//注册会员
-		user = user_model.Create("", ip)
+	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
+	if wxUser != nil {
+		wxUser.UploadHead(info.UserInfo.AvatarUrl)
+		user.CopyWxUserHead(wxUser.Head)
 	}
-	if user == nil {
-		self.ReturnError(403, apps.RegisterUserError, "", nil)
+	type Ret struct {
+		Result bool               `json:"result"`
+		WxUser *user_model.WxUser `json:"wx_user"`
 	}
+	self.Data["json"] = &Ret{WxUser: wxUser, Result: true}
+	self.ServeJSON()
+}
 
+//小程序登录
+func (self *PermitController) XcxLogin() {
+	code := self.GetString("code")
+	inviteId, _ := self.GetInt64("invite_id", 0)
+	//beego.BeeLogger.Warn("XcxLogin code=%s", code)
+	if code == "" {
+		self.ReturnError(403, apps.ParamsRequired, "", nil)
+	}
+	appId := beego.AppConfig.String("WxFohowXcxAppId")
+	appSecret := beego.AppConfig.String("WxFohowXcxAppSecret")
+	key := wx_mp.GetXcxSessionKey(appId, appSecret, code)
+	if key == nil {
+		self.ReturnError(403, apps.XcxGetSessionKeyError, "", nil)
+	}
+	//beego.BeeLogger.Warn("XcxLogin key=%s", key)
+	wxUser := user_model.GetWxUserByUnionid(key.Unionid, false)
 	if wxUser != nil {
-		wxUser.Openid = encryptedData.OpenId
+		if len(wxUser.Head) > 0 {
+			wxUser.FullHead = self.GetFullImgUrl(wxUser.Head)
+		}
+		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
+		self.SetSession(apps.SessionUserKey, wxUser.UserId)
 	} else {
-		//首次授权
-		first = true
+		//注册会员
+		ip := self.Ctx.Input.IP()
+		var user *user_model.User
+		//注册会员
+		user = user_model.Create("", ip)
+
+		//注册微信会员
 		introUserId := int64(1)
 		depart := int64(0)
 		if inviteId == int64(0) {
@@ -153,47 +162,34 @@ func (self *PermitController) XcxAuthorize() {
 			}
 			depart = inviter.Depart
 		}
-		wxUser = new(user_model.WxUser).QuickCreate(encryptedData.OpenId, encryptedData.UnionId, ip, channel, time.Now().Unix(), user.Id, inviteId, introUserId, depart)
-	}
-	user.Nickname = wxUser.Nickname
-	user.Country = wxUser.Country
-	user.Province = wxUser.Province
-	user.City = wxUser.City
-	user.Sex = wxUser.Sex
-	//参数第一,cookie第二
-	cId, _ := strconv.ParseInt(self.Ctx.GetCookie("sign_up_channel"), 10, 64)
-	user.SignupChannelId = cId
-	user.Save()
-	if user != nil {
-		self.SetSession(apps.SessionUserKey, user.Id)
-	}
-	//wxUser.UserId = user.Id
-	wxUser.Nickname = info.UserInfo.NickName
-	wxUser.Sex = info.UserInfo.Gender
-	wxUser.City = info.UserInfo.City
-	wxUser.Province = info.UserInfo.Province
-	wxUser.Country = info.UserInfo.Country
-	// beego.BeeLogger.Warn("XcxAuthorize wxUser before save() Nickname:%s, Sex:%s, City:%s, Province:%s, Country:%s ", wxUser.Nickname, wxUser.Sex, wxUser.City, wxUser.Province, wxUser.Country)
-	wxUser.Save()
-	beego.BeeLogger.Warn("XcxAuthorize wxUser after save() Nickname:%s, Sex:%s, City:%s, Province:%s, Country:%s ", wxUser.Nickname, wxUser.Sex, wxUser.City, wxUser.Province, wxUser.Country)
-
-	if wxUser != nil {
+		wxUser = new(user_model.WxUser).QuickCreate(key.Openid, key.Unionid, ip, user.Id, inviteId, introUserId, depart)
 		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-	}
-	//赠送积分
-	if first {
-		//go wxUser.UploadHead(info.UserInfo.AvatarUrl)
-		wxUser.UploadHead(info.UserInfo.AvatarUrl)
-		go user.XcxPermitUploadHead(info.UserInfo.AvatarUrl)
+		self.SetSession(apps.SessionUserKey, wxUser.UserId)
+		//赠送积分
 		go helpers.SendCent(wxUser.Id, inviteId)
 	}
-	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-	if wxUser != nil && wxUser.UserId > 0 {
-		user := user_model.GetUserById(wxUser.UserId, false)
-		user.CopyWxUserHead(wxUser.Head)
-		self.SetSession(apps.SessionUserKey, wxUser.UserId)
+	//self.SetSession(apps.XcxSessionKey, key.SessionKey)
+	sessionKey := lib_redis.GetKeySessionKey(wxUser.Id)
+	lib_redis.SetRedisValue(sessionKey, key.SessionKey, time.Hour*10)
+	beego.BeeLogger.Warn("XcxLogin SessionKey=%s", key.SessionKey)
+	if self.CruSession == nil {
+		self.ReturnError(401, apps.NoExist, "", nil)
+	}
+	//更新会员token
+	var jwtUser token_model.JwtUser
+	jwtUser.Id = wxUser.Id
+	token, err := token_model.GenerateToken(&jwtUser, 0)
+	if err != nil {
+		self.ReturnError(401, apps.TokenError, "", nil)
 	}
-	self.Data["json"] = encryptedData
+
+	sId := self.CruSession.SessionID()
+	type Ret struct {
+		TokenKey   string             `json:"token"`
+		SessionKey string             `json:"session_key"`
+		WxUser     *user_model.WxUser `json:"wx_user"`
+	}
+	self.Data["json"] = &Ret{SessionKey: sId, WxUser: wxUser, TokenKey: token}
 	self.ServeJSON()
 }
 
@@ -221,124 +217,47 @@ func (self *PermitController) SaveWxuserInfo() {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
 
-	wxUId := self.GetCurrentWxUserId()
-	wxUser := user_model.GetWxUserById(wxUId, true)
+	//wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentUserIdByToken()
+
+	beego.BeeLogger.Info("SaveWxuserInfo wxUId:%d", wxUId)
 
+	wxUser := user_model.GetWxUserById(wxUId, true)
 	if wxUser == nil {
 		self.ReturnError(403, apps.WxUserInfoError, "", nil)
 	}
-	wxUser.UploadHead(info.AvatarUrl)
+	headPath := wxUser.UploadHead(info.AvatarUrl)
+
+	//更新用户信息
+	wxUser.Nickname = info.NickName
+	wxUser.Sex = info.Gender
+	wxUser.City = info.City
+	wxUser.Province = info.Province
+	wxUser.Country = info.Country
+	wxUser.Save()
+
+	user := user_model.GetUserById(wxUser.UserId, true)
+	if user != nil {
+		user.Nickname = wxUser.Nickname
+		user.Country = wxUser.Country
+		user.Province = wxUser.Province
+		user.City = wxUser.City
+		user.Sex = wxUser.Sex
+		user.Save()
+		go user.CopyWxUserHead(wxUser.Head)
+	}
+	//消除user,wxuser缓存
+	go wxUser.CleanCache()
+	headImag := tool.GetCdnFullImgUrl(headPath)
+	//beego.BeeLogger.Info("save_wx_user_info err: %v ", wxUser)
 	type Ret struct {
 		Result bool   `json:"result"`
 		Head   string `json:"head"`
 	}
-	headImag := tool.GetCdnFullImgUrl(wxUser.Head)
-	//beego.BeeLogger.Info("save_wx_user_info err: %v ", wxUser)
-
 	self.Data["json"] = &Ret{Result: true, Head: headImag}
 	self.ServeJSON()
 }
 
-//小程序登录
-func (self *PermitController) XcxLogin() {
-	code := self.GetString("code")
-
-	//beego.BeeLogger.Warn("XcxLogin code=%s", code)
-
-	if code == "" {
-		self.ReturnError(403, apps.ParamsRequired, "", nil)
-	}
-	appId := beego.AppConfig.String("WxFohowXcxAppId")
-	appSecret := beego.AppConfig.String("WxFohowXcxAppSecret")
-	key := wx_mp.GetXcxSessionKey(appId, appSecret, code)
-	if key == nil {
-		self.ReturnError(403, apps.XcxGetSessionKeyError, "", nil)
-	}
-	//beego.BeeLogger.Warn("XcxLogin key=%s", key)
-	//beego.BeeLogger.Warn("XcxLogin key=%s, key.Openid=%s", key, key.Openid)
-	//beego.BeeLogger.Warn("XcxLogin key=%s, key.Unionid=%s", key, key.Unionid)
-
-	wxUser := user_model.GetByOpenid(key.Openid, false)
-	//beego.BeeLogger.Warn("XcxLogin key=[%s], key.Openid=[%s], wxUser= [%s]", key, key.Openid, wxUser)
-
-	if wxUser != nil {
-		wxUser.FullHead = self.GetFullImgUrl(wxUser.Head)
-		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-	}
-
-	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-	if wxUser != nil && wxUser.UserId > 0 {
-		self.SetSession(apps.SessionUserKey, wxUser.UserId)
-	}
-
-	self.SetSession(apps.XcxSessionKey, key.SessionKey)
-	//beego.BeeLogger.Warn("XcxLogin SessionKey=%s", key.SessionKey)
-	if self.CruSession == nil {
-		self.ReturnError(200, apps.NoExist, "", nil)
-	}
-	//设置code对应的 redis openId unionId 值
-	openid_key := lib_redis.GetOpenIdRedisKey(code)
-	unionid_key := lib_redis.GetUnionIdRedisKey(code)
-	lib_redis.SetRedisValue(openid_key, key.Openid, time.Duration(30*60)*time.Second)
-	lib_redis.SetRedisValue(unionid_key, key.Unionid, time.Duration(30*60)*time.Second)
-
-	sId := self.CruSession.SessionID()
-	// beego.BeeLogger.Warn("XcxLogin sId=%s", sId)
-	type Ret struct {
-		SessionKey string             `json:"session_key"`
-		WxUser     *user_model.WxUser `json:"wx_user"`
-	}
-	self.Data["json"] = &Ret{SessionKey: sId, WxUser: wxUser}
-
-	self.ServeJSON()
-}
-
-//小程序登录
-func GetXcxLoginInfo(code string) (openId, unionId string) {
-	openid_key := lib_redis.GetOpenIdRedisKey(code)
-	unionid_key := lib_redis.GetUnionIdRedisKey(code)
-
-	_, openid := lib_redis.GetSimpleValue(openid_key)
-	_, unionid := lib_redis.GetSimpleValue(unionid_key)
-
-	return openid, unionid
-}
-
-//生成订单ID
-func createUnionId(prefix string) string {
-	n := time.Now().Format("20060102150405")
-	u := uuid.NewV4().String()
-	c := strings.Split(u, "-")
-	oId := strings.ToUpper(fmt.Sprintf("%s%s%s", prefix, n, c[0]))
-	beego.BeeLogger.Info("createUnionId=%s", oId)
-	return oId
-}
-
-func (self *PermitController) XcxTest() {
-	wxUser := self.GetCurrentWxUser(true)
-	self.Data["json"] = wxUser
-	self.ServeJSON()
-}
-
-// // 统一登录路径
-// // 该接口尽量不被前端调用,供服务器开发者使用
-// func (self *PermitController) Login() {
-// 	cb := self.GetString("cb")
-// 	url := ""
-// 	if self.IsWxClient() {
-// 		url = fmt.Sprintf("%s/login/mp?cb=%s", beego.AppConfig.String("ApiHost"), cb)
-// 	}
-// 	self.Redirect(url, 302)
-// 	return
-// }
-
-// // 退出登录
-// func (self *PermitController) Logout() {
-// 	self.DelSession(apps.SessionUserKey)
-// 	self.DelSession(apps.SessionWxUserKey)
-// 	self.ReturnError(200, apps.HasLogout, "", nil)
-// }
-
 //公众号静默授权回调
 func (self *PermitController) AfterWxMpAuth() {
 	// beego.BeeLogger.Warn("AfterWxMpAuth........")
@@ -386,52 +305,6 @@ func (self *PermitController) AfterWxMpAuth() {
 	self.ServeJSON()
 }
 
-// //公众号静默授权
-// func (self *PermitController) WxMpAuth() {
-// 	// beego.BeeLogger.Warn("WxMpAuth.......")
-// 	if !self.IsWxClient() {
-// 		self.ReturnError(403, apps.NotWeixinClient, "", nil)
-// 	}
-// 	_id := self.Ctx.Input.Param(":id")
-// 	cb := self.GetString("cb")
-// 	id, _ := strconv.ParseInt(_id, 10, 64)
-// 	gzh := wx_gongzhonghao_model.GetGZHById(id, true)
-// 	if gzh == nil {
-// 		self.ReturnError(403, apps.GongZhongHaoNoExist, "", nil)
-// 	}
-// 	appId := gzh.AppId
-// 	u := strings.Split(uuid.NewV4().String(), "-")[0]
-// 	state := fmt.Sprintf("AuthCb[%s]", u)
-// 	cache.Cache.Put(state, cb, 60*time.Second)
-// 	redirectURI := fmt.Sprintf("%s/auth/mp/%d/after",
-// 		beego.AppConfig.String("ApiHost"), gzh.Id)
-// 	scope := "snsapi_base"
-// 	url := wx_mp.AuthCodeURL(appId, redirectURI, scope, state)
-// 	// beego.BeeLogger.Warn("wx mp auth, redirect url: %s", url)
-// 	self.Redirect(url, 302)
-// }
-
-// //check是否授权过某个公众号
-// func (self *PermitController) CheckWxAuth() {
-// 	_gId := self.Ctx.Input.Param(":id")
-// 	gId, _ := strconv.ParseInt(_gId, 10, 64)
-// 	gzh := wx_gongzhonghao_model.GetGZHById(gId, true)
-// 	type Ret struct {
-// 		IsAuth int64 `json:"is_auth"`
-// 	}
-// 	var auth int64 = 0
-// 	wxUser := self.GetCurrentWxUser(true)
-// 	if gzh != nil {
-// 		authWxUser := user_model.GetAuthWxUserByMpIdAndUnionId(gzh.WxHao, wxUser.Unionid, false)
-// 		if authWxUser != nil {
-// 			auth = 1
-// 		}
-// 	}
-// 	// beego.BeeLogger.Warn("check auth: %v", auth)
-// 	self.Data["json"] = &Ret{IsAuth: auth}
-// 	self.ServeJSON()
-// }
-
 // 微信公众号平台登录
 func (self *PermitController) WxMpLogin() {
 	cb := self.GetString("cb")
@@ -710,250 +583,43 @@ func (self *PermitController) Logout() {
 	self.ReturnError(200, apps.HasLogout, "", nil)
 }
 
-// // 微信开放平台登录
-// func (self *PermitController) WxOpenLogin() {
-// 	cb := self.GetString("cb")
-// 	u := strings.Split(uuid.NewV4().String(), "-")[0]
-// 	state := fmt.Sprintf("loginCb[%s]", u)
-// 	cache.Cache.Put(state, cb, 60*time.Second)
-// 	appId := beego.AppConfig.String("WxOpenAppId")
-// 	redirectURI := fmt.Sprintf("%s/login/open/after",
-// 		beego.AppConfig.String("ApiHost"))
-// 	url := wx_open.AuthCodeURL(appId, redirectURI, "snsapi_login", state)
-// 	self.Redirect(url, 302)
-// 	return
-// }
-
-// //微信开放平台登录
-// func (self *PermitController) AfterWxOpenLogin() {
-// 	scope := "snsapi_login"
-// 	code := self.GetString("code")
-// 	state := self.GetString("state")
-// 	a := beego.AppConfig.String("WxOpenAppId")
-// 	s := beego.AppConfig.String("WxOpenAppSecret")
-// 	redirectURI := fmt.Sprintf("%s/after_wx_open_login",
-// 		beego.AppConfig.String("ApiHost"))
-// 	token, err := wx_open.AuthExchangeToken(code, a, s, redirectURI, scope)
-// 	if err != nil {
-// 		self.ReturnError(403, apps.NetworkBusy, "", nil)
-// 	}
-// 	openOpenid := token.OpenId
-// 	unionId := token.UnionId
-// 	// 这里不能取缓存数据,因为UserId这个字段在外部有可能已被赋值
-// 	wxUser := user_model.GetWxUserByUnionid(unionId, false)
-// 	if wxUser == nil {
-// 		info, err := wx_open.AuthUserInfo(token.AccessToken, redirectURI, scope, openOpenid, a, s)
-// 		if err == nil {
-// 			ip := self.Ctx.Input.IP()
-// 			wxUser = new(user_model.WxUser).Create("", openOpenid, token.UnionId, info.Nickname,
-// 				info.City, info.Country, info.Province, ip, int64(info.Sex), 1, time.Now().Unix())
-// 			//上传头像至alioss
-// 			go wxUser.UploadHead(info.HeadImageURL)
-// 		}
-// 	} else {
-// 		if wxUser.OpenOpenid != openOpenid {
-// 			wxUser.OpenOpenid = openOpenid
-// 			go wxUser.UpdateField("OpenOpenid")
-// 		}
-// 	}
-// 	self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-// 	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-// 	if wxUser.UserId > 0 {
-// 		self.SetSession(apps.SessionUserKey, wxUser.UserId)
-// 	}
-// 	if cbUrl, ok := cache.Cache.Get(state).(string); ok {
-// 		if cbUrl == "" {
-// 			if wxUser.UserId <= 0 {
-// 				self.Redirect(fmt.Sprintf("%s/user/binding/state", beego.AppConfig.String("WWWHost")), 302)
-// 				return
-
-// 			}
-// 			self.Redirect(beego.AppConfig.String("WWWHost"), 302)
-// 			return
-// 		}
-// 		self.Redirect(cbUrl, 302)
-// 		return
-// 	} else {
-// 		self.Redirect(beego.AppConfig.String("WWWHost"), 302)
-// 		return
-// 	}
-// 	self.ReturnError(403, apps.NetworkBusy, "", nil)
-// }
-
-// //PC端手机号码登录
-// func (self *PermitController) TelLogin() {
-// 	//防止用户先登录微信user,未绑定手机,同时又使用tel登录,默认清除wxuser的session
-// 	self.DelSession(apps.SessionWxUserKey)
-
-// 	tel := self.GetString("tel")
-// 	pwd := self.GetString("pwd")
-
-// 	user := user_model.GetByTel(tel, false)
-// 	signUpURL := fmt.Sprintf("%s/v1/signup", beego.AppConfig.String("ApiHost"))
-// 	if user == nil {
-// 		self.ReturnError(403, apps.UserNotExist, signUpURL, nil)
-// 	}
-// 	md5Ctx := md5.New()
-// 	md5Ctx.Write([]byte(pwd))
-// 	cipherStr := md5Ctx.Sum(nil)
-// 	md5Pwd := hex.EncodeToString(cipherStr)
-
-// 	if user.Pwd != md5Pwd {
-// 		self.ReturnError(403, apps.LoginPasswordError, "", nil)
-// 	}
-// 	self.SetSession(apps.SessionUserKey, user.Id)
-// 	// 找出微信用户
-// 	wxUser := user_model.GetWxUserByUserId(user.Id, false)
-// 	if wxUser != nil {
-// 		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-// 	}
-// 	// self.Data["json"] = "ok"
-// 	self.ServeJSON()
-// }
-
-// //使用key登录,key通过GenerateLoginKey生成
-// func (self *PermitController) KeyLogin() {
-// 	//不支持微信端
-// 	if self.IsWxClient() {
-// 		self.ReturnError(403, apps.NoExist, "", nil)
-// 	}
-// 	key := self.Ctx.Input.Param(":key")
-// 	uId, _ := self.GetInt64("user_id")
-
-// 	if key == "" || uId == 0 {
-// 		self.ReturnError(403, apps.ParamsRequired, "", nil)
-// 	}
-
-// 	k := cache.GetKey(cache.WapAutoLoginKey, uId)
-// 	//校验key
-// 	if s, ok := cache.Cache.Get(k).(string); ok {
-// 		// beego.BeeLogger.Warn("11111111, k:%s, s: %s, key: %s, uId: %d", k, s, key, uId)
-// 		if s == key {
-// 			// self.DelSession(apps.SessionUserKey)
-// 			self.SetSession(apps.SessionUserKey, uId)
-// 			//销毁缓存
-// 			cache.Cache.Delete(k)
-// 		} else {
-// 			self.ReturnError(403, apps.NoExist, "", nil)
-// 		}
-// 	} else {
-// 		self.ReturnError(403, apps.NoExist, "", nil)
-// 	}
-
-// 	// self.Data["json"] = "ok"
-// 	self.ServeJSON()
-// }
-
-// //PC端注册
-// func (self *PermitController) SignUp() {
-// 	code := self.GetString("code")
-// 	tel := self.GetString("tel")
-// 	k := fmt.Sprintf("%s%s", sms_model.SIGN_UP, tel)
-// 	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
-// 		if code != cacheCode {
-// 			self.ReturnError(403, apps.TelCodesError, "", nil)
-// 		}
-// 	} else {
-// 		//验证码过期
-// 		self.ReturnError(403, apps.TelCodesExpired, "", nil)
-// 	}
-
-// 	user := user_model.GetByTel(tel, false)
-// 	if user == nil {
-// 		loginPwd := tool.Get8Uuid()
-// 		md5Ctx := md5.New()
-// 		md5Ctx.Write([]byte(loginPwd))
-// 		cipherStr := md5Ctx.Sum(nil)
-// 		md5Pwd := hex.EncodeToString(cipherStr)
-// 		ip := self.Ctx.Input.IP()
-// 		user = user_model.Create(tel, md5Pwd, ip)
-// 		// 注册渠道处理
-// 		cId, _ := strconv.ParseInt(self.Ctx.GetCookie("sign_up_channel"), 10, 64)
-// 		channel := user_model.GetSignUpChannelById(cId, true)
-// 		if channel != nil {
-// 			user.SignupChannelId = cId
-// 			user.Save()
-// 			// wpsvip注册的用户,因为真功夫项目的,需要通知赠送稻米
-// 			if cId == 8 {
-// 				key1 := beego.AppConfig.String("CookieWpsVipUId")
-// 				key2 := beego.AppConfig.String("CookieWpsVipExtra")
-// 				wpsUserId, _ := strconv.ParseInt(self.Ctx.GetCookie(key1), 10, 64)
-// 				extra := self.Ctx.GetCookie(key2)
-// 				go wps.Reward(wpsUserId, extra, wps.OT_ZGF_ZHUC)
-// 				go wps_user_model.CreateWpsUser(wpsUserId, user.Id, 0, extra)
-// 			}
-// 		}
-// 		sign, template, action := sms_model.GetAliMsgContent(sms_model.LOGIN_PWD)
-// 		go sms_model.SendSmsWithAli([]string{tel}, sign, template, action, loginPwd)
-// 	} else {
-// 		self.ReturnError(403, apps.PhoneExist, "", nil)
-// 	}
-
-// 	self.SetSession(apps.SessionUserKey, user.Id)
-// 	//如果是体验金专题页面点击过来的,也送
-// 	key := beego.AppConfig.String("TYJName")
-// 	c := self.Ctx.GetCookie(key)
-
-// 	if c != "" {
-// 		id, err := strconv.ParseInt(c, 10, 64)
-// 		if err == nil {
-// 			trialInfo := trial_coin_model.GetTrialCoinById(id, true)
-// 			if trialInfo != nil && trialInfo.Deadline.Unix() >= time.Now().Unix() {
-// 				new(trial_coin_model.TrialCoinOrder).Create(user.Id, trialInfo.Id, trialInfo.Amount)
-// 			}
-// 		}
-// 	}
-
-// 	self.Data["json"] = user_model.User{Tel: tel}
-// 	self.ServeJSON()
-// }
-
-// //忘记密码
-// func (self *PermitController) ResetPwd() {
-// 	code := self.GetString("code")
-// 	tel := self.GetString("tel")
-// 	pwd := self.GetString("pwd")
-// 	confirmedPwd := self.GetString("confirmed_pwd")
-// 	if pwd != confirmedPwd {
-// 		self.ReturnError(403, apps.PasswordError, "", nil)
-// 	}
-
-// 	lengthPwd := len(pwd)
-// 	if lengthPwd < 6 || lengthPwd > 20 {
-// 		self.ReturnError(403, apps.PasswordLengthError, "", nil)
-// 	}
-
-// 	k := fmt.Sprintf("%s%s", sms_model.RESET_PWD, tel)
-// 	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
-// 		if code != cacheCode {
-// 			self.ReturnError(403, apps.TelCodesError, "", nil)
-// 		}
-// 	} else {
-// 		//验证码过期
-// 		self.ReturnError(403, apps.TelCodesExpired, "", nil)
-// 	}
-// 	md5Ctx := md5.New()
-// 	md5Ctx.Write([]byte(pwd))
-// 	cipherStr := md5Ctx.Sum(nil)
-// 	md5Pwd := hex.EncodeToString(cipherStr)
-
-// 	user := user_model.GetByTel(tel, false)
-// 	if user == nil {
-// 		self.ReturnError(403, apps.UserNotExist, "", nil)
-// 	} else {
-// 		user.Pwd = md5Pwd
-// 		user.Save()
-// 	}
-
-// 	self.Data["json"] = user_model.User{Tel: tel}
-// 	self.ServeJSON()
-// }
-
-// func createXkUser(uid, openid string) {
-// 	if uid == "" || openid == "" {
-// 		return
-// 	}
-// 	url := fmt.Sprintf("http://api.xikego.com/v1/createwxuser/superd5c/%s/%s", uid, openid)
-// 	tool.PostJSON(url, nil)
-// 	return
-// }
+//忘记密码
+func (self *PermitController) ResetPwd() {
+	code := self.GetString("code")
+	tel := self.GetString("tel")
+	pwd := self.GetString("pwd")
+	confirmedPwd := self.GetString("confirmed_pwd")
+	if pwd != confirmedPwd {
+		self.ReturnError(403, apps.PasswordError, "", nil)
+	}
+
+	lengthPwd := len(pwd)
+	if lengthPwd < 6 || lengthPwd > 20 {
+		self.ReturnError(403, apps.PasswordLengthError, "", nil)
+	}
+
+	k := fmt.Sprintf("%s%s", sms_model.RESET_PWD, tel)
+	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
+		if code != cacheCode {
+			self.ReturnError(403, apps.TelCodesError, "", nil)
+		}
+	} else {
+		//验证码过期
+		self.ReturnError(403, apps.TelCodesExpired, "", nil)
+	}
+	md5Ctx := md5.New()
+	md5Ctx.Write([]byte(pwd))
+	cipherStr := md5Ctx.Sum(nil)
+	md5Pwd := hex.EncodeToString(cipherStr)
+
+	user := user_model.GetByTel(tel, false)
+	if user == nil {
+		self.ReturnError(403, apps.UserNotExist, "", nil)
+	} else {
+		user.Pwd = md5Pwd
+		user.Save()
+	}
+
+	self.Data["json"] = user_model.User{Tel: tel}
+	self.ServeJSON()
+}

+ 9 - 3
go/gopath/src/fohow.com/apps/controllers/product_controller/product_controller.go

@@ -24,6 +24,8 @@ func (self *ProductController) Latest() {
 	perPage, _ := self.GetInt64("per_page")
 	cache, _ := self.GetBool("cache", false)
 	ptype := self.GetString("ptype")
+	price_sort, _ := self.GetInt64("price_sort")
+	sale_sort, _ := self.GetInt64("sale_sort")
 
 	if page <= 0 {
 		page = 1
@@ -42,7 +44,7 @@ func (self *ProductController) Latest() {
 		ListCount int64                    `json:"list_count"`
 	}
 
-	pds := product_model.GetLatest(page, perPage, recommend, ptype, cache)
+	pds := product_model.GetLatest(page, perPage, recommend, price_sort, sale_sort, ptype, cache)
 	count := product_model.GetLatestCount(recommend, ptype, cache)
 	for _, pd := range pds {
 		pd.SoldCount = pd.SaleNums
@@ -195,7 +197,8 @@ func (self *ProductController) Get() {
 
 	// ret.Product = pd
 	self.Data["json"] = pd
-	self.ServeJSON()
+	self.ServeResultJSON()
+	//self.ServeJSON()
 }
 
 //商品详情
@@ -308,6 +311,9 @@ func (self *ProductController) GetProductsByCat() {
 	perPage, _ := self.GetInt64("per_page")
 	words := self.GetString("words")
 	cache, _ := self.GetBool("cache", false)
+	price_sort, _ := self.GetInt64("price_sort")
+	sale_sort, _ := self.GetInt64("sale_sort")
+
 	if page <= 0 {
 		page = 1
 	}
@@ -318,7 +324,7 @@ func (self *ProductController) GetProductsByCat() {
 		List      []*product_model.Product `json:"list"`
 		ListCount int64                    `json:"list_count"`
 	}
-	list := product_model.GetProductsByCatId(catId, page, perPage, words, cache)
+	list := product_model.GetProductsByCatId(catId, page, perPage, price_sort, sale_sort, words, cache)
 	count := product_model.GetProductCountByCatId(catId, words, cache)
 	for _, pd := range list {
 		pd.SoldCount = pd.SaleNums

+ 18 - 2
go/gopath/src/fohow.com/apps/controllers/test_controller/test_controller.go

@@ -6,6 +6,7 @@ import (
 	"fohow.com/apps/models/user_model"
 	"fohow.com/libs/lib_redis"
 	"fohow.com/libs/wx_mp"
+	"github.com/astaxie/beego"
 	"math/rand"
 	"strings"
 	"time"
@@ -49,7 +50,9 @@ func (self *TestController) TestOrderListen() {
 
 //测试redis 存储userInfo
 func (self *TestController) GetUserInfoFromRedis() {
-	userId := int64(1388)
+
+	//-------测试个人------------//
+	userId := int64(1458)
 	key := fmt.Sprintf("userinfo_%d", userId)
 	var user user_model.User
 	ok, resp := lib_redis.GetRedisValue(key, user)
@@ -59,11 +62,24 @@ func (self *TestController) GetUserInfoFromRedis() {
 		lib_redis.SetJsonEx(key, resp, 90*60)
 
 	}
+	beego.BeeLogger.Warn("resp---%v", resp)
+
+	//-------测试数组------------//
+	key_ar := fmt.Sprintf("array_userinfo_a")
+	var users []user_model.User
+	ok, resp_ar := lib_redis.GetRedisValue(key_ar, users)
+	if !ok {
+		//发送请求
+		resp_ar = user_model.GetUserByIsRegistAndIsRegistBefore()
+		lib_redis.SetJsonEx(key_ar, resp_ar, 90*60)
+
+	}
+	beego.BeeLogger.Warn("resp_ar---%v", resp_ar)
 	type Ret struct {
 		Resp interface{} `json:"resp"`
 	}
 	ret := &Ret{}
-	ret.Resp = resp
+	ret.Resp = resp_ar
 	self.Data["json"] = ret
 	self.ServeJSON()
 }

+ 6 - 109
go/gopath/src/fohow.com/apps/controllers/user_controller/binding_wx_phone_controller.go

@@ -5,110 +5,10 @@ import (
 	"fohow.com/apps"
 	"fohow.com/apps/helpers"
 	"fohow.com/apps/models/user_model"
+	"fohow.com/libs/lib_redis"
 	"github.com/astaxie/beego"
 )
 
-func (self *UserController) BindingWxPhone() {
-
-	wxUser := self.GetCurrentWxUser(false)
-
-	//如果已经绑定了user,直接返回
-	if wxUser.UserId != 0 {
-		self.ReturnError(403, apps.WxUserHasBindingTel, "", nil)
-	}
-
-	var tel string
-
-	//获取参数
-	//sign := self.GetString("sign")
-	//unixTime := self.GetString("tistamp")
-	//tel := self.GetString("phonumer")
-	//beego.BeeLogger.Warn("BindingWxPhone-sign:%s, unixTime:%s, tel:%s", sign, unixTime, tel)
-	//if strings.TrimSpace(tel) == "" || strings.TrimSpace(sign) == "" || strings.TrimSpace(unixTime) == ""{
-	//	self.ReturnError(403, apps.ParamsError, "", nil)
-	//}
-	//
-	//if !self.CheckParamsIsValid(tel, sign, unixTime){
-	//	self.ReturnError(403, apps.ParamsError, "", nil)
-	//}
-
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
-	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
-	}
-
-	params := self.GetString("userinfo")
-	type Info struct {
-		Iv            string `json:"iv"`
-		EncryptedData string `json:"encryptedData"`
-	}
-	info := new(Info)
-	err := json.Unmarshal([]byte(params), &info)
-
-	if err != nil {
-		beego.BeeLogger.Error("BindingWxPhone err: %s, info:%s", err, info)
-		self.ReturnError(403, apps.ParamsError, "", nil)
-	}
-
-	type WatermarkInfo struct {
-		Appid     string `json:"appid"`
-		Timestamp string `json:"timestamp"`
-	}
-	type EncryptedData struct {
-		PhoneNumber     string         `json:"phoneNumber"`
-		PurePhoneNumber string         `json:"purePhoneNumber"`
-		CountryCode     string         `json:"countryCode"`
-		Watermark       *WatermarkInfo `json:"watermark"`
-	}
-	//phoneNumber	String	用户绑定的手机号(国外手机号会有区号)
-	//purePhoneNumber	String	没有区号的手机号
-	//countryCode	String	区
-
-	pc := helpers.WxBizDataCrypt{AppID: beego.AppConfig.String("WxFohowXcxAppId"), SessionKey: sessionKey}
-	result, err := pc.Decrypt(info.EncryptedData, info.Iv, true) //第三个参数解释: 需要返回 JSON 数据类型时 使用 true, 需要返回 map 数据类型时 使用 false
-	if err != nil {
-		beego.BeeLogger.Error("xcx BindingWxPhone descrypt failed, err:%s", err)
-		self.ReturnError(403, apps.BindingWxPhoneError, "", nil)
-	}
-	encryptedData := &EncryptedData{}
-	json.Unmarshal([]byte(result.(string)), encryptedData)
-
-	if encryptedData.PurePhoneNumber == "" {
-		self.ReturnError(403, apps.BindingWxPhoneError, "", nil)
-	}
-
-	tel = encryptedData.PurePhoneNumber
-
-	user := user_model.GetByTel(tel, false)
-	if user != nil {
-		self.ReturnError(403, apps.BindingTelExisted, "", nil)
-	} else { //手机号未被注册
-
-		ip := self.Ctx.Input.IP()
-		user = user_model.Create(tel, ip)
-		if user == nil {
-			self.ReturnError(403, apps.BindingUserTelError, "", nil)
-		}
-		wxUser.UserId = user.Id
-		wxUser.Save()
-		user.CopyWxUserHead(wxUser.Head)
-		user.Nickname = wxUser.Nickname
-		user.Country = wxUser.Country
-		user.Province = wxUser.Province
-		user.City = wxUser.City
-		user.Sex = wxUser.Sex
-		user.Save()
-		// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-		if wxUser != nil && wxUser.UserId > 0 {
-			self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-			self.SetSession(apps.SessionUserKey, wxUser.UserId)
-		}
-	}
-	self.Data["json"] = user
-	self.ServeJSON()
-
-}
-
 func (self *UserController) BindingWxPhoneNew() {
 
 	wxUser := self.GetCurrentWxUser(false)
@@ -119,11 +19,13 @@ func (self *UserController) BindingWxPhoneNew() {
 	}
 
 	var tel string
-
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
+	wxUserKey := lib_redis.GetKeySessionKey(wxUser.Id)
+	_, sessionKey := lib_redis.GetSimpleValue(wxUserKey)
+	//sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
 	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+		//self.ReturnError(403, apps.UserNeedLogin, "", nil)
 	}
+	beego.BeeLogger.Warn("XcxLogin SessionKeys=%s", sessionKey)
 
 	params := self.GetString("userinfo")
 	type Info struct {
@@ -177,11 +79,6 @@ func (self *UserController) BindingWxPhoneNew() {
 		}
 		user.Tel = tel
 		user.Save()
-		// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-		if wxUser != nil && wxUser.UserId > 0 {
-			self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-			self.SetSession(apps.SessionUserKey, wxUser.UserId)
-		}
 	}
 	self.Data["json"] = user
 	self.ServeJSON()

+ 89 - 144
go/gopath/src/fohow.com/apps/init.go

@@ -2,6 +2,7 @@ package apps
 
 import (
 	"fmt"
+	"fohow.com/apps/models/token_model"
 	"regexp"
 	"strings"
 	// "time"
@@ -14,8 +15,6 @@ import (
 	// "fohow.com/apps/models/balance_model"
 	"fohow.com/apps/models/channel_gzh_qrcode_model"
 	"fohow.com/apps/models/user_model"
-	// "fohow.com/libs/tool"
-	// "fohow.com/libs/wx_mp"
 )
 
 const (
@@ -43,6 +42,7 @@ var (
 	ShopNoRepit           = []string{"shopNoRepit", "请勿重复申请"}
 	NoCart                = []string{"noCart", "请选择您需要结算的产品"}
 	NoExist               = []string{"noExist", "该记录不存在"}
+	TokenError            = []string{"tokenError", "生成令牌出错"}
 	HasOver               = []string{"hasOver", "已结束"}
 	NoShopSale            = []string{"noShopSale", "该商品非专区商品"}
 	HasPaied              = []string{"hasPaied", "已支付"}
@@ -65,7 +65,7 @@ var (
 	// 登录相关
 	HasLogin            = []string{"hasLogin", "已登录"}
 	HasLogout           = []string{"hasLogout", "已登出"}
-	UserNeedLogin       = []string{"userNeedLogin", "需要用户登录"}
+	UserNeedLogin       = []string{"userNeedLogin", "授权无效,需要用户登录"}
 	UserAuthorizeFailed = []string{"userAuthorizeFailed", "用户授权失败"}
 	UserNeedTel         = []string{"userNeedTel", "需要用户绑定手机"}
 	UserTelNotMatch     = []string{"userTelNotMatch", "手机号码不匹配,请使用当前登录用户的号码"}
@@ -268,70 +268,27 @@ func (self *BaseController) GetCurrentWxUser(useCache bool) *user_model.WxUser {
 	return u
 }
 
-// //检查是否是邀请注册,绑定上下级关系, 发送微信通知。使用范围:注册、绑定手机、拉新专题
-// func (self *BaseController) CheckInviteBinding(user *user_model.User) {
-// 	if user == nil {
-// 		return
-// 	}
-// 	//邀请注册,绑定关系
-// 	inviteKey := beego.AppConfig.String("InviteName")
-// 	inviterId := self.Ctx.GetCookie(inviteKey)
-// 	if inviterId != "" {
-// 		id, err := strconv.ParseInt(inviterId, 10, 64)
-// 		if err == nil {
-// 			inviter := user_model.GetUserById(id, true)
-// 			if inviter != nil && user.InviteId == 0 {
-// 				//绑定关系
-// 				user.InviteId = id
-// 				go user.Save()
-// 				//增加邀请收益统计记录, 记录注册用户的ip
-// 				ip := self.Ctx.Input.IP()
-// 				new(user_model.UserInviteBenefitStat).Create(user.Id, user.InviteId,
-// 					1, 0, time.Now(), ip)
-// 				//给邀请人发邀请成功的通知
-// 				WxInviter := user_model.GetWxUserByUserId(inviter.Id, true)
-// 				if WxInviter != nil {
-// 					//给邀请人发注册成功通知
-// 					openId := WxInviter.MpOpenid
-// 					url := fmt.Sprintf("%s/v1/cfc/36", beego.AppConfig.String("ApiHost"))
-// 					title := "有人通过您的邀请,并成功注册\n"
-// 					telwStar := tool.ReplaceTelMid4(inviter.Tel)
-// 					nickName, account := telwStar, telwStar
-// 					if user.Nickname != "" {
-// 						nickName = user.Nickname
-// 					}
-// 					cTime := inviter.CreatedAt.Format("2006-01-02 15:04:05")
-// 					remark := "\n点击详情,可以看一看TA"
-// 					wx_mp.TmplmsgInviteSignUp(openId, url, title, nickName, account, cTime, remark)
-// 				}
-// 				//给新人发红包,并发通知
-// 				c := int64(user_model.BenefitNewUser)
-// 				s := balance_model.BALANCE_SOURCE_SIGN_UP_ONLINE
-// 				remark := balance_model.BALANCE_SOURCE_SIGN_UP_ONLINE_NAME
-// 				rId := ""
-// 				balance := new(balance_model.Balance).Create(user.Id, c, s, rId, remark, 1)
-// 				if balance != nil {
-// 					wxUser := user_model.GetWxUserByUserId(user.Id, true)
-// 					//发送红包的通知
-// 					if wxUser != nil {
-// 						openId := wxUser.MpOpenid
-// 						url := fmt.Sprintf("%s/v1/cfc/37", beego.AppConfig.String("ApiHost"))
-// 						first := "注册成功,返现金额已到账\n"
-// 						count := fmt.Sprintf("%0.2f 元", float64(c)/100.0)
-// 						//新用户,余额是0
-// 						leftAmount := c //balance_model.GetUserTotalBalance(user.Id)
-// 						balance := fmt.Sprintf("%0.2f 元", float64(leftAmount)/100.0)
-// 						ctime := time.Now().Format("2006-01-02 15:04:05")
-// 						remark := "\n点击立即提现>"
-// 						wx_mp.TmplmsgBalanceChange(openId, url, first, ctime, count, balance, remark)
-// 					}
-// 				}
-// 			}
-// 		}
-// 	}
-// }
-
-//检验是否需要关注
+//根据token解析userId
+func (self *BaseController) GetCurrentUserIdByToken() int64 {
+	return getCurrentUserIdByToken(self.Ctx)
+}
+
+//TODO校验是否微信客户端
+func getCurrentUserIdByToken(ctx *context.Context) int64 {
+	inputToken := ""
+	wxUserId := int64(0)
+	requestAuthordata := ctx.Request.Header.Get("Authorization")
+	if len(requestAuthordata) > 0 {
+		authorizationData := strings.SplitN(ctx.Request.Header.Get("Authorization"), " ", 2)
+		inputToken = authorizationData[1]
+	}
+	token_user, err := token_model.ValidateToken(inputToken)
+	if err == nil {
+		wxUserId = token_user.Id
+	}
+	return wxUserId
+}
+
 //sceneId, 关注场景id
 func (self *BaseController) CheckWxUserSubscribe(sceneId int64) {
 	beego.BeeLogger.Info("check wx_user subscribe")
@@ -369,79 +326,55 @@ func (self *BaseController) CheckWxUserSubscribe(sceneId int64) {
 }
 
 func checkWxUserLogin(ctx *context.Context) {
-	// TODO : 整个项目也应该更加适合采用 token 机制
-	beego.BeeLogger.Info("check wx_user login")
-	if !isWxClient(ctx) {
-		return
-	}
-	wxUserId, ok := ctx.Input.Session(SessionWxUserKey).(int64)
-	if ok {
-		_, ok := ctx.Input.Session(SessionUserKey).(int64)
-		if !ok {
-			// 如果微信用户登录了,且有绑定了user,则设置用户登录
-			wxUser := user_model.GetWxUserById(wxUserId, true)
-			beego.BeeLogger.Warn("wx_user has login, ", wxUser)
-			if wxUser != nil && int(wxUser.UserId) > 0 {
-				ctx.Output.Session(SessionUserKey, wxUser.UserId)
-			}
-		}
-	} else {
-		// beego.BeeLogger.Warn("---------------%v", ctx.Input.IsAjax())
-		// beego.BeeLogger.Warn("---------------%s", ctx.Input)
-		// if ctx.Input.IsAjax() {
-
-		beego.BeeLogger.Info("show the request : %s from UserAgent: %s", ctx.Input.URI(), ctx.Input.UserAgent())
-		uri := ctx.Input.URI()
-		//外链进来需要自动登录
-		if strings.Contains(uri, "/v1/cfc/") && isWxClient(ctx) {
-
-			// 微信用户自动登录
-			url := fmt.Sprintf("%s/login/mp?cb=%s%s",
-				beego.AppConfig.String("ApiHost"),
-				ctx.Input.Site(), ctx.Input.URI())
-			ctx.Redirect(302, url)
-			return
-
-		} else {
+	//beego.BeeLogger.Info("show the request : %s from UserAgent: %s", ctx.Input.URI(), ctx.Input.UserAgent())
+	//检测 token 是否合法
+	var inputToken string
+	beego.BeeLogger.Warn("request authorizationData : %s", ctx.Request.Header.Get("Authorization"))
+	requestAuthordata := ctx.Request.Header.Get("Authorization")
+	if len(requestAuthordata) > 0 {
+		authorizationData := strings.SplitN(ctx.Request.Header.Get("Authorization"), " ", 2)
+		if len(authorizationData) != 2 {
 			errCode := &ErrCode{
 				Code:     UserNeedLogin[0],
 				Msg:      UserNeedLogin[1],
 				Redirect: "",
 				Data:     nil,
 			}
-			ctx.Output.SetStatus(401)
+			//换成userNeedLogin
+			ctx.Output.SetStatus(403)
 			ctx.Output.JSON(errCode, true, true)
-			return
-
+		} else {
+			inputToken = authorizationData[1]
+			var wxUser *user_model.WxUser
+			user_token, err := token_model.ValidateToken(inputToken)
+			wxUser = user_model.GetWxUserById(user_token.Id, true)
+			if err != nil || wxUser == nil {
+				beego.BeeLogger.Warn("token error : %v", err)
+				// 验证 Token 无效
+				errCode := &ErrCode{
+					Code:     UserNeedLogin[0],
+					Msg:      UserNeedLogin[1],
+					Redirect: "",
+					Data:     nil,
+				}
+				ctx.Output.SetStatus(403)
+				ctx.Output.JSON(errCode, true, true)
+			} else {
+				ctx.Output.Session(SessionUserKey, wxUser.UserId)
+				ctx.Output.Session(SessionWxUserKey, wxUser.Id)
+			}
 		}
-
-		// } else {
-		// // FIXME : 这里 IsAjax 判断是否有问题? 微信来的应该属于api请求
-		// beego.BeeLogger.Debug("WEIXIN user not login", ctx.Input)
-
-		// errCode := &ErrCode{
-		// 	Code:     UserNeedLogin[0], // FIXME : 这里应该 是 WxUserNeedLogin, 因为前端编码用了UserNeedLogin,以后一起修改
-		// 	Msg:      UserNeedLogin[1],
-		// 	Redirect: "",
-		// 	Data:     nil,
-		// }
-		// ctx.Output.SetStatus(401)
-		// ctx.Output.JSON(errCode, true, true)
-		// return
-
-		// beego.BeeLogger.Warn("this is not a ajax request!")
-		// 微信用户自动登录
-		// if isWxClient(ctx) {
-		// 	// beego.BeeLogger.Warn("---------------%s", ctx.Input.Site())
-		// 	url := fmt.Sprintf("%s/login/mp?cb=%s%s",
-		// 		beego.AppConfig.String("ApiHost"),
-		// 		ctx.Input.Site(), ctx.Input.URI())
-		// 	// beego.BeeLogger.Warn("auto login mp cb url=%s", url)
-		// 	ctx.Redirect(302, url)
-		// 	return
-		// }
-		// }
+	} else {
+		errCode := &ErrCode{
+			Code:     UserNeedLogin[0],
+			Msg:      UserNeedLogin[1],
+			Redirect: "",
+			Data:     nil,
+		}
+		ctx.Output.SetStatus(401)
+		ctx.Output.JSON(errCode, true, true)
 	}
+	return
 }
 
 func checkUserLogin(ctx *context.Context) {
@@ -502,9 +435,9 @@ func CheckIsInvokeFromRailsAdmin(ctx *context.Context) {
 }
 
 func (self *BaseController) Prepare() {
-	beego.BeeLogger.Info("invote controller Prepare func")
+	//beego.BeeLogger.Info("invote controller Prepare func")
 	needChkWxUserLogin := true
-	needChkUserLogin := true
+	//needChkUserLogin := true
 	// needChkWxUserSubscribe := false
 	_, actionName := self.GetControllerAndAction()
 
@@ -516,21 +449,10 @@ func (self *BaseController) Prepare() {
 			}
 		}
 	}
-	if len(self.ExceptCheckUserLoginAction) > 0 {
-		for _, an := range self.ExceptCheckUserLoginAction {
-			if strings.ToLower(an) == "*" || strings.ToLower(an) == strings.ToLower(actionName) {
-				needChkUserLogin = false
-				break
-			}
-		}
-	}
 
 	if needChkWxUserLogin {
 		checkWxUserLogin(self.Ctx)
 	}
-	if needChkUserLogin {
-		checkUserLogin(self.Ctx)
-	}
 
 }
 
@@ -630,3 +552,26 @@ func (self *BaseController) GetCdnFullImgUrl(img string) string {
 		return fmt.Sprintf("%s/%s", beego.AppConfig.String("AliCDNImgHost"), img)
 	}
 }
+
+// ServeJSON sends a json response with encoding charset.
+func (c *BaseController) ServeResultJSON(encoding ...bool) {
+	from := c.GetString("source")
+	beego.BeeLogger.Warn("from--%s", from)
+	type Result struct {
+		Result interface{} `json:"result"`
+	}
+	var (
+		hasIndent   = true
+		hasEncoding = false
+	)
+	if beego.AppConfig.String("RunMode") == "prod" {
+		hasIndent = false
+	}
+	if len(encoding) > 0 && encoding[0] == true {
+		hasEncoding = true
+	}
+	if from == beego.AppConfig.String("SourceList") {
+		c.Data["json"] = &Result{Result: c.Data["json"]}
+	}
+	c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
+}

+ 2 - 0
go/gopath/src/fohow.com/apps/models/order_model/order.go

@@ -36,6 +36,8 @@ const (
 	PAY_WAY_INTEGRAl = "integral"  //提货券支付
 	PAY_WAY_CENT     = "cent"      //积分支付
 
+	SOURCE_APP = "app"
+
 	SOURCE_XCX     = "xcx"
 	SOURCE_GZH     = "gzh"
 	SOURCE_D5C_SYS = "d5c_sys"

+ 72 - 18
go/gopath/src/fohow.com/apps/models/product_model/product.go

@@ -122,19 +122,45 @@ type Product struct {
 }
 
 //获取最新推荐商品
-func GetLatest(page, perPage, recommend int64, ptype string, useCache bool) (products []*Product) {
+func GetLatest(page, perPage, recommend, priceSort, saleSort int64, ptype string, useCache bool) (products []*Product) {
 	k := fmt.Sprintf("product_model.GetLatest.page(%d).perPage(%d).recommend(%d)", page, perPage, recommend)
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).([]*Product); ok {
 			return ret
 		}
 	}
-	o := orm.NewOrm()
-	_, err := o.QueryTable(new(Product)).Filter("status", 1).
-		Filter("recommend__gt", recommend).Filter("show_flag", true).Filter("ptype", ptype).
-		OrderBy("-recommend", "-created_at").
-		Limit(perPage, (page-1)*perPage).
-		All(&products)
+	var priceSql, saleSql, orderSql string
+	if priceSort == int64(1) {
+		//降序
+		priceSql = "price desc"
+	} else if priceSort == int64(2) {
+		//升序
+		priceSql = "price asc"
+	}
+	if saleSort == int64(1) {
+		//降序
+		saleSql = "sale_nums desc"
+	} else if priceSort == int64(2) {
+		saleSql = "sale_nums asc"
+	}
+	if len(priceSql) <= 0 && len(saleSql) <= 0 {
+		orderSql = "recommend desc,created_at desc"
+	} else if len(priceSql) <= 0 {
+		orderSql = saleSql
+	} else if len(saleSql) <= 0 {
+		orderSql = priceSql
+	} else {
+		orderSql = fmt.Sprintf("%s,%s", priceSql, saleSql)
+	}
+	sql := `
+		select * from products
+		where status = ? and recommend > ? and show_flag=? and ptype=?
+		order by %s limit %d, %d; 
+	`
+	sql = fmt.Sprintf(sql, orderSql, (page-1)*perPage, perPage)
+	//beego.BeeLogger.Warn("sql=%s", sql)
+	_, err := orm.NewOrm().Raw(sql, 1, recommend, true, ptype).QueryRows(&products)
+
 	if err != nil {
 		beego.BeeLogger.Debug("GetLatest err=%s", err)
 	}
@@ -183,32 +209,60 @@ func GetProductById(id int64, useCache bool) *Product {
 	return item
 }
 
-func GetProductsByCatId(cId, page, perPage int64, words string, useCache bool) (products []*Product) {
+func GetProductsByCatId(cId, page, perPage, priceSort, saleSort int64, words string, useCache bool) (products []*Product) {
 	k := fmt.Sprintf("product_model.GetProductsByCatId(%d).page(%d).perPage(%d).words(%d)", cId, page, perPage, words)
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).([]*Product); ok {
 			return ret
 		}
 	}
-	o := orm.NewOrm()
-	qs := o.QueryTable(new(Product)).Filter("status", 1).Filter("show_flag", true).Filter("ptype", TYPE_DIRECT_SALE)
+	var priceSql, saleSql, orderSql string
+	if priceSort == int64(1) {
+		//降序
+		priceSql = "price desc"
+	} else if priceSort == int64(2) {
+		//升序
+		priceSql = "price asc"
+	}
+	if saleSort == int64(1) {
+		//降序
+		saleSql = "sale_nums desc"
+	} else if priceSort == int64(2) {
+		saleSql = "sale_nums asc"
+	}
+	if len(priceSql) <= 0 && len(saleSql) <= 0 {
+		orderSql = "recommend desc,created_at desc"
+	} else if len(priceSql) <= 0 {
+		orderSql = saleSql
+	} else if len(saleSql) <= 0 {
+		orderSql = priceSql
+	} else {
+		orderSql = fmt.Sprintf("%s,%s", priceSql, saleSql)
+	}
+
+	var cidSql string
 	if cId != 0 {
-		qs = qs.Filter("category_id", cId)
+		cidSql = fmt.Sprintf("and category_id=%d", cId)
 	}
+
 	if len(words) > 0 {
-		qs = qs.Filter("key_words__icontains", words)
+		cidSql = cidSql + fmt.Sprintf(" and key_words like '%s'", "%"+words+"%")
 	}
-	_, err := qs.
-		OrderBy("-recommend", "-created_at").
-		Limit(perPage, (page-1)*perPage).
-		All(&products)
+
+	sql := `
+		select * from products
+		where status = ? and show_flag=? and ptype=? %s
+		order by %s limit %d, %d ; 
+		`
+	sql = fmt.Sprintf(sql, cidSql, orderSql, (page-1)*perPage, perPage)
+	//beego.BeeLogger.Warn("cate sql=%s", sql)
+	_, err := orm.NewOrm().Raw(sql, 1, true, TYPE_DIRECT_SALE).QueryRows(&products)
+
 	if err != nil {
 		beego.BeeLogger.Debug("GetProductsByCatId err=%s", err)
 	}
 	for _, pd := range products {
 		pd.Cover = GetCoverByPId(pd.Id, useCache)
-		//TODO: 订单相关
-		// pd.SaleCount = pd.GetSaleCount()
 	}
 	cache.Cache.Put(k, products, 10*time.Minute)
 	return products

+ 1 - 1
go/gopath/src/fohow.com/apps/models/promotion_model/order_promotion.go

@@ -65,7 +65,7 @@ func GetEffetivePromotions(queryDate time.Time, orderType, depart int64, useCach
 	sql := `
 		select a.* from
 		promotions a left join depart_records_promotions b on a.id=b.promotion_id
-		where DATE_ADD(a.begin_time,INTERVAL 8 HOUR) <= ? and DATE_ADD(a.end_time,INTERVAL 8 HOUR) >= ? and a.order_type = ? and b.depart_record_id=?  and a.is_enable = 1 ;
+		where DATE_ADD(a.begin_time,INTERVAL 8 HOUR) <= ? and DATE_ADD(a.end_time,INTERVAL 8 HOUR) >= ? and a.order_type = ? and (b.depart_record_id=?)  and a.is_enable = 1 ;
 		`
 
 	_, err := orm.NewOrm().Raw(sql, queryDate.Format("2006-01-02 15:04:05"), queryDate.Format("2006-01-02 15:04:05"), orderType, depart).QueryRows(&list)

+ 14 - 0
go/gopath/src/fohow.com/apps/models/token_model/init.go

@@ -0,0 +1,14 @@
+package token_model
+
+import (
+	"github.com/astaxie/beego"
+)
+
+var KEY string
+var DEFAULT_EXPIRE_SECONDS int
+
+func init() {
+	KEY = beego.AppConfig.String("TokenSecrets")
+	tokenexp, _ := beego.AppConfig.Int("Tokenexp")
+	DEFAULT_EXPIRE_SECONDS = tokenexp
+}

+ 107 - 0
go/gopath/src/fohow.com/apps/models/token_model/token.go

@@ -0,0 +1,107 @@
+package token_model
+
+import (
+	"fmt"
+	"github.com/astaxie/beego"
+	"github.com/dgrijalva/jwt-go"
+	"time"
+)
+
+type JwtUser struct {
+	Id int64 `json:"id"`
+}
+
+// JWT -- json web token
+// HEADER PAYLOAD SIGNATURE
+// This struct is the PAYLOAD
+type MyCustomClaims struct {
+	JwtUser
+	jwt.StandardClaims
+}
+
+//刷新jwt token
+func RefreshToken(tokenString string) (string, error) {
+	// first get previous token
+	token, err := jwt.ParseWithClaims(
+		tokenString,
+		&MyCustomClaims{},
+		func(token *jwt.Token) (interface{}, error) {
+			return []byte(KEY), nil
+		})
+	claims, ok := token.Claims.(*MyCustomClaims)
+	if !ok || !token.Valid {
+		return "", err
+	}
+	mySigningKey := []byte(KEY)
+	expireAt := time.Now().Add(time.Second * time.Duration(DEFAULT_EXPIRE_SECONDS)).Unix()
+	newClaims := MyCustomClaims{
+		claims.JwtUser,
+		jwt.StandardClaims{
+			ExpiresAt: expireAt,
+			Issuer:    "",
+			IssuedAt:  time.Now().Unix(),
+		},
+	}
+	// generate new token with new claims
+	newToken := jwt.NewWithClaims(jwt.SigningMethodHS256, newClaims)
+	tokenStr, err := newToken.SignedString(mySigningKey)
+	if err != nil {
+		beego.BeeLogger.Error("generate new fresh json web token failed !! error :%v", err)
+		return "", err
+	}
+	return tokenStr, err
+}
+
+//验证jtw token
+func ValidateToken(tokenString string) (info JwtUser, err error) {
+	token, err := jwt.ParseWithClaims(
+		tokenString,
+		&MyCustomClaims{},
+		func(token *jwt.Token) (interface{}, error) {
+			return []byte(KEY), nil
+		})
+	if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
+		//fmt.Printf("%v %v", claims.User, claims.StandardClaims.ExpiresAt)
+		//fmt.Println("token will be expired at ", time.Unix(claims.StandardClaims.ExpiresAt, 0))
+		info = claims.JwtUser
+	} else {
+		beego.BeeLogger.Error("validate tokenString failed !!!:%v", err)
+	}
+	return info, err
+}
+
+//获取jwt token
+func GenerateToken(info *JwtUser, expiredSeconds int) (tokenString string, err error) {
+	if expiredSeconds == 0 {
+		expiredSeconds = DEFAULT_EXPIRE_SECONDS
+	}
+	// Create the Claims
+	mySigningKey := []byte(KEY)
+	expireAt := time.Now().Add(time.Second * time.Duration(expiredSeconds)).Unix()
+	beego.BeeLogger.Warn("token will be expired at %v ", time.Unix(expireAt, 0))
+
+	// pass parameter to this func or not
+	user := *info
+	claims := MyCustomClaims{
+		user,
+		jwt.StandardClaims{
+			ExpiresAt: expireAt,
+			Issuer:    "",
+			IssuedAt:  time.Now().Unix(),
+		},
+	}
+	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+	tokenStr, err := token.SignedString(mySigningKey)
+	if err != nil {
+		beego.BeeLogger.Error("generate json web token failed !! error : %v", err)
+	} else {
+		tokenString = tokenStr
+	}
+	return
+}
+
+// return this result to client then all later request should have header "Authorization: Bearer <token> "
+func getHeaderTokenValue(tokenString string) string {
+	//Authorization: Bearer <token>
+	return fmt.Sprintf("Bearer %s", tokenString)
+}

+ 3 - 2
go/gopath/src/fohow.com/apps/models/user_model/user.go

@@ -30,6 +30,7 @@ type User struct {
 
 	Tel         string    `orm:"column(tel);null"                               json:"tel"`
 	TradePwd    string    `orm:"column(trade_pwd)"                              json:"-"`        // varchar(255)
+	Pwd         string    `orm:"column(pwd)"                                    json:"-"`        // varchar(255)
 	HasTradePwd int64     `orm:"-"                  json:"has_trade_pwd"`                        // tinyint(1)
 	Nickname    string    `orm:"column(nickname);null"                          json:"nickname"` // varchar(100)
 	Country     string    `orm:"column(country);null"                           json:"-"`        // varchar(20)
@@ -262,11 +263,11 @@ func GetUserByIsRegistAndIsRegistBefore() (list []*User) {
 
 	usr := new(User)
 	o := orm.NewOrm()
-	count, _ := o.QueryTable(usr).Filter("is_regist_d5c", 0).Filter("is_regist_before_d5c", 0).Count()
+	count, _ := o.QueryTable(usr).Count()
 	if count <= 0 {
 		return nil
 	}
-	_, err := o.QueryTable(usr).Filter("is_regist_d5c", 0).Filter("is_regist_before_d5c", 0).Limit(count).All(&list)
+	_, err := o.QueryTable(usr).Limit(count).All(&list)
 	if err != nil {
 		beego.Debug("GetUserByIsRegistAndIsRegistBefore err=[%s]", err)
 		return nil

+ 9 - 10
go/gopath/src/fohow.com/apps/models/user_model/wx_user.go

@@ -75,17 +75,16 @@ func (self *WxUser) TableName() string {
 	return wx_users_tablename
 }
 
-func (self *WxUser) QuickCreate(openid, unionid, ip string, channel, lastConversationAt, userId, inviteId, introUserId, depart int64) *WxUser {
+func (self *WxUser) QuickCreate(openid, unionid, ip string, userId, inviteId, introUserId, depart int64) *WxUser {
 	item := &WxUser{
-		UserId:             userId,
-		Openid:             openid,
-		Unionid:            unionid,
-		SignupIp:           ip,
-		ChannelQrcodeId:    channel,
-		IntroUserId:        introUserId,
-		InviteId:           inviteId,
-		Depart:             depart,
-		LastConversationAt: lastConversationAt}
+		UserId:      userId,
+		Openid:      openid,
+		Unionid:     unionid,
+		SignupIp:    ip,
+		IntroUserId: introUserId,
+		InviteId:    inviteId,
+		Depart:      depart,
+	}
 	id, err := orm.NewOrm().Insert(item)
 	if err != nil {
 		beego.BeeLogger.Error("QuickCreate WxUser err=[%s]", err)

+ 23 - 5
go/gopath/src/fohow.com/conf/app.conf

@@ -38,11 +38,18 @@ AliOssAccessSecret = "3QFdigF8Ngm5Z1X1U3WkTHYoAHyajh"
 AliOssEndPoint = "oss-cn-shenzhen.aliyuncs.com"
 AliCDNImgHost = "https://tcfohow.hiwavo.com"
 
+#------------------------------------------------------------小程序appid
 WxFohowXcxAppId = "wx84f6c33a9fa3977d"
 WxFohowXcxAppSecret = "da2882779e983e2acfb573d01cb1fb7d"
+
+#------------------------------------------------------------Androd App appid
+WxFohowAndroAppAppId = "wxcd02795bd58d9bb4"
+WxFohowAndroAppSecret = "da2882779e983e2acfb573d01cb1fb7d"
+
+
 #------------------------------------------------------------
 JsSDKConfigTicketAppId = "wxbddd1caf692557c4"
-JsSDKConfigTicketAppSecret = "be6cb03f9a8c13a557728616a9e6039c"
+JsSDKConfigTicketAppSecret = "315e368b472ac4aa6d4fc500d184f5eb"
 
 #凤凰菁选测试公众号
 WxMPAppId = "wxbddd1caf692557c4"
@@ -126,8 +133,11 @@ OuBiaoMchCertFile= "/opt/wxpay/oubiao/apiclient_cert.pem"
 OuBiaoMchKeyFile = "/opt/wxpay/oubiao/apiclient_key.pem"
 
 #JWT TOKEN
-Tokenexp = "3600"
-TokenSecrets = "todayisagoodday20210425"
+Tokenexp = 600
+TokenSecrets = "gt69m8b144lr5a6ifjdavheeln4qmmzhqhyy9tudcemazz3es7relb945zep54g4"
+
+#http source
+SourceList = "app"
 
 #######################################################################
 [prod]
@@ -160,6 +170,11 @@ AliCDNImgHost = "https://cfohow.hiwavo.com"
 
 WxFohowXcxAppId = "wx84f6c33a9fa3977d"
 WxFohowXcxAppSecret = "da2882779e983e2acfb573d01cb1fb7d"
+
+#------------------------------------------------------------Androd App appid
+WxFohowAndroAppAppId = "wxcd02795bd58d9bb4"
+WxFohowAndroAppSecret = "315e368b472ac4aa6d4fc500d184f5eb"
+
 #------------------------------------------------------------
 JsSDKConfigTicketAppId = "wx2479f58240be58aa"
 JsSDKConfigTicketAppSecret = "d9243f828f3c9dac198a539981a578b8"
@@ -251,5 +266,8 @@ OuBiaoMchCertFile= "/opt/wxpay/oubiao/apiclient_cert.pem"
 OuBiaoMchKeyFile = "/opt/wxpay/oubiao/apiclient_key.pem"
 
 #JWT TOKEN
-Tokenexp = "3600"
-TokenSecrets = "todayisagoodday20210425"
+Tokenexp = 2592000
+TokenSecrets = "gt69m8b144lr5a6ifjdavheeln4qmmzhqhyy9tudcemazz3es7relb945zep54g4"
+
+#http source
+SourceList = "app"

BIN
go/gopath/src/fohow.com/fohowmall.com


+ 5 - 0
go/gopath/src/fohow.com/libs/lib_redis/redis.go

@@ -193,3 +193,8 @@ func GetOpenIdRedisKey(code string) string {
 func GetUnionIdRedisKey(code string) string {
 	return fmt.Sprintf("user:unionid%s", code)
 }
+
+//小程序sessionkey
+func GetKeySessionKey(Id int64) string {
+	return fmt.Sprintf("wx_user:session:key%d", Id)
+}

+ 0 - 34
go/gopath/src/fohow.com/libs/tool/token.go

@@ -1,34 +0,0 @@
-package tool
-
-import (
-	"fmt"
-	"github.com/astaxie/beego"
-	"github.com/dgrijalva/jwt-go"
-	"strconv"
-	"time"
-)
-
-func CreateToken(Phone string) string {
-	token := jwt.New(jwt.SigningMethodHS256)
-	claims := make(jwt.MapClaims)
-	tokenexp, _ := strconv.Atoi(beego.AppConfig.String("Tokenexp"))
-	claims["exp"] = time.Now().Add(time.Hour * time.Duration(tokenexp)).Unix()
-	claims["iat"] = time.Now().Unix()
-	claims["phone"] = Phone
-	token.Claims = claims
-	tokenString, _ := token.SignedString([]byte(beego.AppConfig.String("TokenSecrets")))
-	return tokenString
-}
-
-func CheckToken(tokenString string) string {
-	Phone := ""
-	token, _ := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
-		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
-			return nil, fmt.Errorf("Unexpected signing method")
-		}
-		return []byte(beego.AppConfig.String("TokenSecrets")), nil
-	})
-	claims, _ := token.Claims.(jwt.MapClaims)
-	Phone = claims["phone"].(string)
-	return Phone
-}

+ 83 - 3
go/gopath/src/fohow.com/libs/wx_mp/pay.go

@@ -4,6 +4,8 @@ import (
 	// "encoding/json"
 	"encoding/xml"
 	"fmt"
+	"fohow.com/apps/models/order_model"
+
 	// "io/ioutil"
 	// "net/http"
 	"reflect"
@@ -51,12 +53,20 @@ const (
 )
 
 //小程序端微信支付client
-func getMchProxyInitClient(payCode string) *mch.Proxy {
+func getMchProxyInitClient(payCode, source string) *mch.Proxy {
 	mechant := GetMechantInfo(payCode)
-	appId := beego.AppConfig.String("WxFohowXcxAppId") //获取小程序渠道appId
+	appId := ""
+	switch source {
+	case order_model.SOURCE_APP:
+		appId = beego.AppConfig.String("WxFohowAndroAppAppId") //获取小程序渠道appId
+	default:
+		appId = beego.AppConfig.String("WxFohowXcxAppId") //获取小程序渠道appId
+	}
+
 	mchProxy := mch.NewProxy(appId, mechant.MchId, mechant.ApiKey, nil)
 	return mchProxy
 }
+
 func getMchTLSProxyInitClient(payCode string) *mch.Proxy {
 	appId := beego.AppConfig.String("WxFohowXcxAppId") //获取小程序渠道appId
 	mechant := GetMechantInfo(payCode)
@@ -119,6 +129,11 @@ func GetMechantInfo(mechantCode string) (ret MechantPayInfo) {
 		ret.ApiKey = apiKey
 		ret.MchKeyFile = beego.AppConfig.String("WxMchKeyFile")
 		ret.MchCertFile = beego.AppConfig.String("MchCertFile")
+	case "app":
+		ret.MchId = mchId
+		ret.ApiKey = apiKey
+		ret.MchKeyFile = beego.AppConfig.String("WxMchKeyFile")
+		ret.MchCertFile = beego.AppConfig.String("MchCertFile")
 	case "lehu":
 		ret.MchId = lehuMchId
 		ret.ApiKey = lehuApiKey
@@ -139,6 +154,71 @@ func GetMechantInfo(mechantCode string) (ret MechantPayInfo) {
 
 }
 
+// 获取APP微信支付需要的数据
+func GetAppPayData(outTradeNo string, totalPrice int64, body, notifyUrl, remoteIp, payCode string) (ret map[string]string) {
+	appId := beego.AppConfig.String("WxFohowAndroAppAppId") //获取App appId
+	mechantInfo := GetMechantInfo(payCode)
+	outTradeNo = fmt.Sprintf("%s_%d", outTradeNo, time.Now().Unix())
+
+	prepayId := getAppPayPrepayId(outTradeNo, totalPrice, body, notifyUrl, remoteIp, payCode, true)
+	u := uuid.NewV4().String()
+	us := strings.Split(u, "-")
+	nonce_str := strings.Join(us, "")
+	ret = map[string]string{
+		"appid":     appId,
+		"partnerid": mechantInfo.MchId,
+		"prepayid":  prepayId,
+		"package":   "Sign=WXPay",
+		"timestamp": fmt.Sprintf("%d", time.Now().Unix()),
+		"noncestr":  nonce_str}
+	ret["pasignySign"] = mch.Sign(ret, mechantInfo.ApiKey, nil)
+
+	beego.BeeLogger.Warn("ret--%v", ret)
+	return ret
+
+}
+
+// 获取支付预授权码
+//  [pay.go:76] [E] GetPrepayId err[return_code: "FAIL", return_msg: "不识别的参数wxappid"]
+// 2016/07/07 11:07:02 [pay_controller.go:303] [W] 生成微信支付订单号:DS20160707503D648C,传的参数:openid=o7lR2txmVPh1pSPjIvto2LO_XVYU,
+// 价格:9.90, 名称:希客购, 客户端IP=119.132.31.240;生成的参数:%!v(MISSING)
+func getAppPayPrepayId(outTradeNo string, totalPrice int64, body, notifyUrl, remoteIp, payCode string, limit bool) (prepayId string) {
+	appId := beego.AppConfig.String("WxFohowAndroAppAppId") //获取App渠道appId
+	mechantInfo := GetMechantInfo(payCode)                  //商户号配置信息
+	mchProxy := getMchProxyInitClient(payCode, order_model.SOURCE_APP)
+	u := uuid.NewV4().String()
+	us := strings.Split(u, "-")
+	nonce_str := strings.Join(us, "")
+	req := map[string]string{
+		"mch_id":           mechantInfo.MchId,
+		"appid":            appId,
+		"nonce_str":        nonce_str, //fmt.Sprintf("%d", time.Now().Unix()),
+		"body":             body,
+		"out_trade_no":     outTradeNo,
+		"total_fee":        fmt.Sprintf("%d", totalPrice), //分为单位
+		"spbill_create_ip": remoteIp,
+		"notify_url":       notifyUrl,
+		// "product_id":       outTradeNo,
+		"trade_type": "APP",
+	}
+
+	//beego.BeeLogger.Warn("mechantInfo err[%s]", mechantInfo.MchId)
+
+	if limit {
+		req["limit_pay"] = "no_credit"
+	}
+	sign := mch.Sign(req, mechantInfo.ApiKey, nil)
+	req["sign"] = sign
+	beego.BeeLogger.Warn("%v", req)
+	ret, err := pay.UnifiedOrder(mchProxy, req)
+	if err != nil {
+		beego.BeeLogger.Error("getAppPayPrepayId err[%s]", err)
+		//fmt.Println(err)
+		return ""
+	}
+	return ret["prepay_id"]
+}
+
 // 获取jsSDK微信支付需要的数据
 func GetPayData(openid, outTradeNo string, totalPrice int64, body, notifyUrl, remoteIp, payCode string) (ret map[string]string) {
 	appId := beego.AppConfig.String("WxFohowXcxAppId") //获取小程序渠道appId
@@ -165,7 +245,7 @@ func GetPayData(openid, outTradeNo string, totalPrice int64, body, notifyUrl, re
 func getPayPrepayId(openid, outTradeNo string, totalPrice int64, body, notifyUrl, remoteIp, payCode string, limit bool) (prepayId string) {
 	appId := beego.AppConfig.String("WxFohowXcxAppId") //获取小程序渠道appId
 	mechantInfo := GetMechantInfo(payCode)             //商户号配置信息
-	mchProxy := getMchProxyInitClient(payCode)
+	mchProxy := getMchProxyInitClient(payCode, order_model.SOURCE_XCX)
 
 	outTradeNo = fmt.Sprintf("%s_%d", outTradeNo, time.Now().Unix())
 	u := uuid.NewV4().String()

+ 5 - 0
go/gopath/src/fohow.com/nginx/ngx_prod_config

@@ -14,6 +14,11 @@ server {
       #expires  30d;
     }
 
+    location =/apple-app-site-association {
+          root /home/www/fohow/api/go/gopath/src/fohow.com/static/api/;
+          #expires  30d;
+        }
+
     location =/stcXSY70Qh.txt {
       root /home/www/fohow/api/go/gopath/src/fohow.com/static/api/;
     }

+ 2 - 2
go/gopath/src/fohow.com/nginx/ngx_test_config

@@ -54,8 +54,8 @@ server {
     server_name  tfohowapi.hiwavo.com;
     charset utf-8;
     #ssl on;
-    ssl_certificate      /home/rails/fohow/api/go/gopath/src/fohow.com/static/tapi/5539910_tfohowapi.hiwavo.com.pem;
-    ssl_certificate_key  /home/rails/fohow/api/go/gopath/src/fohow.com/static/tapi/5539910_tfohowapi.hiwavo.com.key;
+    ssl_certificate      /home/rails/fohow/api/go/gopath/src/fohow.com/static/tapi/5754763_tfohowapi.hiwavo.com.pem;
+    ssl_certificate_key  /home/rails/fohow/api/go/gopath/src/fohow.com/static/tapi/5754763_tfohowapi.hiwavo.com.key;
 
     ssl_session_cache    shared:SSL:1m;
     ssl_session_timeout  5m;

+ 4 - 0
go/gopath/src/fohow.com/routers/routes.go

@@ -360,6 +360,10 @@ func init() {
 	//获取当前用户申请店铺金额
 	beego.Router("/v1/sys_config/apply_total", &sys_controller.SysController{}, "get:GetCurApplyInfo")
 
+	//----------------app接口相关-------------------
+	//重置密码
+	beego.Router("/v1/pwd/reset", &permit_controller.PermitController{}, "post:ResetPwd")
+
 	// ----------- 提货地址相关 -----------
 	beego.Router("/v1/pick_address", &pick_address_controller.PickAddressController{}, "get:List")
 	beego.Router("/v1/pick_address", &pick_address_controller.PickAddressController{}, "post:CreatePickAddress")

+ 0 - 27
go/gopath/src/fohow.com/static/tapi/5539910_tfohowapi.hiwavo.com.key

@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA2KwZ0kikIGG9HYnVcyBEeUai1k/JDinrCgJ4R+KG63HpJdKv
-QFdlA7kclrBeXbJriYGjFjx0KgfPl6Q42KqBQ9e58yvyopWQB6SPjR0QFRgLtTpm
-PpKCfMeBZXR69SdDDFKtcne3ySAXLGvKatUDqyOk9PZxgyWlf6khmom+45Zu0RRv
-KKhIwbbsHtkenrBywUBFNBeadYtWSnAlfma4W3nVfOgxNI5fTnag2Rs78echjVZh
-8VHi/ri9HVh9n/I7Q9mSCJ+TXxjwflFOi2QUZYoNS46Rkg7J9GH0nR6zutYKy212
-RfxrtkeORmFDlLEiYDtNZDQTj5aCorkyC5KzLQIDAQABAoIBAAi+xYSzHDYXC9Aw
-kIDG5CH1o7vnriiYBjMPZMsYowkcvg7MlqM6WSA8gqFjDqP/KrpQP69gPZthWP54
-s+IBhm8hEBHMYSIxIYZAHO/SpPlc+5f9z+5QRoZXx8AQYqgYxMAvaW3DKZQAwL6x
-E73vyWfzwS7b8DqdXzUsXpKuDZos6gHf8e6LaqHh0U5SWFjSGlmQ0Mv4cW7CXuVs
-kIfqPDlwPGVlz6xrojdgMD5/5yHLtBf5Cq62x3eHnM3lngmjxDPzp5hzo5DiCAn1
-JN1lA1QGIV1pLtnItj/Zxwd+Dx48KQpMR1mqS+bCvPFlejkG9v+PVJuoUK9gj/Hs
-Q8kxkEcCgYEA9KxNj9D9NTajVigcwudjxx0ivEGU1QPSIshNJlts2a8tAttO3sIH
-Qg6h4BN8lc/jWh+42uxdMjZiwTPh+ikEUrDk0JvHE+Cxol2S2frlSWX5BiTJkHbP
-XKsj0LZjHx8CzP5Y2qgo/aKlX4ustL+CvygkRP73iHRUBxeHXAPqrNMCgYEA4rPz
-puuo9lnqvhDV8Lm5TlQcRiQm64YZPZfmYl7judTSltMAVnk9jEmluOofuZlHtp6n
-WgpITq6VqldllVPyMrwqfw5NCTGhlzK2Fbtt3frUCvyFM2cytpMyR7dVh/du2oZR
-wjicnRcap3+EBvgJRRX1kBUkYTK4mqC1PlSxH/8CgYB+5KGxNb0sjPK3K0SHXMQl
-rxmlswmCVGH2QhWpD/9rAmwAsEa+RrjG7JnNga26cL/DrPINMErBUO10r/jB6eXh
-EPcKrc/Yok7eG1OfE304zNcS9Z9H+iZfNC71/rF3oXitYjgo5s+jg2frHqBqeWxQ
-wXvWALnWHia6Kty7vxhFmwKBgDP4bPLnM2TGWDoaQfFdok2Cmri5sPJtW3vzRq1m
-c242i9BnrrwkLyfp+kPZ6Ev0B6yl0leh49Gl1Emon3EMPYnD+ToHXUGuTw0KYxO4
-VAd/aPzbxu1xyv5v4CbwsHrrDk6qXDPaJo0crs+XO/0c/4MG9bSCJETkC83m6aXQ
-ZIqhAoGBAIm5piFVyV7Z0zjqJB/mv+JKe354gSrFfO6D+Rcf4bywomTj09OiF91K
-eog80vt8EPbZ5MZDGa6ZmKF99GiLG6FqOmU1M7nRQypMWWtYxlmNzXYam2ckrxjo
-jD2ZW6qTu7Cx2XSOudIyJGpHAkdEvek2+Te42w5XcgNkQd5gfzKp
------END RSA PRIVATE KEY-----

+ 27 - 0
go/gopath/src/fohow.com/static/tapi/5754763_tfohowapi.hiwavo.com.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAl8wqDViw7clrOhPxdpBhYTMnck40kMxrfU/y1MRz5lCufePy
+BSFJY1VXg1XT2XPJBDmEiT/G1rfeMASRmOE63bTww+LSXtg0OKuBCALR7zBDDjpZ
+jschddyc5JfmsVtNPkfIlpb2iMJeae7vTQavyVhufTVZrtmD1JfV6baiKvl6PutK
+9ADT7oLi7guVAIlsHVhh+84tYML3ks/ll/KYaFr+W/aSqMEa6RqldRtmAaA8IDsj
+kNxk79xygrN8EoGEAMJxBo0UpnDIb1CEhaDmBGztmpcGwiFIebHiOcYGxW0ug+i4
+xqDetXTHZw6tKEdL9MdUv+ew7l9tBZnVCTFXPwIDAQABAoIBAAnVXoYF0FRfH3Sg
+NRy2prBKxYvomAwnSfFQvAzfexiY8mzSVuvRJ7VpImWuKi6kiwmchkLz4DgpqhmX
+Oi1ardsN7SjraTBetidTqOSxdhMWH8nsqr+Ok9LUS0+drYKgxQS7Vrm2ptreKIqZ
+QWROghW7hlDTI2+pxJoBigh9Xc0Fyb3n5lWnfvb88IZpG3JTssGzF8TZs4x/CJb/
+IA2JhuWAvGmsaVFv/rvDYaGEjXQm7i/U9Hz00XXX33j4pWZldZy4TJ5i3yNfSsqr
+7uiu2ntzp8nM1YZ4jhBNJ7PJGgSdTIrryTeFNh9lzHcPZ1bAId1AKSiFzUKMOgns
+cF3xegkCgYEAzkfuA6I2Vu7WO3uywLswdVkMjW3Dev0b1K7JEHfMG6h7wVpsckj1
+kvbI2qDazZ+QFAHcQuWdSwODsb/Uy/rz5XZj/aXRjIE2sNuLrnNFsKBRC9ZfYdj4
+Z876JwuhlkxZLKMzox/tLEqf/FjVLFvDYLrw6Usxa3TrykrjS3+KcgkCgYEAvGJ2
+zAjej4qrcoNX5zVzMGOGcWV2Vj2COmAb/poClUoZjXsNjIeiRq/0EEy/xJHq3xSf
+rg2bJyYvAcXoZ15iDXroVZvqryyl3e71MPc0spV0mPzzk7UGt09xFyuPsXZgL5I9
+BUqo3Vf+E4N0PZYRIeyffiM4WYhv1OOgmdsQsQcCgYA1F8ZnIQUjcu2o+bmUaZmb
+WoQkkq/Ro/vZzfLqTis2ozLXHVL0R1sNrH8d5nDqo7sNqzzp6veFKy5mPZ2jsr+7
+u7EYw+kfZNKSyq81A25Ye6rghRifspyc+2TfT9sTOCtrlcXgooME92AeLy8O779l
+0jfXlAbwRXO66XN/JyCXIQKBgG2ZG2Q5BMKd+oD0yP9KqWlNfbobPW2O+2Ta5W6K
+S1Zvdc5J+Of5QP++/k89V5QVEIAYj43DfLCaFl8BtOPulT0idGjZ/P9NCnLDwwJp
+z87WBK+8+jjE6NNc9H52aXLlW7BRdA7QEM41kyvnHol19SG3eFL6Sp5MMkO46oaY
+XG2hAoGBAIz+vtJ0Jn5w28eNYAE+t42aoKnZJTgpjiCdy9/gIg0wQo4uYk7nmPQU
+uadBuHL0jdjSBZQeFr9Z8NGNXmDJpxaHPPN0CAjjbouDan93K4jfxdrqEZ47Z9Jv
+sh2diJ2YJYXpTd0ioJSwa6VFmkph/1y7MyzN6IHOw+f65O0TiSsI
+-----END RSA PRIVATE KEY-----

+ 24 - 25
go/gopath/src/fohow.com/static/tapi/5539910_tfohowapi.hiwavo.com.pem

@@ -1,37 +1,36 @@
 -----BEGIN CERTIFICATE-----
-MIIF/TCCBOWgAwIBAgIQCYbknXaOwzDQRTcAtmbc6TANBgkqhkiG9w0BAQsFADBu
+MIIF/DCCBOSgAwIBAgIQAtCpPuDiMRr+8F6OCY+/nTANBgkqhkiG9w0BAQsFADBu
 MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
-RFYgVExTIENBIC0gRzEwHhcNMjEwNDI0MDAwMDAwWhcNMjIwNDI0MjM1OTU5WjAf
+RFYgVExTIENBIC0gRzEwHhcNMjEwNjA2MDAwMDAwWhcNMjIwNjA2MjM1OTU5WjAf
 MR0wGwYDVQQDExR0Zm9ob3dhcGkuaGl3YXZvLmNvbTCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBANisGdJIpCBhvR2J1XMgRHlGotZPyQ4p6woCeEfihutx
-6SXSr0BXZQO5HJawXl2ya4mBoxY8dCoHz5ekONiqgUPXufMr8qKVkAekj40dEBUY
-C7U6Zj6SgnzHgWV0evUnQwxSrXJ3t8kgFyxrymrVA6sjpPT2cYMlpX+pIZqJvuOW
-btEUbyioSMG27B7ZHp6wcsFARTQXmnWLVkpwJX5muFt51XzoMTSOX052oNkbO/Hn
-IY1WYfFR4v64vR1YfZ/yO0PZkgifk18Y8H5RTotkFGWKDUuOkZIOyfRh9J0es7rW
-CsttdkX8a7ZHjkZhQ5SxImA7TWQ0E4+WgqK5MguSsy0CAwEAAaOCAuQwggLgMB8G
-A1UdIwQYMBaAFFV0T7JyT/VgulDR1+ZRXJoBhxrXMB0GA1UdDgQWBBSSgFRvXh0J
-J0OOPUUip1fVb9linzAfBgNVHREEGDAWghR0Zm9ob3dhcGkuaGl3YXZvLmNvbTAO
+BQADggEPADCCAQoCggEBAJfMKg1YsO3JazoT8XaQYWEzJ3JONJDMa31P8tTEc+ZQ
+rn3j8gUhSWNVV4NV09lzyQQ5hIk/xta33jAEkZjhOt208MPi0l7YNDirgQgC0e8w
+Qw46WY7HIXXcnOSX5rFbTT5HyJaW9ojCXmnu700Gr8lYbn01Wa7Zg9SX1em2oir5
+ej7rSvQA0+6C4u4LlQCJbB1YYfvOLWDC95LP5ZfymGha/lv2kqjBGukapXUbZgGg
+PCA7I5DcZO/ccoKzfBKBhADCcQaNFKZwyG9QhIWg5gRs7ZqXBsIhSHmx4jnGBsVt
+LoPouMag3rV0x2cOrShHS/THVL/nsO5fbQWZ1QkxVz8CAwEAAaOCAuMwggLfMB8G
+A1UdIwQYMBaAFFV0T7JyT/VgulDR1+ZRXJoBhxrXMB0GA1UdDgQWBBRy89bOJHG0
+vD4tK2P0Q/vKwCAemjAfBgNVHREEGDAWghR0Zm9ob3dhcGkuaGl3YXZvLmNvbTAO
 BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMD4G
 A1UdIAQ3MDUwMwYGZ4EMAQIBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGln
 aWNlcnQuY29tL0NQUzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRw
 Oi8vb2NzcC5kaWdpY2VydC5jb20wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jYWNlcnRz
 LmRpZ2ljZXJ0LmNvbS9FbmNyeXB0aW9uRXZlcnl3aGVyZURWVExTQ0EtRzEuY3J0
-MAkGA1UdEwQCMAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2ACl5vvCeOTkh
-8FZzn2Old+W+V32cYAr4+U1dJlwlXceEAAABeQMljh8AAAQDAEcwRQIgZHeGUViA
-vROfZzCIXP9XgWtUFVMM9gWpwD1P4STaZrECIQCSNd90pHM3zxzJUTtOEXLJuVEC
-Kc7gi6gMy+KAV3oeaAB2ACJFRQdZVSRWlj+hL/H3bYbgIyZjrcBLf13Gg1xu4g8C
-AAABeQMljZAAAAQDAEcwRQIgaaxNEUbfx2JrqzlRB57cFfIxA2AvbmaagaN0GkPH
-ZoICIQDmTlfjG9kdJRA1k+DiWqJLDpXJM9TMpNUPD6SY5epeAAB2AEHIyrHfIkZK
-EMahOglCh15OMYsbA+vrS8do8JBilgb2AAABeQMljj4AAAQDAEcwRQIgICxkPKOf
-gqAvhD4fQIJBIDkwe9Awbca/lRCrC7189osCIQCHvPelI3BpvymtZzPm54OXEX3T
-9iyK6w3R+md2tudzdjANBgkqhkiG9w0BAQsFAAOCAQEAmHZIRDXqrhZ7yW21SaNZ
-ajVWVTCOK/vaUbX/9jlQAJieP213rNzhas06mMZdjMvYgjwR3pFfQ7IZ/MRjX1G4
-vBCWG/0z1xROeW+/3czEVJmjt4qbu2NLj4pA3vH1uyqJ271c8d1I835cQP/VZtmn
-SUY8SYZhNW2FLW9bLf41Vn/egVV8s57/ecSkG2UF3M2XoZnmtrWSz3wPIQmErHte
-CDs0ivWsHhYsZRXGdR5DjuDeX7uUCSjpPR+tU7/hMpWS7+zW/iKkvjx33JCp3q4R
-zBiURTw75M25NLZrA5jladTFzn9HLqbJ5L1viaM+tpTEEyi68X8XSIOUOz8/KTRt
-2w==
+MAkGA1UdEwQCMAAwggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB1ACl5vvCeOTkh
+8FZzn2Old+W+V32cYAr4+U1dJlwlXceEAAABeeFNNvUAAAQDAEYwRAIgaQ1ZPK+h
+sqd6PHp3Pzpdx6l9Vd5iZ/kyFTsKczyH3EQCIGrgUjujvguUczrs89mD4ToXocbN
+e5M3xP3dcXPIGDR7AHYAIkVFB1lVJFaWP6Ev8fdthuAjJmOtwEt/XcaDXG7iDwIA
+AAF54U02vAAABAMARzBFAiBGRVpj7qODsWHrw2tS439rKIjxFQg+JPwaKRmTWZn2
+/wIhAIMw1VoPeKsEwdNpkdseuyE59IbjkbcqTobn+i7Ko4qLAHYAUaOw9f0BeZxW
+bbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF54U03AwAABAMARzBFAiEAlJAMR75H
+gayyXUR4s7cKSoVwP0eVAdkXrTcRpYedTVACIC1eP4yjuHodbKNWNYaegC1jsyAY
+wat03uCPY9qL3BkfMA0GCSqGSIb3DQEBCwUAA4IBAQCG5FwPTjlw6EBk4l8w9XJ3
+s9QoWsBVByas21/dbb/6N6dz7lxcK4o8oZyuJ/tySNCnFXN1KcbzaRUXxwkij1Ka
+dy17JjQCvKc4GbsFUs5vD2zhMrmXSPdbvSLq56pEAt+Cytn6amls/YyaEymO+eWB
+ZR1sETxVbNUfZjFL/QQ7Z2ubnms41i9c2atjjoLRXnFvNAiPoqaaVlzGfUM5RkCG
+4CcjB9lFkRLkIW1O8ARfQJF4NmsQAuKqpPHSoc80ihbs/bmUKREZ27qiTEQhvmfz
+25KIZTlPLVxs4rlwSFFqVMtIgeN6vZ/IVAc11p/2eMHyBPWLuO9uwMjFddxzc/iY
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
 MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh

+ 0 - 2
go/gopath/src/github.com/chanxuehong/wechat/mch/sign.go

@@ -39,7 +39,6 @@ func Sign(parameters map[string]string, apiKey string, fn func() hash.Hash) stri
 		if v == "" {
 			continue
 		}
-
 		buf = buf[:0]
 		buf = append(buf, k...)
 		buf = append(buf, '=')
@@ -51,7 +50,6 @@ func Sign(parameters map[string]string, apiKey string, fn func() hash.Hash) stri
 	buf = append(buf, "key="...)
 	buf = append(buf, apiKey...)
 	h.Write(buf)
-
 	signature := make([]byte, h.Size()*2)
 	hex.Encode(signature, h.Sum(nil))
 	return string(bytes.ToUpper(signature))