52 lines
1.3 KiB
Go
52 lines
1.3 KiB
Go
package payment
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"strconv"
|
||
"sync/atomic"
|
||
"time"
|
||
)
|
||
|
||
const (
|
||
// 订单号前缀
|
||
AlipayPrefix = "ALI" // 支付宝订单前缀
|
||
WechatPrefix = "WX" // 微信支付订单前缀
|
||
ApplePrefix = "APP" // 苹果支付订单前缀
|
||
)
|
||
|
||
const (
|
||
RefundPrefix = "REF" // 退款订单前缀
|
||
)
|
||
|
||
// 全局原子计数器
|
||
var orderCounter uint32 = 0
|
||
|
||
// GenerateOrderNo 生成统一格式的订单号
|
||
// prefix: 订单前缀(ALI/WX/APP)
|
||
// 返回格式:前缀 + 时间戳(10位) + 计数器(6位) + 随机数(6位)
|
||
// 例如:ALI202403151234567890123456
|
||
func GenerateOrderNo(prefix string) string {
|
||
// 获取当前时间戳(秒级)
|
||
timestamp := time.Now().Unix()
|
||
timeStr := strconv.FormatInt(timestamp, 10)
|
||
|
||
// 原子递增计数器
|
||
counter := atomic.AddUint32(&orderCounter, 1)
|
||
|
||
// 生成4字节真随机数
|
||
randomBytes := make([]byte, 4)
|
||
_, err := rand.Read(randomBytes)
|
||
if err != nil {
|
||
// 如果随机数生成失败,回退到使用时间纳秒数据
|
||
randomBytes = []byte(strconv.FormatInt(time.Now().UnixNano()%1000000, 16))
|
||
}
|
||
randomHex := hex.EncodeToString(randomBytes)
|
||
|
||
// 组合所有部分: 前缀 + 时间戳 + 计数器 + 随机数
|
||
orderNo := fmt.Sprintf("%s_%s%06x%s", prefix, timeStr, counter%0xFFFFFF, randomHex[:6])
|
||
|
||
return orderNo
|
||
}
|