
本文详解如何在 Go Web 服务中接收并解析 iOS(Swift)通过 NSJSONSerialization 发送的 JSON 数据,包括结构体定义、请求体读取、JSON 反序列化及 receipt 字段的 Base64 编码处理。
本文详解如何在 go web 服务中接收并解析 ios(swift)通过 `nsjsonserialization` 发送的 json 数据,包括结构体定义、请求体读取、json 反序列化及 receipt 字段的 base64 编码处理。
在 iOS 端,你使用 NSJSONSerialization.dataWithJSONObject(...) 将字典(如 ["receipt": receiptData, "prod_id": "com.example.product"])序列化为 UTF-8 编码的 JSON 字节流,并作为 HTTP POST 请求体发送——这意味着 Go 服务器接收到的是标准 JSON 格式(非 raw binary),其 Content-Type 应为 application/json(建议客户端显式设置:request.addValue("application/json", forHTTPHeaderField: "Content-Type"))。
在 Go 侧,需按以下步骤安全、规范地解析:
-
定义匹配的结构体
结构体字段名应与 JSON 键名一致(大小写敏感),并通过 json tag 显式映射。注意:iOS 传入的 receipt 是 NSData(即原始二进制数据),经 NSJSONSerialization 序列化后,在 JSON 中实际为 Base64 编码字符串(iOS 自动完成),因此 Go 中应声明为 string 类型;prod_id 同理为字符串。
type ReceiptRequest struct {
Receipt string `json:"receipt"` // iOS 自动将 NSData 转为 Base64 字符串
ProdID string `json:"prod_id"` // 注意 key 名需与 iOS 字典键完全一致
}
-
读取并解析请求体
使用 ioutil.ReadAll(Go 1.16+ 推荐改用 io.ReadAll)读取完整请求体,再通过 json.Unmarshal 解析到结构体实例。务必检查错误并及时关闭 request.Body:
func handleReceipt(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 读取请求体
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
return
}
defer r.Body.Close() // 防止资源泄漏
// 解析 JSON 到结构体
var req ReceiptRequest
if err := json.Unmarshal(body, &req); err != nil {
http.Error(w, "Invalid JSON format", http.StatusBadRequest)
return
}
// 此时 req.Receipt 即为 Base64 编码的字符串(iOS 生成)
// 如需还原为原始字节(例如验证 Apple Receipt),可解码:
receiptBytes, err := base64.StdEncoding.DecodeString(req.Receipt)
if err != nil {
http.Error(w, "Invalid Base64 in receipt", http.StatusBadRequest)
return
}
// ✅ 现在 receiptBytes 就是原始 receipt 二进制数据
// 可用于后续 Apple IAP 验证逻辑(如 POST 到 https://buy.itunes.apple.com/verifyReceipt)
// 示例:打印 prod_id 和 receipt 长度
log.Printf("Received product ID: %s, receipt length: %d bytes", req.ProdID, len(receiptBytes))
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
}
⚠️ 关键注意事项:
- iOS 的 NSJSONSerialization 对 NSData 默认执行 Base64 编码并转为字符串(符合 JSON 规范),因此 Go 中直接接收 string 类型即可,无需手动处理二进制边界;
- 若未来需传输纯二进制(非 JSON 封装),应改用 multipart/form-data 或自定义 Content-Type,此时才需像旧方案一样直接读取 request.Body 并 Base64 编码;
- 始终校验 Content-Type: application/json(可选增强安全性);
- 生产环境务必添加超时、限流及日志审计,尤其对 Apple 收据验证等敏感操作。
通过以上方式,你的 Go 服务器即可健壮、清晰地对接 iOS 客户端发送的结构化 JSON 请求,为应用内购验证提供可靠后端支持。











