300 lines
12 KiB
Go
300 lines
12 KiB
Go
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 = "当前请求人数过多,请稍后重试"
|
||
)
|
||
|
||
// 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),
|
||
}
|
||
|
||
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))
|
||
}
|