Raysoft.Framework.Encrypt.PassService

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Raysoft.Framework.Encrypt
{
    /// <summary>
    /// 用于生成Kingdee K3系统用户密码
    /// </summary>
    public class PassService
    {
        //数字
        string[] p0 = new string[] { " P ", "#  ", ",  " };
        string[] p1 = new string[] { " Q ", "#$ ", ",0 " };
        string[] p2 = new string[] { " R ", "#( ", ",@ " };
        string[] p3 = new string[] { " S ", "#, ", ",P " };
        string[] p4 = new string[] { " T ", "#0 ", "-  " };
        string[] p5 = new string[] { " U ", "#4 ", "-0 " };
        string[] p6 = new string[] { " V ", "#8 ", "-@ " };
        string[] p7 = new string[] { " W ", "#< ", "-P " };
        string[] p8 = new string[] { " X ", "#@ ", ".  " };
        string[] p9 = new string[] { " Y ", "#D ", ".0 " };
        //小写字母
        string[] pa = new string[] { "!A ", "&$ ", "80" };
        string[] pb = new string[] { "!B ", "&( ", "8@" };
        string[] pc = new string[] { "!C ", "&, ", "8P" };
        string[] pd = new string[] { "!D ", "&0 ", "9 " };
        string[] pe = new string[] { "!E ", "&4 ", "90" };
        string[] pf = new string[] { "!F ", "&8 ", "9@" };
        string[] pg = new string[] { "!G ", "&< ", "9P" };
        string[] ph = new string[] { "!H ", "&@ ", ": " };
        string[] pi = new string[] { "!I ", "&D ", ":0" };
        string[] pj = new string[] { "!J ", "&H ", ":@" };
        string[] pk = new string[] { "!K ", "&L ", ":P" };
        string[] pl = new string[] { "!L ", "&P ", "; " };
        string[] pm = new string[] { "!M ", "&T ", ";0" };
        string[] pn = new string[] { "!N ", "&X ", ";@" };
        string[] po = new string[] { "!O ", "&/ ", ";P" };
        string[] pp = new string[] { "!P ", "'  ", "< " };
        string[] pq = new string[] { "!Q ", "'$ ", "<0" };
        string[] pr = new string[] { "!R ", "'( ", "<@" };
        string[] ps = new string[] { "!S ", "', ", "<P" };
        string[] pt = new string[] { "!T ", "'0 ", "= " };
        string[] pu = new string[] { "!U ", "'4 ", "=0" };
        string[] pv = new string[] { "!V ", "'8 ", "=@" };
        string[] pw = new string[] { "!W ", "'< ", "=P" };
        string[] px = new string[] { "!X ", "'@ ", "> " };
        string[] py = new string[] { "!Y ", "'D ", ">0" };
        string[] pz = new string[] { "!Z ", "'H ", ">@" };
        //大写字母
        string[] pA = new string[] { "!! ", "$$ ", "00" };
        string[] pB = new string[] { "!\" ", "$( ", "0@" };
        string[] pC = new string[] { "!# ", "$, ", "0P" };
        string[] pD = new string[] { "!$ ", "$0 ", "1 " };
        string[] pE = new string[] { "!% ", "$4 ", "10" };
        string[] pF = new string[] { "!& ", "$8 ", "1@" };
        string[] pG = new string[] { "!' ", "$< ", "1P" };
        string[] pH = new string[] { "!( ", "$@ ", "2 " };
        string[] pI = new string[] { "!) ", "$D ", "20" };
        string[] pJ = new string[] { "!* ", "$H ", "2@" };
        string[] pK = new string[] { "!+ ", "$L ", "2P" };
        string[] pL = new string[] { "!, ", "$P ", "3 " };
        string[] pM = new string[] { "!- ", "$T ", "30" };
        string[] pN = new string[] { "!. ", "$X ", "3@" };
        string[] pO = new string[] { "!/ ", "$/ ", "3P" };
        string[] pP = new string[] { "!0 ", "%  ", "4 " };
        string[] pQ = new string[] { "!1 ", "%$ ", "40" };
        string[] pR = new string[] { "!2 ", "%( ", "4@" };
        string[] pS = new string[] { "!3 ", "%, ", "4P" };
        string[] pT = new string[] { "!4 ", "%0 ", "5 " };
        string[] pU = new string[] { "!5 ", "%4 ", "50" };
        string[] pV = new string[] { "!6 ", "%8 ", "5@" };
        string[] pW = new string[] { "!7 ", "%< ", "5P" };
        string[] pX = new string[] { "!8 ", "%@ ", "6 " };
        string[] pY = new string[] { "!9 ", "%D ", "60" };
        string[] pZ = new string[] { "!: ", "%H ", "6@" };
        //符号
        //!
        string[] p11 = new string[] { " A ", "\"$ ", "(0" };
        //@
        string[] p12 = new string[] { " ! ", "$  ", "0 " };
        //#
        string[] p13 = new string[] { " C ", "\", ", "(P" };
        //$
        string[] p14 = new string[] { " D ", "\"0 ", ") " };
        //%
        string[] p15 = new string[] { " E ", "\"4 ", ")0" };
        //^
        string[] p16 = new string[] { "!> ", "%X ", "7@" };
        //&
        string[] p17 = new string[] { " F ", "\"8 ", ")@" };
        //*
        string[] p18 = new string[] { " J ", "\"H ", "*@" };
        //(
        string[] p19 = new string[] { " H ", "\"@ ", "* " };
        //)
        string[] p20 = new string[] { " I ", "\"D ", "*0" };

        //_
        string[] p21 = new string[] { "!? ", "%/ ", "7P" };
        //+
        string[] p22 = new string[] { " K ", "\"L ", "*P" };
        //=
        string[] p23 = new string[] { " ] ", "#T ", "/0" };
        //-
        string[] p24 = new string[] { " M ", "\"T ", "+0" };
        //[
        string[] p25 = new string[] { "!; ", "%L ", "6P" };
        //]
        string[] p26 = new string[] { "!= ", "%T ", "70" };
        //{
        string[] p27 = new string[] { "![ ", "'L ", ">P" };
        //}
        string[] p28 = new string[] { "!] ", "'T ", "?0" };
        //;
        string[] p29 = new string[] { " [ ", "#L ", ".P" };
        //:
        string[] p30 = new string[] { " Z ", "#H ", ".@" };

        //"
        string[] p31 = new string[] { " B ", "\"( ", "(@" };
        //'
        string[] p32 = new string[] { " G ", "\"< ", ")P" };
        //,
        string[] p33 = new string[] { " L ", "\"P ", "+ " };
        //.
        string[] p34 = new string[] { " N ", "\"X ", "+@" };
        //?
        string[] p35 = new string[] { " _ ", "#/ ", "/P" };
        /// 
        string[] p36 = new string[] { "!< ", "%P ", "7 " };
        //|
        string[] p37 = new string[] { "!/ ", "'P ", "? " };
        //\
        string[] p38 = new string[] { " 0 ", "\"/", "+P" };
        //\
        string[] p39 = new string[] { "!@ ", "&  ", "8 " };
        //~
        string[] p40 = new string[] { "!^ ", "'X ", "?@" };

        //<
        string[] p41 = new string[] { " / ", "#P ", "/ " };
        //>
        string[] p42 = new string[] { " ^ ", "#X ", "/@" };

        /// <summary>
        /// 查询密码表,对应生成Kingdee密码
        /// 版本号是用来区别V11以下的K3,前面有一组字符前缀
        /// </summary>
        /// <param name="pass">密码明文</param>
        /// <param name="KingdeeVersion">版本号</param>
        /// <returns></returns>
        public string EncryptPassword(string pass, int KingdeeVersion)
        {
            string retVal = "";

            for (int i = 0; i < pass.Length; i++)
            {
                //该位是数字
                if (Regex.IsMatch(pass[i].ToString(), @"^[0-9]*$"))
                {
                    if (pass[i].ToString() == "0")
                    {
                        retVal += i % 6 == 3 ? p0[0].Substring(1) : p0[i % 3];
                    }
                    else if (pass[i].ToString() == "1")
                    {
                        retVal += i % 6 == 3 ? p1[0].Substring(1) : p1[i % 3];
                    }
                    else if (pass[i].ToString() == "2")
                    {
                        retVal += i % 6 == 3 ? p2[0].Substring(1) : p2[i % 3];
                    }
                    else if (pass[i].ToString() == "3")
                    {
                        retVal += i % 6 == 3 ? p3[0].Substring(1) : p3[i % 3];
                    }
                    else if (pass[i].ToString() == "4")
                    {
                        retVal += i % 6 == 3 ? p4[0].Substring(1) : p4[i % 3];
                    }
                    else if (pass[i].ToString() == "5")
                    {
                        retVal += i % 6 == 3 ? p5[0].Substring(1) : p5[i % 3];
                    }
                    else if (pass[i].ToString() == "6")
                    {
                        retVal += i % 6 == 3 ? p6[0].Substring(1) : p6[i % 3];
                    }
                    else if (pass[i].ToString() == "7")
                    {
                        retVal += i % 6 == 3 ? p7[0].Substring(1) : p7[i % 3];
                    }
                    else if (pass[i].ToString() == "8")
                    {
                        retVal += i % 6 == 3 ? p8[0].Substring(1) : p8[i % 3];
                    }
                    else if (pass[i].ToString() == "9")
                    {
                        retVal += i % 6 == 3 ? p9[0].Substring(1) : p9[i % 3];
                    }
                    else
                    {
                        retVal += "";
                    }
                }
                else if (Regex.IsMatch(pass[i].ToString(), @"^[a-z]+$"))//是小写字母
                {
                    if (pass[i].ToString() == "a")
                    {
                        retVal += pa[i % 3];
                    }
                    else if (pass[i].ToString() == "b")
                    {
                        retVal += pb[i % 3];
                    }
                    else if (pass[i].ToString() == "c")
                    {
                        retVal += pc[i % 3];
                    }
                    else if (pass[i].ToString() == "d")
                    {
                        retVal += pd[i % 3];
                    }
                    else if (pass[i].ToString() == "e")
                    {
                        retVal += pe[i % 3];
                    }
                    else if (pass[i].ToString() == "f")
                    {
                        retVal += pf[i % 3];
                    }
                    else if (pass[i].ToString() == "g")
                    {
                        retVal += pg[i % 3];
                    }
                    else if (pass[i].ToString() == "h")
                    {
                        retVal += ph[i % 3];
                    }
                    else if (pass[i].ToString() == "i")
                    {
                        retVal += pi[i % 3];
                    }
                    else if (pass[i].ToString() == "j")
                    {
                        retVal += pj[i % 3];
                    }
                    else if (pass[i].ToString() == "k")
                    {
                        retVal += pk[i % 3];
                    }
                    else if (pass[i].ToString() == "l")
                    {
                        retVal += pl[i % 3];
                    }
                    else if (pass[i].ToString() == "m")
                    {
                        retVal += pm[i % 3];
                    }
                    else if (pass[i].ToString() == "n")
                    {
                        retVal += pn[i % 3];
                    }
                    else if (pass[i].ToString() == "o")
                    {
                        retVal += po[i % 3];
                    }
                    else if (pass[i].ToString() == "p")
                    {
                        retVal += pp[i % 3];
                    }
                    else if (pass[i].ToString() == "q")
                    {
                        retVal += pq[i % 3];
                    }
                    else if (pass[i].ToString() == "r")
                    {
                        retVal += pr[i % 3];
                    }
                    else if (pass[i].ToString() == "s")
                    {
                        retVal += ps[i % 3];
                    }
                    else if (pass[i].ToString() == "t")
                    {
                        retVal += pt[i % 3];
                    }
                    else if (pass[i].ToString() == "u")
                    {
                        retVal += pu[i % 3];
                    }
                    else if (pass[i].ToString() == "v")
                    {
                        retVal += pv[i % 3];
                    }
                    else if (pass[i].ToString() == "w")
                    {
                        retVal += pw[i % 3];
                    }
                    else if (pass[i].ToString() == "x")
                    {
                        retVal += px[i % 3];
                    }
                    else if (pass[i].ToString() == "y")
                    {
                        retVal += py[i % 3];
                    }
                    else if (pass[i].ToString() == "z")
                    {
                        retVal += pz[i % 3];
                    }
                }
                else if (Regex.IsMatch(pass[i].ToString(), @"^[A-Z]+$"))//是大写字母
                {
                    if (pass[i].ToString() == "A")
                    {
                        retVal += pA[i % 3];
                    }
                    else if (pass[i].ToString() == "B")
                    {
                        retVal += pB[i % 3];
                    }
                    else if (pass[i].ToString() == "C")
                    {
                        retVal += pC[i % 3];
                    }
                    else if (pass[i].ToString() == "D")
                    {
                        retVal += pD[i % 3];
                    }
                    else if (pass[i].ToString() == "E")
                    {
                        retVal += pE[i % 3];
                    }
                    else if (pass[i].ToString() == "F")
                    {
                        retVal += pF[i % 3];
                    }
                    else if (pass[i].ToString() == "G")
                    {
                        retVal += pG[i % 3];
                    }
                    else if (pass[i].ToString() == "H")
                    {
                        retVal += pH[i % 3];
                    }
                    else if (pass[i].ToString() == "I")
                    {
                        retVal += pI[i % 3];
                    }
                    else if (pass[i].ToString() == "J")
                    {
                        retVal += pJ[i % 3];
                    }
                    else if (pass[i].ToString() == "K")
                    {
                        retVal += pK[i % 3];
                    }
                    else if (pass[i].ToString() == "L")
                    {
                        retVal += pL[i % 3];
                    }
                    else if (pass[i].ToString() == "M")
                    {
                        retVal += pM[i % 3];
                    }
                    else if (pass[i].ToString() == "N")
                    {
                        retVal += pN[i % 3];
                    }
                    else if (pass[i].ToString() == "O")
                    {
                        retVal += pO[i % 3];
                    }
                    else if (pass[i].ToString() == "P")
                    {
                        retVal += pP[i % 3];
                    }
                    else if (pass[i].ToString() == "Q")
                    {
                        retVal += pQ[i % 3];
                    }
                    else if (pass[i].ToString() == "R")
                    {
                        retVal += pR[i % 3];
                    }
                    else if (pass[i].ToString() == "S")
                    {
                        retVal += pS[i % 3];
                    }
                    else if (pass[i].ToString() == "T")
                    {
                        retVal += pT[i % 3];
                    }
                    else if (pass[i].ToString() == "U")
                    {
                        retVal += pU[i % 3];
                    }
                    else if (pass[i].ToString() == "V")
                    {
                        retVal += pV[i % 3];
                    }
                    else if (pass[i].ToString() == "W")
                    {
                        retVal += pW[i % 3];
                    }
                    else if (pass[i].ToString() == "X")
                    {
                        retVal += pX[i % 3];
                    }
                    else if (pass[i].ToString() == "Y")
                    {
                        retVal += pY[i % 3];
                    }
                    else if (pass[i].ToString() == "Z")
                    {
                        retVal += pZ[i % 3];
                    }
                }
                else//是符号
                {
                    if (pass[i].ToString() == "!")
                    {
                        retVal += p11[i % 3];
                    }
                    else if (pass[i].ToString() == "@")
                    {
                        retVal += p12[i % 3];
                    }
                    else if (pass[i].ToString() == "#")
                    {
                        retVal += p13[i % 3];
                    }
                    else if (pass[i].ToString() == "$")
                    {
                        retVal += p14[i % 3];
                    }
                    else if (pass[i].ToString() == "%")
                    {
                        retVal += p15[i % 3];
                    }
                    else if (pass[i].ToString() == "^")
                    {
                        retVal += p16[i % 3];
                    }
                    else if (pass[i].ToString() == "&")
                    {
                        retVal += p17[i % 3];
                    }
                    else if (pass[i].ToString() == "*")
                    {
                        retVal += p18[i % 3];
                    }
                    else if (pass[i].ToString() == "(")
                    {
                        retVal += p19[i % 3];
                    }
                    else if (pass[i].ToString() == ")")
                    {
                        retVal += p20[i % 3];
                    }
                    else if (pass[i].ToString() == "_")
                    {
                        retVal += p21[i % 3];
                    }
                    else if (pass[i].ToString() == "+")
                    {
                        retVal += p22[i % 3];
                    }
                    else if (pass[i].ToString() == "=")
                    {
                        retVal += p23[i % 3];
                    }
                    else if (pass[i].ToString() == "-")
                    {
                        retVal += p24[i % 3];
                    }
                    else if (pass[i].ToString() == "[")
                    {
                        retVal += p25[i % 3];
                    }
                    else if (pass[i].ToString() == "]")
                    {
                        retVal += p26[i % 3];
                    }
                    else if (pass[i].ToString() == "{")
                    {
                        retVal += p27[i % 3];
                    }
                    else if (pass[i].ToString() == "}")
                    {
                        retVal += p28[i % 3];
                    }
                    else if (pass[i].ToString() == ";")
                    {
                        retVal += p29[i % 3];
                    }
                    else if (pass[i].ToString() == ":")
                    {
                        retVal += p30[i % 3];
                    }
                    else if (pass[i].ToString() == "\"")
                    {
                        retVal += p31[i % 3];
                    }
                    else if (pass[i].ToString() == "'")
                    {
                        retVal += p32[i % 3];
                    }
                    else if (pass[i].ToString() == ",")
                    {
                        retVal += p33[i % 3];
                    }
                    else if (pass[i].ToString() == ".")
                    {
                        retVal += p34[i % 3];
                    }
                    else if (pass[i].ToString() == "?")
                    {
                        retVal += p35[i % 3];
                    }
                    else if (pass[i].ToString() == "/")
                    {
                        retVal += p36[i % 3];
                    }
                    else if (pass[i].ToString() == "|")
                    {
                        retVal += p37[i % 3];
                    }
                    else if (pass[i].ToString() == "\\")
                    {
                        retVal += p38[i % 3];
                    }
                    else if (pass[i].ToString() == "`")
                    {
                        retVal += p39[i % 3];
                    }
                    else if (pass[i].ToString() == "~")
                    {
                        retVal += p40[i % 3];
                    }
                    else if (pass[i].ToString() == "<")
                    {
                        retVal += p41[i % 3];
                    }
                    else if (pass[i].ToString() == ">")
                    {
                        retVal += p42[i % 3];
                    }
                    else
                    {
                        retVal += "";
                    }
                }

                //retVal += pass[i].ToString();
            }

            retVal = KingdeeVersion >= 11 ? ")  F \", ,P T #8 *P!D &D 80!N &@ <0 C \'< : !M &4 )0" + retVal : retVal;

            return retVal;
        }
    }
}

<think>我们正在处理一个Spring Cloud配置中心解密失败的问题。用户遇到了一个异常:`Caused by: java.lang.UnsupportedOperationException: No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?`。 根据引用[1]和[2],这个问题通常是由于没有正确配置加密密钥导致的。Spring Cloud Config Server使用一个对称密钥或密钥库来加密和解密配置属性。当客户端尝试解密一个加密的属性时,如果配置不正确,就会抛出上述异常。 ### 原因分析 1. **未配置加密密钥**:在Config Server的配置中,没有设置`encrypt.key`属性(对称加密)或`encrypt.keyStore`(非对称加密)。 2. **密钥配置错误**:配置的密钥与加密时使用的密钥不一致。 3. **配置属性格式错误**:加密的属性值没有使用`{cipher}`前缀,或者格式不正确。 4. **Config Server未启用加密端点**:客户端在解密时可能需要调用Config Server的加密端点,但Config Server没有正确配置。 ### 解决方案 #### 1. 配置对称加密密钥 在Config Server的`bootstrap.yml`(或`application.yml`)中配置对称密钥: ```yaml spring: cloud: config: server: encrypt: enabled: true encrypt: key: your_symmetric_key_here # 设置一个对称密钥 ``` 确保这个密钥与加密时使用的密钥相同。 #### 2. 配置密钥库(非对称加密) 如果需要使用非对称加密,可以配置密钥库: ```yaml spring: encrypt: key-store: location: classpath:/keystore.jks # 密钥库文件路径 password: keystore_password # 密钥库密码 alias: myalias # 别名 secret: mysecret # 别名密码(可选) ``` #### 3. 检查加密属性格式 加密的属性值应该以`{cipher}`开头,例如: ```yaml spring.datasource.password: '{cipher}密文' ``` 如果格式不正确,Config Server将不会尝试解密。 #### 4. 确保Config Server的加密端点可用 在Config Server中,确保`/encrypt`和`/decrypt`端点可用。默认情况下,当配置了加密密钥后,这些端点会自动启用。可以通过发送请求来测试: ```bash curl -X POST http://localhost:8888/encrypt -d "plaintext" ``` 如果返回密文,则说明加密端点工作正常。 #### 5. 客户端配置 客户端需要配置Config Server的地址,以便在启动时获取配置并解密。在客户端的`bootstrap.yml`中: ```yaml spring: cloud: config: uri: http://config-server-host:port # Config Server地址 ``` #### 6. 避免使用FailsafeTextEncryptor 异常信息中提到了`FailsafeTextEncryptor`,这是在无法创建真正的加密器时使用的后备方案(它实际上不会进行解密)。因此,确保正确配置加密密钥,这样Spring Cloud就会使用真正的加密器(如`TextEncryptor`)而不是后备方案。 ### 参考引用 - 引用[1]提到,通过Config Server的`/encrypt`端点可以获取密文,然后将其放入配置文件中,并在前面加上`{cipher}`前缀[^1]。 - 引用[2]展示了在`bootstrap.yml`中配置对称密钥`spring.encrypt.key`的示例[^2]。 - 引用[3]和[4]虽然提到了其他问题,但强调了配置正确性的重要性,特别是类加载顺序和依赖问题[^3][^4]。 ### 注意事项 - 在配置密钥时,确保Config Server和客户端使用的配置文件一致(特别是密钥)。 - 如果使用非对称加密,确保密钥库文件在正确的位置,并且密码和别名正确。 - 在Docker或云环境中,注意文件路径和权限问题。 §§相关问题§§ 1. 如何为Spring Cloud Config Server配置非对称加密? 2. 如何在Spring Cloud Config中加密多个属性? 3. 如何解决Spring Cloud Config客户端无法解密配置的问题? 4. Spring Cloud Config支持哪些加密算法?</think>### Spring Cloud配置中心解密失败解决方案 #### 问题分析 您遇到的`No decryption for FailsafeTextEncryptor`错误表明Spring Cloud无法正确初始化加密组件。核心原因是**配置中心未正确识别加密密钥**,导致系统回退到无解密功能的`FailsafeTextEncryptor`。常见原因包括: 1. **密钥配置缺失**:未在Config Server设置`encrypt.key`参数 2. **密钥格式错误**:密钥未按规范配置在`bootstrap.yml`中 3. **依赖冲突**:类加载顺序导致加密组件初始化失败(引用[3]) 4. **安全策略限制**:JCE无限制策略未安装(引用[4]) #### 解决方案 ##### 1. 配置对称密钥(推荐) 在Config Server的`bootstrap.yml`中添加: ```yaml spring: cloud: config: server: encrypt: enabled: true encrypt: key: IMSYMMETRIC # 自定义对称密钥(引用[2]) ``` > 注意:所有客户端必须使用相同密钥 ##### 2. 验证加密端点 启动Config Server后测试加密功能: ```bash curl localhost:8888/encrypt -d "your_password" ``` 正常应返回密文(如`682bc583f464183...`),否则说明密钥配置无效(引用[1]) ##### 3. 配置文件格式规范 加密值必须用`{cipher}`包裹: ```yaml spring.datasource.password: '{cipher}682bc583f4641835fa2db...' ``` ##### 4. 解决依赖冲突 若存在`EnvironmentDecryptApplicationInitializer`冲突(引用[3]): 1. 在客户端创建同名类: ```java package org.springframework.cloud.bootstrap; public class EnvironmentDecryptApplicationInitializer { // 空实现或自定义逻辑 } ``` 2. 确保该类优先于Spring Cloud加载 ##### 5. 安装JCE无限制策略 Docker环境需添加JCE策略包(引用[4]): ```Dockerfile RUN curl -LO "http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip" \ && unzip jce_policy-8.zip \ && cp -v /UnlimitedJCEPolicyJDK8/*.jar $JAVA_HOME/jre/lib/security/ ``` #### 验证步骤 1. 启动Config Server检查日志:应出现`Located encryptor`提示 2. 访问`/encrypt`端点生成密文 3. 客户端启动时观察日志:`Decrypting property source`表示解密成功 > **关键点**:对称密钥必须在所有服务中保持一致,且必须通过`bootstrap.yml`加载(引用[2])
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值