活动模块,计划任务模块 加入第三方

This commit is contained in:
ayflying
2025-02-28 12:12:03 +08:00
parent 6d2b68a202
commit e9540d0971
103 changed files with 4258 additions and 74 deletions

156
pay/apple.go Normal file
View File

@@ -0,0 +1,156 @@
package pay
import (
"context"
"github.com/go-pay/gopay/apple"
"github.com/gogf/gf/v2/errors/gerror"
"strings"
"sync"
"time"
)
// ApplePay 苹果支付
// 这是一个用于处理苹果支付的结构体。
type ApplePay struct {
pass string // pass 是用于苹果支付过程中的密钥。
lock sync.RWMutex // lock 用于确保在并发访问或修改 pass 时的安全性。
}
// Init 是ApplePay类型的初始化函数。
//
// @Description: 对ApplePay对象进行初始化将传入的数据存储到对象中。
// @receiver p: ApplePay对象的指针用于接收初始化操作。
// @param data: 一个字节切片,包含需要初始化的数据。
func (p *ApplePay) Init(data []byte) {
p.lock.Lock() // 加锁以保证在多线程环境下的线程安全
defer p.lock.Unlock() // 确保在函数执行完毕退出时自动解锁,避免死锁
p.pass = string(data) // 将传入的字节切片数据转换为字符串并赋值给pass字段
}
// VerifyPay 验证苹果支付
//
// @Description: 验证苹果支付的收据信息,以确认支付的有效性。
// @receiver p *ApplePay: ApplePay对象用于执行验证支付的操作。
// @param userId uint64: 用户ID。
// @param OrderId string: 订单ID。
// @param package1 string: 付费产品的包装名称。
// @param subscriptionID string: 订阅ID。
// @param purchaseToken string: 购买令牌,用于苹果服务器的收据验证。
// @param isDebug bool: 是否为调试模式决定使用哪个验证URL。
// @param cb func(string) error: 回调函数用于处理验证成功后的产品ID。
// @return error: 返回错误信息,如果验证过程中出现错误,则返回相应的错误信息。
func (p *ApplePay) VerifyPay(userId uint64, OrderId, package1, subscriptionID, purchaseToken string, isDebug bool, cb func(string) error) error {
p.lock.RLock() // 加读锁,保证并发安全
defer p.lock.RUnlock() // 解读锁,确保函数执行完毕后释放锁
// 根据是否为调试模式选择验证URL
url := apple.UrlProd
if isDebug {
url = apple.UrlSandbox
}
// 向苹果服务器验证收据
info, err := apple.VerifyReceipt(context.Background(), url, p.pass, purchaseToken)
if err != nil {
// 如果验证失败,则返回错误
return err
}
// 检查收据验证的状态
if info.Status == 0 {
// 检查收据中是否包含内购信息
if len(info.Receipt.InApp) <= 0 {
return gerror.Wrap(err, "info.Receipt.InApp = 0")
}
// 调用回调函数处理商品ID
if err := cb(info.Receipt.InApp[0].ProductId); err != nil {
// 如果回调处理失败,则返回错误
return err
}
} else {
// 如果收据验证状态异常,则返回状态错误信息
return gerror.Wrapf(err, "status err = %v", info.Status)
}
return nil
}
// VerifyPayV1 验证苹果支付的交易
//
// @Description:
// @receiver p
// @param purchaseToken
// @param isDebug
// @param cb
// @return error
func (p *ApplePay) VerifyPayV1(purchaseToken string, isDebug bool, cb func(string, string) error) error {
p.lock.RLock() // 加读锁,确保并发安全
defer p.lock.RUnlock() // 结束时自动释放读锁
// 根据调试模式选择验证服务的URL
url := apple.UrlProd
if isDebug {
url = apple.UrlSandbox
}
// 向苹果服务器验证收据
info, err := apple.VerifyReceipt(context.Background(), url, p.pass, purchaseToken)
if err != nil {
// 验证失败,返回错误
return err
}
// 检查验证结果状态
if info.Status == 0 {
// 验证成功,检查收据中是否有内购信息
if len(info.Receipt.InApp) <= 0 {
// 收据中无内购信息,返回错误
return gerror.Wrap(err, "info.Receipt.InApp = 0")
}
// 调用回调函数,处理内购产品信息
if err := cb(info.Receipt.InApp[0].ProductId, info.Receipt.InApp[0].OriginalTransactionId); err != nil {
// 回调函数执行失败,返回错误
return gerror.Wrap(err, "回调函数执行失败")
}
} else {
// 验证结果状态异常,返回错误
return gerror.Wrapf(err, "status err = %v", info.Status)
}
// 验证成功返回nil
return nil
}
// VerifyPayTest 用于验证苹果支付的测试购买。
//
// @Description:
// @receiver p
// @param purchaseToken
// @return interface{}
// @return error
func (p *ApplePay) VerifyPayTest(purchaseToken string) (interface{}, error) {
// 使用沙箱环境的URL进行验证
url := apple.UrlSandbox
// 调用apple.VerifyReceipt进行收据验证
return apple.VerifyReceipt(context.Background(), url, p.pass, purchaseToken)
}
// GetTime 根据提供的 timer 字符串解析时间,格式为 "YYYY-MM-DD HH:MM:SS ZZZ",若解析失败则返回当前时间
//
// @Description: 根据指定格式解析时间字符串,如果解析失败或者格式不正确,则返回当前时间。
// @param timer 时间字符串,格式为 "YYYY-MM-DD HH:MM:SS ZZZ",其中 ZZZ 为时区标识。
// @return time.Time 解析得到的时间,若失败则返回当前时间。
func GetTime(timer string) time.Time {
// 将 timer 字符串按空格分割为年月日和时分秒两部分
ts := strings.Split(timer, "")
// 如果分割后的数组长度不为3则说明格式不正确返回当前时间
if len(ts) != 3 {
return time.Now()
}
// 尝试加载指定时区信息
location, err := time.LoadLocation(ts[2])
// 如果加载时区失败,则返回当前时间
if err != nil {
return time.Now()
}
// 使用指定时区解析时间字符串
t, err := time.ParseInLocation("2006-01-02 15:04:05 MST", ts[0]+" "+ts[1], location)
// 如果解析失败,则返回当前时间
if err != nil {
return time.Now()
}
// 将解析得到的时间转换为本地时间并返回
return t.In(time.Local)
}