智汇创想pytest接口自动化测试框架

        本测试框架是基于pytest搭建的接口自动化框架,对象为深圳智汇创想官方网站。深圳智汇创想科技有限责任公司(深圳智汇创想科技有限责任公司),是一家专注于跨境电子商务的集团公司,全球电商平台多品类多品牌的零售商,技术先进型服务企业,国家高新技术企业。一路走来,公司始终坚持以市场为导向、以客户需求及提升客户体验为目标,长期致力于自主设计、研发及创新,不断开发出高颜值、高品质、高性价比的产品,并努力打造中国品牌。

1、整体架构

整体用pytest+requests+allure+jenkins框架实现脚本编写。

项目框架有脚本层,配置层,报告层,公共方法层,数据层等。

script是脚本层;pytest.ini是配置文件;report是报告层,func是公共方法层,testdatafile是数据层。

2、脚本层

2.1 公司首页

打开网址,点击公司首页。F12抓包并写脚本如下

test_company_portal.py

这里用四种方法来做断言,分别是响应状态码,响应内容,响应头和响应长度。

# -- coding: utf-8 --
import time
import unittest2

import os
import unittest
import requests
class TestZhcxkhPortal(unittest2.TestCase):
    def setUp(self):
        self.url = "https://www.zhcxkj.com/"

    def test_zhcxkj_portal(self):
        # 发送接口请求
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")

        # 2、断言响应内容
        # print(response.text)
        self.assertIn("深圳智汇创想科技有限责任公司", response.text)
        print("2响应内容断言成功")

        # 3、断言响应头:验证HTTP响应头是否包含特定的字段和值
        print(response.headers)
        self.assertIn("Content-Type", response.headers)
        print("3响应头断言成功")

        # 4、断言响应长度
        print(len(response.text))
        self.assertEqual(len(response.text),22393, msg="响应体中的项目数量不符合预期")
        print("4、响应断言长度(条数)成功!!")

执行结果如下:


============================= test session starts =============================
collecting ... collected 1 item

test_company_portal.py::TestZhcxkhPortal::test_zhcxkj_portal 200
1响应状态码断言成功
2响应内容断言成功
{'Cache-Control': 'private', 'Pragma': 'no-cache', 'Content-Type': 'text/html; charset=utf-8', 'Expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'Server': 'Microsoft-IIS/7.5', 'Set-Cookie': 'PHPSESSID=9buhskd6crodp1o5t0g1svs561; path=/', 'X-Powered-By': 'ThinkPHP, ASP.NET', 'Date': 'Thu, 12 Sep 2024 08:30:13 GMT', 'Content-Length': '24699'}
3响应头断言成功
22393
4、响应断言长度(条数)成功!!
PASSED

======================== 1 passed, 2 warnings in 0.39s ========================

Process finished with exit code 0

2.2关于我们

关于我们有四个菜单,分别为

包含公司概况、企业文化、业务版图、公司社团,
在test_about_us.py 中定义了四个方法

具体代码如下:

# -- coding: utf-8 --
import time
import unittest2
from selenium import webdriver
from selenium.webdriver import ActionChains
import os
import unittest
import requests
import csv

#关于我们接口,包含公司概况、企业文化、业务版图、公司社团
class TestAboutUs(unittest.TestCase):
    def setUp(self):
        self.url1 = "https://www.zhcxkj.com/index.php/Home/index/about/about_id/4.html"
        self.url2 = "https://www.zhcxkj.com/index.php/Home/index/about/about_id/7.html"
        self.url3 = "https://www.zhcxkj.com/index.php/Home/index/about/about_id/8.html"
        self.url4 = "https://www.zhcxkj.com/index.php/Home/index/about/about_id/9.html"

    # 关于我们--公司概况
    def test_about_company(self):
        # 发送接口请求
        response = requests.get(self.url1)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")

        # 2、断言响应内容
        # print(response.text)
        self.assertIn("深圳智汇创想科技有限责任公司", response.text)
        print("2响应内容断言成功")

        # 3、断言响应头:验证HTTP响应头是否包含特定的字段和值
        print(response.headers)
        self.assertIn("Content-Type", response.headers)
        print("3响应头断言成功")

        # 4、断言响应长度
        print(len(response.text))
        self.assertEqual(len(response.text),14919, msg="响应体中的项目数量不符合预期")
        print("4、响应断言长度(条数)成功!!")

    # 关于我们--企业文化
    def test_corporate_culture(self):
        # 发送接口请求
        response = requests.get(self.url2)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1test_about_joinus响应状态码断言成功")


    # 业务版图
    def test_Business_Landscape(self):
        # 发送接口请求
        response = requests.get(self.url3)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1test_about_joinus响应状态码断言成功")

    # 公司社团
    def test_Corporate_Societies(self):
        # 发送接口请求
        response = requests.get(self.url4)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1test_about_joinus响应状态码断言成功")

执行结果:

============================= test session starts =============================
collecting ... collected 4 items

test_about_us.py::TestAboutUs::test_Business_Landscape 
test_about_us.py::TestAboutUs::test_Corporate_Societies 
test_about_us.py::TestAboutUs::test_about_company 
test_about_us.py::TestAboutUs::test_corporate_culture 

======================== 4 passed, 8 warnings in 1.76s ========================

Process finished with exit code 0
200
1test_about_joinus响应状态码断言成功
PASSED200
1test_about_joinus响应状态码断言成功
PASSED200
1响应状态码断言成功
2响应内容断言成功
{'Cache-Control': 'private', 'Pragma': 'no-cache', 'Content-Type': 'text/html; charset=utf-8', 'Expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'Server': 'Microsoft-IIS/7.5', 'Set-Cookie': 'PHPSESSID=thf56p7g0oo5v44ka4elqlmsl1; path=/', 'X-Powered-By': 'ThinkPHP, ASP.NET', 'Date': 'Thu, 12 Sep 2024 08:34:15 GMT', 'Content-Length': '16786'}
3响应头断言成功
14919
4、响应断言长度(条数)成功!!
PASSED200
1test_about_joinus响应状态码断言成功
PASSED

2.3 新闻中心

新闻中心有

公司动态、员工活动、员工培训、福利图签。
test_news.py中定义了这四个方法

具体接口代码实现:

# -- coding: utf-8 --
import time
import unittest2

import os
import unittest
import requests
# 新闻中心:公司动态、员工活动、员工培训、福利图签。
class TestNews(unittest2.TestCase):
    def setUp(self):
        self.url = "https://www.zhcxkj.com/index.php/Home/index/news/parent_id/12.html"
    #公司动态、
    def test_Company_dynamics(self):
        # 发送接口请求
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")

    # 员工活动、
    def test_employee_activities(self):
        # 发送接口请求
        self.url="https://www.zhcxkj.com/index.php/Home/index/news/parent_id/14.html"
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")
    # 员工培训、
    def test_welfare_signs(self):
        # 发送接口请求
        self.url="https://www.zhcxkj.com/index.php/Home/index/news/parent_id/17.html"
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")
    # 福利图签。
    def test_Welfare_Pictorial(self):
        # 发送接口请求
        self.url="https://www.zhcxkj.com/index.php/Home/index/news/parent_id/31.html"
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")

执行结果:

============================= test session starts =============================
collecting ... collected 4 items

test_news.py::TestNews::test_Company_dynamics 
test_news.py::TestNews::test_Welfare_Pictorial 
test_news.py::TestNews::test_employee_activities 
test_news.py::TestNews::test_welfare_signs 

======================== 4 passed, 8 warnings in 1.39s ========================

Process finished with exit code 0
200
1响应状态码断言成功
PASSED200
1响应状态码断言成功
PASSED200
1响应状态码断言成功
PASSED200
1响应状态码断言成功
PASSED

2.4 联系我们

联系我们只有一个类,包含一个方法

test_contact_us.py

代码如下:

# -- coding: utf-8 --
import time
import unittest2
import os
import unittest
import requests

# 智汇有品界面
class TestContactUs(unittest2.TestCase):
    def setUp(self):
        self.url = "https://www.zhcxkj.com/index.php/Home/index/life.html"

    def test_life(self):
        # 发送接口请求
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")

响应如下:

============================= test session starts =============================
collecting ... collected 1 item

test_contact_us.py::TestContactUs::test_life 

======================== 1 passed, 2 warnings in 0.69s ========================

Process finished with exit code 0
200
1响应状态码断言成功
PASSED

        2.5 智汇有品

只有一个类,包含一个方法

test_zhyp.py
# -- coding: utf-8 --
import time
import unittest2

import os
import unittest
import requests
class TestZhyp(unittest2.TestCase):
    def setUp(self):
        self.url = "http://www.unixde.com/api/v1/stat/visit?site_id=60407&lang=en&k=72.1.0.0.0&u=http:%2F%2Fwww.unixde.com%2Fen"

    def test_Zhyp(self):
        # 发送接口请求
        response = requests.get(self.url)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")


============================= test session starts =============================
collecting ... collected 1 item

test_zhyp.py::TestZhyp::test_Zhyp 

============================== 1 passed in 0.16s ==============================

Process finished with exit code 0
200
1响应状态码断言成功
PASSED

 2.5 正常登录test_loginV1.py

输入正常的用户名和密码进行登录

test_loginV1.py

代码如下:

# -- coding: utf-8 --
import time
import unittest2

import os
import unittest
import requests
import json
class TestLogin(unittest2.TestCase):
    def setUp(self):
        self.url = "https://zhcxkj.com/backend/token/login"
        self.userinfo={}
        self.userinfo={"account":"1tenantId:soyotec:zhaot@163.comemail",
                       "password":"KZaHt2InubCNYziqF4JCGasg==",
                       "forceLogin":1,
                       "lang":"cn",
                       "tenantId":1}
        # 将字典类型转化为json类型
        self.userjson = json.dumps(self.userinfo)
    def test_login(self):
        # 发送接口请求

        response=requests.post(self.url,data=self.userjson , headers={"Content-Type": "application/json;charset=UTF-8"})

        print(response)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")

if __name__ == '__main__':
    # registobj=register_test()
    # registobj.registertest()
    unittest.main()

响应结果为:


============================= test session starts =============================
collecting ... collected 1 item

test_loginV1.py::TestLogin::test_login <- ..\unixdeInterfacePytest\script\test_loginV1.py 

======================== 1 passed, 2 warnings in 0.29s ========================

Process finished with exit code 0
<Response [200]>
200
1响应状态码断言成功
PASSED

2.6 异常登录test_loginV2.py

包括总共5种情况

1、实现使用正确的用户名密码登录

2、使用错误的用户名正确的密码登录

3、使用正确的用户名错误的密码登录

4、使用正确用户名加空密码。并使用装饰器跳过执行。(会执行失败)

@unittest2.skipIf(3>2,'当条件为True时跳过测试')

5、使用空的用户名和正确的密码,会执行。

@unittest2.skipUnless(3 > 2, '当条件为True时执行测试')

代码如下:

# -- coding: utf-8 --
import time
import unittest2

import os
import unittest
import requests
import json

class TestLogin(unittest2.TestCase):
    def setUp(self):
        self.url = "https://zhcxkj.com/backend/token/login"
        self.userinfo={}
        self.userinfo={"account":"1tenantId:soyotec:zhaot@163.comemail",
                       "password":"KZaHt2InubCNYziqF4JCGasg==",
                       "forceLogin":1,
                       "lang":"cn",
                       "tenantId":1}
        # 将字典类型转化为json类型
        self.userjson = json.dumps(self.userinfo)
    # 定义一个函数,实现使用正确的用户名密码登录,最后需要进行断言,获取登录用户名判断是否为预期的zhaodahai
    def test_01__login_by_correct_username_and_password(self):
        # 发送接口请求
        response = requests.post(self.url, data=self.userjson,
                                 headers={"Content-Type": "application/json;charset=UTF-8"})
        print(response)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(200, response.status_code)
        print("1响应状态码断言成功")
        # self.assertEqual('', response.json()['message'])

    # 定义一个函数,实现使用错误的用户名正确的密码登录,最后需要进行断言,获取提示信息是否为预期的“User does not exist”
    def test_02_login_by_wrong_username_and_correct_password(self):
        # 发送接口请求
        userinfo={"account":"1tenantId:soyotec:zhaot@163.comemail",
                       "password":"KZaHt2InubCNYziqF4JCGasg==",
                       "forceLogin":1,
                       "lang":"cn",
                       "tenantId":1}
        # 将字典类型转化为json类型
        userjson = json.dumps(userinfo)
        response = requests.post(self.url, data=userjson,
                                 headers={"Content-Type": "application/json;charset=UTF-8"})
        print(response.text)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(500, response.status_code)
        print("1响应状态码断言成功")
        # 2、断言响应内容
        print(response.json()["code"])
        self.assertEqual(400, response.json()["code"])
        self.assertIn('User does not exist', response.json()['message'])
        print("2响应内容断言成功")

    # # 定义一个函数,实现使用正确的用户名错误的密码登录,最后需要进行断言,获取提示信息是否为预期的“If the login name or password is incorrect for 9 more times, the user will be locked for 1 minutes”
    def test_03_login_by_correct_username_and_wrong_password(self):
        # 发送接口请求
        userinfo={"account":"1tenantId:soyotec:zhaot@163.comemail",
                       "password":"KZaHt2InubCNYziqF4JCGasg==",
                       "forceLogin":1,
                       "lang":"cn",
                       "tenantId":1}
        # 将字典类型转化为json类型
        userjson = json.dumps(userinfo)
        response = requests.post(self.url, data=userjson,
                                 headers={"Content-Type": "application/json;charset=UTF-8"})
        print(response.text)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(500, response.status_code)
        print("1响应状态码断言成功")
        # 2、断言响应内容
        print(response.json()["code"])
        self.assertEqual(400, response.json()["code"])
        self.assertIn('If the login name or password is incorrect', response.json()['message'])
        print("2响应内容断言成功")

    #使用正确用户名加空密码
    @unittest2.skipIf(3>2,'当条件为True时跳过测试')
    def test_04_login_by_correct_username_and_null_password(self):
        # 发送接口请求
        userinfo={"account":"1tenantId:soyotec:zhaot@163.comemail",
                       "password":"KZaHt2InubCNYziqF4JCGasg==",
                       "forceLogin":1,
                       "lang":"cn",
                       "tenantId":1}
        # 将字典类型转化为json类型
        userjson = json.dumps(userinfo)
        response = requests.post(self.url, data=userjson,
                                 headers={"Content-Type": "application/json;charset=UTF-8"})
        print(response.text)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(500, response.status_code)
        print("1响应状态码断言成功")
        # 2、断言响应内容
        print(response.json()["code"])
        self.assertEqual(400, response.json()["code"])
        self.assertIn('If the login name or password is incorrect', response.json()['message'])
        print("2响应内容断言成功")

    @unittest2.skipUnless(3 > 2, '当条件为True时执行测试')
    def test_05_login_by_null_username_and_correct_password(self):
        # 发送接口请求
        userinfo={"account":"1tenantId:soyotec:zhaot@163.comemail",
                       "password":"KZaHt2InubCNYziqF4JCGasg==",
                       "forceLogin":1,
                       "lang":"cn",
                       "tenantId":1}
        # 将字典类型转化为json类型
        userjson = json.dumps(userinfo)
        response = requests.post(self.url, data=userjson,
                                 headers={"Content-Type": "application/json;charset=UTF-8"})
        print(response.text)
        # 1、断言响应状态码
        print(response.status_code)
        self.assertEqual(500, response.status_code)
        print("1响应状态码断言成功")
        # 2、断言响应内容
        print(response.json()["code"])
        self.assertEqual(500, response.json()["code"])
        self.assertIn('操作失败,服务器异常', response.json()['message'])
        print("2响应内容断言成功")

# 执行测试用例
if __name__=="__main__":
    unittest2.TextTestRunner()

执行结果如下:

============================= test session starts =============================
collecting ... collected 5 items

test_loginV2.py::TestLogin::test_01__login_by_correct_username_and_password 
test_loginV2.py::TestLogin::test_02_login_by_wrong_username_and_correct_password 
test_loginV2.py::TestLogin::test_03_login_by_correct_username_and_wrong_password 
test_loginV2.py::TestLogin::test_04_login_by_correct_username_and_null_password 
test_loginV2.py::TestLogin::test_05_login_by_null_username_and_correct_password 

================== 4 passed, 1 skipped, 8 warnings in 0.76s ===================

Process finished with exit code 0
<Response [200]>
200
1响应状态码断言成功
PASSED{"code":400,"message":"User does not exist","data":null}
500
1响应状态码断言成功
400
2响应内容断言成功
PASSED{"code":400,"message":"If the login name or password is incorrect for 9 more times, the user will be locked for 1 minutes","data":null}
500
1响应状态码断言成功
400
2响应内容断言成功
PASSEDSKIPPED
Skipped: 当条件为True时跳过测试
{"code":500,"message":"操作失败,服务器异常","data":null}
500
1响应状态码断言成功
500
2响应内容断言成功
PASSED

2.7 数据驱动DDT test_loginV3.py

它会调用func文件夹的csvFileManager2.py 读取testdatafile里面的login_test_case.csv,并读取最后的状态码和数据做接口断言。

代码如下:

__author__ = 'Administrator'
import sys
sys.path.append("D:\\framework\\zhcxkjInterfacePytest")

import time
from time import sleep
import unittest2
from func.csvFileManager2 import reader

import ddt
import os

import requests
import json

@ddt.ddt #在类上面加一个装饰器,说明我们的这个类是一个数据驱动的测试的类
class TestLogin3(unittest2.TestCase):
    table = reader("login_test_case.csv")
    print(table)
    # table=table[0]
    # print(table)
    @ddt.data(*table)  #在类的上面加一个装饰器,说明我们的这个类是一个数据驱动的测试类
    def test_login(self,row):
        self.url = "https://zhcxkj.com/backend/token/login"
        self.userinfo={}
        self.userinfo={"account":row[0],
                       "password":row[1],
                       "forceLogin":row[2],
                       "lang":row[3],
                       "tenantId":row[4]}
        print(row[5])
        # 将字典类型转化为json类型
        self.userjson = json.dumps(self.userinfo)
        # 发送接口请求
        response = requests.post(self.url, data=self.userjson,headers={"Content-Type": "application/json;charset=UTF-8"})
        print(response.json())
        # 1、断言响应状态码
        print(response.status_code)
        print(row[5])
        self.assertEqual(int(row[5]), response.status_code)
        print(row[6])
        if response.json()['message'] is not None:
            self.assertIn(row[6], response.json()['message'])
        else:
            print(111)
        print("1响应状态码断言成功")


# 执行测试用例
if __name__=="__main__":
    unittest2.TextTestRunner()

打印结果:

============================= test session starts =============================
collecting ... ../testdatafile/ind_interface/login_test_case.csv path
[['1409tenantId:soyotec:zhao_test@163.comemail', 'KZaHt2InubCNYziqF4JCGg==', '1', 'cn', '1409', '200', ''], ['1409tenantId:soyotec:zhao_test1@163.comemail', 'KZaHt2InubCNYziqF4JCGg==', '1', 'cn', '1409', '500', 'User does not exist'], ['1409tenantId:soyotec:zhao_test@163.comemail', 'KZaHt2InubCNYziqF4JCGg==1', '1', 'cn', '1409', '500', 'If the login name or password is incorrect'], ['1409tenantId:soyotec:zhao_test@163.comemail', '', '1', 'cn', '1409', '500', 'If the login name or password is incorrect'], ['', 'KZaHt2InubCNYziqF4JCGg==', '1', 'cn', '1409', '500', '操作失败,服务器异常']]
collected 5 items

test_loginV3.py::TestLogin3::test_login_1___1409tenantId_soyotec_zhao_test_163_comemail____KZaHt2InubCNYziqF4JCGg______1____cn____1409____200______ <- ..\unixdeInterfacePytest\script\test_loginV3.py 
test_loginV3.py::TestLogin3::test_login_2___1409tenantId_soyotec_zhao_test1_163_comemail____KZaHt2InubCNYziqF4JCGg______1____cn____1409____500____User_does_not_exist__ <- ..\unixdeInterfacePytest\script\test_loginV3.py 
test_loginV3.py::TestLogin3::test_login_3___1409tenantId_soyotec_zhao_test_163_comemail____KZaHt2InubCNYziqF4JCGg__1____1____cn____1409____500____If_the_login_name_or_password_is_incorrect__ <- ..\unixdeInterfacePytest\script\test_loginV3.py 
test_loginV3.py::TestLogin3::test_login_4___1409tenantId_soyotec_zhao_test_163_comemail________1____cn____1409____500____If_the_login_name_or_password_is_incorrect__ <- ..\unixdeInterfacePytest\script\test_loginV3.py 
test_loginV3.py::TestLogin3::test_login_5_______KZaHt2InubCNYziqF4JCGg______1____cn____1409____500____操作失败_服务器异常__ <- ..\unixdeInterfacePytest\script\test_loginV3.py 

======================= 5 passed, 10 warnings in 0.95s ========================

Process finished with exit code 0
200
{'code': 200, 'message': None, 'data': {'access_token': '6227e889-63b2-4c10-8d31-97fa9f194bb3', 'token_type': 'bearer', 'refresh_token': '4e523eb2-eed2-4832-94b8-0be81bc9d389', 'expires_in': 43199, 'scope': 'server', 'loginHoldTime': '21600', 'sessionId': 'XpgrDCFpJlEJzvZP6E2w65JybmX1wYKHsDirCe-T'}}
200
200

111
1响应状态码断言成功
PASSED500
{'code': 400, 'message': 'User does not exist', 'data': None}
500
500
User does not exist
1响应状态码断言成功
PASSED500
{'code': 400, 'message': 'If the login name or password is incorrect for 9 more times, the user will be locked for 1 minutes', 'data': None}
500
500
If the login name or password is incorrect
1响应状态码断言成功
PASSED500
{'code': 400, 'message': 'If the login name or password is incorrect for 8 more times, the user will be locked for 1 minutes', 'data': None}
500
500
If the login name or password is incorrect
1响应状态码断言成功
PASSED500
{'code': 500, 'message': '操作失败,服务器异常', 'data': None}
500
500
操作失败,服务器异常
1响应状态码断言成功
PASSED

3、Jenkins持续集成

新建一个Jenkins项目,Project zhcxkjInterfacePytest

进行配置

点击Build Now,进行执行,并生成测试报告。

执行成功,查看控制台

最后执行成功,21条通过,1个跳过。

4、生成Allure测试报告

到report下的index.html。右键Open In Browser Chrome,查看报告

可以看到,执行22条用例,测试用时4s 655ms,21条成功,1条跳过,成功率95.45%。

深圳智汇创想企业文化

企业使命:让中国智造走向世界

企业愿景:成为跨境电商行业领先者

企业价值观:尊重协作、务实高效、追求卓越、以奋斗者为本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值