Commit ca711789 authored by Nastuzzi Samy's avatar Nastuzzi Samy
Browse files

Change completely the API protocol

Can now add easely new API
API have to dictate what to do
API can configurate 3 different responses for each request and set a special request
API can print a message or a list of information formatted
parent a63e1895
......@@ -2,7 +2,6 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/PayUTC.iml" filepath="$PROJECT_DIR$/PayUTC.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/jessy.iml" filepath="$PROJECT_DIR$/jessy.iml" />
</modules>
......
apply plugin: 'com.android.application'
android {
signingConfigs {
config {
keyAlias 'jessy'
keyPassword 'kVg6ikc+(lTkre8//m%f1'
storeFile file('/root/jessy.jks')
storePassword 'kVg6ikc+(lTkre8//m%f1'
}
}
compileSdkVersion 26
buildToolsVersion '26.0.2'
defaultConfig {
......@@ -13,6 +21,10 @@ android {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFile '/root'
}
debug {
proguardFile '/root'
}
}
packagingOptions {
......
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":42},"path":"app-release.apk","properties":{"packageId":"fr.utc.simde.jessy","split":"","minSdkVersion":"21"}}]
\ No newline at end of file
......@@ -2,11 +2,8 @@ package fr.utc.simde.jessy;
import android.Manifest;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.DownloadManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
......@@ -24,7 +21,6 @@ import android.util.Log;
import android.widget.TextView;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.ArrayList;
......@@ -33,8 +29,6 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import fr.utc.simde.jessy.responses.BottomatikResponse;
import fr.utc.simde.jessy.tools.Bottomatik;
import fr.utc.simde.jessy.tools.CASConnexion;
import fr.utc.simde.jessy.tools.Config;
import fr.utc.simde.jessy.tools.Dialog;
......@@ -626,16 +620,41 @@ public abstract class BaseActivity extends InternetActivity {
}.start();
}
protected void setKey(final String name, final String key) {
if (name.equals("") || key.equals(""))
protected void setGingerKey(final String key) {
if (key.equals(""))
return;
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key_" + name, key);
editor.apply();
dialog.startLoading(BaseActivity.this, getString(R.string.key_registration), getString(R.string.ginger_registering));
new Thread() {
@Override
public void run() {
try {
ginger.getInfo(nemopaySession.getUsername());
Thread.sleep(100);
if (name.equals("ginger"))
ginger.setKey(key);
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key_ginger", key);
editor.apply();
}
});
} catch (Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage());
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.errorDialog(BaseActivity.this, getString(R.string.key_registration), getString(R.string.ginger_error_registering));
}
});
}
}
}.start();
}
protected boolean haveStoragePermission() {
......
......@@ -116,27 +116,27 @@ public class FoundationsOptionsActivity extends BaseActivity {
this.optionList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
if (isOption(position,0)) {
if (isOption(position, 0)) {
nemopaySession.setFoundation(-1, "", -1);
startActivity(new Intent(FoundationsOptionsActivity.this, BuyerInfoActivity.class));
}
else if (isOption(position,1))
else if (isOption(position, 1))
editDialog();
else if (isOption(position,2))
dialog.infoDialog(FoundationsOptionsActivity.this, "Non encore fait", "Pour la version 0.12");
else if (isOption(position,3))
dialog.infoDialog(FoundationsOptionsActivity.this, "Non encore fait", "Pour la version 0.12");
else if (isOption(position,4))
else if (isOption(position, 2))
editDialog();
else if (isOption(position, 3))
startQRCodeReaderActivity(FoundationsOptionsActivity.this);
else if (isOption(position,5))
else if (isOption(position, 4))
startCardManagementActivity(FoundationsOptionsActivity.this);
else if (isOption(position,6))
else if (isOption(position, 5))
keyNemopayDialog();
else if (isOption(position,7))
else if (isOption(position, 6))
keyGingerDialog();
else if (isOption(position, 7))
keyEditDialog();
else if (isOption(position,8))
else if (isOption(position, 8))
checkUpdate();
else if (isOption(position,9))
else if (isOption(position, 9))
creditDialog();
else
configDialog();
......@@ -150,22 +150,46 @@ public class FoundationsOptionsActivity extends BaseActivity {
hasRights(getString(R.string.nemopay), new String[]{}, new Runnable(){
@Override
public void run() {
final View keyView = getLayoutInflater().inflate(R.layout.dialog_edit_key, null);
final View keyView = getLayoutInflater().inflate(R.layout.dialog_key_edit, null);
final EditText keyInput = keyView.findViewById(R.id.input_key);
keyView.findViewById(R.id.input_name).setVisibility(View.GONE);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(FoundationsOptionsActivity.this);
alertDialogBuilder
.setTitle(getString(R.string.key_registration) + " " + getString(R.string.nemopay))
.setView(keyView)
.setCancelable(false)
.setPositiveButton(R.string.register, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int id) {
if (!keyInput.getText().toString().equals(""))
setNemopayKey(keyInput.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null);
.setTitle(getString(R.string.key_registration) + " " + getString(R.string.nemopay))
.setView(keyView)
.setCancelable(false)
.setPositiveButton(R.string.register, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int id) {
if (!keyInput.getText().toString().equals(""))
setNemopayKey(keyInput.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null);
dialog.createDialog(alertDialogBuilder, keyInput);
}
});
}
protected void keyGingerDialog() {
hasRights(getString(R.string.nemopay), new String[]{}, new Runnable(){
@Override
public void run() {
final View keyView = getLayoutInflater().inflate(R.layout.dialog_key_edit, null);
final EditText keyInput = keyView.findViewById(R.id.input_key);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(FoundationsOptionsActivity.this);
alertDialogBuilder
.setTitle(getString(R.string.key_registration) + " " + getString(R.string.ginger))
.setView(keyView)
.setCancelable(false)
.setPositiveButton(R.string.register, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int id) {
if (!keyInput.getText().toString().equals(""))
setGingerKey(keyInput.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null);
dialog.createDialog(alertDialogBuilder, keyInput);
}
......@@ -176,8 +200,9 @@ public class FoundationsOptionsActivity extends BaseActivity {
hasRights(getString(R.string.key_registration), new String[]{}, new Runnable(){
@Override
public void run() {
final View keyView = getLayoutInflater().inflate(R.layout.dialog_edit_key, null);
final View keyView = getLayoutInflater().inflate(R.layout.dialog_key_set, null);
final EditText nameInput = keyView.findViewById(R.id.input_name);
final EditText urlInput = keyView.findViewById(R.id.input_url);
final EditText keyInput = keyView.findViewById(R.id.input_key);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(FoundationsOptionsActivity.this);
......@@ -187,8 +212,8 @@ public class FoundationsOptionsActivity extends BaseActivity {
.setCancelable(false)
.setPositiveButton(R.string.register, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int id) {
if (!nameInput.getText().toString().equals("") || !keyInput.getText().toString().equals(""))
setKey(nameInput.getText().toString(), keyInput.getText().toString());
if (!nameInput.getText().toString().equals(""))
config.setApi(nameInput.getText().toString(), urlInput.getText().toString(), keyInput.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null);
......
......@@ -23,7 +23,6 @@ import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import fr.utc.simde.jessy.tools.Bottomatik;
import fr.utc.simde.jessy.tools.CASConnexion;
import fr.utc.simde.jessy.tools.Config;
import fr.utc.simde.jessy.tools.Ginger;
......@@ -449,7 +448,7 @@ public class MainActivity extends BaseActivity {
}
protected void keyDialog() {
final View keyView = getLayoutInflater().inflate(R.layout.dialog_add_key, null);
final View keyView = getLayoutInflater().inflate(R.layout.dialog_key_add, null);
final EditText nameInput = keyView.findViewById(R.id.input_name);
final EditText descriptionInput = keyView.findViewById(R.id.input_description);
final String date = new SimpleDateFormat("yyyy/MM/dd", Locale.FRANCE).format(new Date());
......@@ -504,7 +503,7 @@ public class MainActivity extends BaseActivity {
}
protected void optionDialog() {
final View keyView = getLayoutInflater().inflate(R.layout.dialog_edit_key, null);
final View keyView = getLayoutInflater().inflate(R.layout.dialog_key_set, null);
final EditText keyInput = keyView.findViewById(R.id.input_key);
keyView.findViewById(R.id.input_name).setVisibility(View.GONE);
......
package fr.utc.simde.jessy.responses;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Map;
/**
* Created by Samy on 10/11/2017.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class APIResponse {
@JsonIgnoreProperties(ignoreUnknown = true)
public class APICommand {
// Informations nécessaires
protected String command;
// Informations complémentaires
protected String name;
protected String description;
protected Map<String, String> arguments;
public String getCommand() { return command; }
public String getName() { return name; }
public String getDescription() { return description; }
public Map<String, String> getArguments() { return arguments; }
}
// Informations nécessaires
protected String id;
protected String username;
protected String type;
protected long creation_date;
protected long expires_at;
// Informations complémentaires
protected Long creationDate;
protected Long expirationDate;
// Affiche soit un message, soit une liste de données rangée par catégorie
protected String message;
protected Map<String, Map<String, String>> data;
// Permet d'exécuter des commandes suites à l'affichage (rien d'obligatoire mais button Ok par défaut)
protected APICommand neutralCommand;
protected APICommand negativeCommand;
protected APICommand positiveCommand;
public String getId() { return this.id; }
public String getUsername() { return this.username; }
public String getType() { return this.type; }
public long getCreation_date() { return this.creation_date; }
public long getExpires_at() { return this.expires_at; }
public String getMessage() { return message; }
public Map<String, Map<String, String>> getData() { return this.data; }
public Long getCreationDate() { return this.creationDate; }
public Long getExpirationDate() { return this.expirationDate; }
public void removeExpirationDate() { this.expirationDate = null; }
public APICommand getNeutralCommand() { return neutralCommand; }
public APICommand getNegativeCommand() { return negativeCommand; }
public APICommand getPositiveCommand() { return positiveCommand; }
}
package fr.utc.simde.jessy.responses;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
......@@ -10,15 +11,16 @@ import java.util.List;
* Created by Samy on 10/11/2017.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class BottomatikResponse extends APIResponse {
protected String _id;
protected Integer fun_id;
protected Integer funId;
protected boolean paid;
protected boolean validated;
protected List<List<String>> articles;
public String get_id() { return this._id; }
public Integer getFun_id() { return this.fun_id; }
public Integer getFunId() { return this.funId; }
public boolean isPaid() { return this.paid; }
public boolean isValidated() { return this.validated; }
public List<List<String>> getArticles() { return this.articles; }
......
package fr.utc.simde.jessy.responses;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Created by Samy on 10/11/2017.
*/
public class ReservationResponse extends APIResponse {
protected Integer reservation_id;
protected String seance;
public Integer getReservation_id() { return this.reservation_id; }
public String getSeance() { return this.seance; }
}
......@@ -2,6 +2,9 @@ package fr.utc.simde.jessy.tools;
import android.app.Activity;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
......@@ -48,18 +51,15 @@ public class API {
public HTTPRequest getRequest() { return this.request; }
public int validate(final String id) throws Exception {
public int interact(final String id, final String command) throws Exception {
return request(
id + "/validate"
id + "/" + command
);
}
public int validate(final String id, final boolean paid, final boolean served) throws Exception {
public int interact(final String id, final String command, Map<String, Object> postArgs) throws Exception {
return request(
id + "/validate",
new HashMap<String, Object>() {{
put("paid", paid);
put("served", served);
}}
id + "/" + command,
postArgs
);
}
......@@ -88,7 +88,7 @@ public class API {
responseCode = this.request.get();
else {
this.request.setPost(postArgs);
responseCode = this.request.post();
responseCode = this.request.post(false);
}
if (responseCode == 200)
......
package fr.utc.simde.jessy.tools;
import android.app.Activity;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import fr.utc.simde.jessy.R;
/**
* Created by Samy on 21/11/2017.
*/
public class Bottomatik {
private static final String LOG_TAG = "_Bottomatik";
private static final String url = "https://picasso.bottomatik.com/bot/transactions/";
private String key;
private HTTPRequest request;
private String noKey;
private String noRight;
private String serviceText;
private String notFound;
private String badRequest;
private String internalError;
private String errorRequest;
public Bottomatik(final Activity activity) {
this.key = "";
this.noKey = activity.getString(R.string.ginger_no_key);
this.noRight = activity.getString(R.string.ginger_no_rights);
this.serviceText = activity.getString(R.string.service);
this.notFound = activity.getString(R.string.not_found);
this.badRequest = activity.getString(R.string.bad_request);
this.internalError = activity.getString(R.string.internal_error);
this.errorRequest = activity.getString(R.string.error_request);
}
public void setKey(final String key) { this.key = key; }
public HTTPRequest getRequest() { return this.request; }
public int setTransaction(final String id, final boolean paid, final boolean served) throws Exception {
return request(
id + "/validate",
new HashMap<String, Object>() {{
put("paid", paid);
put("served", served);
}}
);
}
public int getTransactionFromId(final String id) throws Exception {
return request(
id
);
}
public int getTransactionFromUsername(final String username) throws Exception {
return request(
"user/" + username
);
}
protected int request(final String request) throws Exception { return request(request, new HashMap<String, Object>()); }
protected int request(final String request, Map<String, Object> postArgs) throws Exception {
this.request = new HTTPRequest(url + request);
int responseCode;
this.request.setGet(new HashMap<String, String>(){{ put("app_key", key); }});
if (postArgs.size() == 0) {
responseCode = this.request.get();
}
else {
this.request.setPost(postArgs);
responseCode = this.request.post();
}
if (responseCode == 200)
return 200;
else if (responseCode == 401)
throw new Exception(this.noKey);
else if (responseCode == 403)
throw new Exception(this.noRight);
else if (responseCode == 404)
throw new Exception("Bottomatik " + this.notFound);
else if (responseCode == 400)
throw new Exception("Bottomatik " + this.badRequest);
else if (responseCode == 500 || responseCode == 503) {
throw new Exception("Bottomatik " + this.internalError);
}
else
throw new Exception("Bottomatik " + this.errorRequest + " " + responseCode);
}
}
......@@ -6,6 +6,11 @@ import android.util.Log;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Created by Samy on 04/11/2017.
*/
......@@ -28,6 +33,8 @@ public class Config {
private Boolean printCotisant;
private Boolean print18;
private String currentApi;
public Config(final SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
......@@ -48,6 +55,8 @@ public class Config {
this.inGrid = sharedPreferences.getBoolean("config_in_grid", true);
this.printCotisant = sharedPreferences.getBoolean("config_print_cotisant", false);
this.print18 = sharedPreferences.getBoolean("config_print_18", false);
this.currentApi = sharedPreferences.getString("api_current", "");
}
public Integer getFoundationId() { return this.foundationId; }
......@@ -150,4 +159,49 @@ public class Config {
setPrintCotisant(false);
setPrint18(false);
}
public String getCurrentApi() { return this.currentApi; }
public void setCurrentApi(final String currentApi) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("api_current", currentApi);
editor.apply();
this.currentApi = currentApi;
}
public Map<String, String> getApi(final String name) {
final String api = name.toLowerCase().replace(" ", "-");
Map<String, String> apiInfo = new HashMap<String, String>() {{
put("api", api);
put("name", sharedPreferences.getString("api_name_" + api, ""));
put("url", sharedPreferences.getString("api_url_" + api, ""));
put("key", sharedPreferences.getString("api_key_" + api, ""));
}};
if (apiInfo.get("name").isEmpty() || apiInfo.get("url").isEmpty())
return null;
else {
setCurrentApi(name);
return apiInfo;
}</