手机端与服务器加密方式介绍

Android移动端与服务器api接口加密示例(AES,MD5,Token) 移动端接口安全流程: 1.通过登录接口返回AES加密后的token,并本地保存; 2.token到期之后请求更新token接口,同样返回加密后的token; 3.其它post或者get请求: 阅读详情

      移动开发中遇到的最让人纠结的要属Java、Android和iPhone三个平台加解密不一致的问题。因为手机端后台通常是用JAVA开发的Web Service,Android和iPhone客户端调用同样的Web Service接口,为了数据安全考虑,要对数据进行加密。头疼的问题就来了,很难编写出一套加密程序,在3个平台间加解密的结果一致,总不能为Android和iPhone两个客户端各写一套Web Service接口吧?我相信还会有很多朋友为此困惑,在此分享一套3DES加密程序,能够实现Java、Android和iPhone三个平台加解密一致。

首先是JAVA端的加密工具类,它同样适用于Android端,无需任何修改,即可保证Java与Android端的加解密一致,并且中文不会乱码

 

》》》》》》》》》》》》java(android)

package org.liuyq.des3;
 
import java.security.Key;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
 
/**
 * 3DES加密工具类
 */
public class Des3 {
        // 密钥
        private final static String secretKey = "liuyunqiang@lx100$#365#$";
        // 向量
        private final static String iv = "01234567";
        // 加解密统一使用的编码方式
        private final static String encoding = "utf-8";
 
        /**
         * 3DES加密
         *
         * @param plainText 普通文本
         * @return
         * @throws Exception
         */
        public static String encode(String plainText) throws Exception {
                Key deskey = null;
                DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
                SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
                deskey = keyfactory.generateSecret(spec);
 
                Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
                IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
                cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
                byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding));
                return Base64.encode(encryptData);
        }
 
        /**
         * 3DES解密
         *
         * @param encryptText 加密文本
         * @return
         * @throws Exception
         */
        public static String decode(String encryptText) throws Exception {
                Key deskey = null;
                DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
                SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
                deskey = keyfactory.generateSecret(spec);
                Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
                IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
                cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
 
                byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));
 
                return new String(decryptData, encoding);
        }
}

 

》》》》》》》》》》》》》》》》》工具类Base64源代码》》》》》》

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
 
/**
 * Base64编码工具类
 */
public class Base64 {
        private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
 
        public static String encode(byte[] data) {
                int start = 0;
                int len = data.length;
                StringBuffer buf = new StringBuffer(data.length * 3 / 2);
 
                int end = len - 3;
                int i = start;
                int n = 0;
 
                while (i <= end) {
                        int d = ((((int) data<i>) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff);
 
                        buf.append(legalChars[(d >> 18) & 63]);
                        buf.append(legalChars[(d >> 12) & 63]);
                        buf.append(legalChars[(d >> 6) & 63]);
                        buf.append(legalChars[d & 63]);
 
                        i += 3;
 
                        if (n++ >= 14) {
                                n = 0;
                                buf.append(" ");
                        }
                }
 
                if (i == start + len - 2) {
                        int d = ((((int) data<i>) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8);
 
                        buf.append(legalChars[(d >> 18) & 63]);
                        buf.append(legalChars[(d >> 12) & 63]);
                        buf.append(legalChars[(d >> 6) & 63]);
                        buf.append("=");
                } else if (i == start + len - 1) {
                        int d = (((int) data<i>) & 0x0ff) << 16;
 
                        buf.append(legalChars[(d >> 18) & 63]);
                        buf.append(legalChars[(d >> 12) & 63]);
                        buf.append("==");
                }
 
                return buf.toString();
        }
 
        private static int decode(char c) {
                if (c >= 'A' && c <= 'Z')
                        return ((int) c) - 65;
                else if (c >= 'a' && c <= 'z')
                        return ((int) c) - 97 + 26;
                else if (c >= '0' && c <= '9')
                        return ((int) c) - 48 + 26 + 26;
                else
                        switch (c) {
                        case '+':
                                return 62;
                        case '/':
                                return 63;
                        case '=':
                                return 0;
                        default:
                                throw new RuntimeException("unexpected code: " + c);
                        }
        }
 
        /**
         * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned.
         */
 
        public static byte[] decode(String s) {
 
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                try {
                        decode(s, bos);
                } catch (IOException e) {
                        throw new RuntimeException();
                }
                byte[] decodedBytes = bos.toByteArray();
                try {
                        bos.close();
                        bos = null;
                } catch (IOException ex) {
                        System.err.println("Error while decoding BASE64: " + ex.toString());
                }
                return decodedBytes;
        }
 
        private static void decode(String s, OutputStream os) throws IOException {
                int i = 0;
 
                int len = s.length();
 
                while (true) {
                        while (i < len && s.charAt(i) <= ' ')
                                i++;
 
                        if (i == len)
                                break;
 
                        int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3)));
 
                        os.write((tri >> 16) & 255);
                        if (s.charAt(i + 2) == '=')
                                break;
                        os.write((tri >> 8) & 255);
                        if (s.charAt(i + 3) == '=')
                                break;
                        os.write(tri & 255);
 
                        i += 4;
                }
        }
}</i></i></i>

 

 

》》》》》》》》》》》》》》iphone端

//
//  DES3Util.h
//
 
#import <Foundation/Foundation.h>
 
 
@interface DES3Util : NSObject {
 
}
 
// 加密方法
+ (NSString*)encrypt:(NSString*)plainText;
 
// 解密方法
+ (NSString*)decrypt:(NSString*)encryptText;
 
@end

 

》》》》》》》》

//
//  DES3Util.m
//
 
#import "DES3Util.h"
#import <CommonCrypto/CommonCryptor.h>
#import "GTMBase64.h"
 
#define gkey                        @"liuyunqiang@lx100$#365#$"
#define gIv             @"01234567"
 
@implementation DES3Util
 
// 加密方法
+ (NSString*)encrypt:(NSString*)plainText {
    NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
        size_t plainTextBufferSize = [data length];
        const void *vplainText = (const void *)[data bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    const void *vkey = (const void *) [gkey UTF8String];
    const void *vinitVec = (const void *) [gIv UTF8String];
    
    ccStatus = CCCrypt(kCCEncrypt,
                       kCCAlgorithm3DES,
                       kCCOptionPKCS7Padding,
                       vkey,
                       kCCKeySize3DES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        NSString *result = [GTMBase64 stringByEncodingData:myData];
    return result;
}
 
// 解密方法
+ (NSString*)decrypt:(NSString*)encryptText {
    NSData *encryptData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];
        size_t plainTextBufferSize = [encryptData length];
        const void *vplainText = [encryptData bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    const void *vkey = (const void *) [gkey UTF8String];
    const void *vinitVec = (const void *) [gIv UTF8String];
    
    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithm3DES,
                       kCCOptionPKCS7Padding,
                       vkey,
                       kCCKeySize3DES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    
    NSString *result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr
                                                                length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease];
    return result;
}
 
@end

 

 

》》》》》》》》》》》》》》》iphone所用工具“GTMBase64.h”,是iOS平台的Base64编码工具类

ESP8266新手避坑指南:从串口调试到Station模式实战(附手机端调试工具推荐) 本文为ESP8266新手提供全面的避坑指南,从硬件连接到Station模式实战,详细解析串口调试、AT指令使用及手机端调试工具推荐。重点解决电源干扰、波特率匹配等常见问题,帮助开发者快速掌握ESP8266模块的应用技巧,提升物联网项目开发效率。 阅读详情

相关推荐

PKI体系快速介绍

首先,PKI(PublicKeyInfrastructure)是一个体系。公钥基础设施是一个包括硬件、软件、人员、策略和规程的集合,用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。PKI体系是计算机软硬件、权威机构及应用系统的结合。它为实施电子商务、电子政务、办公自动化等提供了基本的安全服务,从而使那些彼此不认识或距离很远的用户能通过信任链安全地交流。—百度百科说白了,PKI还是提供了彼此身份确认的服务,确保通信的安全。...

测试开发的成长点滴 3476

Burp Suite抓包配置全攻略:从代理原理到浏览器与手机端实战

在Web安全测试与开发调试中,抓包是一项基础且关键的技能,它允许安全工程师和开发者深入分析应用层网络通信。其核心原理是通过代理服务器作为中间人,对HTTP/HTTPS请求与响应进行拦截、查看和修改。为了解密HTTPS流量,需要安装并信任由抓包工具生成的CA证书,这本质上是一次受控的中间人攻击过程。掌握这一技术对于进行安全审计、漏洞挖掘、API接口调试及逆向分析具有重要价值,广泛应用于渗透测试、移动应用安全评估和前后端联调等场景。本文以行业标杆工具Burp Suite为例,详细解析其代理设置与HTTPS解密机

weixin_28716443的博客 273

手把手教会51单片机应用esp8266wifi模块

51单片机应用wifi无线esp8266模块过程相关难点如串行通讯、波特率基础知识,AT命令等。

qq_37942840的博客 1万+

移动端安全交互-加密过程场景解析

对于移动应用的安全交互在金融类似的领域要求比较高;在一些对数据比较敏感的应用中也有类似的要求;今天找时间就把我所知道的和大家分享下,本文算是科普文,想深入了解的同学请自行阅读相关书籍;概要:首先我们需要区分几个比较重要的概念:摘要、签名和加密;之后我们介绍实现这些过程的方式-密码学基础; 1.哈希函数; 2.对称加密; 3.非对称加密;最后我们介绍几个常用的加密算法: 哈希...

baby_hua的专栏 2325

esp8266手机端网络调试助手_使用ESP8266连接OneNET

上一次介绍了如何使用Arduino IDE对ESP8266进行开发,并利用对ESP01模块进行了改造,今天介绍一下如何使用ESP8266模块连接OneNET物联网服务器,并通过串口上传数据到服务器。OneNET是由中国移动打造的PaaS物联网开放平台。OneNET定位为PaaS服务,即在物联网应用和真实设备之间搭建高效、稳定、安全的应用平台:面向设备,适配多种网络环境和常见传输协议,提供...

weixin_39880895的博客 1691

手把手教你用手机App(网络调试助手/网络测试)玩转STM32F103+ESP8266的Wi-Fi通信

本文详细介绍了如何利用手机App(网络调试助手/网络测试)实现STM32F103与ESP8266的Wi-Fi通信。从硬件连接到数据收发,涵盖TCP/UDP模式配置及常见问题排查,帮助开发者快速验证物联网项目的无线通信功能。

weixin_33717117的博客 260

移动端与服务器间加密通信

对于移动端与服务器端进行加密通信,传统的方法是移动端和服务器都采用非对称加密方法进行加解密: 1、服务器端生成私钥和公钥对,移动端预先存放服务器端公钥 2、移动端在登陆时,使用服务器端的公钥加密登陆信息。移动端生成私钥和公钥,然后将公钥发送给服务器。 3、服务器私用移动端的公钥给移动端发送消息。 但是,非对称加解密的速度要比对称加解密慢,尤其是在移动端性能有限的情况下,所以折中的方式是非对

yuetingzhuying的专栏 3223

远程桌面控制PPC手机端软件:3389端口应用

远程桌面控制软件允许用户通过网络从一台计算机远程访问另一台计算机的桌面环境。这种软件为远程工作、IT支持和网络管理提供便利,使得用户可以执行文件操作、运行程序和管理远程系统等任务。3389端口是微软远程桌面服务(Remote Desktop Protocol, RDP)所使用的默认端口。RDP允许用户通过网络远程连接到另一台计算机上,执行管理任务或访问数据。由于其简便性和功能性,RDP是企业环境中远程桌面访问和管理的常用工具。3389端口的配置通常发生在客户端与服务器端的设置中。

weixin_42514540的博客 1135

一般的视频加密方式主要分为几种,哪种是适合自己的?

随着版权意识的增强,越来越多的人开始用到加密工具,下面给大家介绍三种基本的加密方式,希望可以对你有所帮助。 1.文件加密 这种的一般就是通常说的一机一码的加密方式,通过专用工具对视频进行加密,加密后的视频发给学员,学员只能通过特定的激活码和播放器才能观看。 优点是破解难度比较高,缺点是学员需要下载播放器和视频才可以观看,灵活性上体现出不足。(如果有服务器的话可以不用学员下载视频,但是播放器也是需要进行下载的) 2.flash视频加密 由于移动端的普及情况,这种加密方式已经很少有人在用了,其实这种的加密方式.

diandunyun2019的博客 1607

实现前端、Android、iPhone和Java后端四个平台一致的加密工具

NULL 博文链接:https://aaron7524.iteye.com/blog/2090075

气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型

本文通过建立不同类型干旱传播过程的触发阈值模型,解析了在不同等级气象干旱胁迫下诱发次一级干旱类型的触发阈值。通过贝叶斯概率模型,我们推导了气象干旱与水文干旱、农业干旱、地下水干旱之间的条件概率关系,进一步明确了气象干旱引发水文干旱、农业干旱和地下水干旱的概率及其触发阈值。该模型有效揭示了气象干旱对各级干旱类型的传播机制及其动态变化,为干旱预警系统的建立和水资源管理提供了理论依据和技术支持。

frankgis的博客 2503

小程序如何在手机端处理微信客服消息?

很多朋友小程序上线后,客服消息这块一直没得到解决。小程序客服消息只能在PC端回复,是让众多小程序运营商及商家头疼的问题,因为一个再牛逼的客服,也不可能随时随地都抱着电脑,这就导致很多用户的留言不能及时得到回复,从而影响用户的使用体验,严重的可能导致顾客投诉、跳单,甚至直接把你的小程序打入“冷宫”,挥挥手再也不见。 接下来,告诉大家一个方法,就可以实现小程序在手机端处理微信客服消息!   一、...

学无紫晶 3445

直流电动机的建模仿真(1)他励,串励和并励电动机建模仿真

本文根据不同励磁方式的直流电动机的接线原理图,建立了相应的数学模型,然后根据与数学模型对应的等效电路以及模拟机械运动方程的等效电路,用Matlab/simulink中的SpecializedPower system库中的电路元件,建立了他励,并励和串励直流电动机的全等效电路仿真模型,经过与Matlab自带的直流电动机仿真模型比较以及仿真实例验证,所建立的仿真模型时完全正确的。

weixin_45670943的博客 7520

微信聊天记录存储位置、存储方式及如何彻底清除

微信聊天记录在移动端和PC端的存储方式不同:移动端(iOS/Android)存储在设备本地的加密SQLite数据库和缓存文件中,路径受系统保护;PC端则保存在电脑硬盘的独立加密文件中。清除方法:移动端可通过微信设置内"清空聊天记录"或卸载微信彻底删除;PC端需在微信设置中清除记录或手动删除WeChatFiles文件夹。特别注意的是,PC端仅卸载微信不会自动删除聊天记录,必须额外手动清除数据文件。

木木的学习笔记 8722

知识图谱中的 Ontology(本体论)

本文的部分图片和内容来自中国科学院自动化研究所刘康老师的课件 Ontology(本体论) Ontology 是(特定领域)信息组织的一种形式,是领域知识规范的抽象和描述,是表达、共享、重用知识的方法。 Ontology 是知识体系构建的关键技术,知识图谱是一种人工智能技术,它的关键在于让计算机能够处理人类的知识。然而,人类脑海中的知识通常是直觉性的,我们无法将这种直觉性的知识直接输入给计算机,On...

P01son的博客 2万+

人形机器人核心架构梳理

定义:机器人是能进行运动、操纵或定位且具有一定程度自主能力的可编程执行机构。按外在形态分类可分为传统机器人和人形机器人,其中人形机器人是一种利用人工智能和机器人技术制造的具有类似人类外观和行为的机器人。

小海聊智造 1万+

手机端“记住密码”功能的安全性解决方案

本人刚踏入这行不久,所以以下文章在高手眼里可能比较稚嫩,还望高手看到后口下留情,另外欢迎提出意见。 由于公司不大,没人带,属于单干型,很多东西也只能摸索和搜索。苦恼。 最近研究android手机端的 登录的 “记住密码“功能。第一想到的就是sharedpreference中,也就是一个xml文件中。但android手机一旦root后,那么只要有人有心,还是能够找到这密码的。而且andr

daguaio_O的专栏 8200

凝聚态物理新引擎:AI 驱动材料预测与相变识别大突破

摘要:本文深入探讨 AI 在凝聚态物理中的创新应用。在材料性质预测方面,AI 借助数据收集、特征提取和模型训练,能依据材料微观信息准确预估其宏观性质,以石墨烯为例验证了高效性。对于拓扑相变识别,AI 通过分析量子力学数据,利用机器学习算法判别相变节点,助力拓扑绝缘体研究。尽管面临数据质量、模型可解释性等挑战,但未来多模态数据融合、可解释 AI 等发展方向,将推动 AI 与凝聚态物理深度融合,助力探索物质奥秘与新材料研发。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1828

foxmail邮件服务器端口,Foxmail设置教程

设置foxmail前,请确保在网页端上能正常的登录自己的邮箱(非常重要)。如果开启了密码二次验证,请仔细阅读本教程下面设置不成功的解决方法。1、选择foxmail 帐号管理2. 新建(左下角)建议将定时收取邮件设置为1分钟,不然所有进入邮箱的邮件,在foxmail上看到需要在15分钟后。3. 选择其它帐号4. 手动设置(左下角)5. 建议选择IMAP协议,填写自己的邮箱帐号,密码,IMAP服务器:...

weixin_28811055的博客 8491

Java全栈:电影数据检索与推荐系统实战

全文检索个性化推荐数据缓存容器化部署通过这个项目,我们不仅实践了Java全栈开发的各项技术,还接触了推荐系统的核心算法实现。用户历史行为数据物品特征数据上下文信息实时反馈算法的准确性推荐的多样性系统的实时性冷启动问题性能优化效果评估VIEW, // 浏览CLICK, // 点击SEARCH, // 搜索RATE, // 评分COMMENT, // 评论SHARE, // 分享WATCH_TIME, // 观看时长。

exlink2012的专栏 891

基于8266WIFI模块实现智能手机与51单片机的通信入门

1  芯片及电路的介绍 1.1  8266WIFI模块       在文章的最开始我们首先要介绍今天的主角,8266WIFI模块。这是一个非常好用的模块,其他的废话不在多说,我们直接上干货.                                             这是一张我从百度上盗的一张8266WIFI模块的原理图,虽然8个引脚看着很复杂,但实际上我们只会用到最多五个引脚...

IamDaodaoLi的博客 4万+

字符编码——简体中文编码中区位码、国标码、内码、外码、字形码的区别及关系

目录区位码国标码(交换码)内码(机内码)区位码、国际码、内码的转换为什么要加上20H为什么加上80H 本文以GB2312为例,讲述区位码、国标码、内码、外码、字形码 区位码 整个GB2312字符集分成94个区,每区有94个位,每个区位上只有一个字符,即每区含有94个汉字或符号,用所在的区和位来对字符进行编码(实际上就是字符编号、码点编号),因此称为区位码。 换言之,GB2312将包括汉字在内的所有字符编入一个94 * 94的二维表,行就是“区”、列就是“位”,每个字符由区、位唯一定位,其对应的区、位编号合并

路人coder 5341

浅谈常用视频加密原理及加密的几种应用形式

一、视频加密 视频加密是对某些自有版权的视频进行加密处理,用户只有在一定的条件下才能获得视频的观看权。比如对于教育视频加密后,只有学员才能观看,每个学员都有自己的唯一账号。或者说设定在一定的时间内可以无限次观看...

cili1688的博客 2619

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

ESP8266与STM32通信点亮LED

先关闭服务器(AT+CIPSERVER=0)然后用单片机按键切换开启服务器(AT+CIPSERVER=1,8080) 不然前面串口助手调试完,ESP8266一上电就会寻找端口,我们手机还来不及连接,就会导致连接失败,所有等手机连接好后,按下按键再开启服务器连接。设置AP模式下的参数:AT+CWSAP="网络名称","密码",通道号(1~14),加密方式(0~4) 如:AT+CWSAP="ESP8266_Test","12345678",1,3。基础指令: 测试指令(AT) 复位指令(AT+RST)

2202_75449126的博客 3770

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: java中文字符编码3
下一篇: 20条设计原则
柏澜
博客等级 码龄14年 3粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值