package payment import ( "encoding/json" "fmt" "time" ) // Refund 申请退款 // 对齐 YouChuKoffee 的 OrderRefund 流程: // 1. 构建完整 {head, body} 结构(body 包含 busiMainId, reqTransTime, data) // 2. 整个 {head, body} 一起加密 // 3. head 同时作为 HTTP Header 明文传输 func (c *Client) Refund(req RefundRequest) (*RefundResponse, error) { now := time.Now().Format("20060102150405") BusiMainId := now + RandomNumber(10) // 构建完整 request(head+body 一起加密,对齐 YouChuKoffee) requestBody := map[string]interface{}{ "head": map[string]string{ "partnerTxSriNo": BusiMainId, "reqTime": now, "method": "b2c.gatewaypay.orderRefund", "version": "1", "merchantId": c.cfg.MerchantId, "appID": c.cfg.AppID, "accessType": "API", "reserve": "", }, "body": map[string]interface{}{ "busiMainId": BusiMainId, "reqTransTime": now, "data": map[string]string{ "txnCode": "1003", "sourceId": "16", "reqTraceId": req.OrderNo + now[4:14], // MMDDHHmmss 10位后缀 "reqDate": now, // 14 位 YYYYMMDDHHmmss "mchtNo": c.cfg.MchtNo, "orgTxnSeq": req.OrgTxnSeq, "txnAmt": req.Price, "orgTxnAmt": req.Price, "refundDesc": "用户主动退款", }, }, } // 整个 {head, body} 一起加密 encryptedReq, err := EncryptRequest(requestBody, c.cfg) if err != nil { return nil, fmt.Errorf("加密请求失败: %v", err) } encryptedBytes, _ := json.Marshal(encryptedReq) url := c.cfg.OrderHost + c.cfg.MerchantId + ".htm?partnerTxSriNo=" + BusiMainId // head 同时作为 HTTP Header 明文传输 head := requestBody["head"].(map[string]string) body, err := c.doPost(url, head, encryptedBytes) if err != nil { return nil, err } responseData, err := c.DecryptResponse(string(body), false) if err != nil { return nil, fmt.Errorf("解密响应失败: %v,原始响应: %s", err, string(body)) } var result RefundResponse if err := json.Unmarshal([]byte(responseData), &result); err != nil { return nil, fmt.Errorf("解析响应失败: %v,响应内容: %s", err, responseData) } if result.RespCode != "" && result.RespCode != "0000" && result.RespCode != "00" { return nil, fmt.Errorf("退款申请失败,错误码: %s,错误信息: %s", result.RespCode, result.RespMsg) } return &result, nil }