diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/AiLangType.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/AiLangType.java new file mode 100644 index 00000000..54b61b1e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/AiLangType.java @@ -0,0 +1,29 @@ +package me.chanjar.weixin.mp; + +import lombok.Getter; + +/** + *
+ * AI开放接口里的语言类型,目前只支持两种:中文和英文 + * Created by BinaryWang on 2018/6/10. + *+ * + * @author Binary Wang + */ +@Getter +public enum AiLangType { + /** + * 中文 汉语 + */ + zh_CN("zh_CN"), + /** + * 英文 英语 + */ + en_US("en_US"); + + private String code; + + AiLangType(String code) { + this.code = code; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java new file mode 100644 index 00000000..1e9c8e02 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpAiOpenService.java @@ -0,0 +1,97 @@ +package me.chanjar.weixin.mp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.AiLangType; + +import java.io.File; + +/** + *
+ * 微信AI开放接口(语音识别,微信翻译). + * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21516712282KzWVE + * Created by BinaryWang on 2018/6/9. + *+ * + * @author Binary Wang + */ +public interface WxMpAiOpenService { + String VOICE_UPLOAD_URL = "http://api.weixin.qq.com/cgi-bin/media/voice/addvoicetorecofortext?format=%s&voice_id=%s&lang=%s"; + String VOICE_QUERY_RESULT_URL = "http://api.weixin.qq.com/cgi-bin/media/voice/queryrecoresultfortext"; + + /** + *
+ * 提交语音. + * 接口调用请求说明 + * + * http请求方式: POST + * http://api.weixin.qq.com/cgi-bin/media/voice/addvoicetorecofortext?access_token=ACCESS_TOKEN&format=&voice_id=xxxxxx&lang=zh_CN + * 参数说明 + * + * 参数 是否必须 说明 + * access_token 是 接口调用凭证 + * format 是 文件格式 (只支持mp3,16k,单声道,最大1M) + * voice_id 是 语音唯一标识 + * lang 否 语言,zh_CN 或 en_US,默认中文 + * 语音内容放body里或者上传文件的形式 + *+ * + * @param lang 语言,zh_CN 或 en_US,默认中文 + * @param voiceFile 语音文件 + * @param voiceId 语音唯一标识 + */ + void uploadVoice(String voiceId, AiLangType lang, File voiceFile) throws WxErrorException; + + /** + *
+ * 获取语音识别结果. + * 接口调用请求说明 + * + * http请求方式: POST + * http://api.weixin.qq.com/cgi-bin/media/voice/queryrecoresultfortext?access_token=ACCESS_TOKEN&voice_id=xxxxxx&lang=zh_CN + * 请注意,添加完文件之后10s内调用这个接口 + * + * 参数说明 + * + * 参数 是否必须 说明 + * access_token 是 接口调用凭证 + * voice_id 是 语音唯一标识 + * lang 否 语言,zh_CN 或 en_US,默认中文 + *+ * + * @param lang 语言,zh_CN 或 en_US,默认中文 + * @param voiceId 语音唯一标识 + */ + String queryRecognitionResult(String voiceId, AiLangType lang) throws WxErrorException; + + /** + * 识别指定语音文件内容. + * 此方法揉合了前两两个方法:uploadVoice 和 queryRecognitionResult + * + * @param lang 语言,zh_CN 或 en_US,默认中文 + * @param voiceFile 语音文件 + * @param voiceId 语音唯一标识 + */ + String recogniseVoice(String voiceId, AiLangType lang, File voiceFile) throws WxErrorException; + + /** + *
+ * 微信翻译. + * 接口调用请求说明 + * + * http请求方式: POST + * http://api.weixin.qq.com/cgi-bin/media/voice/translatecontent?access_token=ACCESS_TOKEN&lfrom=xxx<o=xxx + * 参数说明 + * + * 参数 是否必须 说明 + * access_token 是 接口调用凭证 + * lfrom 是 源语言,zh_CN 或 en_US + * lto 是 目标语言,zh_CN 或 en_US + * 源内容放body里或者上传文件的形式(utf8格式,最大600Byte) + *+ * + * @param langFrom 源语言,zh_CN 或 en_US + * @param langTo 目标语言,zh_CN 或 en_US + * @param content 要翻译的文本内容 + */ + String translate(AiLangType langFrom, AiLangType langTo, String content) throws WxErrorException; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 1ae411e8..dc45e9a8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -408,6 +408,13 @@ public interface WxMpService { */ WxMpMassMessageService getMassMessageService(); + /** + * 返回AI开放接口方法的实现类对象,以方便调用其各个接口 + * + * @return WxMpAiOpenService + */ + WxMpAiOpenService getAiOpenService(); + void setKefuService(WxMpKefuService kefuService); void setMaterialService(WxMpMaterialService materialService); @@ -437,4 +444,6 @@ public interface WxMpService { void setMemberCardService(WxMpMemberCardService memberCardService); void setMassMessageService(WxMpMassMessageService massMessageService); + + void setAiOpenService(WxMpAiOpenService aiOpenService); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceBaseImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java similarity index 97% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceBaseImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java index 59a76c56..a874a117 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceBaseImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java @@ -26,11 +26,14 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.locks.Lock; -public abstract class WxMpServiceBaseImpl
+ * Created by BinaryWang on 2018/6/9. + *+ * + * @author Binary Wang + */ +public class WxMpAiOpenServiceImpl implements WxMpAiOpenService { + + private static final JsonParser JSON_PARSER = new JsonParser(); + public static final String TRANSLATE_URL = "http://api.weixin.qq.com/cgi-bin/media/voice/translatecontent?lfrom=%s<o=%s"; + private WxMpService wxMpService; + + public WxMpAiOpenServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public void uploadVoice(String voiceId, AiLangType lang, File voiceFile) throws WxErrorException { + if (lang == null) { + lang = AiLangType.zh_CN; + } + + this.wxMpService.execute(VoiceUploadRequestExecutor.create(this.wxMpService.getRequestHttp()), + String.format(VOICE_UPLOAD_URL, "mp3", voiceId, lang.getCode()), + voiceFile); + } + + @Override + public String recogniseVoice(String voiceId, AiLangType lang, File voiceFile) throws WxErrorException { + this.uploadVoice(voiceId, lang, voiceFile); + return this.queryRecognitionResult(voiceId, lang); + } + + @Override + public String translate(AiLangType langFrom, AiLangType langTo, String content) throws WxErrorException { + final String responseContent = this.wxMpService.post(String.format(TRANSLATE_URL, langFrom.getCode(), langTo.getCode()), + content); + final JsonObject jsonObject = new JsonParser().parse(responseContent).getAsJsonObject(); + if (jsonObject.get("errcode") == null || jsonObject.get("errcode").getAsInt() == 0) { + return jsonObject.get("to_content").getAsString(); + } + + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MP)); + } + + @Override + public String queryRecognitionResult(String voiceId, AiLangType lang) throws WxErrorException { + if (lang == null) { + lang = AiLangType.zh_CN; + } + + final String responseContent = this.wxMpService.get(VOICE_QUERY_RESULT_URL, + String.format("voice_id=%s&lang=%s", voiceId, lang.getCode())); + final JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + if (jsonObject.get("errcode") == null || jsonObject.get("errcode").getAsInt() == 0) { + return jsonObject.get("result").getAsString(); + } + + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MP)); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java index ae574092..3db9e9b1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java @@ -22,7 +22,7 @@ import java.util.concurrent.locks.Lock; /** * apache http client方式实现. */ -public class WxMpServiceHttpClientImpl extends WxMpServiceBaseImpl
+ * Created by BinaryWang on 2018/6/9. + *+ * + * @author Binary Wang + */ +public class VoiceUploadApacheHttpRequestExecutor extends VoiceUploadRequestExecutor
+ * Created by BinaryWang on 2018/6/9. + *+ * + * @author Binary Wang + */ +public abstract class VoiceUploadRequestExecutor
+ * Created by BinaryWang on 2018/6/10. + *+ * + * @author Binary Wang + */ +@Test +@Guice(modules = ApiTestModule.class) +public class WxMpAiOpenServiceImplTest { + @Inject + protected WxMpService wxService; + + @Test + public void testUploadVoice() throws WxErrorException { + String voiceId = System.currentTimeMillis() + "a"; + AiLangType lang = AiLangType.zh_CN; + this.wxService.getAiOpenService().uploadVoice(voiceId, lang, new File("d:\\t.mp3")); + } + + @Test + public void testRecogniseVoice() throws WxErrorException { + String voiceId = System.currentTimeMillis() + "a"; + AiLangType lang = AiLangType.zh_CN; + final String result = this.wxService.getAiOpenService().recogniseVoice(voiceId, lang, new File("d:\\t.mp3")); + System.out.println(result); + } + + @Test + public void testTranslate() throws WxErrorException { + final String responseContent = this.wxService.getAiOpenService() + .translate(AiLangType.zh_CN, AiLangType.en_US, "微信文档很坑爹"); + System.out.println(responseContent); + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java index 959e2daa..98173f7d 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.concurrent.locks.ReentrantLock; +import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,7 @@ public class ApiTestModule implements Module { TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream); config.setAccessTokenLock(new ReentrantLock()); - WxMpService wxService = new WxMpServiceOkHttpImpl(); + WxMpService wxService = new WxMpServiceHttpClientImpl(); wxService.setWxMpConfigStorage(config); binder.bind(WxMpService.class).toInstance(wxService);