package wechatrepoimpl import ( "fmt" "strings" "github.com/go-kratos/kratos/v2/errors" err2 "voucher/api/err" ) // ErrCode 定义错误码类型 // https://pay.weixin.qq.com/doc/v3/merchant/4012463767 type ErrCode string // 定义错误码常量 const ( APPID_MCHID_NOT_MATCH ErrCode = "APPID_MCHID_NOT_MATCH" INVALID_REQUEST ErrCode = "INVALID_REQUEST" PARAM_ERROR ErrCode = "PARAM_ERROR" MCH_NOT_EXISTS ErrCode = "MCH_NOT_EXISTS" NOT_ENOUGH ErrCode = "NOT_ENOUGH" REQUEST_BLOCKED ErrCode = "REQUEST_BLOCKED" RULE_LIMIT ErrCode = "RULE_LIMIT" USER_ACCOUNT_ABNORMAL ErrCode = "USER_ACCOUNT_ABNORMAL" RESOURCE_NOT_EXISTS ErrCode = "RESOURCE_NOT_EXISTS" FREQUENCY_LIMITED ErrCode = "FREQUENCY_LIMITED" ) // APIError 定义 API 错误结构体 type APIError struct { StatusCode int `json:"status_code"` ErrorCode ErrCode `json:"error_code"` Description string `json:"description"` Hint string `json:"hint"` } // 定义错误映射,方便根据错误码获取错误信息 var _ = map[ErrCode][]APIError{ APPID_MCHID_NOT_MATCH: { { StatusCode: 400, ErrorCode: APPID_MCHID_NOT_MATCH, Description: "商户号与AppID不匹配", Hint: "调用接口的商户号需与接口传入的AppID有绑定关系,请参考常见问题Q4", }, }, INVALID_REQUEST: { { StatusCode: 400, ErrorCode: INVALID_REQUEST, Description: "OpenID与AppID不匹配", Hint: "OpenID与AppID需有对应关系", }, { StatusCode: 400, ErrorCode: INVALID_REQUEST, Description: "非法的商户号", Hint: "请检查商户号准确性", }, { StatusCode: 400, ErrorCode: INVALID_REQUEST, Description: "调用频率过高", Hint: "请降低API调用频率", }, { StatusCode: 400, ErrorCode: INVALID_REQUEST, Description: "活动已结束或未激活", Hint: "请检查批次状态", }, { StatusCode: 400, ErrorCode: INVALID_REQUEST, Description: "批次信息获取失败,请确认参数是否有误", Hint: "请检查创建商户号与批次号的对应关系", }, }, PARAM_ERROR: { { StatusCode: 400, ErrorCode: PARAM_ERROR, Description: "AppID必填", Hint: "请输入AppID", }, { StatusCode: 400, ErrorCode: PARAM_ERROR, Description: "OpenID必填", Hint: "请输入OpenID", }, { StatusCode: 400, ErrorCode: PARAM_ERROR, Description: "批次号必填", Hint: "请输入批次号", }, { StatusCode: 400, ErrorCode: PARAM_ERROR, Description: "商户号必填", Hint: "请输入商户号", }, { StatusCode: 400, ErrorCode: PARAM_ERROR, Description: "非法的批次状态", Hint: "请检查批次状态,仅支持发放状态为“运营中”的代金券批次", }, }, MCH_NOT_EXISTS: { { StatusCode: 403, ErrorCode: MCH_NOT_EXISTS, Description: "商户号不合法", Hint: "请检查商户号准确性", }, }, NOT_ENOUGH: { { StatusCode: 403, ErrorCode: NOT_ENOUGH, Description: "批次预算不足", Hint: "批次预算已发放完,请补充批次预算", }, { StatusCode: 403, ErrorCode: NOT_ENOUGH, Description: "发券超过单天限额", Hint: "已超过该批次设置的单天发放限制额度,无法发放", }, { StatusCode: 403, ErrorCode: NOT_ENOUGH, Description: "账户余额不足,请充值", Hint: "商户号余额不足,无法继续发券,请充值", }, { StatusCode: 403, ErrorCode: NOT_ENOUGH, Description: "批次预算耗尽", Hint: "该批次的预算已经耗尽", }, }, REQUEST_BLOCKED: { { StatusCode: 403, ErrorCode: REQUEST_BLOCKED, Description: "商户无权发券", Hint: "该批次不支持其他商户发放,请参考常见问题Q1", }, { StatusCode: 403, ErrorCode: REQUEST_BLOCKED, Description: "批次不支持跨商户发券", Hint: "该批次不支持其他商户发放,请参考常见问题Q1", }, { StatusCode: 403, ErrorCode: REQUEST_BLOCKED, Description: "用户被限领拦截", Hint: "该用户已达到该批次的领取上限,请参考常见问题Q6", }, { StatusCode: 403, ErrorCode: REQUEST_BLOCKED, Description: "不能在API渠道发放", Hint: "请检查批次信息,仅支持发放微信支付代金券,不支持发放立减与折扣", }, { StatusCode: 403, ErrorCode: REQUEST_BLOCKED, Description: "不支持指定面额发券", Hint: "仅在发券时指定面额及门槛的场景才生效,常规发券场景请勿传入该信息", }, { StatusCode: 403, ErrorCode: REQUEST_BLOCKED, Description: "仅在广告场景下发放批次", Hint: "该批次已在朋友圈广告发放,不支持在其他渠道发放", }, }, RULE_LIMIT: { { StatusCode: 403, ErrorCode: RULE_LIMIT, Description: "用户已达最大领券次数", Hint: "该用户已达到该批次的领取上限,请参考常见问题Q6", }, { StatusCode: 403, ErrorCode: RULE_LIMIT, Description: "被自然人规则拦截", Hint: "该自然人已达到该批次的领取上限,请参考常见问题Q6", }, }, USER_ACCOUNT_ABNORMAL: { { StatusCode: 403, ErrorCode: USER_ACCOUNT_ABNORMAL, Description: "用户非法", Hint: "用户命中微信支付风控模型,请参考常见问题Q5", }, }, RESOURCE_NOT_EXISTS: { { StatusCode: 404, ErrorCode: RESOURCE_NOT_EXISTS, Description: "批次不存在", Hint: "请检查批次及制券商户号信息", }, }, FREQUENCY_LIMITED: { { StatusCode: 429, ErrorCode: FREQUENCY_LIMITED, Description: "当前请求人数过多,请稍后重试", Hint: "请降低API调用频率", }, }, } // 使用常量定义错误描述,减少硬编码 const ( ErrorWechatUserIllegal = "用户非法" ErrorWechatAppIDMchIDMismatch = "商户号与AppID不匹配" ErrorWechatOpenIDAppIDMismatch = "OpenID与AppID不匹配" ErrorWechatInvalidMerchantID = "非法的商户号" ErrorWechatHighFrequency = "调用频率过高" ErrorWechatActivityInactive = "活动已结束或未激活" ErrorWechatBatchInfoError = "批次信息获取失败,请确认参数是否有误" ErrorWechatAppIDRequired = "AppID必填" ErrorWechatOpenIDRequired = "OpenID必填" ErrorWechatBatchIDRequired = "批次号必填" ErrorWechatMerchantIDRequired = "商户号必填" ErrorWechatInvalidBatchStatus = "非法的批次状态" ErrorWechatMchNotExists = "商户号不合法" ErrorWechatBatchBudgetInsufficient = "批次预算不足" ErrorWechatDailyLimitExceeded = "发券超过单天限额" ErrorWechatAccountBalanceInsufficient = "账户余额不足,请充值" ErrorWechatBatchBudgetDepleted = "批次预算耗尽" ErrorWechatMerchantNoPermission = "商户无权发券" ErrorWechatCrossMerchantNotSupported = "批次不支持跨商户发券" ErrorWechatUserReceiveLimit = "用户被限领拦截" ErrorWechatAPIChannelNotSupported = "不能在API渠道发放" ErrorWechatSpecifiedDenominationNotSupported = "不支持指定面额发券" ErrorWechatOnlyAdvertisingBatch = "仅在广告场景下发放批次" ErrorWechatUserMaxCoupons = "用户已达最大领券次数" ErrorWechatNaturalPersonRuleBlocked = "被自然人规则拦截" ErrorWechatResourceNotExists = "批次不存在" ErrorWechatFrequencyLimited = "当前请求人数过多,请稍后重试" ErrorWechatAccountFail = "该用户账号异常,无法领券。商家可联系微信支付或让用户联系微信支付客服处理" ) // WechatError 映射错误描述到具体的错误处理 var WechatError = map[string]*errors.Error{ ErrorWechatUserIllegal: err2.ErrorWechatUserIllegal(ErrorWechatUserIllegal), ErrorWechatAppIDMchIDMismatch: err2.ErrorWechatAppIDMchIDMismatch(ErrorWechatAppIDMchIDMismatch), ErrorWechatOpenIDAppIDMismatch: err2.ErrorWechatOpenIDAppIDMismatch(ErrorWechatOpenIDAppIDMismatch), ErrorWechatInvalidMerchantID: err2.ErrorWechatInvalidMerchantID(ErrorWechatInvalidMerchantID), ErrorWechatHighFrequency: err2.ErrorWechatHighFrequency(ErrorWechatHighFrequency), ErrorWechatActivityInactive: err2.ErrorWechatActivityInactive(ErrorWechatActivityInactive), ErrorWechatBatchInfoError: err2.ErrorWechatBatchInfoError(ErrorWechatBatchInfoError), ErrorWechatAppIDRequired: err2.ErrorWechatAppIDRequired(ErrorWechatAppIDRequired), ErrorWechatOpenIDRequired: err2.ErrorWechatOpenIDRequired(ErrorWechatOpenIDRequired), ErrorWechatBatchIDRequired: err2.ErrorWechatBatchIDRequired(ErrorWechatBatchIDRequired), ErrorWechatMerchantIDRequired: err2.ErrorWechatMerchantIDRequired(ErrorWechatMerchantIDRequired), ErrorWechatInvalidBatchStatus: err2.ErrorWechatInvalidBatchStatus(ErrorWechatInvalidBatchStatus), ErrorWechatMchNotExists: err2.ErrorWechatMchNotExists(ErrorWechatMchNotExists), ErrorWechatBatchBudgetInsufficient: err2.ErrorWechatBatchBudgetInsufficient(ErrorWechatBatchBudgetInsufficient), ErrorWechatDailyLimitExceeded: err2.ErrorWechatDailyLimitExceeded(ErrorWechatDailyLimitExceeded), ErrorWechatAccountBalanceInsufficient: err2.ErrorWechatAccountBalanceInsufficient(ErrorWechatAccountBalanceInsufficient), ErrorWechatBatchBudgetDepleted: err2.ErrorWechatBatchBudgetDepleted(ErrorWechatBatchBudgetDepleted), ErrorWechatMerchantNoPermission: err2.ErrorWechatMerchantNoPermission(ErrorWechatMerchantNoPermission), ErrorWechatCrossMerchantNotSupported: err2.ErrorWechatCrossMerchantNotSupported(ErrorWechatCrossMerchantNotSupported), ErrorWechatUserReceiveLimit: err2.ErrorWechatUserReceiveLimit(ErrorWechatUserReceiveLimit), ErrorWechatAPIChannelNotSupported: err2.ErrorWechatAPIChannelNotSupported(ErrorWechatAPIChannelNotSupported), ErrorWechatSpecifiedDenominationNotSupported: err2.ErrorWechatSpecifiedDenominationNotSupported(ErrorWechatSpecifiedDenominationNotSupported), ErrorWechatOnlyAdvertisingBatch: err2.ErrorWechatOnlyAdvertisingBatch(ErrorWechatOnlyAdvertisingBatch), ErrorWechatUserMaxCoupons: err2.ErrorWechatUserMaxCoupons(ErrorWechatUserMaxCoupons), ErrorWechatNaturalPersonRuleBlocked: err2.ErrorWechatNaturalPersonRuleBlocked(ErrorWechatNaturalPersonRuleBlocked), ErrorWechatResourceNotExists: err2.ErrorWechatResourceNotExists(ErrorWechatResourceNotExists), ErrorWechatFrequencyLimited: err2.ErrorWechatFrequencyLimited(ErrorWechatFrequencyLimited), ErrorWechatAccountFail: err2.ErrorWechatAccountFail(ErrorWechatAccountFail), } type ErrBody struct { Code ErrCode `json:"Code"` Message string `json:"Message"` } // GetWechatError 根据错误描述获取具体的错误处理 func (s ErrBody) GetWechatError() *errors.Error { lowerDesc := strings.ToLower(s.Message) for desc, err := range WechatError { if strings.ToLower(desc) == lowerDesc { return err } } return err2.ErrorWechatFAIL(fmt.Sprintf("微信返回错误:%s", s.Message)) }