spark-server/docs/clients/SparkImClient.java
2026-09-18 14:50:41 +08:00

127 lines
4.5 KiB
Java

// Spark IM HTTP + TCP demo against production.
// javac docs/clients/SparkImClient.java && java -cp docs/clients SparkImClient
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPInputStream;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public final class SparkImClient {
static final String API = "https://sparkapi.wyrs365.com";
static final String IM_HOST = "sparkim.wyrs365.com";
static final int IM_PORT = 443;
static final int HDR = 23;
static final long DEVICE_ID = 7;
public static void main(String[] args) throws Exception {
String login = httpPost(API + "/v1/auth/login",
"{\"email\":\"test01@spark.com\",\"verify_code\":\"000000\",\"device_id\":"
+ DEVICE_ID + ",\"device_type\":\"android\",\"device_name\":\"demo\"}");
System.out.println("LOGIN " + login);
if (!login.contains("\"code\":\"0\"")) {
return;
}
String token = jsonString(login, "access_token");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket();
SSLParameters params = socket.getSSLParameters();
params.setServerNames(List.of(new SNIHostName(IM_HOST)));
socket.setSSLParameters(params);
socket.connect(new InetSocketAddress(IM_HOST, IM_PORT), 10_000);
socket.startHandshake();
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());
String auth = "{\"token\":\"" + token + "\",\"device_id\":" + DEVICE_ID
+ ",\"app_version\":\"1.0.0\",\"language\":\"zh-CN\"}";
write(out, 1, 1, auth);
System.out.println("AUTH " + read(in));
write(out, 2, 2, "");
System.out.println("HB " + read(in));
write(out, 4, 3, "{\"peer_id\":1,\"client_msg_id\":\"demo-1\",\"content\":{\"t\":1,\"text\":{\"body\":\"hi\"}}}");
System.out.println("SEND " + read(in));
socket.close();
}
static void write(DataOutputStream out, int cmd, int seq, String body) throws IOException {
byte[] b = body.getBytes(StandardCharsets.UTF_8);
ByteBuffer buf = ByteBuffer.allocate(HDR + b.length);
buf.putShort((short) 0x5350).put((byte) 1).putShort((short) cmd).putShort((short) 0)
.putLong(0).putInt(seq).putInt(b.length).put(b);
out.write(buf.array());
out.flush();
}
static String read(DataInputStream in) throws IOException {
byte[] h = in.readNBytes(HDR);
if (h.length < HDR) {
throw new IOException("short header");
}
ByteBuffer buf = ByteBuffer.wrap(h);
if (buf.getShort() != 0x5350) {
throw new IOException("magic");
}
buf.get();
int cmd = buf.getShort() & 0xffff;
int flags = buf.getShort() & 0xffff;
buf.getLong();
int seq = buf.getInt();
int n = buf.getInt();
byte[] body = in.readNBytes(n);
if ((flags & 1) != 0) {
body = gunzip(body);
}
return "cmd=" + cmd + " seq=" + seq + " " + new String(body, StandardCharsets.UTF_8);
}
static byte[] gunzip(byte[] body) throws IOException {
try (GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(body));
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
gz.transferTo(bos);
return bos.toByteArray();
}
}
static String httpPost(String url, String json) throws IOException {
URL u = URI.create(url).toURL();
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("POST");
c.setDoOutput(true);
c.setRequestProperty("Content-Type", "application/json");
c.setRequestProperty("X-Language", "zh-CN");
c.setRequestProperty("X-App-Version", "1.0.0");
try (OutputStream os = c.getOutputStream()) {
os.write(json.getBytes(StandardCharsets.UTF_8));
}
int code = c.getResponseCode();
InputStream is = code >= 400 ? c.getErrorStream() : c.getInputStream();
try (InputStream in = is) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
}
static String jsonString(String env, String key) {
int i = env.indexOf("\"" + key + "\"");
int colon = env.indexOf(':', i);
int a = env.indexOf('"', colon) + 1;
return env.substring(a, env.indexOf('"', a));
}
private SparkImClient() {}
}