即时通讯(腾讯)流程

简述集成腾讯即时通讯sdk的流程 今天整理了下之前在项目中集成腾讯即时通讯的过程欢迎遇到各种问题的朋友来一起探讨 首先,申请帐号神马的就不说了,直接代码部分 在项目的Application类中,通过如下代码做一个初始化 在登录的地方,腾讯即时通讯这边分了自有帐号,腾讯帐号以及混合这三种方式,然后我这边项目使用的是自有帐号,自有帐号的话切记一定要先在后台那边把所有自己的帐号全部导入到腾讯服务器,导入方法以及不同平台使用的代码见 阅读详情

1.controller层

// 拼接用户id
        String imId = String.format("u_%s",finalUser.getId());
        // 获取腾讯云用户信息
        Map imUserInfo = this.tencentService.getImUserInfo(imId);
        // 如果没有腾讯云用户信息
        if(imUserInfo == null){
            // 注册腾讯云用户
            this.tencentService.registerImUser(imId,finalUser.getNickname(),finalUser.getHead());
        }else{
            // 已经有腾讯云账户,更新账户信息
            this.tencentService.updateImUserInfo(imId,finalUser.getNickname(),finalUser.getHead());
        }
        // 获取腾讯云通信签名
        String imSig = this.tencentService.getImUserSig(imId);
        return new Message(new HashMap(){{
            this.put("token",subject.getSession().getId());
            this.put("user", new HashMap(){{
                this.put("id", finalUser.getId());
                this.put("head", finalUser.getHead());
                this.put("role", User.Role.values()[finalUser.getRole() == null ? 0 : finalUser.getRole()].name());
            }});
            this.put("im",new HashMap(){{
                // 腾讯云用户id
                this.put("id",imId);
                // 腾讯云通信签名
                this.put("token",imSig);
            }});
        }});

2.TencentService


import com.fasterxml.jackson.databind.ObjectMapper;
import net.pedicure.exception.SystemException;
import net.pedicure.module.Configuration;
import net.pedicure.module.HttpClient;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.Arrays;
import org.json.JSONObject;
import org.springframework.stereotype.Service;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.security.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

@Service
public class TencentService {

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final HttpClient httpClient = new HttpClient();

    private String imManagerSig;

    /**
     * 更新用户信息
     * @param identifier 用户id
     * @param nick 昵称
     * @param faceUrl 头像
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     */
    public void updateImUserInfo(String identifier,String nick,String faceUrl) throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        Map response = this.objectMapper.readValue(this.httpClient.doPost(String.format("https://console.tim.qq.com/v4/profile/portrait_set?usersig=%s&identifier=%s&sdkappid=%s&random=%s&contenttype=json",this.getImManagerSig(),Configuration.property(Configuration.TENCENT_IM_ACCOUNT_MANAGER),Configuration.property(Configuration.TENCENT_IM_SDK_APP_ID),new Date().getTime()),this.objectMapper.writeValueAsString(new HashMap(){{
            this.put("From_Account",identifier);
            this.put("ProfileItem",new ArrayList(){{
                this.add(new HashMap(){{
                    this.put("Tag","Tag_Profile_IM_Nick");
                    this.put("Value",nick);
                }});
                this.add(new HashMap(){{
                    this.put("Tag","Tag_Profile_IM_Image");
                    this.put("Value",faceUrl);
                }});
            }});
        }})),HashMap.class);
        if(!response.get("ActionStatus").equals("OK")){
            throw new SystemException("腾讯云通信获取账号资料异常,ErrorCode:[ " + response.get("ErrorCode") + " ]" + ",ErrorInfo: [" + response.get("ErrorInfo") + " ]");
        }
    }

    /**
     * 获取用户信息
     * @param identifier 用户id
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     */
    public Map getImUserInfo(String identifier) throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        Map response = this.objectMapper.readValue(this.httpClient.doPost(String.format("https://console.tim.qq.com/v4/profile/portrait_get?usersig=%s&identifier=%s&sdkappid=%s&random=%s&contenttype=json",this.getImManagerSig(),Configuration.property(Configuration.TENCENT_IM_ACCOUNT_MANAGER),Configuration.property(Configuration.TENCENT_IM_SDK_APP_ID),new Date().getTime()),this.objectMapper.writeValueAsString(new HashMap(){{
            this.put("To_Account",new ArrayList(){{
                this.add(identifier);
            }});
            this.put("TagList",new ArrayList(){{
                this.add("Tag_Profile_IM_Nick");
                this.add("Tag_Profile_IM_Image");
            }});
        }})),HashMap.class);
        if(!response.get("ActionStatus").equals("OK")){
            if(((int)response.get("ErrorCode")) == 40003){
                return null;
            }
            throw new SystemException("腾讯云通信获取账号资料异常,ErrorCode:[ " + response.get("ErrorCode") + " ]" + ",ErrorInfo: [" + response.get("ErrorInfo") + " ]");
        }
        return response;
    }

    /**
     * QQ登录
     * @param accessToken
     * @return
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws IOException
     */
    public Auth getOpenId(String accessToken) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException {
        String response = this.httpClient.doGet(String.format("https://graph.qq.com/oauth2.0/me?access_token=%s",accessToken));
        response = response.substring(response.indexOf("(") + 1,response.lastIndexOf(")"));
        Map result = this.objectMapper.readValue(response,HashMap.class);
        if(result.get("error") != null){
            throw new SystemException("QQ授权异常,error [ " + result.get("error") + " ] error_description [ " + result.get("error_description") + " ]");
        }
        if(!result.get("client_id").equals(Configuration.property(Configuration.TENCENT_QQ_APP_ID))){
            throw new SystemException("nonsupport appid");
        }
        Auth auth = new Auth();
        auth.openid = (String)result.get("openid");
        auth.client_id = (String)result.get("client_id");
        return auth;
    }

    /**
     * QQ登录
     * @param openid
     * @param accessToken
     * @return
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws IOException
     */
    public User getUserInfo(String openid, String accessToken) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException {
        Map response = this.objectMapper.readValue(this.httpClient.doGet(String.format("https://graph.qq.com/user/get_user_info?access_token=%s&openid=%s&oauth_consumer_key=%s",accessToken,openid,Configuration.property(Configuration.TENCENT_QQ_APP_ID))),HashMap.class);
        if(((int)response.get("ret")) != 0){
            throw new SystemException("QQ授权异常,ret [ " + response.get("ret") + " ] msg [ " + response.get("msg") +" ]");
        }
        User user = new User();
        user.nickname = (String)response.get("nickname");
        user.figureurl_qq_1 = (String)response.get("figureurl_qq_1");
        user.figureurl_qq_2 = (String)response.get("figureurl_qq_2");
        return user;
    }

    /**
     * 通过用户id获取签名
     * @param identifier
     * @return
     * @throws IOException
     */
    public String getImUserSig(String identifier) throws IOException {
        GenTLSSignatureResult genTLSSignatureResult = GenTLSSignatureEx(Long.valueOf(Configuration.property(Configuration.TENCENT_IM_SDK_APP_ID)), identifier, Configuration.property(Configuration.TENCENT_IM_PRIVATE_KEY));
        return genTLSSignatureResult.urlSig;
    }

    /**
     * 获取管理员账号签名
     * @return
     * @throws IOException
     */
    public String getImManagerSig() throws IOException {
        if(StringUtils.isBlank(this.imManagerSig)){
            this.imManagerSig = this.getImUserSig(Configuration.property(Configuration.TENCENT_IM_ACCOUNT_MANAGER));
        }
        return this.imManagerSig;
    }

    /**
     * 注册用户
     * @param identifier
     * @param nick
     * @param faceUrl
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     */
    public void registerImUser(String identifier,String nick,String faceUrl) throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        Map response = this.objectMapper.readValue(this.httpClient.doPost(String.format("https://console.tim.qq.com/v4/im_open_login_svc/account_import?usersig=%s&identifier=%s&sdkappid=%s&random=%s&contenttype=json",this.getImManagerSig(),Configuration.property(Configuration.TENCENT_IM_ACCOUNT_MANAGER),Configuration.property(Configuration.TENCENT_IM_SDK_APP_ID),new Date().getTime()),this.objectMapper.writeValueAsString(new HashMap(){{
            this.put("Identifier",identifier);
            this.put("Nick",nick);
            this.put("FaceUrl",faceUrl);
            this.put("Type",0);
        }})),HashMap.class);
        if(!response.get("ActionStatus").equals("OK")){
            throw new SystemException("腾讯云通信注册账号异常,ErrorCode:[ " + response.get("ErrorCode") + " ]" + ",ErrorInfo: [" + response.get("ErrorInfo") + " ]");
        }
    }

    /**
     * 发送消息
     * @param fromAccount
     * @param toAccount
     * @param text
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     */
    public void imSendTIMTextElemMsg(String fromAccount,String toAccount,String text) throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        Map response = this.objectMapper.readValue(this.httpClient.doPost(String.format("https://console.tim.qq.com/v4/openim/sendmsg?usersig=%s&identifier=%s&sdkappid=%s&random=%s&contenttype=json",this.getImManagerSig(),Configuration.property(Configuration.TENCENT_IM_ACCOUNT_MANAGER),Configuration.property(Configuration.TENCENT_IM_SDK_APP_ID),new Date().getTime()),this.objectMapper.writeValueAsString(new HashMap(){{
            this.put("SyncOtherMachine",1);
            if(!StringUtils.isBlank(fromAccount)){
                this.put("From_Account",fromAccount);
            }
            this.put("To_Account",toAccount);
            this.put("MsgRandom",new Date().getTime() / 1000);
            this.put("MsgBody",new ArrayList(){{
                this.add(new HashMap(){{
                    this.put("MsgType","TIMTextElem");
                    this.put("MsgContent",new HashMap(){{
                        this.put("Text",text);
                    }});
                }});
            }});
        }})),HashMap.class);
        if(!response.get("ActionStatus").equals("OK")){
            throw new SystemException("腾讯云通信发送消息异常,ErrorCode:[ " + response.get("ErrorCode") + " ]" + ",ErrorInfo: [" + response.get("ErrorInfo") + " ]");
        }
    }

    public final class Auth {
        String openid;
        String client_id;
    }

    public final class User{
        String nickname;
        String figureurl_qq_1;
        String figureurl_qq_2;
    }




    public static class GenTLSSignatureResult
    {
        public String errMessage;
        public String urlSig;
        public int expireTime;
        public int initTime;
        public GenTLSSignatureResult()
        {
            errMessage = "";
            urlSig = "";
        }
    }

    public static class CheckTLSSignatureResult
    {
        public String errMessage;
        public boolean verifyResult;
        public int expireTime;
        public int initTime;
        public CheckTLSSignatureResult()
        {
            errMessage = "";
            verifyResult = false;
        }
    }

    /*public static void main(String[] args) {
        try{
            //Use pemfile keys to test
            String privStr = "-----BEGIN PRIVATE KEY-----\n" +
                    "MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgiBPYMVTjspLfqoq46oZd\n" +
                    "j9A0C8p7aK3Fi6/4zLugCkehRANCAATU49QhsAEVfIVJUmB6SpUC6BPaku1g/dzn\n" +
                    "0Nl7iIY7W7g2FoANWnoF51eEUb6lcZ3gzfgg8VFGTpJriwHQWf5T\n" +
                    "-----END PRIVATE KEY-----";

            //change public pem string to public string
            String pubStr = "-----BEGIN PUBLIC KEY-----\n"+
                    "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1OPUIbABFXyFSVJgekqVAugT2pLtYP3c\n"+
                    "59DZe4iGO1u4NhaADVp6BedXhFG+pXGd4M34IPFRRk6Sa4sB0Fn+Uw==\n"+
                    "-----END PUBLIC KEY-----";

            // generate signature
            GenTLSSignatureResult result = GenTLSSignatureEx(1400000955, "xiaojun", privStr);
            if (0 == result.urlSig.length()) {
                System.out.println("GenTLSSignatureEx failed: " + result.errMessage);
                return;
            }

            System.out.println("---\ngenerate sig:\n" + result.urlSig + "\n---\n");

            // check signature
            CheckTLSSignatureResult checkResult = CheckTLSSignatureEx(result.urlSig, 1400000955, "xiaojun", pubStr);
            if(checkResult.verifyResult == false) {
                System.out.println("CheckTLSSignature failed: " + result.errMessage);
                return;
            }

            System.out.println("\n---\ncheck sig ok -- expire time " + checkResult.expireTime + " -- init time " + checkResult.initTime + "\n---\n");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }*/


    /**
     * @brief 生成 tls 票据
     * @param expire 有效期,单位是秒,推荐一个月
     * @param strAppid3rd 填写与 sdkAppid 一致字符串形式的值
     * @param skdAppid 应用的 appid
     * @param identifier 用户 id
     * @param accountType 创建应用后在配置页面上展示的 acctype
     * @param privStr 生成 tls 票据使用的私钥内容
     * @return 如果出错,GenTLSSignatureResult 中的 urlSig为空,errMsg 为出错信息,成功返回有效的票据
     * @throws IOException
     */
    @Deprecated
    public static GenTLSSignatureResult GenTLSSignature(long expire,
                                                        String strAppid3rd, long skdAppid,
                                                        String identifier, long accountType,
                                                        String privStr ) throws IOException
    {

        GenTLSSignatureResult result = new GenTLSSignatureResult();

        Security.addProvider(new BouncyCastleProvider());
        Reader reader = new CharArrayReader(privStr.toCharArray());
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
        PEMParser parser = new PEMParser(reader);
        Object obj = parser.readObject();
        parser.close();
        PrivateKey privKeyStruct = converter.getPrivateKey((PrivateKeyInfo) obj);

        //Create Json string and serialization String
        String jsonString = "{"
                + "\"TLS.account_type\":\"" + accountType +"\","
                +"\"TLS.identifier\":\"" + identifier +"\","
                +"\"TLS.appid_at_3rd\":\"" + strAppid3rd +"\","
                +"\"TLS.sdk_appid\":\"" + skdAppid +"\","
                +"\"TLS.expire_after\":\"" + expire +"\""
                +"}";
        //System.out.println("#jsonString : \n" + jsonString);

        String time = String.valueOf(System.currentTimeMillis()/1000);
        String SerialString =
                "TLS.appid_at_3rd:" + strAppid3rd + "\n" +
                        "TLS.account_type:" + accountType + "\n" +
                        "TLS.identifier:" + identifier + "\n" +
                        "TLS.sdk_appid:" + skdAppid + "\n" +
                        "TLS.time:" + time + "\n" +
                        "TLS.expire_after:" + expire +"\n";


        //System.out.println("#SerialString : \n" + SerialString);
        //System.out.println("#SerialString Hex: \n" + Hex.encodeHexString(SerialString.getBytes()));

        try{
            //Create Signature by SerialString
            Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
            signature.initSign(privKeyStruct);
            signature.update(SerialString.getBytes(Charset.forName("UTF-8")));
            byte[] signatureBytes = signature.sign();

            String sigTLS = Base64.encodeBase64String(signatureBytes);
            //System.out.println("#sigTLS : " + sigTLS);

            //Add TlsSig to jsonString
            JSONObject jsonObject= new JSONObject(jsonString);
            jsonObject.put("TLS.sig", sigTLS);
            jsonObject.put("TLS.time", time);
            jsonString = jsonObject.toString();

            // System.out.println("#jsonString : \n" + jsonString);

            //compression
            Deflater compresser = new Deflater();
            compresser.setInput(jsonString.getBytes(Charset.forName("UTF-8")));

            compresser.finish();
            byte [] compressBytes = new byte [512];
            int compressBytesLength = compresser.deflate(compressBytes);
            compresser.end();
            //System.out.println("#compressBytes "+ compressBytesLength+": " + Hex.encodeHexString(Arrays.copyOfRange(compressBytes,0,compressBytesLength)));

            //String userSig = Base64.encodeBase64URLSafeString(Arrays.copyOfRange(compressBytes,0,compressBytesLength));
            String userSig = new String(base64_url.base64EncodeUrl(Arrays.copyOfRange(compressBytes,0,compressBytesLength)));

            result.urlSig = userSig;
            //System.out.println("urlSig: "+ userSig);
        }
        catch(Exception e)
        {
            e.printStackTrace();
            result.errMessage = "generate usersig failed";
        }

        return result;
    }

    /**
     * @brief 校验 tls 票据
     * @param urlSig 返回 tls 票据
     * @param strAppid3rd 填写与 sdkAppid 一致的字符串形式的值
     * @param skdAppid 应的 appid
     * @param identifier 用户 id
     * @param accountType 创建应用后在配置页面上展示的 acctype
     * @param publicKey 用于校验 tls 票据的公钥内容,但是需要先将公钥文件转换为 java 原生 api 使用的格式,下面是推荐的命令
     *         openssl pkcs8 -topk8 -in ec_key.pem -outform PEM -out p8_priv.pem -nocrypt
     * @return 如果出错 CheckTLSSignatureResult 中的 verifyResult 为 false,错误信息在 errMsg,校验成功为 true
     * @throws DataFormatException
     */
    @Deprecated
    public static CheckTLSSignatureResult CheckTLSSignature( String urlSig,
                                                             String strAppid3rd, long skdAppid,
                                                             String identifier, long accountType,
                                                             String publicKey ) throws DataFormatException
    {
        CheckTLSSignatureResult result = new CheckTLSSignatureResult();
        Security.addProvider(new BouncyCastleProvider());

        //DeBaseUrl64 urlSig to json
        Base64 decoder = new Base64();

        //byte [] compressBytes = decoder.decode(urlSig.getBytes());
        byte [] compressBytes = base64_url.base64DecodeUrl(urlSig.getBytes(Charset.forName("UTF-8")));

        //System.out.println("#compressBytes Passing in[" + compressBytes.length + "] " + Hex.encodeHexString(compressBytes));

        //Decompression
        Inflater decompression =  new Inflater();
        decompression.setInput(compressBytes, 0, compressBytes.length);
        byte [] decompressBytes = new byte [1024];
        int decompressLength = decompression.inflate(decompressBytes);
        decompression.end();

        String jsonString = new String(Arrays.copyOfRange(decompressBytes, 0, decompressLength));

        //System.out.println("#Json String passing in : \n" + jsonString);

        //Get TLS.Sig from json
        JSONObject jsonObject= new JSONObject(jsonString);
        String sigTLS = jsonObject.getString("TLS.sig");

        //debase64 TLS.Sig to get serailString
        byte[] signatureBytes = decoder.decode(sigTLS.getBytes(Charset.forName("UTF-8")));

        try{

            String sigTime = jsonObject.getString("TLS.time");
            String sigExpire = jsonObject.getString("TLS.expire_after");

            //checkTime
            //System.out.println("#time check: "+ System.currentTimeMillis()/1000 + "-"
            //+ Long.parseLong(sigTime) + "-" + Long.parseLong(sigExpire));
            if( System.currentTimeMillis()/1000 - Long.parseLong(sigTime) > Long.parseLong(sigExpire))
            {
                result.errMessage = new String("TLS sig is out of date ");
                System.out.println("Timeout");
                return result;
            }

            //Get Serial String from json
            String SerialString =
                    "TLS.appid_at_3rd:" + strAppid3rd + "\n" +
                            "TLS.account_type:" + accountType + "\n" +
                            "TLS.identifier:" + identifier + "\n" +
                            "TLS.sdk_appid:" + skdAppid + "\n" +
                            "TLS.time:" + sigTime + "\n" +
                            "TLS.expire_after:" + sigExpire + "\n";

            //System.out.println("#SerialString : \n" + SerialString);

            Reader reader = new CharArrayReader(publicKey.toCharArray());
            PEMParser  parser = new PEMParser(reader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            Object obj = parser.readObject();
            parser.close();
            PublicKey pubKeyStruct  = converter.getPublicKey((SubjectPublicKeyInfo) obj);

            Signature signature = Signature.getInstance("SHA256withECDSA","BC");
            signature.initVerify(pubKeyStruct);
            signature.update(SerialString.getBytes(Charset.forName("UTF-8")));
            boolean bool = signature.verify(signatureBytes);
            //System.out.println("#jdk ecdsa verify : " + bool);
            result.verifyResult = bool;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            result.errMessage = "Failed in checking sig";
        }

        return result;
    }

    /**
     * @brief 生成 tls 票据,精简参数列表,有效期默认为 180 天
     * @param skdAppid 应用的 sdkappid
     * @param identifier 用户 id
     * @param privStr 私钥文件内容
     * @return
     * @throws IOException
     */
    public static GenTLSSignatureResult GenTLSSignatureEx(
            long skdAppid,
            String identifier,
            String privStr) throws IOException {
        return GenTLSSignatureEx(skdAppid, identifier, privStr, 3600*24*180);
    }

    /**
     * @brief 生成 tls 票据,精简参数列表
     * @param skdAppid 应用的 sdkappid
     * @param identifier 用户 id
     * @param privStr 私钥文件内容
     * @param expire 有效期,以秒为单位,推荐时长一个月
     * @return
     * @throws IOException
     */
    public static GenTLSSignatureResult GenTLSSignatureEx(
            long skdAppid,
            String identifier,
            String privStr,
            long expire) throws IOException {

        GenTLSSignatureResult result = new GenTLSSignatureResult();

        Security.addProvider(new BouncyCastleProvider());
        Reader reader = new CharArrayReader(privStr.toCharArray());
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
        PEMParser parser = new PEMParser(reader);
        Object obj = parser.readObject();
        parser.close();
        PrivateKey privKeyStruct = converter.getPrivateKey((PrivateKeyInfo) obj);

        String jsonString = "{"
                + "\"TLS.account_type\":\"" + 0 +"\","
                +"\"TLS.identifier\":\"" + identifier +"\","
                +"\"TLS.appid_at_3rd\":\"" + 0 +"\","
                +"\"TLS.sdk_appid\":\"" + skdAppid +"\","
                +"\"TLS.expire_after\":\"" + expire +"\","
                +"\"TLS.version\": \"201512300000\""
                +"}";

        String time = String.valueOf(System.currentTimeMillis()/1000);
        String SerialString =
                "TLS.appid_at_3rd:" + 0 + "\n" +
                        "TLS.account_type:" + 0 + "\n" +
                        "TLS.identifier:" + identifier + "\n" +
                        "TLS.sdk_appid:" + skdAppid + "\n" +
                        "TLS.time:" + time + "\n" +
                        "TLS.expire_after:" + expire +"\n";

        try {
            //Create Signature by SerialString
            Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
            signature.initSign(privKeyStruct);
            signature.update(SerialString.getBytes(Charset.forName("UTF-8")));
            byte[] signatureBytes = signature.sign();

            String sigTLS = Base64.encodeBase64String(signatureBytes);

            //Add TlsSig to jsonString
            JSONObject jsonObject= new JSONObject(jsonString);
            jsonObject.put("TLS.sig", sigTLS);
            jsonObject.put("TLS.time", time);
            jsonString = jsonObject.toString();

            //compression
            Deflater compresser = new Deflater();
            compresser.setInput(jsonString.getBytes(Charset.forName("UTF-8")));

            compresser.finish();
            byte [] compressBytes = new byte [512];
            int compressBytesLength = compresser.deflate(compressBytes);
            compresser.end();
            String userSig = new String(base64_url.base64EncodeUrl(Arrays.copyOfRange(compressBytes,0,compressBytesLength)));

            result.urlSig = userSig;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            result.errMessage = "generate usersig failed";
        }

        return result;
    }

    public static CheckTLSSignatureResult CheckTLSSignatureEx(
            String urlSig,
            long sdkAppid,
            String identifier,
            String publicKey ) throws DataFormatException {

        CheckTLSSignatureResult result = new CheckTLSSignatureResult();
        Security.addProvider(new BouncyCastleProvider());

        //DeBaseUrl64 urlSig to json
        Base64 decoder = new Base64();
        byte [] compressBytes = base64_url.base64DecodeUrl(urlSig.getBytes(Charset.forName("UTF-8")));

        //Decompression
        Inflater decompression =  new Inflater();
        decompression.setInput(compressBytes, 0, compressBytes.length);
        byte [] decompressBytes = new byte [1024];
        int decompressLength = decompression.inflate(decompressBytes);
        decompression.end();

        String jsonString = new String(Arrays.copyOfRange(decompressBytes, 0, decompressLength));

        //Get TLS.Sig from json
        JSONObject jsonObject= new JSONObject(jsonString);
        String sigTLS = jsonObject.getString("TLS.sig");

        //debase64 TLS.Sig to get serailString
        byte[] signatureBytes = decoder.decode(sigTLS.getBytes(Charset.forName("UTF-8")));

        try {
            String strSdkAppid = jsonObject.getString("TLS.sdk_appid");
            String sigTime = jsonObject.getString("TLS.time");
            String sigExpire = jsonObject.getString("TLS.expire_after");

            if (Integer.parseInt(strSdkAppid) != sdkAppid)
            {
                result.errMessage = new String( "sdkappid "
                        + strSdkAppid
                        + " in tls sig not equal sdkappid "
                        + sdkAppid
                        + " in request");
                return result;
            }

            if ( System.currentTimeMillis()/1000 - Long.parseLong(sigTime) > Long.parseLong(sigExpire)) {
                result.errMessage = new String("TLS sig is out of date");
                return result;
            }

            //Get Serial String from json
            String SerialString =
                    "TLS.appid_at_3rd:" + 0 + "\n" +
                            "TLS.account_type:" + 0 + "\n" +
                            "TLS.identifier:" + identifier + "\n" +
                            "TLS.sdk_appid:" + sdkAppid + "\n" +
                            "TLS.time:" + sigTime + "\n" +
                            "TLS.expire_after:" + sigExpire + "\n";

            Reader reader = new CharArrayReader(publicKey.toCharArray());
            PEMParser  parser = new PEMParser(reader);
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            Object obj = parser.readObject();
            parser.close();
            PublicKey pubKeyStruct  = converter.getPublicKey((SubjectPublicKeyInfo) obj);

            Signature signature = Signature.getInstance("SHA256withECDSA","BC");
            signature.initVerify(pubKeyStruct);
            signature.update(SerialString.getBytes(Charset.forName("UTF-8")));
            boolean bool = signature.verify(signatureBytes);
            result.expireTime = Integer.parseInt(sigExpire);
            result.initTime = Integer.parseInt(sigTime);
            result.verifyResult = bool;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            result.errMessage = "Failed in checking sig";
        }

        return result;
    }

    public static class base64_url {
        static  byte base64_table_url[] =
                { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
                        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
                        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '-', '\0'};

        static  byte base64_pad_url = '_';

        static  short base64_reverse_table_url[] = {
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, 63, -1, -1,
                52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
                -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
                15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
                -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
                41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
        };

        public static int unsignedToBytes(int b)
        {
            return b & 0xFF;
        }

        //int base64_encode_url(const unsigned char *in_str, int length, char *out_str,int *ret_length)
        public static byte [] base64EncodeUrl(byte [] in_str)
        {
            byte [] out_str = new byte [1024] ;

            int out_current = 0;
            int current = 0;
            int length = in_str.length;

            while (length > 2) { /* keep going until we have less than 24 bits */

                out_str[out_current++] = base64_table_url[unsignedToBytes((unsignedToBytes(in_str[current]) >>> 2))];
                out_str[out_current++] = base64_table_url[unsignedToBytes(unsignedToBytes(unsignedToBytes(in_str[current]) & 0x03) << 4) + unsignedToBytes((unsignedToBytes(in_str[current+1]) >>> 4))];
                out_str[out_current++] = base64_table_url[(unsignedToBytes((unsignedToBytes(in_str[current+1]) & 0x0f)) << 2) + unsignedToBytes((unsignedToBytes(in_str[current+2]) >>> 6))];
                out_str[out_current++] = base64_table_url[unsignedToBytes((unsignedToBytes(in_str[current+2]) & 0x3f))];
                current += 3;
                length -= 3; /* we just handle 3 octets of data */
            }

            /* now deal with the tail end of things */
            if (length != 0) {
                out_str[out_current++] = base64_table_url[unsignedToBytes(in_str[current]) >>> 2];
                if (length > 1) {
                    out_str[out_current++] = base64_table_url[unsignedToBytes((unsignedToBytes(in_str[current]) & 0x03) << 4) + unsignedToBytes(unsignedToBytes(in_str[current+1]) >>> 4)];
                    out_str[out_current++] = base64_table_url[unsignedToBytes((unsignedToBytes(in_str[current + 1]) & 0x0f) << 2)];
                    out_str[out_current++] = base64_pad_url;
                } else {
                    out_str[out_current++] = base64_table_url[unsignedToBytes((unsignedToBytes(in_str[current]) & 0x03) << 4)];
                    out_str[out_current++] = base64_pad_url;
                    out_str[out_current++] = base64_pad_url;
                }
            }

            //System.out.println("length in base64EncodeUrl: " + out_current );
            byte [] out_bytes = new String(out_str).getBytes();
            return Arrays.copyOfRange(out_bytes, 0, out_current);
        }

        //int base64_decode_url(const unsigned char *in_str, int length, char *out_str, int *ret_length)
        public static byte [] base64DecodeUrl(byte [] in_str)
        {
            //        const unsigned char *current = in_str;
            int ch, i = 0, j = 0, k;

            int current  = 0;
            int result = 0;
            byte [] out_str = new byte [1024] ;
            int length = in_str.length;
            /* this sucks for threaded environments */

            /* run through the whole string, converting as we go */
            //while ((ch = in_str[current++]) != '\0' && length-- > 0) {
            ch = in_str[0];
            while(length-- > 0){
                ch = in_str[current++];
                if (ch == base64_pad_url) break;
                    /* When Base64 gets POSTed, all pluses are interpreted as spaces.
                       This line changes them back.  It's not exactly the Base64 spec,
                       but it is completely compatible with it (the spec says that
                       spaces are invalid).  This will also save many people considerable
                       headache.  - Turadg Aleahmad <turadg@wise.berkeley.edu>
                */
                if (ch == ' ') ch = '*'; //never using '+'

                ch = base64_reverse_table_url[ch];
                if (ch < 0) continue;

                switch(i % 4) {
                    case 0:
                        out_str[j] = (byte) unsignedToBytes( unsignedToBytes(ch) << 2);
                        break;
                    case 1:
                        out_str[j++] |= (byte) unsignedToBytes(unsignedToBytes(ch) >>> 4);
                        out_str[j] = (byte) unsignedToBytes(unsignedToBytes(unsignedToBytes(ch) & 0x0f) << 4);
                        break;
                    case 2:
                        out_str[j++] |= (byte) unsignedToBytes(unsignedToBytes(ch) >>> 2);
                        out_str[j] = (byte) unsignedToBytes(unsignedToBytes(unsignedToBytes(ch) & 0x03) << 6);
                        break;
                    case 3:
                        out_str[j++] |= (byte) unsignedToBytes(ch);
                        break;
                }
                i++;
            }
            k = j;
            /* mop things up if we ended on a boundary */
            if (ch == base64_pad_url) {
                switch(i % 4) {
                    case 0:
                    case 1:
                        byte [] error =  new byte [1];
                        error[0] = '\0';
                        return error;
                    case 2:
                        k++;
                    case 3:
                        out_str[k++] = 0;
                }
            }
            return Arrays.copyOfRange(out_str, 0, j);
        }
    }
}

参数补充

public static final String TENCENT_IM_ACCOUNT_MANAGER = "tencent.im.accountManager";
tencent.im.accountManager=spring
public static final String TENCENT_IM_SDK_APP_ID = "tencent.im.sdkAppId";
tencent.im.sdkAppId=***
public static final String TENCENT_QQ_APP_ID = "tencent.qq.appId";
tencent.qq.appId=***
public static final String TENCENT_IM_SDK_APP_ID = "tencent.im.sdkAppId";
tencent.im.sdkAppId=***
public static final String TENCENT_IM_PRIVATE_KEY = "tencent.im.privateKey";
//注意私钥书写格式,换行要用\n
tencent.im.privateKey=-----BEGIN PRIVATE KEY-----\n***\n***\n***\n-----END PRIVATE KEY-----
Android直播软件开发中接入腾讯IM大概流程是怎样的 现阶段来看,直播软件中的即时通讯是非常重要的一个部分,毕竟直播过程中的交流和沟通是非常重要的,所以在Android直播软件开发时需要接入相关的IM服务。 通常我们选择的即时聊天服务,会选择集成简单方便、系统稳定、可靠性好、开发成本小的一方,目前比较常见的IM服务商有极光、环信、腾讯、融云等等,本文以选择腾讯IM为例,简单说下如何在Android直播软件开发时集成腾讯IM。 先登录腾讯云官网 htt... 阅读详情

相关推荐

UniApp实现直播视频与即时通讯的详细步骤

直播服务需企业资质认证,即时通讯需遵守《即时通信工具公众信息服务发展管理暂行规定》,上线前完成备案。实际开发中请使用测试环境SDKAppID,避免生产环境密钥泄露。(播放)组件,需搭配第三方云服务(如腾讯云直播):使用腾讯云IM SDK(需安装。

xkxnq的专栏 2190

Java对接腾讯IM以及一些方法的简单封装

一. 腾讯IM快速入门 1. 注册腾讯云账号,找到即时通信IM控制台 腾讯IM控制台:https://console.cloud.tencent.com/im 2. 创建即时通信应用 3. 进到应用里面可以看到这个应用的SDKAppID和key(密钥) 4. 可以参考官方提供的“服务端API接口文档”和“接口调试工具” API接口文档:https://cloud.tencent.com/document/product/269 接口在线调试工具:https://tcc.tencentcs.com/im-

qq_40406380的博客 6779

有关微信小程序接入腾讯云IM即时通讯内容

微信小程序接入腾讯云IM即时通讯(聊天窗口) 1.效果图: 2.功能点: 1.布局要分左右两边布局,如果是自己为发送消息方,都在右边,对方发送的消息在左边。 2.腾讯云返回的是时间戳,需要转换一下时间,腾讯云是没有返回头像的,需要单独获取并且设置自己跟对方的头像。 3.发送的消息分为自定义消息跟普通文本消息,带房源图片 跟价格和小区名称的是自定义的消息,从房源详情进入聊天就自动发送,普通文本消息则在底部栏发送。 4.获取聊天的历史记录,下拉上翻历史记录,这里没有做本地缓存,是做了每次进入都拉取.

m0_66327625的博客 2760

消息之IM签名(腾讯)

@TOC 简介 ​ IM 即时通信(Instant Messaging,IM)基于 QQ 底层 IM 能力开发,仅需植入 SDK 即可轻松集成聊天、会话、群组、资料管理能力,帮助您实现文字、图片、短语音、短视频等富媒体消息收发,全面满足通信需要。 ​ 官方接口文档 yml属性配置 #腾讯IM 签名 tencent: im: sdkAppid: 1400551440 #签名过期时间 默认时间:7 x 24 x 60 x 60 = 604800 = 7 天 expireTime:

weixin_42526326的博客 1017

Fedproto:原型聚合的联邦学习框架

文中说明,联邦学习通过计算传递梯度聚合模型时,客户端之间的异构性通常会阻碍模型优化收敛和泛化性能。故本文提出新的FedProto框架,将梯度替换成为原型,通过计算、聚合从不同客户端收集到的本地原型,然后将全局原型发送回所有客户端,以规范本地模型的训练。对每个客户机进行局部训练的目的是最小化对本地数据的分类损失,同时保持生成的本地原型足够接近相应的全局原型(损失函数最小+正则)。什么是原型?文中提到:“

weixin_47754029的博客 2649

Windows 11/10系统盘被BitLocker锁了别慌!手把手教你用manage-bde命令找回密钥并解锁

本文详细介绍了当Windows 11/10系统盘被BitLocker锁定后的恢复方法,重点讲解了如何使用manage-bde命令行工具找回密钥并解锁加密驱动器。通过进入Windows恢复环境、诊断锁定状态、提取恢复密钥ID以及执行解锁操作等步骤,帮助用户有效解决BitLocker锁定问题,同时提供了后续防护优化建议和高级故障排除技巧。

weixin_42542669的博客 1461

项目中进入腾讯IM

需求:当时公司要求快速的接入一个 Im聊天而不是自己开发 ,然后我就看到了腾讯im 大概流程就是 引入sdk 然后封装 tim.js文件作为tim模块独立出来,引入对应的cos包,并导出tim实例, 当时遇到的难题就是 userSig 签名 ,为了能在本地登录账户,需要利用客户端计算UserSig生成签名,再配上userID,就可以登录到IM系统, 后来我还是参考了官方的示例文件 GenerateTestUserSig.js和lib-generate-test-usersig.min.js来生成签...

m0_61373758的博客 321

Rsoft仿真实战:长周期光纤光栅参数优化与模式耦合分析

本文详细介绍了使用Rsoft软件进行长周期光纤光栅(LPFG)参数优化与模式耦合分析的实战方法。通过Rsoft仿真,可以高效优化光栅周期、包层厚度等关键参数,深入分析纤芯模与包层模的耦合特性,为光纤通信和传感应用提供可靠的设计依据。

h0i1j2k3l的博客 1115

腾讯云IM简介和使用流程

即时通信 (IM )是指能够即时发送和接收 互联网 消息等的业务。自1998年面世以来,特别是近几年的迅速发展,即时通信的功能日益丰富,逐渐集成了 电子邮件 、 博客 、 音乐 、电视、游戏和搜索等多种功能。即时通信不再是一个单纯的 聊天工具 ,它已经发展成集交流、 资讯、娱乐、搜索、电子商务 、办公协作和企业客户服务等为一体的综合化信息平台。

lsf15870973083的博客 2008

Pytorch实现softmax多分类

PyTorch实现softmax多分类

天涯雨的博客 1388

半导体工艺仿真:离子注入工艺仿真_(8).损伤和缺陷仿真

离子注入工艺在半导体制造中是一个重要的步骤,用于在半导体材料中引入特定的掺杂剂。然而,离子注入过程中不可避免地会产生损伤和缺陷,这些损伤和缺陷会直接影响器件的性能和可靠性。因此,对离子注入工艺中的损伤和缺陷进行仿真研究是必不可少的。本节将详细介绍如何使用仿真软件对离子注入过程中的损伤和缺陷进行建模和分析。

2401_87715305的博客 1339

iOS之即时通讯相关理解

Socket: 1>Socket又称"套接字” 2>网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。 3>应用程序通常通过"套接字"向网络发出请求或者应答网络请求 网络通信的要素: 1>网络上的请求就是通过Socket来建立连接然后互相通信 2>IP地址(网络上主机设备的唯一标识) 3>端口号(定...

weixin_30642029的博客 601

行测测评——矩阵、圆形、环形三角图形数列推理解题技巧

写在前面:各大公司的测评做的让人眼花缭乱,很多题型都是第一次见,比如逻辑关系、信息推理,最难的要属找规律的数字推理了。根据B站UP主刘文超老师的课程,记录一下解题技巧。感谢UP主的无私奉献,原地址连接:https://www.bilibili.com/video/BV1it411M7o2?t=528&p=7 解题技巧: 从图形的上下、左右、交叉 角度进行尝试求解 基本法则是“加、减、乘、除、倍数、次方”六种形态。 一、有心数阵 解题技巧:周边数字通过某种运算得到中间数字 1.周边数..

涵盖了计算机专业基础知识、数学建模相关实践、复杂网络论文研究、LeetCode算法刷题经验、C语言开发经验、前端Vue、React框架开发实战相关知识 8642

flutter 集成 腾讯 im

flutter 集成腾讯im比较简单 注意点UserSig的生成 登陆的时候调用 开发者后台生成 在开发者后台,实际上调用云通信IM生成UserSig的库,把以下三个重要信息进行对称加密(非对称的方式已经停用),生成UserSig SdkAppid:云通信IM应用的唯一ID SecretKey:云通信IM应用的唯一密钥 ExpireTime:密码过期时间,开发者指定 GenerateTestUserSig UserSig的生成 /** * * @class na..

一抹离愁 3487

基于MATLAB的井筒多相流模拟

井筒多相流的模拟可以基于不同的数学模型和计算方法。其中,最常用的模型之一是多相流模型,它基于质量守恒、动量守恒和能量守恒等原理,描述了流体在井筒中的流动行为。对于井筒多相流的模拟和分析可以帮助我们理解和优化油气田开发过程中的流体行为,从而提高产量和效率。在本文中,我们将介绍如何使用MATLAB进行井筒多相流的模拟,并提供相应的源代码。需要注意的是,以上示例是一个简化的模拟,仅用于演示如何使用MATLAB进行井筒多相流模拟。实际应用中,我们需要考虑更多的物理过程和参数,并使用更复杂的数值方法和模型进行模拟。

AtdiHtml的博客 706

日常工作记录---在虚拟机中进行slam建图

   今天是10月24号,首先祝各位程序员们节日快乐!!!    最近一周由于实习的原因,对ROS的探索学习,停滞了一段时间,所以今天也就没什么大的进展,本篇文章仅仅记录一下,我在虚拟机中进行slam建图可行性验证的过程,本篇文章同样使用古月学院《如何在Gazebo中实现阿克曼转向车的仿真》的课程资料来进行验证    下面各条之间并没有严格的顺序关系,每一条都是独立的,都是我在验证过程中的经验或者记录:    1、在运行roslaunch bringup racecar_gazebo_rviz.lau

慕羽★的博客 4828

关于使用腾讯云腾讯(即时通讯SDK)遇到的问题

公司项目中需要进行服务器控制用户端操作 由于前期规划提出的需求,放弃了推送和WebSocket 然后转换思路使用即时通讯实现C/S,根据通话消息内容进行判断做出相应的操作 好了。不啰嗦开整。 ----------------------------------------------------------------------------------------------------...

入门到翘辫子 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

腾讯云WebIM和阿里百川即时通讯使用总结

主要使用流程:1.注册平台账号2.创建应用,获取相应的登录凭证    腾讯云:聊天账号所需登录凭证有sdkAppID(所属应用id),identifier(相当于当前登录账户ID),accountType(所属应用帐号类型),userSig(当前用户身份凭证,通过identifier+秘钥TLS生成)。默认会创建一个当前用户,可使用demo或API创建其他用户。    阿里百川:聊天账号所需登录凭...

cyn_653620的博客 7862

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

C# 调用腾讯即时通信 IM

IM SDK API 概述 https://cloud.tencent.com/document/product/269/33543 /// <summary> /// IM SDK 初始化。 /// </summary> /// <param name="sdk_app_id"></param> /// <param name="json_sdk_config"...

marcushbs的博客 1294

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

内网即时通讯,企业内即时通讯带来了工作方式的深刻变革

综上所述,企业内网即时通讯工具在提高沟通效率、促进团队协作、优化工作流程、增强信息安全和降低沟通成本等方面发挥了重要作用,为现代企业的工作方式带来了深刻变革。

u011712942的博客 702

android 腾讯的IM

1.腾讯IM文档地址 https://cloud.tencent.com/document/product/269/1557#.E5.88.9B.E5.BB.BA.E5.BA.94.E7.94.A8 2.下面有两个工具类 /** * 初始化 * 包括imsdk等 * 文档: */ public class InitBusiness { private static f...

54hk的博客 1692

Uni-app 小程序使用腾讯云IM实时通讯

uni-app开发的小程序 集成了腾讯云IM聊天

qq_46591275的博客 1984

如何定时发送云湖社交APP消息?玩转云湖机器人

如何定时发送云湖社交APP消息?玩转云湖机器人

part210的博客 927

如果在自己程序里集成一个微信qq一样的聊天系统呢?腾讯云即时通讯IM(客户端API【部分】)

腾讯云即时通讯IM 客户端API SDK API(Web&小程序) TIM(命名空间) 方法 create() let options = { SDKAppID: 0 // 接入时需要将0替换为您的云通信应用的 SDKAppID,类型为 Number }; let tim = TIM.create(options); // SDK 实例通常用 tim 表示 如果需要海外通信:配置项oversea:true 常量 event:监听处理 SDK 进入 ready 状态时触发,接入侧

weixin_49030317的博客 659

腾讯云-即时通信 IM uni-app 和 java 整合过程

流程 初始化 登录(登录需要seggin授权) 获取genSig的代码 pom.xml 引入 工具类: import com.tencentyun.TLSSigAPIv2; public class IMUtil { static TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(1400336444L,"9f49af87a3d11a077d...

吴灵辉的博客 4593

微信小程序使用腾讯云IM(一):登录

微信小程序使用腾讯云IM 新项目已经完成很久啦,久的我都想放弃啦。 这个项目里主要的难点其实是1v1聊天。他们对比了好几家的即时通讯,最后选择了腾讯云通信。我猜,可能是因为腾讯云上说日活低于10w可以不付费吧。省钱嘛~踩坑踩了大概一周多两周了,就把一些步骤写下来,万一以后也会用到呢。不过,腾讯云的demo和sdk真的是万年不更新了,真的是好难用啊....坑都是自己一个一个踩一个一个填的。 1.下载sdk并且引用至项目 在官网中找到自己所需要的sdk并且下载,然后放在自己的项目中,引用进去。

书写人生 1686
上一篇: 消息推送(极光推送)流程
下一篇: 运用阿里云短信,进行注册流程
谷若怀虚
博客等级 码龄8年 4粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值