验签优化

tags/v0.0.2
zhuxianglong 2 months ago
parent f2cc920537
commit afc205d9ac

@ -1,118 +1,219 @@
# SDK 使用文档
### SDK 调用文档
## 概述
本文档详细说明了如何使用两个SDK文件中的功能一个是用于订单支付签名生成的SDK另一个是用于订单退款签名生成的SDK。我们将分别介绍这两个SDK的使用方法。
本SDK 提供了生成签名的功能,主要用于订单相关操作的签名验证。
---
## 安装
#### 1. 订单支付SDK (`sdk_payment.go`)
在Go项目中导入本SDK
##### 1.1 结构体定义
```bash
go get gitea.weitiangame.com/sdk/wt-game
```go
type Order struct {
Uid string // 用户ID
BsTradeNo string // 交易编号
Role string // 用户角色
RoleId string // 角色ID
ServerId string // 服务器ID
GoodsName string // 商品名称
OutTradeNo string // 外部交易编号
Body string // 商品描述
CpExtraInfo string // 扩展信息
TradeState string // 交易状态
TotalFee string // 总费用
PayFee string // 支付费用
PayTime string // 支付时间
}
```
请将 `"gitea.weitiangame.com/sdk/wt-game"` 替换为实际的导入路径。
##### 1.2 SDK 结构体
## 初始化
```go
type SDK struct {
SecretKey string // 秘钥
}
```
通过 `New` 函数创建SDK实例并传入秘钥
##### 1.3 单例实例化
```go
import (
"fmt"
func NewOrderPayment(secretKey string) *SDK
```
"gitea.weitiangame.com/sdk/wt-game/sdk"
)
- **功能**: 初始化并返回一个SDK单例实例。
- **参数**:
- `secretKey` (string): 用于签名的密钥。
- **返回值**: `*SDK` 类型的单例实例。
func main() {
secretKey := "your_secret_key"
newSdk := sdk.New(secretKey)
// 继续使用SDK
}
##### 1.4 生成签名
```go
func (s *SDK) SignParam(order *Order) (string, error)
```
## 生成签名
- **功能**: 为提供的 `Order` 对象生成签名。
- **参数**:
- `order` (*Order): 包含订单信息的结构体指针。
- **返回值**:
- `string`: 生成的签名字符串。
- `error`: 可能返回的错误,当前实现中总是返回 `nil`
##### 1.5 内部方法
- `createParamMap(order *Order) map[string]string`
- **功能**: 创建一个包含订单参数的映射,排除 `sign``-` 键。
- **返回值**: `map[string]string` 类型的参数映射。
- `BuildSignString(params map[string]string) string`
- **功能**: 按字典顺序排序参数并生成签名字符串。
- **参数**: `params` (map[string]string): 参数映射。
- **返回值**: 拼接后的签名字符串。
- `getSortedKeys(params map[string]string) []string`
- **功能**: 获取排序后的参数键列表,排除 `sign``-` 键。
- **参数**: `params` (map[string]string): 参数映射。
- **返回值**: `[]string` 类型的排序键列表。
---
#### 2. 订单退款SDK (`sdk_refund.go`)
创建一个 `Order` 对象并填充相关字段,然后调用 `SignParam` 方法生成签名:
##### 2.1 结构体定义
```go
order := &sdk.Order{
Uid: "12345",
BsTradeNo: "TRADE001",
Role: "Player",
RoleId: "ROLE001",
ServerId: "SERVER01",
GoodsName: "Game Coin",
OutTradeNo: "OUT001",
Body: "Purchase Game Coin",
CpExtraInfo: "extra_info",
TradeState: "SUCCESS",
TotalFee: "100",
PayFee: "95",
PayTime: "2023-10-05 14:30:00",
type OrderRefund struct {
OutTradeNo string // 订单号
RoleId string // 角色ID
Status string // 订单状态
RefundFee string // 退款金额
Timestamp string // 时间戳
}
```
##### 2.2 SDK 结构体
sign, err := newSdk.SignParam(order)
if err != nil {
fmt.Println("生成签名失败:", err)
return
```go
type RefundSDK struct {
SecretKey string // 密钥
}
fmt.Println("签名:", sign)
```
## 示例代码
##### 2.3 单例实例化
```go
func NewRefundSDK(secretKey string) *RefundSDK
```
- **功能**: 初始化并返回一个 RefundSDK 单例实例。
- **参数**:
- `secretKey` (string): 用于签名的密钥。
- **返回值**: `*RefundSDK` 类型的单例实例。
完整的示例代码如下:
##### 2.4 生成签名
```go
func (sdk *RefundSDK) SignParam(order *OrderRefund) string
```
- **功能**: 为提供的 `OrderRefund` 对象生成签名。
- **参数**:
- `order` (*OrderRefund): 包含退款信息的结构体指针。
- **返回值**: `string` 类型的签名字符串(大写形式)。
##### 2.5 内部方法
- `createFormUrl(order *OrderRefund) string`
- **功能**: 生成用于签名的参数字符串。
- **参数**: `order` (*OrderRefund): 包含退款信息的结构体指针。
- **返回值**: 拼接后的参数字符串。
---
### 示例代码
#### 1. 订单支付SDK 使用示例
```go
package main
import (
"fmt"
"gitea.weitiangame.com/sdk/wt-game/sdk"
)
func main() {
secretKey := "your_secret_key"
newSdk := sdk.New(secretKey)
// 初始化SDK实例
sdkInstance := sdk.NewOrderPayment("your_secret_key")
// 创建订单对象
order := &sdk.Order{
Uid: "12345",
BsTradeNo: "TRADE001",
BsTradeNo: "BT12345",
Role: "Player",
RoleId: "ROLE001",
ServerId: "SERVER01",
RoleId: "R001",
ServerId: "S001",
GoodsName: "Game Coin",
OutTradeNo: "OUT001",
OutTradeNo: "OT12345",
Body: "Purchase Game Coin",
CpExtraInfo: "extra_info",
TradeState: "SUCCESS",
TotalFee: "100",
PayFee: "95",
PayTime: "2023-10-05 14:30:00",
PayTime: "20231030120000",
}
sign, err := newSdk.SignParam(order)
// 生成签名
sign, err := sdkInstance.SignParam(order)
if err != nil {
fmt.Println("生成签名失败:", err)
fmt.Println("签名生成失败:", err)
return
}
fmt.Println("签名:", sign)
fmt.Println("生成的签名:", sign)
}
```
#### 2. 订单退款SDK 使用示例
```go
package main
import (
"fmt"
"gitea.weitiangame.com/sdk/wt-game/sdk"
)
func main() {
// 初始化SDK实例
refundSdk := sdk.NewRefundSDK("your_secret_key")
// 创建退款订单对象
refundOrder := &sdk.OrderRefund{
OutTradeNo: "OT12345",
RoleId: "R001",
Status: "REFUNDED",
RefundFee: "95",
Timestamp: "20231030120000",
}
// 生成签名
sign := refundSdk.SignParam(refundOrder)
fmt.Println("生成的签名:", sign)
}
```
## 注意事项
---
- **秘钥安全**:秘钥是生成签名的重要参数,务必妥善保管,防止泄露。
- **签名生成**:签名生成过程中,参数按字典序排序,并且排除`sign`和`-`字段。
- **时间格式**`PayTime`字段请使用`YYYY-MM-DD HH:MM:SS`格式,以保证签名的一致性。
### 注意事项
## 常见问题
1. **单例模式**: 两个SDK都使用了单例模式确保在应用程序中只有一个实例。
2. **线程安全**: 初始化SDK实例时使用了 `sync.Once`,确保线程安全。
3. **签名生成**: 签名生成过程中要注意参数的顺序和拼接方式,确保与服务端一致。
4. **密钥保管**: 保证密钥的安全,不要硬编码在代码中,建议从配置文件或环境变量中读取。
- **签名不匹配**:请检查参数是否正确,秘钥是否一致,以及时间格式是否正确。
---
## 联系方式
### 参考资料
如有任何问题,请联系开发人员或查阅相关文档。
- [Go 语言 sync.Once 包](https://golang.org/pkg/sync/#Once)
- [Go 语言字符串拼接](https://golang.org/pkg/strings/)
- [Go 语言排序](https://golang.org/pkg/sort/)

@ -1,8 +1,7 @@
package sdk
import (
"crypto/md5"
"encoding/hex"
"gitea.weitiangame.com/sdk/wt-game/utils"
"sort"
"strings"
"sync"
@ -34,8 +33,8 @@ type SDK struct {
var instance *SDK
var once sync.Once
// New 返回一个SDK单例实例初始化时传入秘钥
func New(secretKey string) *SDK {
// NewOrderPayment 返回一个SDK单例实例初始化时传入秘钥
func NewOrderPayment(secretKey string) *SDK {
once.Do(func() {
instance = &SDK{
SecretKey: secretKey,
@ -44,12 +43,6 @@ func New(secretKey string) *SDK {
return instance // 返回单例实例
}
// Md5String 生成给定字符串的MD5哈希值并返回十六进制字符串
func (s *SDK) Md5String(str string) string {
hash := md5.Sum([]byte(str)) // 计算MD5哈希
return hex.EncodeToString(hash[:]) // 转为十六进制字符串并返回
}
// SignParam 为提供的Order对象生成签名
func (s *SDK) SignParam(order *Order) (string, error) {
// 创建待签名参数映射
@ -59,7 +52,7 @@ func (s *SDK) SignParam(order *Order) (string, error) {
signStr := s.BuildSignString(paramMap)
// 计算最终签名并返回
return s.Md5String(signStr), nil
return utils.Md5String(signStr), nil
}
// createParamMap 构建参数映射,跳过 "sign" 和 "-" 键

@ -0,0 +1,63 @@
package sdk
import (
"gitea.weitiangame.com/sdk/wt-game/utils"
"strings"
"sync"
)
// OrderRefund 表示一个订单退款对象,用于生成签名参数
type OrderRefund struct {
OutTradeNo string // 订单号
RoleId string // 角色ID
Status string // 订单状态
RefundFee string // 退款金额
Timestamp string // 时间戳
}
// RefundSDK 封装了SDK配置和工具方法
type RefundSDK struct {
SecretKey string // 密钥
}
// 全局变量,用于保存单例实例和线程安全控制
var (
instance2 *RefundSDK
once2 sync.Once // 确保单例实例只初始化一次
)
// NewRefundSDK 返回一个使用密钥初始化的 RefundSDK 单例实例
func NewRefundSDK(secretKey string) *RefundSDK {
// 使用 sync.Once 确保实例只初始化一次
once2.Do(func() {
instance2 = &RefundSDK{
SecretKey: secretKey,
}
})
return instance2
}
// SignParam 为指定的 OrderRefund 对象生成签名
func (sdk *RefundSDK) SignParam(order *OrderRefund) string {
// 创建用于签名的参数字符串
paramStr := sdk.createFormUrl(order)
// 生成MD5签名
md5Str := utils.Md5String(paramStr)
// 返回大写的签名
return strings.ToUpper(md5Str)
}
// createFormUrl 生成用于签名的参数字符串
func (sdk *RefundSDK) createFormUrl(order *OrderRefund) string {
var builder strings.Builder
// 按顺序拼接所有参数
builder.WriteString(order.OutTradeNo)
builder.WriteString(order.RoleId)
builder.WriteString(order.Status)
builder.WriteString(order.RefundFee)
builder.WriteString(order.Timestamp)
// 拼接密钥
builder.WriteString(sdk.SecretKey)
// 返回拼接后的字符串
return builder.String()
}

@ -6,11 +6,11 @@ import (
"testing"
)
var newSdk = sdk.New("your-secret-key")
var orderSdk = sdk.NewOrderPayment("your-secret-key")
func TestOrderSign(t *testing.T) {
// Generate signed parameters
signature, err := newSdk.SignParam(&sdk.Order{
signature, err := orderSdk.SignParam(&sdk.Order{
Uid: "1",
BsTradeNo: "trade123",
Role: "user",
@ -32,3 +32,19 @@ func TestOrderSign(t *testing.T) {
// Example output
fmt.Println(signature)
}
var refundSdk = sdk.NewRefundSDK("your-secret-key")
func TestRefundSign(t *testing.T) {
// Generate signed parameters
signature := refundSdk.SignParam(&sdk.OrderRefund{
OutTradeNo: "trade123",
RoleId: "1234",
Status: "1",
RefundFee: "100",
Timestamp: "1234567890",
})
// Example output
fmt.Println(signature)
}

@ -0,0 +1,12 @@
package utils
import (
"crypto/md5"
"encoding/hex"
)
// Md5String 生成给定字符串的MD5哈希值并返回十六进制字符串
func Md5String(str string) string {
hash := md5.Sum([]byte(str)) // 计算MD5哈希
return hex.EncodeToString(hash[:]) // 转为十六进制字符串并返回
}
Loading…
Cancel
Save