
Mixin Network 是一个免费的 极速的端对端加密数字货币交易系统. 在本章中,你可以按教程在 Mixin Messenger 中创建一个 bot 来接收用户消息, 学到如何给机器人转比特币 或者 让机器人给你转比特币.
如果你运行的是 macOS, 手动到此下载 JDK12, 下载完成后,双击 jdk-11.0.2_osx-x64_bin.dmg, 在弹出的新窗口中,点击 JDK 11.0.2.pkg 文件,依提示一步一步完成安装,Java 会安装在 /Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/bin/ 目录中,将这个路径加入到$PATH
echo 'export PATH=/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/bin/:$PATH' >> ~/.bash_profile source ~/.bash_profile 安装成功后,执行 java --version 将得到如下信息:
wenewzha:mixin_labs-java-bot wenewzhang$ java --version java 11.0.2 2019-01-15 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.2+9-LTS) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+9-LTS, mixed mode) Ubuntu
apt update apt upgrade apt install unzip java --version 以 Ubuntu 16.04 为例,openjdk 版本的 Java 已经安装好了, 执行 java --version来验证安装情况。
root@ubuntu:~# java --version openjdk 10.0.2 2018-07-17 OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4) OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4, mixed mode) 本教程采用 Gradle 来构建,你可从下面的地址来下载安装!Gradle 下载 macOS
brew update brew install gradle Ubuntu 下的 Gradle 太旧,我们手动安装它:
cd ~/Downloads wget https://services.gradle.org/distributions/gradle-5.1.1-bin.zip unzip gradle-5.1.1-bin.zip 解压 gradle-5.1.1-bin.zip 后,增加安装目录到$PATH 中:
echo 'export PATH=/root/gradle-5.1.1/bin:$PATH' >> ~/.bashrc source ~/.bashrc 当 Gradle 安装成功后, 执行gradle -v来验证安装情况:
root@ubuntu:~# gradle -v ------------------------------------------------------------ Gradle 5.1.1 ------------------------------------------------------------ ... 按下面的提示,到 mixin.one 创建一个 APPtutorial.
记下这些生成的参数 它们将用于 Config.java 中.
进入到你的工作目录,创建 mixin_labs-java-bot 目录, 执行gradle init来生成基本信息资料.
gradle init --dsl kotlin --type java-application --test-framework junit --project-name mixin_labs-java-bot 进入 src/main/java/mixin_labs/java/bot 目录,新建一个 Config.java, 填写如下内容:
Config.java
package mixin_labs.java.bot; import mixin.java.sdk.MixinUtil; import java.security.PrivateKey; import java.security.interfaces.RSAPrivateKey; import java.util.Base64; import mixin.java.sdk.PrivateKeyReader; public class Config { public static final String CLIENT_ID = "b1ce2967-a534-417d-bf12-c86571e4eefa"; public static final String CLIENT_SECRET = "e6b14c6bbb20a43c603c468e225e6e4c666c940792cde43e41b34c3f1dd45713"; public static final String PIN = "536071"; public static final String SESSION_ID = "2f1c44a3-d4d2-4dd2-bdb6-8eda67694b91"; public static final String PIN_TOKEN = "ajJJngHmWgIfH3S2mgH4bAsoPeoXV6hI1KoTZW9AvFUK1R8e28X1zVRCcrOMVeXkvBKQeEMgRdX1kRgH3ksITTBm2mgK5eUnfBHUuRC85oKoQGB9e2Bp4O4ZKGg/6bqLeD66pnBPcO2s7VtgLSAK0tHa2jMzmGlWuxsO6Wo5JHE="; private static RSAPrivateKey loadPrivateKey() { try { PrivateKey key = new PrivateKeyReader(Config.class.getClassLoader().getResourceAsStream("rsa_private_key.txt")) .getPrivateKey(); System.out.println(key); return (RSAPrivateKey) key; } catch (Exception e) { e.printStackTrace(); System.exit(1); return null; } } public static final RSAPrivateKey RSA_PRIVATE_KEY = loadPrivateKey(); public static final byte[] PAY_KEY = MixinUtil.decrypt(RSA_PRIVATE_KEY, PIN_TOKEN, SESSION_ID); } 用你创建的 APP 的参数,替换文件中的内容: CLIENT_ID, client_id, CLIENT_SECRET, and the PIN, PIN_TOKEN, SESSION_ID.
创建 App.java 文件,内容如下:
App.java
/* * This Java source file was generated by the Gradle 'init' task. */ package mixin_labs.java.bot; import mixin.java.sdk.MixinBot; import mixin.java.sdk.MixinUtil; import mixin.java.sdk.MIXIN_Category; import mixin.java.sdk.MIXIN_Action; import java.security.PrivateKey; import java.security.interfaces.RSAPrivateKey; import com.google.gson.JsonObject; import com.google.gson.JsonParser; // import java.util.Base64; import org.apache.commons.codec.binary.Base64; import okhttp3.Response; import okhttp3.WebSocket; import okhttp3.WebSocketListener; import okio.ByteString; public class App { public static void main(String[] args) { MixinBot.connectToRemoteMixin(new WebSocketListener() { @Override public void onOpen(WebSocket webSocket, Response response) { System.out.println("[onOpen !!!]"); System.out.println("request header:" + response.request().headers()); System.out.println("response header:" + response.headers()); System.out.println("response:" + response); // 请求获取所有 pending 的消息 MixinBot.sendListPendingMessages(webSocket); } @Override public void onMessage(WebSocket webSocket, String text) { System.out.println("[onMessage !!!]"); System.out.println("text: " + text); } @Override public void onMessage(WebSocket webSocket, ByteString bytes) { try { System.out.println("[onMessage !!!]"); String msgIn = MixinUtil.bytesToJsonStr(bytes); System.out.println("json: " + msgIn); JsonObject obj = new JsonParser().parse(msgIn).getAsJsonObject(); MIXIN_Action action = MIXIN_Action.parseFrom(obj); System.out.println(action); MIXIN_Category category = MIXIN_Category.parseFrom(obj); System.out.println(category); if (action == MIXIN_Action.CREATE_MESSAGE && obj.get("data") != null && category != null ) { String userId; String messageId = obj.get("data").getAsJsonObject().get("message_id").getAsString(); MixinBot.sendMessageAck(webSocket, messageId); switch (category) { case PLAIN_TEXT: String cOnversationId= obj.get("data").getAsJsonObject().get("conversation_id").getAsString(); userId = obj.get("data").getAsJsonObject().get("user_id").getAsString(); byte[] msgData = Base64.decodeBase64(obj.get("data").getAsJsonObject().get("data").getAsString()); MixinBot.sendText(webSocket,conversationId,userId,new String(msgData,"UTF-8")); break; default: System.out.println("Category: " + category); } } } catch (Exception e) { e.printStackTrace(); } } @Override public void onClosing(WebSocket webSocket, int code, String reason) { System.out.println("[onClosing !!!]"); System.out.println("code: " + code); System.out.println("reason: " + reason); } @Override public void onClosed(WebSocket webSocket, int code, String reason) { System.out.println("[onClosed !!!]"); System.out.println("code: " + code); System.out.println("reason: " + reason); } @Override public void onFailure(WebSocket webSocket, Throwable t, Response response) { System.out.println("[onFailure !!!]"); System.out.println("throwable: " + t); System.out.println("response: " + response); } }, Config.RSA_PRIVATE_KEY, Config.CLIENT_ID, Config.SESSION_ID); } } 进入 src/main/resources, 新建文件:rsa_private_key.txt, 填写私钥信息:
rsa_private_key.txt
-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY----- 本教程依赖 mixin-java-sdk 现在回到项目目录,从 github 下载 mixin-java-sdk
mkdir libs cd libs wget https://github.com/wenewzhang/mixin-java-sdk/releases/download/v2/mixin-java-sdk.jar 增加依赖到 build.gradle.kts ,增加编译文件 compile(files("libs/mixin-java-sdk.jar")), 完整的依赖包如下:
dependencies { // This dependency is found on compile classpath of this component and consumers. implementation("com.google.guava:guava:26.0-jre") // dependent on mixin-java-sdk, copy it to libs directory compile(files("libs/mixin-java-sdk.jar")) implementation("commons-codec:commons-codec:1.11") implementation("com.auth0:java-jwt:3.5.0") implementation("com.squareup.okio:okio:2.2.1") implementation("com.squareup.okhttp3:okhttp:3.12.1") implementation("com.google.code.gson:gson:2.8.5") // Use JUnit test framework testImplementation("junit:junit:4.12") } 进入到 src/test/java/mixin_labs/java/bot, 注释掉下面的代码
AppTest.java
// assertNotNull("app should have a greeting", classUnderTest.getGreeting()); 最后一步,回到项目目录 mixin_labs-java-bot, 编译并运行.
gradle build gradle run 如果你看到如下信息,表示已经连接成功了,机器人小程序已经就绪,你可以发信息给他了!
response:Response{protocol=http/1.1, code=101, message=Switching Protocols, url=https://blaze.mixin.one/} [onMessage !!!] json: {"id":"4ee01b68-817e-4f29-bcb4-b40f7c163f61","action":"LIST_PENDING_MESSAGES"} LIST_PENDING_MESSAGES MixinBot.connectToRemoteMixin(new WebSocketListener() { @Override public void onOpen(WebSocket webSocket, Response response) { MixinBot.sendListPendingMessages(webSocket); } 连接到 Mixin Network 并发送"LISTPENDINGMESSAGES"消息,服务器以后会将收到的消息转发给此程序!
public void onMessage(WebSocket webSocket, ByteString bytes) { try { System.out.println("[onMessage !!!]"); String msgIn = MixinUtil.bytesToJsonStr(bytes); 当服务器给机器人推送消息的时候,机器人的 onMessage 函数会被调用
String messageId = obj.get("data").getAsJsonObject().get("message_id").getAsString(); MixinBot.sendMessageAck(webSocket, messageId); 机器人收到消息后需要发送响应给服务器,这样服务器就知道消息已经收到,不会再发一遍
switch (category) { case PLAIN_TEXT: String cOnversationId= obj.get("data").getAsJsonObject().get("conversation_id").getAsString(); userId = obj.get("data").getAsJsonObject().get("user_id").getAsString(); byte[] msgData = Base64.decodeBase64(obj.get("data").getAsJsonObject().get("data").getAsString()); MixinBot.sendText(webSocket,conversationId,userId,new String(msgData,"UTF-8")); 好了,你的第一个机器人小程序已经运行起来了, 你有什么新的想法,来试试吧!
完整的代码 这儿