Files
junhong_cmp_fiber/pkg/fuiou/notify.go
huang a308ee228b feat: 新增富友支付 SDK(RSA 签名、GBK 编解码、XML 协议、回调验签)
- pkg/fuiou/types.go: WxPreCreateRequest/Response、NotifyRequest 等 XML 结构体
- pkg/fuiou/client.go: Client 结构体、NewClient、字典序+GBK+MD5+RSA 签名/验签、HTTP 请求
- pkg/fuiou/wxprecreate.go: WxPreCreate 方法,支持公众号 JSAPI(JSAPI)和小程序(LETPAY)
- pkg/fuiou/notify.go: VerifyNotify(GBK→UTF-8+XML 解析+RSA 验签)、BuildNotifyResponse

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-16 23:28:42 +08:00

85 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package fuiou
import (
"encoding/xml"
"fmt"
"net/url"
"strings"
)
// VerifyNotify 验证回调通知并解析数据
// rawBody: 原始请求 body可能包含 req= 前缀的 URL 编码 GBK XML
func (c *Client) VerifyNotify(rawBody []byte) (*NotifyRequest, error) {
content := string(rawBody)
// 处理 req= 前缀(富友回调可能以 form 格式发送)
if strings.HasPrefix(content, "req=") {
content = content[4:]
}
// URL 解码
decoded, err := url.QueryUnescape(content)
if err != nil {
return nil, fmt.Errorf("URL 解码回调数据失败: %w", err)
}
// GBK → UTF-8
utf8Bytes, err := GBKToUTF8([]byte(decoded))
if err != nil {
return nil, fmt.Errorf("GBK 转 UTF-8 失败: %w", err)
}
// 替换编码声明
utf8Str := strings.Replace(string(utf8Bytes), `encoding="GBK"`, `encoding="UTF-8"`, 1)
// XML 解析
var notify NotifyRequest
if err := xml.Unmarshal([]byte(utf8Str), &notify); err != nil {
return nil, fmt.Errorf("XML 解析回调数据失败: %w", err)
}
// 验证签名
if err := c.Verify(&notify, notify.Sign); err != nil {
return nil, fmt.Errorf("回调签名验证失败: %w", err)
}
// 检查结果码
if notify.ResultCode != "000000" {
return &notify, fmt.Errorf("回调结果非成功: %s - %s", notify.ResultCode, notify.ResultMsg)
}
return &notify, nil
}
// BuildNotifySuccessResponse 构建成功响应GBK 编码的 XML
func BuildNotifySuccessResponse() []byte {
return buildNotifyResponse("000000", "success")
}
// BuildNotifyFailResponse 构建失败响应GBK 编码的 XML
func BuildNotifyFailResponse(msg string) []byte {
return buildNotifyResponse("999999", msg)
}
// buildNotifyResponse 构建回调响应 XMLGBK 编码)
func buildNotifyResponse(code, msg string) []byte {
resp := NotifyResponse{
ResultCode: code,
ResultMsg: msg,
}
xmlBytes, err := xml.Marshal(resp)
if err != nil {
return []byte(`<?xml version="1.0" encoding="GBK"?><xml><result_code>999999</result_code><result_msg>internal error</result_msg></xml>`)
}
xmlStr := `<?xml version="1.0" encoding="GBK"?>` + string(xmlBytes)
gbkBytes, err := utf8ToGBK([]byte(xmlStr))
if err != nil {
return []byte(xmlStr)
}
return gbkBytes
}