“This is the 10th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

GitHub:https://github.com/baiyuliang/Qrobot_Flutter

Previous article we basically achieved a simple chat interface, also basic mastered how to through the Flutter to complete such a layout and the realization of functions, but from what we need to implement the title is poor so step, since is a bot, it will not be able to do only local chat, + robot network request API is a must!

First of all, the robot API used in this project is Tencent AI platform: ai.qq.com/doc/nlpchat… So you can go in here and apply, and you’ll get APP_ID and APP_KEY, and you can call its API and put in parameters and ask for a response from the robot.

Dart network requests need to introduce a library: HTTP: ^0.12.0

Specific writing:

import 'package:http/http.dart' as http;

http.get(Uri.parse(url), headers:{})
     .then((res){ })
     .catchError((error){ });
http.post(Uri.parse(url), headers:{},body:)
     .then((res){ })
     .catchError((error){ });
Copy the code

The HTTP get, POST, PUT, and delete methods are all provided. The HTTP method varies according to the interface Type. Headers are passed in the format of headers: {‘ content-type ‘: ‘application/x – WWW – form – urlencoded’}, then is to request the correction, res is request as a result, catchError is request exception handling, additional parameters need to use the body into a post request, such as: Body :params, params is key1=value1&key2=value2&… String, such a network request is completed, is not very simple!

So let’s first try to request the robot API. The URL of the API has been given in the document: api.ai.qq.com/fcgi-bin/nl… Let’s test the HTTP request method by ignoring the parameters:

import 'package:http/http.dart' as http;

main() {
  http.post("https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat").then((res) {
    print(res.body);
  });
}
Copy the code

Running results:

{
  "ret": 4096,
  "msg": "paramter invalid",
  "data": {
      "session": "",
      "answer": ""
  }
}
Copy the code

There was nothing wrong with the network request, but the interface returned an error message: parameter error! Then we need to look at the documentation to see what parameters are required for this interface:One of the most important is the “sign” parameter. Click interface authentication to see how to generate sign:The first step:Parameter ascending order:

App_id, nonce_str, question, session, time_stamp;

Step 2: Splicing and coding:

The key-value pair splicing is carried out in the above order, and the value part needs URL encoding. In fact, except that question parameter is input by us, most of which are in Chinese and need to be encoded, other parameters do not need encoding, so only question encoding can be done. We know that in Java, we can just call the system method URLEncoder. Encode (), but what do we use in DART? This requires the URi. encodeFull method of the class that dart provides;

Step 3: Splice appKey:

Concatenate &app_key= XXX after the concatenated parameter in step 2;

Step 4: capitalize after MD5:

The MD5 method in DART needs to import two libraries:

Crypto: ^ 2.0.6 utf: ^ 0.9.0 + 5

Encode (params) utf8.encode(params) utf8.encode(params) utf8.encode(params)

var sign = md5.convert(utf8.encode(params));
Copy the code

The last step, converting toUpperCase, is easy. Just call the String method: sign.tostring ().touppercase ()!

Alternatively, a DateTime can be used to obtain the current time in a Flutter:

DateTime.now().millisecondsSinceEpoch
Copy the code

You get milliseconds, similar to android:

System.currentTimeMillis()
Copy the code

Since seconds are passed in the argument, /1000 is required:

DateTime.now().millisecondsSinceEpoch/1000
Copy the code

Dart casts do not directly precede the code with a conversion type, as in Java, but instead use as:

DateTime.now().millisecondsSinceEpoch/1000 as int
Copy the code

It can be simplified as:

DateTime.now().millisecondsSinceEpoch ~/ 1000
Copy the code

Isn’t the symbol “~” magical?

Ok, parameters calculated, let’s test the effect:

import 'dart:convert'; import 'package:crypto/crypto.dart'; import 'package:http/http.dart' as http; var url = "https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat"; var app_id = ""; Var app_key = ""; // Fill in your own appKey main() {getText(" hello "); } getText(question) { var params = "app_id=$app_id&nonce_str=fa577ce340859f9fe&question=${Uri.encodeFull(question)}&session=10000&time_stamp=${DateTime.now ().millisecondsSinceEpoch ~/ 1000}"; http .post(Uri.parse(url), headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: params + "&sign=" + getSign(params)) .then((res) { print(res.body); }).catchError((error) { print(error); }); GetSign (params) {params += "&app_key=$app_key"; var sign = md5.convert(utf8.encode(params)); return sign.toString().toUpperCase(); }Copy the code

Running results:

Note: AppID and AppKey need to fill in your own application!

Dart :convert: Dart :convert: Dart :convert: Dart :convert:

jsonDecode(json)
Copy the code

Note that this method yields a map. For example, if I want to fetch ret, I would write:

jsonDecode(json)['ret']
Copy the code

Finally, we encapsulate it as a class:

import 'dart:convert'; class RobotMessage { int ret; var msg; RobotData data; RobotMessage(json) { var map = jsonDecode(json); ret = map['ret']; msg = map['msg']; var _data = map['data']; data = RobotData(_data); } } class RobotData { var session; String answer; RobotData(data) { session = data['session']; answer = data['answer']; }}Copy the code

After the interface request completes, we can directly use:

RobotMessage robotMessage = RobotMessage(res.body);
Copy the code

Parse and convert to a RobotMessage object!

Now that the UI and interface are complete, you’ve basically got a simple chatbot application combined!

Dart can also use event_bus: ^1.0.3.

1. Initialization: Initialization needs to be done in the Event class of your life, such as:

EventBus eventBus=EventBus();

class EventTest{

}
Copy the code

Make sure that the initialization code is written outside the class;

2. Send Event:

 eventBus.fire(EventTest());
Copy the code

3. Receive events:

   eventBus.on<EventTest>().listen((event) {
  
   });
Copy the code