Files
LingXi-CRM/server/service/subscribe.go
T
2022-12-16 20:39:36 +08:00

181 lines
4.9 KiB
Go

package service
import (
"crm/global"
"crm/models"
"crm/response"
"encoding/json"
"fmt"
"log"
"net/url"
"time"
"github.com/smartwalle/alipay/v3"
"github.com/smartwalle/xid"
)
const (
Paying = 1 // 支付中
Payed = 2 // 已支付
)
type SubscribeService struct {
}
// 订阅专业版,发起支付
func (s *SubscribeService) Pay(param models.SubscribePayParam) (*models.SubscribePayUrl, int) {
// 构建订单支付信息
tradeNo := fmt.Sprintf("%d", xid.Next())
var p = alipay.TradePagePay{}
p.NotifyURL = global.Config.Alipay.NotifyURL
p.ReturnURL = global.Config.Alipay.ReturnURL
fmt.Println(p.ReturnURL)
p.Subject = "支付测试:" + tradeNo
p.OutTradeNo = tradeNo
p.ProductCode = "FAST_INSTANT_TRADE_PAY"
switch param.Version {
case 2:
p.TotalAmount = "18.00"
case 3:
p.TotalAmount = "198.00"
}
// 缓存订单信息
order, _ := json.Marshal(&models.SubscribePayOrder{
Uid: param.Uid,
Version: param.Version,
})
err := global.Rdb.Set(ctx, tradeNo, string(order), time.Minute*30).Err()
if err != nil {
return nil, response.ErrCodeFailed
}
// 设置支付状态
key := fmt.Sprintf("uid:%v:pay:status", param.Uid)
if err := global.Rdb.Set(ctx, key, Paying, time.Minute*10).Err(); err != nil {
return nil, response.ErrCodeFailed
}
// 返回支付链接
payUrl, err := global.Alipay.TradePagePay(p)
if err != nil {
return nil, response.ErrCodeFailed
}
subscribePayUrl := models.SubscribePayUrl{
PayUrl: payUrl.String(),
}
return &subscribePayUrl, response.ErrCodeSuccess
}
// 支付成功回调
func (s *SubscribeService) Callback(outTradeNo string) (string, int) {
// 验证订单信息
var p = alipay.TradeQuery{}
p.OutTradeNo = outTradeNo
rsp, err := global.Alipay.TradeQuery(p)
if err != nil {
log.Printf("验证订单 %s 信息发生错误: %s", outTradeNo, err.Error())
return StringNull, response.ErrCodeFailed
}
if !rsp.IsSuccess() {
log.Printf("验证订单 %s 信息发生错误: %s-%s", outTradeNo, rsp.Content.Msg, rsp.Content.SubMsg)
return StringNull, response.ErrCodeFailed
}
// 获取订单信息
var order models.SubscribePayOrder
orderJson, err := global.Rdb.Get(ctx, outTradeNo).Result()
if err != nil {
return StringNull, response.ErrCodeFailed
}
if err := json.Unmarshal([]byte(orderJson), &order); err != nil {
return StringNull, response.ErrCodeFailed
}
// 创建订阅信息
var expired int64
switch order.Version {
case 2:
expired = time.Now().Unix() + int64(2592000)
case 3:
expired = time.Now().Unix() + int64(31104000)
}
subscribe := models.Subscribe{
Version: order.Version,
Expired: expired,
}
if global.Db.Table(SUBSCRIBE).Where("uid = ?", order.Uid).First(&models.Subscribe{}).RowsAffected == 0 {
subscribe.Uid = order.Uid
subscribe.Created = time.Now().Unix()
err := global.Db.Table(SUBSCRIBE).Create(&subscribe).Error
if err != nil {
return StringNull, response.ErrCodeFailed
}
} else {
subscribe.Updated = time.Now().Unix()
err = global.Db.Model(&models.Subscribe{}).Where("uid = ?", order.Uid).Updates(&subscribe).Error
if err != nil {
return StringNull, response.ErrCodeFailed
}
}
// 修改支付状态
key := fmt.Sprintf("uid:%v:pay:status", order.Uid)
if err := global.Rdb.Set(ctx, key, Payed, time.Hour*10).Err(); err != nil {
return StringNull, response.ErrCodeFailed
}
return global.Config.Alipay.PaySuccessURL, response.ErrCodeSuccess
}
// 异步验签
func (s *SubscribeService) Notify(data url.Values, outTradeNo string) int {
ok, err := global.Alipay.VerifySign(data)
if err != nil {
log.Println("异步通知验证签名发生错误", err)
return response.ErrCodeFailed
}
if !ok {
log.Println("异步通知验证签名未通过")
return response.ErrCodeFailed
}
log.Println("异步通知验证签名通过")
var p = alipay.TradeQuery{}
p.OutTradeNo = outTradeNo
rsp, err := global.Alipay.TradeQuery(p)
if err != nil {
log.Printf("异步通知验证订单 %s 信息发生错误: %s \n", outTradeNo, err.Error())
return response.ErrCodeFailed
}
if !rsp.IsSuccess() {
log.Printf("异步通知验证订单 %s 信息发生错误: %s-%s \n", outTradeNo, rsp.Content.Msg, rsp.Content.SubMsg)
return response.ErrCodeFailed
}
log.Printf("订单 %s 支付成功 \n", outTradeNo)
return response.ErrCodeSuccess
}
// 获取订阅信息
func (s *SubscribeService) GetInfo(uid int64) (*models.SubscribeInfo, int) {
var si models.SubscribeInfo
if err := global.Db.Table(SUBSCRIBE).First(&si, "uid = ?", uid).Error; err != nil {
return nil, response.ErrCodeFailed
}
// 判断用户订阅是否过期
if si.Version == 2 && time.Now().Unix() > int64(si.Expired) {
err := global.Db.Model(&models.Subscribe{}).Where("uid = ?", uid).Update("version", 1).Error
if err != nil {
return nil, response.ErrCodeFailed
}
}
if err := global.Db.Table(SUBSCRIBE).First(&si, "uid = ?", uid).Error; err != nil {
return nil, response.ErrCodeFailed
}
return &si, response.ErrCodeSuccess
}