接口返回值校验

目录

一、背景

二、基础匹配规则

1、值校验

(1)完全匹配校验-Matcher

(2)正则匹配校验-Term

(3)枚举匹配校验-Enum

2、类型校验-Like

3、数组类型校验-EachLike

三、复杂数据结果匹配规则

1、{{}}格式-字典套叠

2、[{}]格式-数组字典套叠

3、{[]}

4、Like-Term 套叠

5、Like-Matcher套叠

四、异常场景匹配

1、null匹配nullable

2、{}匹配dict_emptiable

3、json格式串匹配jsonloads

4、key不存在匹配key_missable

5、多类型匹配extra_types

四、自动生成 json 契约


一、背景

接口返回的字段需要对返回结构校验、每个字段值类型、每个字段值校验

返回结果如果是json嵌套的情况且数组包含这样结果有伸缩性的,校验代码会很长,考虑返回的异常场景也多

例如:

data里面的结构体校验,似乎for循环也能解决,但是是不是需要”造轮子“,我想讲的是一个已经有的轮子--pip install pactverify

官网:https://pypi.org/project/pactverify/

{
    "msg": "success",
    "code": 0,
    "data": [{
            "type_id": 249,
            "name": "王者荣耀",
            "order_index": 1,
            "status": 1,
            "subtitle": " ",
            "game_name": "王者荣耀"
        }, {
            "type_id": 250,
            "name": "绝地求生",
            "order_index": 2,
            "status": 1,
            "subtitle": " ",
            "game_name": "绝地求生"
        }, {
            "type_id": 251,
            "name": "刺激战场",
            "order_index": 3,
            "status": 1,
            "subtitle": " ",
            "game_name": "刺激战场"
        }
    ]
}

二、基础匹配规则

1、值校验

(1)完全匹配校验-Matcher

学习点:from pactverify.matchers import Matcher, PactVerify, PactJsonVerify

Matcher声明的结构体需要完全匹配

python类契约---PactVerify类初始化

json类契约---PactJsonVerify类初始化

verify匹配后verify_result是匹配结果,verify_info是具体的错误信息

hard_mode=True, 默认为true,hard_mode = True时,实际返回key必须严格等于预期key;hard_mode = False时,实际返回key包含预期key即可

separator='$' 可自定义指定json关键字标识符,默认为$

注意:一旦匹配失败后,verify正确结构体也会是失败(应该是verify_info信息写入后重新verify没有重置造成的)

##############################################################################
# 校验值=11
# 1、python类契约格式
expect_format_1 = Matcher(11)
# 2、json契约格式
expect_format_json_1 = {
    "$Matcher": 11
}

# 校验值=1.0
# 1、python类契约格式
expect_format_2 = Matcher(1.0)
# 2、json契约格式
expect_format_json_2 = {
    '$Matcher': 1.0
}

# 校验值='1'
# 1、python类契约格式
expect_format_3 = Matcher('11')
# 2、json契约格式
expect_format_json_3 = {
    '$Matcher': '11'
}

################################################################################
# 校验值={'k1': 'v1'}
# 1、python类契约格式
expect_format_4 = Matcher({'k1': 'v1'})
# 2、json契约格式
expect_format_json_4 = {
    '$Matcher': {'k1': 'v1'}
}
# 使用实例---pactVerify初始化之后只能使用一次
>>> from pactverify.matchers import Matcher, PactVerify, PactJsonVerify
>>> p1_1 = PactVerify(expect_format_1,hard_mode=True)
>>> p1_1.verify(11)
>>> p1_1.verify_result
True
>>> p1_1.verify(12)
>>> p1_1.verify_result # 这里12是不匹配的,返回False
False
>>> p1_1.verify(11)
>>> p1_1.verify_result #接着使用p1_1,就不能正确匹配了,下面那样初始化下
False
>>> p1_1 = PactVerify(expect_format_1,hard_mode=True)
>>> p1_1.verify(11)
>>> p1_1.verify_result
True

>>> p1_2 = PactJsonVerify(expect_format_json_1,hard_mode=True, separator='$')
>>> p1_2.verify(11)
>>> p1_2.verify_result
True

# separate自定义
>>> expect_format_json_2 = {
...     '&Matcher': 1.0
... }
>>> pp= PactJsonVerify(expect_format_json_2,separator='&')
>>> pp.verify(1.0)
>>> pp.verify_result
True

#  hard_mode=False,实际多出来的k2没有校验
>>> p4_1 = PactVerify(expect_format_4,hard_mode=False)
>>> p4_1.verify({"k1":"v1","k2":"v2"})
>>> p4_1.verify_result

True

>>> p4_1 = PactVerify(expect_format_4,hard_mode=True)
>>> p4_1.verify({"k1":"v1"})
>>> p4_1.verify_result
True
>>> p4_1.verify({"k1":"v2"})
>>> p4_1.verify_result
False
>>> p4_1.verify_info
{'value_not_match_error': [{'actual_key': 'root.k1', 'actual_value': 'v2', 'expect_value': 'v1'}]}

(2)正则匹配校验-Term

example 、type_strict参数使用

from pactverify.matchers import Term

# 校验值=r'^\d{2}$'example为了校验类型,如下需要name的字段类型是int
# 1、python类契约
expect_format_1 = Term(r'^\d{2}$', example=11)
# 2、json契约--
expect_format_json_1 ={
        '$Like': {
            "name": {
                '$Term': {
                    '$values': r'^\d{2}$',
                    '$params': {
                        'example': 11
                    }
                }
            }
        }
    }

# 预期r'^\d{2}$',type_strict = False时跳过对example参数类型校验 
# 1、python类契约
expect_format_2 = Term(r'^\d{2}$', example="11", type_strict=False)
# 2、json契约
expect_format_json_2 = {
        '$Like': {
            "name": {
                '$Term': {
                    '$values': r'^\d{2}$',
                    '$params': {
                        'example': 11,
                        'type_strict': False
                    }
                }
            }
        }
    }
>>> pp=PactJsonVerify(expect_format_json_1, separator="$", hard_mode=True)
>>> pp.verify({"name":11})
>>> pp.verify_result
True
>>> pp.verify({"name":13})
>>> pp.verify_result
True
>>> pp.verify({"name":"22"})
>>> pp.verify_result
False
>>> pp.verify_info
{'type_not_match_error': [{'actual_key': 'root.name', 'actual_vaule': '22', 'expect_type': 'int'}]}
>>>

>>> pp1=PactJsonVerify(expect_format_json_2, separator="$", hard_mode=True)
>>> pp1.verify({"name":"22"})
>>> pp.verify_info
{}
>>> pp.verify_result
True

(3)枚举匹配校验-Enum

from pactverify.matchers import Enum

# 预期11或22  
#1、python类契约
expected_format_1 = Enum([11, 22])
# 2、json契约
expected_format_json_1 = {
    '$Enum': [11, 22]
}

# iterate_list为true时,当目标数据为数组时,会遍历数组中每个元素是否in [11, 22]  
#1、python类契约
expected_format_2 = Enum([11, 22], iterate_list=True)
# 2、json契约
expected_format_json_2 = {
    '$Enum': {
        '$values': [11, 22],
        '$params': {'iterate_list': True}
    }
}
>>> pp = PactVerify(expected_format_1,hard_mode=True)
>>> pp.verify(11)
>>> pp.verify_result
True
>>> pp.verify(22)
>>> pp.verify_result
True
>>> pp.verify(33)
>>> pp.verify_result
False
>>> pp.verify_info
{'enum_not_match_error': [{'actual_key': 'root', 'actual_value': 33, 'expect_enum': [11, 22]}]}

>>> pp1 = PactJsonVerify(expected_format_json_1,separator="$")
>>> pp1.verify(11)
>>> pp1.verify_result
True
>>> pp1.verify(33)
>>> pp1.verify_result
False
>>> pp1.verify_info
{'enum_not_match_error': [{'actual_key': 'root', 'actual_value': 33, 'expect_enum': [11, 22]}]}



>>> pp2 = PactJsonVerify(expected_format_json_2,separator="$")
>>> pp2.verify([11,22,11])
>>> pp2.verify_result
True
>>> pp2.verify([11,22,33])
>>> pp2.verify_result
False
>>> pp2.verify_info
{'enum_not_match_error': [{'actual_key': 'root.2', 'actual_value': 33, 'expect_enum': [11, 22]}]}

2、类型校验-Like

# 预期type(11)  
#1、python类契约
expect_format_1 = Like(11)
# 2、json契约
expect_format_json_1 = {
    '$Like': 11
}

# 预期type(1.0)  
#1、python类契约
expect_format_2 = Like(1.0)
# 2、json契约
expect_format_json_2 = {
    '$Like': 1.0
}


# 预期type('11')  
#1、python类契约
expect_format_3 = Like('11')
# 2、json契约
expect_format_json_3 = {
    '$Like': '11'
}

# 预期返回数据actual为dict结构,actual['k1'] == type('v1')   
#1、python类契约
expect_format_4 = Like({'k1':'v1'})
#2、json契约
expect_format_json_4 =  {
    '$Like': {'k1':'v1'}
}
>>> pp1=PactVerify(expect_format_1)
>>> pp1.verify(22)
>>> pp1.verify_result
True
>>> pp1.verify("11")
>>> pp1.verify_result
False
>>> pp1.verify_info
{'type_not_match_error': [{'actual_key': 'root', 'actual_vaule': '11', 'expect_type': 'int'}]}
>>>

>>> pp2 = PactJsonVerify(expect_format_json_1,separator="$")
>>> pp2.verify(11)
>>> pp2.verify_result
True
>>> pp2.verify("11")
>>> pp2.verify_result
False
>>> pp2.verify_info
{'type_not_match_error': [{'actual_key': 'root', 'actual_vaule': '11', 'expect_type': 'int'}]}


>>> pp3 = PactVerify(expect_format_4,hard_mode=True)
>>> pp3.verify({"k1":"v1"})
>>> pp3.verify_result
True
>>> pp3.verify({"k1":11})
>>> pp3.verify_result
False
>>> pp3.verify_info
{'type_not_match_error': [{'actual_key': 'root.k1', 'actual_vaule': 11, 'expect_type': 'str'}]}

>>> pp4 = PactJsonVerify(expect_format_json_4,hard_mode=True)
>>> pp4.verify({"k1":"dsf"})
>>> pp4.verify_result
True
>>> pp4.verify({"k1":None})
>>> pp4.verify_result
False
>>> pp4.verify_info
{'type_not_match_error': [{'actual_key': 'root.k1', 'actual_vaule': None, 'expect_type': 'str'}]}
>>>

3、数组类型校验-EachLike

# 预期[type(11)]  
#1、python类契约
expect_format_1 = EachLike(11)
#2、json契约
expect_format_json_1 = {
    '$EachLike': 11
}

# 预期[type(1.0)]  
#1、python类契约
expect_format_2 = EachLike(1.0)
#2、json契约
expect_format_json_2 = {
    '$EachLike': 1.0
}

# 预期[type('11')]  
#1、python类契约
expect_format_3 = EachLike('11')
#2、json契约
expect_format_json_3 = {
    '$EachLike': '11'
}

# 预期[Like{'k1':'v1'}] 
#1、python类契约
expect_format_4 = EachLike({'k1': 'v1'})
#2、json契约
expect_format_json_4 = {
    '$EachLike': {'k1': 'v1'}
}

# 预期[Like{'k1':'v1'}]或[],minimum为数组最小长度,默认minimum=1   
#1、python类契约
expect_format_5 = EachLike({'k1': 'v1'}, minimum=0)
#2、json契约
expect_format_json_5 = {
    '$EachLike': {
        # $values,$params结构用于额外传参
        '$values': {'k1': 'v1'},
        '$params': {'minimum': 0}
    }
}
>>> pp=PactVerify(expect_format_1,hard_mode=True)
>>> pp.verify([11,22,44])
>>> pp.verify_result
True
>>> pp.verify([11,22,44,None])
>>> pp.verify_result
False
>>> pp.verify_info
{'type_not_match_error': [{'actual_key': 'root.3', 'actual_vaule': None, 'expect_type': 'int'}]}

>>> pp2 = PactJsonVerify(expect_format_json_5,separator="$")
>>> pp2.verify([])
>>> pp2.verify_result
True
>>> pp2.verify([{"k1":"v1"}])
>>> pp2.verify_result
True
>>> pp2.verify([{"k1","v1"}])
>>> pp2.verify_result
False
>>> pp2.verify_info
{'type_not_match_error': [{'actual_key': 'root.0', 'actual_vaule': {'v1', 'k1'}, 'expect_type': 'dict'}]}

三、复杂数据结果匹配规则

  1. Matcher,Like 和 EachLike 类可以不限层级嵌套,Term 和 Enum 则不能嵌套其他规则

  2. 匹配规则多层嵌套时,内层规则优先生效

1、{{}}格式-字典套叠

actual_data = {
    'code': 0,
    'msg': 'success',
    'data': {
        "id": 1,
        "name": 'lili'
    }
}

# python类契约
expect_format = Like({
    'code': 0,
    'msg': 'success',
    'data': Like({
        "id": 1,
        "name": 'lili'
    })
})

# json契约
expect_format_json = {
    '$Like': {
        'code': 0,
        'msg': 'success',
        'data': {
            '$Like': {
                "id": 1,
                "name": 'lili'
            }
        }
    }
}

2、[{}]格式-数组字典套叠

actual_data = [[{
    "id": 1,
    "name": 'lili'
}]]

# python类契约
expect_format = EachLike(EachLike({
    "id": 1,
    "name": 'lili'
}))

# json契约
expect_format_json = {
    '$EachLike': {
        '$EachLike': {
            "id": 1,
            "name": 'lili'
        }
    }
}

3、{[]}

actual_data = {
    'code': 0,
    'msg': 'success',
    'data': [{
        "id": 1,
        "name": 'lili'
    },{
        "id": 2,
        "name": 'lilei'
    }]
}

# python类契约
expect_format = Like({
    'code': 0,
    'msg': 'success',
    'data': EachLike({
        "id": 1,
        "name": 'lili'
    })
})

# json契约
expect_format_json = {
    '$Like': {
        'code': 0,
        'msg': 'success',
        'data': {
            '$EachLike': {
                "id": 1,
                "name": 'lili'
            }
        }
    }
}

4、Like-Term 套叠

actual_data = {
    'code': 0,
    'msg': 'success',
    'data': {
        "id": 1,
        "name": 'lili'
    }
}

# python类契约
expect_format = Like({
    'code': 0,
    'msg': 'success',
    'data': Like({
        "id": 1,
        "name": Term(r'\w*', example='lili')
    })
})

# json契约
expect_format_json = {
    '$Like': {
        'code': 0,
        'msg': 'success',
        'data': {
            '$Like': {
                "id": 1,
                "name": {
                    '$Term': {
                        '$values': r'\w*',
                        '$params': {
                            'example': 'lili'
                        }
                    }
                }
            }
        }
    }
}

5、Like-Matcher套叠

actual_data = {
    'name': 'lilei',
    'age': 12
}

# python类契约
expect_format = Like({
    # name字段值类型匹配
    'name': 'lilei',
    # age字段值匹配
    'age': Matcher(12),
})

# json契约
expect_format_json = {
    '$Like': {
        # name字段值类型匹配
        'name': 'lilei',
        # age字段值匹配
        'age': {
            '$Matcher': 12
        },
    }
}

四、异常场景匹配

1、null匹配nullable

nullable 参数在 hard_mode = True 时也生效

# nullable为true时允许返回null,预期null和(actual为dict结构,actual['k1'] == 'v1' or null)#1、python类契约
expect_format = Matcher({'k1': 'v1'}, nullable=True)
# 2、json契约
expect_format_json = {
    '$Matcher': {
        '$values': {'k1': 'v1'},
        '$params': {'nullable': True}
    }
}

# nullable为true时允许返回null,预期null和(actual为dict结构,actual['k1'] == type('v1') or null)形式   
#1、python类契约
expect_format = Like({'k1': 'v1'}, nullable=True)
#2、json契约
expect_format_json = {
    '$Like': {
        '$values': {'k1': 'v1'},
        '$params': {'nullable': True}
    }
}

# nullable为true时允许返回null,预期null和[null,{'k1':null}]形式   
#1、python类契约
expect_format = EachLike({'k1': 'v1'}, nullable=True)
#2、json契约
expect_format_json = {
    '$EachLike': {
        '$values': {'k1': 'v1'},
        '$params': {'nullable': True}
    }
}

# nullable为true时允许返回null,预期null和11形式   
#1、python类契约
expect_format = Term(r'^\d{2}$', example=11, nullable=True)
#2、json契约
expect_format_json = {
    '$Term': {
        '$values': r'^\d{2}$',
        '$params': {'example': 11, 'nullable': True}
    }
}

# nullable为true时允许返回null,预期null和11/22/33形式   
#1、python类契约
expect_format = Enum([11, 22, 33], nullable=True)
#2、json契约
expect_format_json = {
    '$Enum': {
        '$values': [11, 22, 33],
        '$params': {'nullable': True}
    }
}

2、{}匹配dict_emptiable

dict_emptiable 在 hard_mode = True 时也生效

# dict_emptiable为true时,允许返回{},预期{}和(actual为dict结构,actual['k1'] == 'v1')形式
#1、python类契约
expect_format = Matcher({'k1': 'v1'}, dict_emptiable=True)
#2、json契约
expect_format_json = {
    '$Matcher': {
        '$values': {'k1': 'v1'},
        '$params': {'dict_emptiable': True}
    }
}

# dict_emptiable为true时,允许返回{},预期{}和(actual为dict结构,actual['k1'] == type('v1'))形式   
#1、python类契约
expect_format = Like({'k1': 'v1'}, dict_emptiable=True)
# 2、json契约
expect_format_json = {
    '$Like': {
        '$values': {'k1': 'v1'},
        '$params': {'dict_emptiable': True}
    }
}

3、json格式串匹配jsonloads

# actual为"{\"k1\":\"v1\"}"json字符串格式时,先进行json.loads再校验   
#1、python类契约
expect_format = Matcher({'k1': 'v1'}, jsonloads=True)
#2、json契约
expect_format_json = {
    '$Matcher': {
        '$values': {'k1': 'v1'},
        '$params': {'jsonloads': True}
    }
}

# actual为"{\"k1\":\"v1\"}"json字符串格式时,先进行json.loads再校验   
#1、python类契约
expect_format = Like({'k1': 'v1'}, jsonloads=True)
#2、json契约
expect_format_json = {
    '$Like': {
        '$values': {'k1': 'v1'},
        '$params': {'jsonloads': True}
    }
}

# actual为"[{\"k1\":\"v1\"}]"json字符串格式时,先进行json.loads再校验  
#1、python类契约
expect_format = EachLike({'k1': 'v1'}, jsonloads=True)
#2、json契约
expect_format_json = {
    '$EachLike': {
        '$values': {'k1': 'v1'},
        '$params': {'jsonloads': True}
    }
}

# actual为"[11,22]"json字符串格式时,先进行json.loads再校验   
#1、python类契约
expected_format = Enum([11, 22], jsonloads=True)
#2、json契约
expected_format_json = {
    '$Enum': {
        '$values': {'k1': 'v1'},
        '$params': {'jsonloads': True}
    }
}

4、key不存在匹配key_missable

1. key_missable 在 hard_mode = True 时也生效
2. key_missable 针对 actual_data 本身的 key,dict_key_missable 针对 actual_data 字典中的 key,可以同时生效

# key_missable为true时,允许key不存在,key存在时走正常校验;Matcher,Like,EachLike,Term和Enum类都可使用该属性   python类契约
expect_format = Matcher({
    'code': Like(0, key_missable=True),
    'msg': Matcher('success', key_missable=True),
    'data': EachLike(11, key_missable=True),
    'age': Term(r'^\d{2}$', example=11, key_missable=True),
    'num': Enum([11, 22, 33], key_missable=True)
})
# key_missable为true时,允许key不存在,key存在时走正常校验;Matcher,Like,EachLike,Term和Enum类都可使用该属性   json契约
expect_format_json = {
    '$Matcher': {
        'code': {
            '$Like': {
                '$values': 0,
                '$params': {'key_missable': True}
            }
        },
        'msg': {
            '$Matcher': {
                '$values': 'success',
                '$params': {'key_missable': True}
            }
        },
        'data': {
            '$EachLike': {
                '$values': 11,
                '$params': {'key_missable': True}
            }
        },
        'age': {
            '$Term': {
                '$values': r'^\d{2}$',
                '$params': {'example': 11, 'key_missable': True}
            }
        },
        'num': {
            '$Enum': {
                '$values': [11, 22, 33],
                '$params': {'key_missable': True}
            }
        },
    }}

# dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验  python类契约
expected_format = Matcher({
    'name': 'lilei',
    'age': 12,
    'sex': 'man'
}, dict_key_missable=True)
# dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验  json契约
expected_format_json = {
    '$Matcher': {
        '$values': {
            'name': 'lilei',
            'age': 12,
            'sex': 'man'
        },
        '$params': {'dict_key_missable': True}
    }
}

# dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验   python类契约
expected_format = Like({
    'name': 'lilei',
    'age': 12,
    'sex': 'man'
}, dict_key_missable=True)
# dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验   json契约
expected_format_json = {
    '$Like': {
        '$values': {
            'name': 'lilei',
            'age': 12,
            'sex': 'man'
        },
        '$params': {'dict_key_missable': True}
    }
}

# dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验   python类契约
expected_format = EachLike({
    'name': 'lilei',
    'age': 12,
    'sex': 'man'
}, dict_key_missable=True)
# dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验   json契约
expected_format_json = {
    '$EachLike': {
        '$values': {
            'name': 'lilei',
            'age': 12,
            'sex': 'man'
        },
        '$params': {'dict_key_missable': True}
    }
}

5、多类型匹配extra_types

# actual数据为type(11)或type('11'),extra_types可以添加多个示例数据,对基础数据类型(int,float,boolean,str,None)示例有效,对list dict等类型无效  python类契约
expect_format = Like(11, extra_types=['11'])
# actual数据为type(11)或type('11'),extra_types可以添加多个示例数据,对基础数据类型(int,float,boolean,str,None)示例有效,对list dict等类型无效  json契约
expect_format_json = {
    '$Like': {
        '$values': 11,
        '$params': {'extra_types': ['11']}
    }
}

# actual数据为[type(11)]或[type('11')],extra_types可以添加多个示例数据,对基础数据类型示例(int,float,boolean,str,None)有效,对list dict等类型无效  python类契约
expect_format = EachLike(11, extra_types=['11'])
# actual数据为[type(11)]或[type('11')],extra_types可以添加多个示例数据,对基础数据类型示例(int,float,boolean,str,None)有效,对list dict等类型无效  json契约
expect_format_json = {
    '$EachLike': {
        '$values': 11,
        '$params': {'extra_types': ['11']}
    }
}

四、自动生成 json 契约

from pactverify.utils import generate_pact_json_by_response

response_json = {
    "msg": "success",
    "code": 0,
    "data": [{
        "type_id": 249,
        "name": "王者荣耀",
        "order_index": 1,
        "status": 1,
        "subtitle": " ",
        "game_name": "王者荣耀"
    }, {
        "type_id": 250,
        "name": "绝地求生",
        "order_index": 2,
        "status": 1,
        "subtitle": " ",
        "game_name": "绝地求生"
    }, {
        "type_id": 251,
        "name": "刺激战场",
        "order_index": 3,
        "status": 1,
        "subtitle": " ",
        "game_name": "刺激战场"
    }
    ]
}
# 参数说明:响应json数据,契约关键字标识符(默认$)
pact_json = generate_pact_json_by_response(response_json, separator='$')
print(pact_json)

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值