【Java】微信小程序imgSecCheck接口示例-校验一张图片是否含有违法违规内容

更新时间:2023年11月6日08:41:5

服务器到期了。空闲了再迁移到其它服务器

https://xsapi.ydxiaoshuai.cn/rest/check/general_url   传递图片URL地址-图片内容安全检查

https://xsapi.ydxiaoshuai.cn/rest/check/general_file  传递图片FILE文件-图片内容安全检查

   https://xsapi.ydxiaoshuai.cn/rest/check/general_msg   文本内容安全检查

接口文档地址:https://www.showdoc.com.cn/ydxsapi/9611526080100591

近期应该部分个人开发者小程序会收到如下通知

为了快速解决问题,就直接使用官方提供的接口

imgSecCheck校验一张图片是否含有违法违规内容

个人小程序只是图片的一些处理识别。固只拿imgSecCheck接口进行代码示例了。
1.在自己的Java后台服务增加接口调用(api.weixin.qq.com不能直接加入小程序安全域名中)
2.在小程序选择图片后优先走违法违规校验。校验通过再走自己的业务代码。

Java实现获取小程序的图片文件并进行违法违规校验

wx.uploadFile 传递图片文件到后台

 wx.uploadFile({
    url: 图片违法违规校验接口地址,
    filePath: res.tempFilePaths[0],
    header: {
        'content-type': 'multipart/form-data'
    },
    name: 'file',
    success: function(checkres) {
        var checkResult = JSON.parse(checkres.data);
        console.info(checkResult);
        if (checkResult.errcode == '0') {
            //校验没有违法违规进行自己业务代码处理
        } else {
            if (checkResult.errcode == '87014') {
                wx.hideLoading();
                wx.showModal({
                    content: '存在敏感内容,请更换图片',
                    showCancel: false,
                    confirmText: '明白了'
                })
            } else {
                wx.hideLoading();
                wx.showModal({
                    content: '其他错误,稍后再试',
                    showCancel: false,
                    confirmText: '明白了'
                })
            }
        }
    }

后台代码

/**
     * 图片过滤检测
     * @param file 图片文件
     * @return
     */
    @RequestMapping(value = "/imgcheck", method = {RequestMethod.POST})
    @ResponseBody
    public AccessTokenWX checkPic(@RequestParam(value = "file") MultipartFile file, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        String access_token = "";
        //自己写一个定时任务或其他方式 获取AccessToken
        AccessTokenWX accessTokenWX = new AccessTokenWX();
        try {
                token = getAccessTokenJob.getAccessToken();
                String url = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + access_token;
                String result = uploadFile(url, file);
                accessTokenWX = JSON.parseObject(result, AccessTokenWX.class);
                System.out.println("图片检测结果 = " + result);
                return accessTokenWX;
        } catch (Exception e) {
            System.out.println("----------------调用腾讯内容过滤系统出错------------------" + e.getMessage());
            accessTokenWX.setErrcode("500");
            accessTokenWX.setErrmsg("system错误");
            return accessTokenWX;
        }
    }
    /**
     * 上传二进制文件
     * @param graphurl 接口地址
     * @param file 图片文件
     * @return
     */
    public static String uploadFile(String graphurl,MultipartFile file) {
        String line = null;//接口返回的结果
        try {
            // 换行符
            final String newLine = "\r\n";
            final String boundaryPrefix = "--";
            // 定义数据分隔线
            String BOUNDARY = "========7d4a6d158c9";
            // 服务器的域名
            URL url = new URL(graphurl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置为POST情
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");
            OutputStream out = new DataOutputStream(conn.getOutputStream());

            // 上传文件
            StringBuilder sb = new StringBuilder();
            sb.append(boundaryPrefix);
            sb.append(BOUNDARY);
            sb.append(newLine);
            // 文件参数,photo参数名可以随意修改
            sb.append("Content-Disposition: form-data;name=\"image\";filename=\""
                    + "https://api.weixin.qq.com" + "\"" + newLine);
            sb.append("Content-Type:application/octet-stream");
            // 参数头设置完以后需要两个换行,然后才是参数内容
            sb.append(newLine);
            sb.append(newLine);

            // 将参数头的数据写入到输出流中
            out.write(sb.toString().getBytes());

            // 读取文件数据
            out.write(file.getBytes());
            // 最后添加换行
            out.write(newLine.getBytes());

            // 定义最后数据分隔线,即--加上BOUNDARY再加上--。
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY
                    + boundaryPrefix + newLine).getBytes();
            // 写上结尾标识
            out.write(end_data);
            out.flush();
            out.close();
            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            while ((line = reader.readLine()) != null) {
                return line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常!" + e);
        }
        return line;
    }

    /**
     * 上传二进制文件
     * @param apiurl 接口地址
     * @param file 图片文件
     * @return
     */
    public static String uploadFile(String apiurl, byte[] file) {
        //接口返回的结果
        String line = null;
        try {
            // 换行符
            final String newLine = "\r\n";
            final String boundaryPrefix = "--";
            // 定义数据分隔线
            String BOUNDARY = "========7d4a6d158c9";
            // 服务器的域名
            URL url = new URL(apiurl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置为POST情
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.15(0x17000f31) NetType/WIFI Language/zh_CN");
            OutputStream out = new DataOutputStream(conn.getOutputStream());

            // 上传文件
            StringBuilder sb = new StringBuilder();
            sb.append(boundaryPrefix);
            sb.append(BOUNDARY);
            sb.append(newLine);
            // 文件参数,photo参数名可以随意修改
            sb.append("Content-Disposition: form-data;name=\"image\";filename=\""
                    + "https://api.weixin.qq.com" + "\"" + newLine);
            sb.append("Content-Type:application/octet-stream");
            // 参数头设置完以后需要两个换行,然后才是参数内容
            sb.append(newLine);
            sb.append(newLine);

            // 将参数头的数据写入到输出流中
            out.write(sb.toString().getBytes());

            // 读取文件数据
            out.write(file);
            // 最后添加换行
            out.write(newLine.getBytes());

            // 定义最后数据分隔线,即--加上BOUNDARY再加上--。
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY
                    + boundaryPrefix + newLine).getBytes();
            // 写上结尾标识
            out.write(end_data);
            out.flush();
            out.close();
            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            while ((line = reader.readLine()) != null) {
                return line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常!" + e);
        }
        return line;
    }

为了方便大家。我这里直接封装了一个接口供大家使用

上传图片文件(file)

接口地址:https://xsapi.ydxiaoshuai.cn/rest/check/general_file

请求方式: POST

Body参数:

access_token 接口调用凭证
file 图片文件

POSTMAN截图示意

上传公网图片URL

接口地址:https://xsapi.ydxiaoshuai.cn/rest/check/general_url

请求方式: POST

Body参数:

access_token 接口调用凭证
url 图片URL地址  确保是访问直接是图片 而不是需要校验  或其他内容

POSTMAN截图示意

 文本内容安全检查URL

接口地址:https://xsapi.ydxiaoshuai.cn/rest/check/general_msg

请求方式: POST

Body参数:

access_token 接口调用凭证
content 要检查的文本内容 最多不超500KB

 POSTMAN截图示意

实现Controller代码如下

package cn.ydxiaoshuai.xsboot.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.ydxiaoshuai.xsboot.base.controller.ApiRestController;
import cn.ydxiaoshuai.xsboot.bean.BaseBean;
import cn.ydxiaoshuai.xsboot.bean.WXAccessToken;
import cn.ydxiaoshuai.xsboot.constants.WeiXinSecurityConts;
import cn.ydxiaoshuai.xsboot.utils.ImageUtil;
import cn.ydxiaoshuai.xsboot.utils.WeiXinSecurityBeanUtil;
import cn.ydxiaoshuai.xsboot.utils.WeiXinSecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.Charset;


/**
 * @author 小帅丶
 * @className ImageCheckRestController
 * @Description 图片检查
 * @Date 2020/9/14-12:10
 **/
@Slf4j
@Controller
@RequestMapping(value = "/rest/check")
@Scope("prototype")
public class ImageCheckRestController extends ApiRestController {
    //1MB图片大小 字节
    private static long IMG_MAX_SIZE = 1024 * 1024;
    //1MB图片大小 字节
    private static int MSG_MAX_SIZE = 500 * 1024;



    /**
     * 文本检测
     * @param content 图片文件
     * @param access_token 微信token
     * @return
     */
    @RequestMapping(value = "/general_msg", method = {RequestMethod.POST})
    public ResponseEntity<Object> checkGeneralMsg(@RequestParam(value = "content",required = false) String content,
                                                  @RequestParam(value = "access_token",required = false) String access_token) {
        log.info("[checkGeneralMsg] :======> 参数:{},{}",content,access_token);
        BaseBean baseBean = new BaseBean();
        WXAccessToken bean;
        try {
            startTime = System.currentTimeMillis();
            if(StrUtil.isEmpty(content)){
                baseBean = baseBean.fail(410101,"msg check fail","接口参数缺失,请检查content是否填写");
            } else if (StrUtil.isEmpty(access_token)) {
                baseBean = baseBean.fail(410101,"msg check fail","接口参数缺失,请检查access_token是否填写");
            } else {
                //文字大小
                long size = content.getBytes(Charset.defaultCharset()).length;
                if(size>MSG_MAX_SIZE){
                    baseBean = baseBean.fail(410101,"msg check fail","文本大小错误,文本大小限制:500KB");
                } else {
                    bean = WeiXinSecurityUtil.checkText(content,access_token);
                    if(WeiXinSecurityConts.WX_OK_CODE.equals(bean.getErrcode())){
                        baseBean = baseBean.success("msg check successful",bean.getErrmsg());
                    } else {
                        baseBean = WeiXinSecurityBeanUtil.dealBean(bean);
                    }
                }
            }
        } catch (Exception e) {
            log.info(requestURI + e.getMessage());
            baseBean = baseBean.error("系统繁忙,稍后再试");
        }
        // 打印接口信息及耗时
        log.info("[checkGeneralMsg]-接口耗时=====>: {} ms",System.currentTimeMillis() - startTime);
        return new ResponseEntity<Object>(baseBean, httpHeaders, HttpStatus.OK);
    }
    /**
     * 图片过滤检测
     *
     * @param file 图片文件
     * @param access_token 微信token
     * @return
     */
    @RequestMapping(value = "/general_file", method = {RequestMethod.POST})
    public ResponseEntity<Object> checkPicGeneralFile(@RequestParam(value = "file",required = false) MultipartFile file,
                                                     @RequestParam(value = "access_token",required = false) String access_token) {
        log.info("[checkPicGeneralFile] :======> 参数:{},{}",file,access_token);
        BaseBean baseBean = new BaseBean();
        WXAccessToken bean;
        try {
            startTime = System.currentTimeMillis();
            if(ObjectUtil.isEmpty(file)){
                baseBean = baseBean.fail(410101,"file check fail","接口参数缺失,请检查图片文件是否传递");
            } else if (StrUtil.isEmpty(access_token)) {
                baseBean = baseBean.fail(410101,"file check fail","接口参数缺失,请检查access_token是否填写");
            } else {
                //文件格式
                String fileSuffix = file.getOriginalFilename()
                        .substring(file.getOriginalFilename().lastIndexOf(".")+1);
                //文件大小
                long size = file.getSize();
                if(size>IMG_MAX_SIZE){
                    baseBean = baseBean.fail(410101,"file check fail","图片大小错误,图片大小限制:1M");
                } else {
                    if (ImageUtil.IMG_TYPE.contains(fileSuffix.toUpperCase())) {
                        bean = WeiXinSecurityUtil.checkImg(file,access_token,request);
                        if(WeiXinSecurityConts.WX_OK_CODE.equals(bean.getErrcode())){
                            baseBean = baseBean.success("file check successful",bean.getErrmsg());
                        } else {
                            baseBean = WeiXinSecurityBeanUtil.dealBean(bean);
                        }
                    }else{
                        baseBean = baseBean.fail(410101,"file check fail","图片格式错误,格式支持PNG、JPEG、JPG、GIF");
                    }
                }
            }
        } catch (Exception e) {
            log.info(requestURI + e.getMessage());
            baseBean = baseBean.error("系统繁忙,稍后再试");
        }
        log.info("[checkPicGeneralFile]-接口耗时=====>: {} ms",System.currentTimeMillis() - startTime);
        return new ResponseEntity<Object>(baseBean, httpHeaders, HttpStatus.OK);
    }

    /**
     * 图片过滤检测
     *
     * @param url 图片公网URL
     * @param access_token 微信token
     * @return
     */
    @RequestMapping(value = "/general_url", method = {RequestMethod.POST})
    public ResponseEntity<Object> checkPicGeneralURL(@RequestParam(value = "url",required = false) String url,
                                                     @RequestParam(value = "access_token",required = false) String access_token) {
        log.info("[checkPicGeneralURL] :======> 参数:{},{}",url,access_token);
        BaseBean baseBean = new BaseBean();
        WXAccessToken bean;
        try {
            startTime = System.currentTimeMillis();
            if (StrUtil.isEmpty(access_token)) {
                baseBean = baseBean.fail(410101,"url check fail","接口参数缺失,请检查access_token是否填写");
            }else if(StrUtil.isEmpty(url)){
                baseBean = baseBean.fail(410101,"url check fail","接口参数缺失,请检查url是否填写");
            } else {
                if(url.startsWith("http://")||url.startsWith("https://")){
                    bean = WeiXinSecurityUtil.checkImg(url,access_token);
                    if(WeiXinSecurityConts.WX_OK_CODE.equals(bean.getErrcode())){
                        baseBean = baseBean.success("url check successful",bean.getErrmsg());
                    } else {
                        baseBean = WeiXinSecurityBeanUtil.dealBean(bean);
                    }
                }else{
                    baseBean = baseBean.fail(410101,"url check fail","接口参数缺失,请检查url是否填写正确");
                }
            }
        } catch (Exception e) {
            log.info(requestURI + e.getMessage());
            baseBean = baseBean.error("系统繁忙,稍后再试");
        }
        log.info("[checkPicGeneralURL]-接口耗时=====>: {} ms",System.currentTimeMillis() - startTime);
        return new ResponseEntity<Object>(baseBean, httpHeaders, HttpStatus.OK);
    }
}
WeiXinSecurityUtil代码
    private static Integer IMG_WIDTH = 750;
    private static Integer IMG_HEIGHT = 1334;
    /**
     * 图片检测接口
     */
    private static String IMG_SEC_URL = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=";

    /**
     * @Author 小帅丶
     * @Description 图片安全检查
     * @Date  2020/9/29
     * @param imageUrl 图片公网地址
     * @param access_token 微信的token
     * @return cn.ydxiaoshuai.modules.weixin.po.WXAccessToken
     **/
    public static WXAccessToken checkImg(String imageUrl,String access_token) throws Exception{
        WXAccessToken bean;
        BufferedImage bufferedImage = ImageUtil.imgUrlConvertBufferedImage(imageUrl);
        String url = IMG_SEC_URL + access_token;
        //750px * 1334px
        if (bufferedImage.getWidth() > IMG_WIDTH || bufferedImage.getHeight() > IMG_HEIGHT) {
            //缩放图片
            byte[] newImage = ImageUtil.zoomImageByte(bufferedImage);
            String result = ImgCheckHttpUtil.uploadFile(url,newImage);
            log.info(result);
            bean = JSON.parseObject(result, WXAccessToken.class);
            System.out.println("general缩放图片检测结果 = " + result);
        } else {
            ByteArrayOutputStream outputStreamSource = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", outputStreamSource);
            String result = ImgCheckHttpUtil.uploadFile(url,outputStreamSource.toByteArray());
            log.info(result);
            bean = JSON.parseObject(result, WXAccessToken.class);
            System.out.println("general图片检测结果 = " + result);
        }
        return bean;
    }

ImageUtil代码

package cn.ydxiaoshuai.common.util;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;

/**
 * @author 小帅丶
 * @className ImageUtil
 * @Description 图片缩放
 * @Date 2020/9/29-9:58
 **/
@Slf4j
public class ImageUtil {
    /**
     * 缩放比例系数
     */
    private static double SCALING = 0.56;
    /**
     * 符合base64的宽
     */
    private static int MAX_WIDTH = 560;
    /**
     * 最大高
     */
    private static int MAX_HEIGHT = 1000;

    /**
     * @Author 小帅丶
     * @Description 根据图片公网地址转BufferedImage
     * @Date  2020/9/29 10:52
     * @param url 图片公网地址
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage imgUrlConvertBufferedImage(String url) throws Exception {
        URL urls = new URL(url);
        Image image = Toolkit.getDefaultToolkit().getImage(urls);
        BufferedImage bufferedImage = toBufferedImage(image);
        return bufferedImage;
    }
    /**
     * @Author 小帅丶
     * @Description 根据BufferedImage处理图片并返回byte[]
     * @Date  2020/9/29 10:55
     * @param bufferedImage
     * @return byte[]
     **/
    public static byte[] zoomImageByte(BufferedImage bufferedImage) throws Exception {
        ByteArrayOutputStream outputStreamZoom = new ByteArrayOutputStream();
        ByteArrayOutputStream outputStreamSource = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", outputStreamSource);
        BufferedImage bufferedImageZoom = zoomImage(outputStreamSource.toByteArray());
        //写入缩减后的图片
        ImageIO.write(bufferedImageZoom, "jpg", outputStreamZoom);
        return outputStreamZoom.toByteArray();
    }

    /**
     * @Author 小帅丶
     * @Description 根据byte[]处理图片并返回byte[]
     * @Date  2020/9/29 10:55
     * @param src
     * @return byte[]
     **/
    public static byte[] zoomImageByte(byte[] src) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        BufferedImage bufferedImage = zoomImage(src);
        //写入缩减后的图片
        ImageIO.write(bufferedImage, "jpg", outputStream);
        return outputStream.toByteArray();
    }

    /**
     * 图片缩放 仅适用于微信内容图片安全检测使用
     *
     * @param src 为源文件byte
     */
    public static BufferedImage zoomImage(byte[] src) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(src);
        double wr = 0, hr = 0;
        BufferedImage bufferedImage = null;
        //读取图片
        BufferedImage bufImg = ImageIO.read(in);
        int height = bufImg.getHeight();
        int width = bufImg.getWidth();
        int cHeight = height;
        int cWidth = width;
        double Scaling = width / height;
        if (Scaling < SCALING) {
            if (height > MAX_HEIGHT) {
                cHeight = MAX_HEIGHT;
                cWidth = (width * MAX_HEIGHT) / height;
            }
            //以宽为缩放比例
        } else {
            if (width > MAX_WIDTH) {
                cWidth = MAX_WIDTH;
                cHeight = (height * MAX_WIDTH) / width;
            }
        }
        //获取缩放后的宽高
        log.info("宽{},高{}", cWidth, cHeight);
        //设置缩放目标图片模板
        Image Itemp = bufImg.getScaledInstance(width, cHeight, BufferedImage.SCALE_SMOOTH);
        //获取缩放比例
        wr = cWidth * 1.0 / width;
        hr = cHeight * 1.0 / height;
        log.info("宽比例{},高比例{}", wr, hr);
        AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
        Itemp = ato.filter(bufImg, null);
        try {
            //写入缩减后的图片
            ImageIO.write((BufferedImage) Itemp, "jpg", outputStream);
            ByteArrayInputStream inNew = new ByteArrayInputStream(outputStream.toByteArray());
            bufferedImage = ImageIO.read(inNew);
        } catch (Exception ex) {
            log.info("缩放图片异常{}", ex.getMessage());
        } finally {
            if (null != outputStream) {
                outputStream.close();
            }
            if (null != in) {
                in.close();
            }
        }
        return bufferedImage;
    }

    /**
     * @Author 小帅丶
     * @Description Image转BufferedImage
     * @Date  2020/9/29 10:47
     * @param image 通过url获取的image对象
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment
                .getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null),
                    image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }
        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null),
                    image.getHeight(null), type);
        }
        // Copy image to buffered image
        Graphics g = bimage.createGraphics();
        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bimage;
    }
}

评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小帅丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值