192 lines
4.4 KiB
Markdown
192 lines
4.4 KiB
Markdown
# Payment SDK
|
||
|
||
支付能力独立 SDK,封装邮储手机银行支付、查询、退款、对账单、回调验签等能力,供支付中心或其他业务系统复用。
|
||
|
||
## 功能特性
|
||
|
||
- 支付链接生成(SM2+SM4 加密)
|
||
- 订单支付状态查询
|
||
- 退款申请
|
||
- 对账单查询与下载
|
||
- 回调通知验签与解密
|
||
- 工具方法:订单号生成、Map 转签名字符串、HMAC-SHA256 签名
|
||
|
||
## 快速开始
|
||
|
||
### 1. 初始化客户端
|
||
|
||
```go
|
||
import "qteam/app/sdk/payment"
|
||
|
||
cfg := payment.Config{
|
||
MerchantId: "yourMerchantId",
|
||
MchtNo: "yourMchtNo",
|
||
AppID: "yourAppId",
|
||
SopPublicKey: "yourSopPublicKey",
|
||
PrivateKey: "yourPrivateKey",
|
||
Pubkey: "yourPubkey",
|
||
BankKey: "yourBankKey",
|
||
Sha: "yourShaKey",
|
||
ReturnUrl: "https://your-domain.com/return",
|
||
SuccessUrl: "https://your-domain.com/success",
|
||
NotifyUrl: "https://your-domain.com/notify",
|
||
ShowTitleBar: "1",
|
||
LoginHost: "https://login.example.com/",
|
||
OrderHost: "https://order.example.com/",
|
||
FileHost: "https://file.example.com/",
|
||
ShopId: "yourShopId",
|
||
}
|
||
|
||
client := payment.NewClient(cfg)
|
||
```
|
||
|
||
### 2. 创建支付链接
|
||
|
||
```go
|
||
link, err := client.CreatePaymentLink(payment.PaymentLinkRequest{
|
||
OrderNo: payment.GenerateOrderNumber(),
|
||
ProductName: "测试商品",
|
||
Price: "19.90",
|
||
BackUrl: "https://mall.example.com/pay",
|
||
})
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
fmt.Println("支付链接:", link.PayUrl)
|
||
fmt.Println("订单号:", link.OrderNo)
|
||
fmt.Println("前端验签:", link.Sign)
|
||
```
|
||
|
||
### 3. 查询订单
|
||
|
||
```go
|
||
result, err := client.OrderQuery("SJ20240101000000001")
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
fmt.Println("订单状态:", result.OrderSta)
|
||
fmt.Println("响应码:", result.RespCode)
|
||
```
|
||
|
||
### 4. 申请退款
|
||
|
||
```go
|
||
refund, err := client.Refund(payment.RefundRequest{
|
||
OrderNo: "SJ20240101000000001",
|
||
Price: "19.90",
|
||
OrgTxnSeq: "bankOrderNo123",
|
||
RefundDesc: "用户主动退款",
|
||
})
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
fmt.Println("退款订单号:", refund.RefundOrderNo)
|
||
fmt.Println("退款状态:", refund.RefundOrderSta)
|
||
```
|
||
|
||
### 5. 对账单查询与下载
|
||
|
||
```go
|
||
// 查询对账单
|
||
bill, err := client.BillQuery(time.Now())
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
// 下载对账单
|
||
for _, file := range bill.Files {
|
||
fileId := file["fileId"].(string)
|
||
data, err := client.BillDownload(fileId, time.Now())
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
// 处理对账单数据
|
||
}
|
||
```
|
||
|
||
### 6. 处理回调通知
|
||
|
||
```go
|
||
// 解密通知
|
||
decrypted, err := client.DecryptNotify(rawJson)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
// 验签并解析
|
||
notifyData, err := client.VerifyAndParseNotify(rawJson)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
fmt.Println("通知数据:", notifyData)
|
||
```
|
||
|
||
## 核心类型说明
|
||
|
||
### Config
|
||
|
||
支付配置,包含商户信息、密钥、URL 等必要配置。
|
||
|
||
### PaymentLinkRequest
|
||
|
||
```go
|
||
type PaymentLinkRequest struct {
|
||
OrderNo string
|
||
ProductName string
|
||
Price string
|
||
BackUrl string
|
||
}
|
||
```
|
||
|
||
### PaymentLinkResponse
|
||
|
||
```go
|
||
type PaymentLinkResponse struct {
|
||
OrderNo string
|
||
NotifyUrl string
|
||
Sign string
|
||
PlainText string
|
||
PayUrl string
|
||
}
|
||
```
|
||
|
||
### OrderQueryResponse
|
||
|
||
```go
|
||
type OrderQueryResponse struct {
|
||
OrderNo string
|
||
OrderSta string
|
||
RespCode string
|
||
RespMsg string
|
||
}
|
||
```
|
||
|
||
### RefundResponse
|
||
|
||
```go
|
||
type RefundResponse struct {
|
||
RespCode string
|
||
RespMsg string
|
||
RefundOrderNo string
|
||
RefundOrderSta string
|
||
TxnAmt string
|
||
}
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **密钥安全**:私钥、公钥等敏感信息请通过配置中心或环境变量传入,不要硬编码在代码中。
|
||
2. **并发安全**:`GenerateOrderNumber` 和 `RandomNumber` 基于时间戳生成,高并发场景下建议由调用方保证唯一性。
|
||
3. **错误处理**:所有接口均返回 `error`,调用方需根据业务场景处理重试、降级等逻辑。
|
||
4. **状态码映射**:邮储订单状态码 `03-支付成功`、`04-支付失败`、`05-检查失败` 等,请参考 `types.go` 中的常量定义。
|
||
|
||
## 与现有系统集成建议
|
||
|
||
- **支付中心**:可直接使用此 SDK 封装统一支付服务。
|
||
- **业务系统**:通过依赖此 SDK 接入支付能力,避免重复实现加密、验签逻辑。
|
||
- **测试环境**:可通过 `Config` 切换测试环境地址和密钥。
|