import std.stdio; import std.conv; import core.sys.linux.unistd; import vibe.d; import vibe.data.json; import vibe.textfilter.urlencode; void helloWorld(HTTPServerRequest req, HTTPServerResponse res) { res.writeBody("Hello"); } class ApiRequest { } struct ApiResponse { ResponseSet[] responseSets; bool pendingResponseSets; } struct ResponseSet { string applicationId; int requestCounter; Json[] responses; } class OpenSession : ApiRequest { string applicationType; string locale; string[string] attributes; this(string applicationType, string locale, string[string] attributes) { this.applicationType = applicationType; this.locale = locale; this.attributes = attributes; } } class StartFlow : ApiRequest { string applicationType; string applicationId; string flowName; string[string] attributes; string[string] privateAttributes; this(string applicationType, string applicationId, string flowName, string[string] attributes, string[string] privateAttributes) { this.applicationType = applicationType; this.applicationId = applicationId; this.flowName = flowName; this.attributes = attributes; this.privateAttributes = privateAttributes; } } class WidgetEvents : ApiRequest { string applicationId; Json[string][] widgetEventInformations; this(string applicationId, string[string] widgetEventInformations, string[string] attributes) { this.applicationId = applicationId; Json[string] eventInformations; foreach(key, value; widgetEventInformations) { eventInformations[key] = value.serializeToJson; } this.widgetEventInformations = [eventInformations]; Json[string] jsonAttributes; foreach(key, value; attributes) { jsonAttributes[key] = value.serializeToJson; } this.widgetEventInformations[0]["attributes"] = jsonAttributes; } } class ApiMessage { string executionMode; string protocolVersion; Json[string][] requests; this(string executionMode) { this.executionMode = executionMode; this.protocolVersion = "2.1"; Json[string] requestArray; this.requests = [requestArray]; } void addRequest(T : ApiRequest)(string name, T request) { requests[0][name] = request.serializeToJson; } } class SessionApiMessage : ApiMessage { string sessionId; string applicationId; string requestCounter; this(string executionMode, string sessionId, string applicationId, int requestCounter) { super(executionMode); this.sessionId = sessionId; this.applicationId = applicationId; this.requestCounter = requestCounter.to!string; } } class ApiClient { enum string Endpoint = "https://m.belfius.be/F2CRenderingDexiaToClient/GEPARendering/machineIdentifier=s4/"; private string _locale; private string _sessionId; private int _requestCounter; this(string locale) { _locale = locale; } void connect() { auto openSessionRequest = new OpenSession("yui3a", _locale, ["application": "Container", "P": "P055"]); auto response = sendRequest("sequential", openSessionRequest); _sessionId = response.responseSets[0].responses[0]["SessionOpened"][0]["sessionId"].get!string; _requestCounter = 1; auto startFlowRequest = new StartFlow("yui3a", "Container", "gef0.gef1.gemd.Flow_MobileApplication.diamlflow", ["deviceType": "simple", "language": "2", "smsType": "otpUrl"], null); response = sendRequest("sequential", startFlowRequest); } void login1(string cardNumber, string phoneZone, string phoneSubscriber) { auto widgetEventsRequest = createClickImageEvent("Container@reuse_Screen@img_Operations"); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createChangeValueEvent("Container@reuse_flowAuthentication@inp_PanNumbersimple", cardNumber[0 .. 4]); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createChangeValueEvent("Container@reuse_flowAuthentication@inp_PanNumbersimple", cardNumber); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createChangeValueEvent("Container@reuse_flowAuthentication@inp_PhoneZone", phoneZone); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createChangeValueEvent("Container@reuse_flowAuthentication@inp_PhoneSubscriber", phoneSubscriber); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createClickButtonEvent("Container@reuse_flowAuthentication@btn_Identification"); sendRequest("sequential", widgetEventsRequest); } void login2(string otp, string password) { auto widgetEventsRequest = createClickImageEvent("Container@reuse_Screen@img_Operations"); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createChangeValueEvent("Container@reuse_flowAuthentication@inp_otp", otp); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createChangeValueEvent("Container@reuse_flowAuthentication@inp_pw", password); sendRequest("sequential", widgetEventsRequest); widgetEventsRequest = createClickButtonEvent("Container@reuse_flowAuthentication@btn_Identification"); sendRequest("sequential", widgetEventsRequest); } WidgetEvents createClickImageEvent(string widgetId) { return new WidgetEvents("Container", [ "widgetId": widgetId, "eventType": "clicked", "widgetType": "Image", ], null); } WidgetEvents createClickButtonEvent(string widgetId) { return new WidgetEvents("Container", [ "widgetId": widgetId, "eventType": "clicked", "widgetType": "ActionButton", ], null); } WidgetEvents createChangeValueEvent(string widgetId, string value) { return new WidgetEvents("Container", [ "widgetId": widgetId, "eventType": "valueChanged", "widgetType": "Input", ], [ "text": value ]); } private ApiResponse sendRequest(T : ApiRequest)(string executionMode, T request) { string requestString; if(_sessionId !is null) { auto message = new SessionApiMessage(executionMode, _sessionId, "Container", ++_requestCounter); message.addRequest(T.stringof, request); requestString = message.serializeToJsonString; } else { auto message = new ApiMessage(executionMode); message.addRequest(T.stringof, request); requestString = message.serializeToJsonString; } writeln("C> " ~ requestString); auto response = requestHTTP(Endpoint, (scope request) { request.method = HTTPMethod.POST; request.headers["Accept"] = "*/*"; request.headers["Content-Type"] = "application/x-www-form-urlencoded"; request.headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"; request.writeBody(cast(ubyte[])("request=" ~ requestString.urlEncode)); } ).bodyReader.readAllUTF8; writeln("S> " ~ response); return response.parseJsonString.deserializeJson!ApiResponse; } } shared static this() { auto router = new URLRouter; router.get("/hello", &helloWorld); auto settings = new HTTPServerSettings; settings.sessionStore = new MemorySessionStore; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; listenHTTP(settings, router); auto apiClient = new ApiClient("nl_BE"); apiClient.connect(); apiClient.login1("67030514325746009", "0470", "854404"); write("OTP: "); auto otp = readln()[0 .. $-1]; auto password = fromStringz(getpass("Password: ")).idup; apiClient.login2(otp, password); }