f
This commit is contained in:
@@ -683,3 +683,172 @@ func (y *YunYinSignPayService) QueryPayeeBill(ctx context.Context, sourceOrderCo
|
||||
RefundAmount: billItem.RefundAmount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RefundPayeeBillRequest 退款请求
|
||||
type RefundPayeeBillRequest struct {
|
||||
SourceOrderCode string `json:"sourceOrderCode,omitempty"` // 来源订单号(与 participateId 二选一)
|
||||
ParticipateId int64 `json:"participateId,omitempty"` // 参与方ID(与 sourceOrderCode 二选一)
|
||||
RefundAmount float64 `json:"refundAmount"` // 退款金额(必填)
|
||||
RefundReason string `json:"refundReason,omitempty"` // 退款原因(可选)
|
||||
}
|
||||
|
||||
// RefundPayeeBillResponse 退款响应
|
||||
type RefundPayeeBillResponse struct {
|
||||
Code interface{} `json:"code"` // 返回码,可能是字符串"200"或数字200
|
||||
Msg string `json:"msg"` // 返回码的描述信息
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// GetCodeInt 获取 code 的 int 值
|
||||
func (r *RefundPayeeBillResponse) GetCodeInt() int {
|
||||
switch v := r.Code.(type) {
|
||||
case int:
|
||||
return v
|
||||
case float64:
|
||||
return int(v)
|
||||
case string:
|
||||
if v == "200" {
|
||||
return 200
|
||||
}
|
||||
return 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// RefundPayeeBill 发起退款
|
||||
func (y *YunYinSignPayService) RefundPayeeBill(ctx context.Context, sourceOrderCode string, participateId int64, refundAmount float64, refundReason string) error {
|
||||
// 1. 获取token和操作ID(带缓存)
|
||||
accessToken, err := y.GetAccessToken(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取云印签token失败: %v", err)
|
||||
}
|
||||
|
||||
operationUserId, err := y.GetUserId(ctx, accessToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取云印签操作ID失败: %v", err)
|
||||
}
|
||||
|
||||
// 2. 如果只提供了 sourceOrderCode,需要先查询收款单获取 participateId
|
||||
if participateId == 0 && sourceOrderCode != "" {
|
||||
// 查询收款单列表获取 participateId
|
||||
reqBody := QueryPayeeBillRequest{
|
||||
SourceOrderCode: sourceOrderCode,
|
||||
ListPageNo: 1,
|
||||
ListPageSize: 10,
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return fmt.Errorf("序列化查询请求失败: %v", err)
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/signFlowBill/payeeBillList", y.config.ApiURL)
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(jsonData))
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建查询请求失败: %v", err)
|
||||
}
|
||||
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
httpReq.Header.Set("appId", y.config.AppID)
|
||||
httpReq.Header.Set("accessToken", accessToken)
|
||||
httpReq.Header.Set("userId", operationUserId)
|
||||
httpReq.Header.Set("source", "pc")
|
||||
|
||||
resp, err := y.client.Do(httpReq)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取查询响应失败: %v", err)
|
||||
}
|
||||
|
||||
var queryResp QueryPayeeBillResponse
|
||||
if err := json.Unmarshal(body, &queryResp); err != nil {
|
||||
return fmt.Errorf("解析查询响应失败: %v, 响应内容: %s", err, string(body))
|
||||
}
|
||||
|
||||
codeInt := queryResp.GetCodeInt()
|
||||
if codeInt != 200 {
|
||||
return fmt.Errorf("查询收款单失败: %s", queryResp.Msg)
|
||||
}
|
||||
|
||||
if len(queryResp.Data) == 0 {
|
||||
return fmt.Errorf("未找到匹配的收款单记录,订单号: %s", sourceOrderCode)
|
||||
}
|
||||
|
||||
// 获取第一条记录的 participateId
|
||||
billItem := queryResp.Data[0]
|
||||
participateId = billItem.ParticipateID
|
||||
logx.Infof("通过订单号查询到参与方ID: %d", participateId)
|
||||
}
|
||||
|
||||
// 3. 验证参数
|
||||
if participateId == 0 {
|
||||
return fmt.Errorf("参与方ID不能为空,请提供 participateId 或 sourceOrderCode")
|
||||
}
|
||||
|
||||
if refundAmount <= 0 {
|
||||
return fmt.Errorf("退款金额必须大于0")
|
||||
}
|
||||
|
||||
// 4. 构建退款请求
|
||||
refundReq := RefundPayeeBillRequest{
|
||||
RefundAmount: refundAmount,
|
||||
RefundReason: refundReason,
|
||||
}
|
||||
|
||||
// 优先使用 participateId
|
||||
if participateId > 0 {
|
||||
refundReq.ParticipateId = participateId
|
||||
} else if sourceOrderCode != "" {
|
||||
// 如果 participateId 仍然为0,使用 sourceOrderCode
|
||||
refundReq.SourceOrderCode = sourceOrderCode
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(refundReq)
|
||||
if err != nil {
|
||||
return fmt.Errorf("序列化退款请求失败: %v", err)
|
||||
}
|
||||
|
||||
// 5. 调用退款API
|
||||
url := fmt.Sprintf("%s/signFlowBill/refund", y.config.ApiURL)
|
||||
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(jsonData))
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建退款请求失败: %v", err)
|
||||
}
|
||||
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
httpReq.Header.Set("appId", y.config.AppID)
|
||||
httpReq.Header.Set("accessToken", accessToken)
|
||||
httpReq.Header.Set("userId", operationUserId)
|
||||
httpReq.Header.Set("source", "pc")
|
||||
|
||||
resp, err := y.client.Do(httpReq)
|
||||
if err != nil {
|
||||
return fmt.Errorf("退款请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取退款响应失败: %v", err)
|
||||
}
|
||||
|
||||
var refundResp RefundPayeeBillResponse
|
||||
if err := json.Unmarshal(body, &refundResp); err != nil {
|
||||
return fmt.Errorf("解析退款响应失败: %v, 响应内容: %s", err, string(body))
|
||||
}
|
||||
|
||||
// 6. 检查响应码
|
||||
codeInt := refundResp.GetCodeInt()
|
||||
if codeInt != 200 {
|
||||
return fmt.Errorf("退款失败: %s", refundResp.Msg)
|
||||
}
|
||||
|
||||
logx.Infof("云印签退款成功,参与方ID: %d, 退款金额: %.2f, 退款原因: %s", participateId, refundAmount, refundReason)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user