2
This commit is contained in:
parent
5dd3c44917
commit
73e41552e4
@ -2,9 +2,14 @@ package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"hepa-calc-api/api/dao"
|
||||
"hepa-calc-api/api/responses"
|
||||
"hepa-calc-api/api/service"
|
||||
"hepa-calc-api/extend/weChat"
|
||||
"hepa-calc-api/global"
|
||||
"hepa-calc-api/utils"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CallBack 回调
|
||||
@ -12,7 +17,7 @@ type CallBack struct{}
|
||||
|
||||
// WxPaySingle 微信支付回调-单项
|
||||
func (r *CallBack) WxPaySingle(c *gin.Context) {
|
||||
notifyReq, err := weChat.ParseNotify(c)
|
||||
notifyReq, transaction, err := weChat.ParseNotify(c)
|
||||
if err != nil {
|
||||
responses.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
@ -20,7 +25,195 @@ func (r *CallBack) WxPaySingle(c *gin.Context) {
|
||||
|
||||
// 记录日志
|
||||
utils.LogJsonErr("微信支付回调-单项", notifyReq)
|
||||
utils.LogJsonErr("微信支付回调-单项", transaction)
|
||||
|
||||
if transaction == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少订单数据"})
|
||||
return
|
||||
}
|
||||
|
||||
if transaction.OutTradeNo == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少外部订单号"})
|
||||
return
|
||||
}
|
||||
|
||||
// 查询订单
|
||||
orderSingleDao := dao.OrderSingleDao{}
|
||||
maps := make(map[string]interface{})
|
||||
maps["order_no"] = transaction.OutTradeNo
|
||||
orderSingle, err := orderSingleDao.GetOrderSingle(maps)
|
||||
if err != nil || orderSingle == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "无订单数据"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证订单状态-订单状态(1:待支付 2:已完成 3:已取消)
|
||||
if orderSingle.OrderStatus != 1 {
|
||||
message := "订单状态:" + utils.OrderSingleStatusToString(orderSingle.OrderStatus) + " 无需处理"
|
||||
c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message})
|
||||
return
|
||||
}
|
||||
|
||||
// 处理支付状态
|
||||
if transaction.TradeState == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少支付状态"})
|
||||
return
|
||||
}
|
||||
|
||||
// 处理支付状态
|
||||
wxPayResult, err := weChat.HandlePayStatus(transaction)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err})
|
||||
return
|
||||
}
|
||||
|
||||
// 开始事务
|
||||
tx := global.Db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
// 修改订单
|
||||
orderSingleData := make(map[string]interface{})
|
||||
if wxPayResult.OrderStatus != nil {
|
||||
orderSingleData["order_status"] = &wxPayResult.OrderStatus
|
||||
}
|
||||
orderSingleData["pay_status"] = &wxPayResult.PayStatus
|
||||
if wxPayResult.PayTime != nil {
|
||||
orderSingleData["pay_time"] = &wxPayResult.PayTime
|
||||
}
|
||||
orderSingleData["escrow_trade_no"] = transaction.TransactionId
|
||||
orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
err = orderSingleDao.EditOrderSingleById(tx, orderSingle.OrderId, orderSingleData)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err})
|
||||
return
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "OK"})
|
||||
}
|
||||
|
||||
// WxPayMember 微信支付回调-会员
|
||||
func (r *CallBack) WxPayMember(c *gin.Context) {
|
||||
notifyReq, transaction, err := weChat.ParseNotify(c)
|
||||
if err != nil {
|
||||
responses.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 记录日志
|
||||
utils.LogJsonErr("微信支付回调-会员", notifyReq)
|
||||
utils.LogJsonErr("微信支付回调-会员", transaction)
|
||||
|
||||
if transaction == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少订单数据"})
|
||||
return
|
||||
}
|
||||
|
||||
if transaction.OutTradeNo == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少外部订单号"})
|
||||
return
|
||||
}
|
||||
|
||||
// 查询订单
|
||||
orderMemberDao := dao.OrderMemberDao{}
|
||||
maps := make(map[string]interface{})
|
||||
maps["order_no"] = transaction.OutTradeNo
|
||||
orderMember, err := orderMemberDao.GetOrderMember(maps)
|
||||
if err != nil || orderMember == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "无订单数据"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证订单状态-订单状态(1:待支付 2:已完成 3:已取消)
|
||||
if orderMember.OrderStatus != 1 {
|
||||
message := "订单状态:" + utils.OrderSingleStatusToString(orderMember.OrderStatus) + " 无需处理"
|
||||
c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message})
|
||||
return
|
||||
}
|
||||
|
||||
// 处理支付状态
|
||||
if transaction.TradeState == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少支付状态"})
|
||||
return
|
||||
}
|
||||
|
||||
// 处理支付状态
|
||||
wxPayResult, err := weChat.HandlePayStatus(transaction)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户数据
|
||||
userDao := dao.UserDao{}
|
||||
user, err := userDao.GetUserById(orderMember.UserId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "用户数据错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 开始事务
|
||||
tx := global.Db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
// 修改订单
|
||||
orderSingleData := make(map[string]interface{})
|
||||
if wxPayResult.OrderStatus != nil {
|
||||
orderSingleData["order_status"] = &wxPayResult.OrderStatus
|
||||
}
|
||||
orderSingleData["pay_status"] = &wxPayResult.PayStatus
|
||||
if wxPayResult.PayTime != nil {
|
||||
orderSingleData["pay_time"] = &wxPayResult.PayTime
|
||||
}
|
||||
orderSingleData["escrow_trade_no"] = transaction.TransactionId
|
||||
orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
err = orderMemberDao.EditOrderMemberById(tx, orderMember.OrderId, orderSingleData)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": err})
|
||||
return
|
||||
}
|
||||
|
||||
// 处理未支付单项订单
|
||||
if *wxPayResult.OrderStatus == 2 {
|
||||
orderSingleService := service.OrderSingleService{}
|
||||
res, err := orderSingleService.CompleteUnPayOrderSingle(tx, orderMember.UserId)
|
||||
if err != nil || res == false {
|
||||
tx.Rollback()
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 处理用户会员过期时间
|
||||
if *wxPayResult.OrderStatus == 2 {
|
||||
// 获取订单配置
|
||||
systemMemberDao := dao.SystemMemberDao{}
|
||||
systemMember, err := systemMemberDao.GetSystemMemberById(orderMember.SystemMemberId)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": "会员配置错误"})
|
||||
return
|
||||
}
|
||||
|
||||
userService := service.UserService{}
|
||||
res := userService.AddUserMemberValidDate(tx, user, int(systemMember.MemberDays))
|
||||
if res == false {
|
||||
tx.Rollback()
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": "增加用户会员到期时间失败"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "OK"})
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ import (
|
||||
"hepa-calc-api/extend/weChat"
|
||||
"hepa-calc-api/global"
|
||||
"hepa-calc-api/utils"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -20,18 +19,89 @@ type Login struct{}
|
||||
|
||||
// LoginPhone 手机号登录
|
||||
func (r *Login) LoginPhone(c *gin.Context) {
|
||||
loginRequest := requests.LoginRequest{}
|
||||
req := loginRequest.LoginPhone
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
responses.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 参数验证
|
||||
if err := global.Validate.Struct(req); err != nil {
|
||||
responses.FailWithMessage(utils.Translate(err), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 检测用户信息
|
||||
userDao := dao.UserDao{}
|
||||
maps := make(map[string]interface{})
|
||||
maps["mobile"] = req.Mobile
|
||||
user, _ := userDao.GetUser(maps)
|
||||
// 新用户处理方式
|
||||
if user == nil {
|
||||
// 开始事务
|
||||
tx := global.Db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println(r)
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
avatar := "www.baidu.com"
|
||||
|
||||
// 新增用户
|
||||
user = &model.User{
|
||||
UserName: "",
|
||||
Mobile: req.Mobile,
|
||||
RegisterSource: req.Source,
|
||||
OpenId: "",
|
||||
UnionId: "",
|
||||
Age: nil,
|
||||
Sex: 0,
|
||||
Avatar: avatar,
|
||||
IsMember: 0,
|
||||
MemberExpireDate: nil,
|
||||
LoginAt: model.LocalTime(time.Now()),
|
||||
LoginIp: req.LoginIp,
|
||||
}
|
||||
user, err := userDao.AddUser(tx, user)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
responses.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(user)
|
||||
|
||||
// 获取app用户信息
|
||||
//var result *string
|
||||
//if result == nil {
|
||||
// // 新增app用户信息
|
||||
//}
|
||||
|
||||
tx.Commit()
|
||||
}
|
||||
|
||||
// 下发token
|
||||
token := &utils.Token{
|
||||
UserId: strconv.FormatInt(1, 10),
|
||||
UserId: fmt.Sprintf("%d", user.UserId),
|
||||
}
|
||||
|
||||
// 生成jwt
|
||||
jwt, err := token.NewJWT()
|
||||
if err != nil {
|
||||
if err != nil || jwt == "" {
|
||||
responses.FailWithMessage("登陆失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
responses.OkWithData(jwt, c)
|
||||
// 处理返回值
|
||||
g := dto.LoginMobileDto(user)
|
||||
|
||||
// 加载token
|
||||
g.LoadToken(jwt)
|
||||
|
||||
responses.OkWithData(g, c)
|
||||
}
|
||||
|
||||
// LoginWx 微信授权登录
|
||||
@ -55,7 +125,6 @@ func (r *Login) LoginWx(c *gin.Context) {
|
||||
responses.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
fmt.Println(webAccessToken)
|
||||
|
||||
// 网页授权拉取用户信息
|
||||
userInfo, err := weChat.GetUserInfo(webAccessToken.AccessToken, webAccessToken.OpenId)
|
||||
|
||||
@ -214,3 +214,68 @@ func (b *OrderMember) GetOrderMemberPay(c *gin.Context) {
|
||||
|
||||
responses.OkWithData(g, c)
|
||||
}
|
||||
|
||||
// GetOrderMemberPayStatus 查询订单支付状态-会员
|
||||
func (b *OrderMember) GetOrderMemberPayStatus(c *gin.Context) {
|
||||
userId := c.GetInt64("UserId")
|
||||
|
||||
id := c.Param("order_id")
|
||||
if id == "" {
|
||||
responses.FailWithMessage("缺少参数", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 将 id 转换为 int64 类型
|
||||
orderId, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
responses.Fail(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取订单数据
|
||||
orderMemberDao := dao.OrderMemberDao{}
|
||||
maps := make(map[string]interface{})
|
||||
maps["user_id"] = userId
|
||||
maps["order_id"] = orderId
|
||||
orderMember, err := orderMemberDao.GetOrderMember(maps)
|
||||
if err != nil {
|
||||
responses.FailWithMessage("订单异常", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 处理返回值
|
||||
g := dto.GetOrderMemberPayStatus(orderMember)
|
||||
|
||||
// 处理有效期
|
||||
if g.PayStatus == 2 {
|
||||
// 获取单项配置
|
||||
systemMemberDao := dao.SystemMemberDao{}
|
||||
systemMember, err := systemMemberDao.GetSystemMemberById(orderMember.SystemMemberId)
|
||||
if err != nil {
|
||||
responses.FailWithMessage("内部错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户数据
|
||||
userDao := dao.UserDao{}
|
||||
user, err := userDao.GetUserById(orderMember.UserId)
|
||||
if err != nil {
|
||||
responses.FailWithMessage("用户数据错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取有效期
|
||||
var validTime time.Time
|
||||
if user.MemberExpireDate != nil {
|
||||
validTime = user.MemberExpireDate.Add(time.Duration(systemMember.MemberDays) * 24 * time.Hour)
|
||||
} else {
|
||||
now := time.Now()
|
||||
validTime = now.Add(time.Duration(systemMember.MemberDays) * 24 * time.Hour)
|
||||
}
|
||||
|
||||
// 加载到期时间
|
||||
g.LoadValidDate(&validTime)
|
||||
}
|
||||
|
||||
responses.OkWithData(g, c)
|
||||
}
|
||||
|
||||
@ -334,3 +334,56 @@ func (b *OrderSingle) DeleteOrderSingle(c *gin.Context) {
|
||||
tx.Commit()
|
||||
responses.Ok(c)
|
||||
}
|
||||
|
||||
// GetOrderSinglePayStatus 查询订单支付状态-单项
|
||||
func (b *OrderSingle) GetOrderSinglePayStatus(c *gin.Context) {
|
||||
userId := c.GetInt64("UserId")
|
||||
|
||||
id := c.Param("order_id")
|
||||
if id == "" {
|
||||
responses.FailWithMessage("缺少参数", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 将 id 转换为 int64 类型
|
||||
orderId, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
responses.Fail(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取订单数据
|
||||
orderSingleDao := dao.OrderSingleDao{}
|
||||
maps := make(map[string]interface{})
|
||||
maps["user_id"] = userId
|
||||
maps["order_id"] = orderId
|
||||
orderSingle, err := orderSingleDao.GetOrderSingle(maps)
|
||||
if err != nil {
|
||||
responses.FailWithMessage("订单异常", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 处理返回值
|
||||
g := dto.GetOrderSinglePayStatus(orderSingle)
|
||||
|
||||
// 处理有效期
|
||||
if g.PayStatus == 2 {
|
||||
// 获取单项配置
|
||||
systemSingleDao := dao.SystemSingleDao{}
|
||||
|
||||
maps = make(map[string]interface{})
|
||||
systemSingle, err := systemSingleDao.GetSystemSingle(maps)
|
||||
if err != nil {
|
||||
responses.FailWithMessage("内部错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取有效期
|
||||
validTime := orderSingle.PayTime.Add(time.Duration(systemSingle.ValidDays) * 24 * time.Hour)
|
||||
|
||||
// 加载到期时间
|
||||
g.LoadValidDate(&validTime)
|
||||
}
|
||||
|
||||
responses.OkWithData(g, c)
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ func (r *Question) GetQuestionBuyStatus(c *gin.Context) {
|
||||
|
||||
// 判断是否还在有效期内
|
||||
now := time.Now()
|
||||
ValidTime := single.PayTime.Add(time.Duration(systemSingle.ValidDays))
|
||||
ValidTime := single.PayTime.Add(time.Duration(systemSingle.ValidDays) * 24 * time.Hour)
|
||||
if ValidTime.Before(now) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -56,8 +56,8 @@ func (r *OrderMemberDao) EditOrderMember(tx *gorm.DB, maps interface{}, data int
|
||||
}
|
||||
|
||||
// EditOrderMemberById 修改-id
|
||||
func (r *OrderMemberDao) EditOrderMemberById(tx *gorm.DB, OrderMemberId int64, data interface{}) error {
|
||||
err := tx.Model(&model.OrderMember{}).Where("order_id = ?", OrderMemberId).Updates(data).Error
|
||||
func (r *OrderMemberDao) EditOrderMemberById(tx *gorm.DB, OrderId int64, data interface{}) error {
|
||||
err := tx.Model(&model.OrderMember{}).Where("order_id = ?", OrderId).Updates(data).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -56,8 +56,8 @@ func (r *OrderSingleDao) EditOrderSingle(tx *gorm.DB, maps interface{}, data int
|
||||
}
|
||||
|
||||
// EditOrderSingleById 修改-id
|
||||
func (r *OrderSingleDao) EditOrderSingleById(tx *gorm.DB, OrderSingleId int64, data interface{}) error {
|
||||
err := tx.Model(&model.OrderSingle{}).Where("order_id = ?", OrderSingleId).Updates(data).Error
|
||||
func (r *OrderSingleDao) EditOrderSingleById(tx *gorm.DB, orderId int64, data interface{}) error {
|
||||
err := tx.Model(&model.OrderSingle{}).Where("order_id = ?", orderId).Updates(data).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -7,7 +7,18 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type LoginDto struct {
|
||||
type WxDto struct {
|
||||
UserId string `json:"user_id"` // 用户id
|
||||
UserName string `json:"user_name"` // 用户名称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
OpenId string `json:"open_id"` // 用户微信标识
|
||||
Avatar string `json:"avatar"` // 头像
|
||||
IsMember int `json:"is_member"` // 是否会员(0:否 1:是)
|
||||
MemberExpireDate *time.Time `json:"member_expire_date"` // 会员到期时间(非会员时为null)
|
||||
Token string `json:"token"` // token
|
||||
}
|
||||
|
||||
type MobileDto struct {
|
||||
UserId string `json:"user_id"` // 用户id
|
||||
UserName string `json:"user_name"` // 用户名称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
@ -19,8 +30,21 @@ type LoginDto struct {
|
||||
}
|
||||
|
||||
// LoginWxDto 微信登陆
|
||||
func LoginWxDto(m *model.User) *LoginDto {
|
||||
return &LoginDto{
|
||||
func LoginWxDto(m *model.User) *WxDto {
|
||||
return &WxDto{
|
||||
UserId: fmt.Sprintf("%d", m.UserId),
|
||||
UserName: m.UserName,
|
||||
Mobile: m.Mobile,
|
||||
OpenId: m.OpenId,
|
||||
Avatar: utils.AddOssDomain(m.Avatar),
|
||||
IsMember: m.IsMember,
|
||||
MemberExpireDate: m.MemberExpireDate,
|
||||
}
|
||||
}
|
||||
|
||||
// LoginMobileDto 手机号登陆
|
||||
func LoginMobileDto(m *model.User) *MobileDto {
|
||||
return &MobileDto{
|
||||
UserId: fmt.Sprintf("%d", m.UserId),
|
||||
UserName: m.UserName,
|
||||
Mobile: m.Mobile,
|
||||
@ -32,7 +56,13 @@ func LoginWxDto(m *model.User) *LoginDto {
|
||||
}
|
||||
|
||||
// LoadToken 加载token
|
||||
func (r *LoginDto) LoadToken(token string) *LoginDto {
|
||||
func (r *WxDto) LoadToken(token string) *WxDto {
|
||||
r.Token = token
|
||||
return r
|
||||
}
|
||||
|
||||
// LoadToken 加载token
|
||||
func (r *MobileDto) LoadToken(token string) *MobileDto {
|
||||
r.Token = token
|
||||
return r
|
||||
}
|
||||
|
||||
@ -46,6 +46,13 @@ type OrderMemberPayDto struct {
|
||||
PrepayApp *app.PrepayWithRequestPaymentResponse `json:"prepay_app"` // 预支付交易数据-app
|
||||
}
|
||||
|
||||
// OrderMemberPayStatusDto 会员订单支付状态
|
||||
type OrderMemberPayStatusDto struct {
|
||||
PayStatus int `json:"pay_status"` // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款)
|
||||
PaymentAmountTotal float64 `json:"payment_amount_total"` // 实际付款金额
|
||||
ValidDate model.LocalTime `json:"valid_date"` // 到期时间
|
||||
}
|
||||
|
||||
// GetOrderMemberListDto 列表
|
||||
func GetOrderMemberListDto(m []*model.OrderMember) []*OrderMemberDto {
|
||||
// 处理返回值
|
||||
@ -89,7 +96,7 @@ func GetOrderMemberListDto(m []*model.OrderMember) []*OrderMemberDto {
|
||||
return responses
|
||||
}
|
||||
|
||||
// GetOrderMemberPayDto 获取单项订单支付数据
|
||||
// GetOrderMemberPayDto 获取会员订单支付数据
|
||||
func GetOrderMemberPayDto(m *model.OrderMember) *OrderMemberPayDto {
|
||||
return &OrderMemberPayDto{
|
||||
OrderId: fmt.Sprintf("%d", m.OrderId),
|
||||
@ -102,6 +109,14 @@ func GetOrderMemberPayDto(m *model.OrderMember) *OrderMemberPayDto {
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrderMemberPayStatus 获取会员订单支付状态
|
||||
func GetOrderMemberPayStatus(m *model.OrderMember) *OrderMemberPayStatusDto {
|
||||
return &OrderMemberPayStatusDto{
|
||||
PayStatus: m.PayStatus,
|
||||
PaymentAmountTotal: m.PaymentAmountTotal,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadSystemMember 加载会员数据
|
||||
func (r *OrderMemberDto) LoadSystemMember(m *model.SystemMember) *OrderMemberDto {
|
||||
if m != nil {
|
||||
@ -109,3 +124,11 @@ func (r *OrderMemberDto) LoadSystemMember(m *model.SystemMember) *OrderMemberDto
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// LoadValidDate 加载到期时间
|
||||
func (r *OrderMemberPayStatusDto) LoadValidDate(m *time.Time) *OrderMemberPayStatusDto {
|
||||
if m != nil {
|
||||
r.ValidDate = model.LocalTime(*m)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@ -46,6 +46,13 @@ type OrderSinglePayDto struct {
|
||||
PrepayApp *app.PrepayWithRequestPaymentResponse `json:"prepay_app"` // 预支付交易数据-app
|
||||
}
|
||||
|
||||
// OrderSinglePayStatusDto 单项订单支付状态
|
||||
type OrderSinglePayStatusDto struct {
|
||||
PayStatus int `json:"pay_status"` // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款)
|
||||
PaymentAmountTotal float64 `json:"payment_amount_total"` // 实际付款金额
|
||||
ValidDate model.LocalTime `json:"valid_date"` // 到期时间
|
||||
}
|
||||
|
||||
// GetOrderSingleListDto 列表
|
||||
func GetOrderSingleListDto(m []*model.OrderSingle) []*OrderSingleDto {
|
||||
// 处理返回值
|
||||
@ -102,6 +109,14 @@ func GetOrderSinglePayDto(m *model.OrderSingle) *OrderSinglePayDto {
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrderSinglePayStatus 获取单项订单支付状态
|
||||
func GetOrderSinglePayStatus(m *model.OrderSingle) *OrderSinglePayStatusDto {
|
||||
return &OrderSinglePayStatusDto{
|
||||
PayStatus: m.PayStatus,
|
||||
PaymentAmountTotal: m.PaymentAmountTotal,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadQuestion 加载题目数据
|
||||
func (r *OrderSingleDto) LoadQuestion(m *model.Question) *OrderSingleDto {
|
||||
if m != nil {
|
||||
@ -109,3 +124,11 @@ func (r *OrderSingleDto) LoadQuestion(m *model.Question) *OrderSingleDto {
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// LoadValidDate 加载到期时间
|
||||
func (r *OrderSinglePayStatusDto) LoadValidDate(m *time.Time) *OrderSinglePayStatusDto {
|
||||
if m != nil {
|
||||
r.ValidDate = model.LocalTime(*m)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
package requests
|
||||
|
||||
type LoginRequest struct {
|
||||
LoginWx // 微信授权登录
|
||||
LoginWx // 微信授权登录
|
||||
LoginPhone // 手机号登录
|
||||
}
|
||||
|
||||
// LoginWx 微信授权登录
|
||||
type LoginWx struct {
|
||||
Code string `json:"code" form:"code" label:"授权码"`
|
||||
Source int `json:"source" form:"source" label:"来源(1:app 2:公众号)"`
|
||||
Code string `json:"code" form:"code" label:"授权码" validate:"required"`
|
||||
Source int `json:"source" form:"source" label:"来源" validate:"required,oneof=1 2"` // (1:app 2:公众号
|
||||
LoginIp string `json:"login_ip" form:"login_ip" label:"登录ip"`
|
||||
}
|
||||
|
||||
// LoginPhone 手机号登录
|
||||
type LoginPhone struct {
|
||||
Mobile string `json:"mobile" form:"mobile" label:"手机号" validate:"required"`
|
||||
Source int `json:"source" form:"source" label:"来源)" validate:"required"` // (1:app 2:公众号
|
||||
LoginIp string `json:"login_ip" form:"login_ip" label:"登录ip"`
|
||||
}
|
||||
|
||||
@ -100,6 +100,9 @@ func publicRouter(r *gin.Engine, api controller.Api) {
|
||||
{
|
||||
// 单项
|
||||
wxpayGroup.POST("/single", api.CallBack.WxPaySingle)
|
||||
|
||||
// 会员
|
||||
wxpayGroup.POST("/member", api.CallBack.WxPayMember)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,6 +204,9 @@ func privateRouter(r *gin.Engine, api controller.Api) {
|
||||
|
||||
// 删除单项订单
|
||||
singleGroup.DELETE("/:order_id", api.OrderSingle.DeleteOrderSingle)
|
||||
|
||||
// 查询订单支付状态-单项
|
||||
singleGroup.GET("/pay/status/:order_id", api.OrderSingle.GetOrderSinglePayStatus)
|
||||
}
|
||||
|
||||
// 会员订单
|
||||
@ -214,6 +220,9 @@ func privateRouter(r *gin.Engine, api controller.Api) {
|
||||
|
||||
// 获取会员订单支付数据
|
||||
memberGroup.GET("/pay/:order_id", api.OrderMember.GetOrderMemberPay)
|
||||
|
||||
// 查询订单支付状态-会员
|
||||
memberGroup.GET("/pay/status/:order_id", api.OrderMember.GetOrderMemberPayStatus)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ type OrderMemberService struct {
|
||||
|
||||
// AddOrderMember 创建会员订单
|
||||
func (r *OrderMemberService) AddOrderMember(tx *gorm.DB, UserId, SystemMemberId int64, UserCouponId *int64, payChannel int, orderPrice float64) (orderMember *model.OrderMember, err error) {
|
||||
// 检测多次请求
|
||||
// 检测并发请求
|
||||
redisKey := "AddOrderMember" + fmt.Sprintf("%d", UserId) + fmt.Sprintf("%d", SystemMemberId)
|
||||
res, _ := global.Redis.Get(context.Background(), redisKey).Result()
|
||||
if res != "" {
|
||||
|
||||
@ -20,8 +20,9 @@ type OrderSingleService struct {
|
||||
}
|
||||
|
||||
// AddOrderSingle 创建单项订单
|
||||
// payChannel:支付渠道(1:h5支付 2:app支付 3:会员支付)
|
||||
func (r *OrderSingleService) AddOrderSingle(tx *gorm.DB, UserId, QuestionId int64, UserCouponId *int64, payChannel int, orderPrice float64) (orderSingle *model.OrderSingle, err error) {
|
||||
// 检测多次请求
|
||||
// 检测并发请求
|
||||
redisKey := "AddOrderSingle" + fmt.Sprintf("%d", UserId) + fmt.Sprintf("%d", QuestionId)
|
||||
res, _ := global.Redis.Get(context.Background(), redisKey).Result()
|
||||
if res != "" {
|
||||
@ -343,3 +344,36 @@ func (r *OrderSingleService) GetAppPrepay(m *model.OrderSingle) (prepay *app.Pre
|
||||
|
||||
return prepay, nil
|
||||
}
|
||||
|
||||
// CompleteUnPayOrderSingle 完成未支付单项订单-开通会员成功时使用
|
||||
func (r *OrderSingleService) CompleteUnPayOrderSingle(tx *gorm.DB, userId int64) (bool, error) {
|
||||
// 获取所有未支付单项订单
|
||||
orderSingleDao := dao.OrderSingleDao{}
|
||||
maps := make(map[string]interface{})
|
||||
maps["user_id"] = userId
|
||||
maps["order_status"] = 1
|
||||
maps["pay_status"] = 1
|
||||
maps["cancel_status"] = 0
|
||||
orderSingles, err := orderSingleDao.GetOrderSingleList(maps)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, single := range orderSingles {
|
||||
// 生成第三方支付流水号
|
||||
escrowTradeNo := "GD" + global.Snowflake.Generate().String()
|
||||
|
||||
orderSingleData := make(map[string]interface{})
|
||||
orderSingleData["order_status"] = 2
|
||||
orderSingleData["pay_status"] = 2
|
||||
orderSingleData["pay_time"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
orderSingleData["escrow_trade_no"] = escrowTradeNo
|
||||
orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
err = orderSingleDao.EditOrderSingleById(tx, single.OrderId, orderSingleData)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"hepa-calc-api/api/dao"
|
||||
"hepa-calc-api/api/model"
|
||||
"hepa-calc-api/extend/aliyun"
|
||||
@ -82,3 +83,25 @@ func (r *UserService) CheckUserBuyOrderMember(userId int64) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// AddUserMemberValidDate 增加用户会员过期时间
|
||||
func (r *UserService) AddUserMemberValidDate(tx *gorm.DB, user *model.User, d int) bool {
|
||||
userData := make(map[string]interface{})
|
||||
if user.IsMember == 0 {
|
||||
userData["is_member"] = 1
|
||||
}
|
||||
|
||||
if user.MemberExpireDate == nil {
|
||||
userData["is_member"] = time.Now().Format("2006-01-02 15:04:05")
|
||||
} else {
|
||||
userData["is_member"] = user.MemberExpireDate.Add(time.Duration(d) * 24 * time.Hour)
|
||||
}
|
||||
|
||||
userDao := dao.UserDao{}
|
||||
err := userDao.EditUserById(tx, user.UserId, userData)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -5,8 +5,10 @@ import (
|
||||
"errors"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/utils"
|
||||
"hepa-calc-api/config"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 创建客户端
|
||||
@ -38,3 +40,66 @@ func createClient() (*core.Client, error) {
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
type WxPayResult struct {
|
||||
OrderStatus *int `json:"order_status"` // 订单状态(1:待支付 2:已完成 3:已取消)
|
||||
PayStatus *int `json:"pay_status"` // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款)
|
||||
PayTime *time.Time `json:"pay_time"` // 支付时间
|
||||
}
|
||||
|
||||
// HandlePayStatus 处理支付状态
|
||||
func HandlePayStatus(t *payments.Transaction) (w *WxPayResult, err error) {
|
||||
// 支付成功
|
||||
if *t.TradeState == "SUCCESS" {
|
||||
orderStatus := 2
|
||||
w.OrderStatus = &orderStatus
|
||||
|
||||
payStatus := 2
|
||||
w.PayStatus = &payStatus
|
||||
|
||||
parse, err := time.Parse("2006-01-02T15:04:05+07:00", *t.SuccessTime)
|
||||
if err != nil {
|
||||
return nil, errors.New("支付时间处理错误")
|
||||
}
|
||||
|
||||
w.PayTime = &parse
|
||||
if err != nil {
|
||||
return nil, errors.New("支付时间错误")
|
||||
}
|
||||
}
|
||||
|
||||
switch *t.TradeState {
|
||||
case "SUCCESS": // 支付成功
|
||||
orderStatus := 2
|
||||
w.OrderStatus = &orderStatus
|
||||
|
||||
payStatus := 2
|
||||
w.PayStatus = &payStatus
|
||||
|
||||
parse, err := time.Parse("2006-01-02T15:04:05+07:00", *t.SuccessTime)
|
||||
if err != nil {
|
||||
return nil, errors.New("支付时间处理错误")
|
||||
}
|
||||
|
||||
w.PayTime = &parse
|
||||
if err != nil {
|
||||
return nil, errors.New("支付时间错误")
|
||||
}
|
||||
case "CLOSED": // 已关闭
|
||||
payStatus := 6
|
||||
w.PayStatus = &payStatus
|
||||
case "REVOKED": // 已撤销(付款码支付)
|
||||
payStatus := 7
|
||||
w.PayStatus = &payStatus
|
||||
case "USERPAYING": // 用户支付中(付款码支付)
|
||||
payStatus := 3
|
||||
w.PayStatus = &payStatus
|
||||
case "PAYERROR": // 支付失败(其他原因,如银行返回失败)
|
||||
payStatus := 4
|
||||
w.PayStatus = &payStatus
|
||||
default:
|
||||
return nil, errors.New("未知支付状态")
|
||||
}
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ package weChat
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
|
||||
@ -14,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// ParseNotify 回调通知的验签与解密
|
||||
func ParseNotify(c *gin.Context) (notifyReq *notify.Request, err error) {
|
||||
func ParseNotify(c *gin.Context) (notifyReq *notify.Request, t *payments.Transaction, err error) {
|
||||
mchId := config.C.Wechat.Pay1659662936.MchId // 商户号
|
||||
mchCertificateSerialNumber := config.C.Wechat.Pay1659662936.MchCertificateSerialNumber // 商户证书序列号
|
||||
v3ApiSecret := config.C.Wechat.Pay1659662936.V3ApiSecret // 商户APIv3密钥
|
||||
@ -23,13 +22,13 @@ func ParseNotify(c *gin.Context) (notifyReq *notify.Request, err error) {
|
||||
// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
|
||||
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)
|
||||
if err != nil {
|
||||
return nil, errors.New("微信支付生成失败")
|
||||
return nil, nil, errors.New("微信支付生成失败")
|
||||
}
|
||||
|
||||
// 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器
|
||||
err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(c, mchPrivateKey, mchCertificateSerialNumber, mchId, v3ApiSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// 2. 获取商户号对应的微信支付平台证书访问器
|
||||
@ -41,9 +40,8 @@ func ParseNotify(c *gin.Context) (notifyReq *notify.Request, err error) {
|
||||
notifyReq, err = handler.ParseNotifyRequest(context.Background(), c.Request, transaction)
|
||||
// 如果验签未通过,或者解密失败
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fmt.Println(transaction)
|
||||
return notifyReq, nil
|
||||
return notifyReq, transaction, nil
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@ -43,6 +43,7 @@ require (
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
|
||||
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
|
||||
github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@ -57,6 +57,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434 h1:AFIATPhFj7mrISc4z9zEpfm4a8UfwsCWzJ+Je5jA5Rs=
|
||||
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434/go.mod h1:PY9iiFMrFjTzegsqfKCcb+Ekk5/j0ch0sMdBwlT6atI=
|
||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
||||
|
||||
@ -13,3 +13,17 @@ func OrderCancelReasonToString(i int) string {
|
||||
return "取消"
|
||||
}
|
||||
}
|
||||
|
||||
// OrderSingleStatusToString 订单状态(1:待支付 2:已完成 3:已取消)
|
||||
func OrderSingleStatusToString(i int) string {
|
||||
switch i {
|
||||
case 1:
|
||||
return "待支付"
|
||||
case 2:
|
||||
return "已完成"
|
||||
case 3:
|
||||
return "已取消"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user