All traffic on all operating systems will favor WiFi above cellular connections. However for Silent Network Auth, the API request must be made using the cellular connection. We realize that users are unlikely to turn off WiFi and so the following code is provided for both iOS and Android to include in your applications that will allow a small payload (~40 bytes) to be delivered over the cellular modem, even when WiFi is connected.
Only downloadable and installable applications are suitable for this fix. If you are attempting to use Silent Network Auth in a website this solution will not work. You should instruct users to turn off WiFi.
The following will allow Android applications using API Release M and above to use Cellular for the Silent Network Auth API request.
1@TargetApi(Build.VERSION_CODES.LOLLIPOP)2public static void doAPIonCellularNetwork(Context context, final String url) {34ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);56NetworkRequest request = new NetworkRequest.Builder()7.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)8.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();910connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() {1112@Override13public void onAvailable(final Network network) {14OkHttpClient okHttpClient = new OkHttpClient.Builder().socketFactory(network.getSocketFactory()).build();15Request request = new Request.Builder()16.url(url)17.build();18try {19Response response = okHttpClient.newCall(request).execute();20Log.i("", "doAPIonCellularNetwork RESULT:\n" + response.body().string());21} catch (Exception ex) {22ex.printStackTrace();23}24}25});26}
For iOS, start by downloading the library from here.
Add the NetworkingLogic folder, which contains six files, to your project folder as shown below.
Include #import "HTTPRequester.h
in the Swift bridging header file. Also, include the code below as a member function in the ViewController that fires the EVURL.
1//2// EvurlRequestWithCellularData.swift3//4// Created by BENJAMIN BRYANT BUDIMAN on 05/09/18.5// Copyright © 2021 Boku, Inc. All rights reserved.6//78import Foundation910/**11Requests the EvURL with cellular data, and checks whether the Silent Network Auth process completes or not.12Important note: this function shall always return false if cellular data is not available.1314- Parameter evurl: The EvURL to be requested15- Returns: true if the Silent Network Auth process is successful and vice versa16*/17func requestEvurlWithCellularData(evurl:String) -> Bool {18let response = requestHelper(url: evurl)1920// If any internal and network errors occured in HTTPRequester.performGetRequest, the function will return "ERROR"21if response == "ERROR" {22return false;23}2425// Boku returns "ErrorCode=0&ErrorDescription=Success" only when the Silent Network Auth process is complete26if response.range(of:"ErrorCode=0&ErrorDescription=Success") != nil {27return true;28}2930// Any HTTP responses without the above substring indicate an incomplete Silent Network Auth process31return false;32}3334/**35Recursive function that keeps requesting a new URL with cellular data when the HTTP request returns a HTTP redirect code (3xx)3637- Parameter url: The URL to be requested38- Returns: string response from the HTTP request39*/40func requestHelper(url:String) -> String {41// If the HTTP GET request returns a HTTP redirect code (3xx), HTTPRequester.performGetRequest returns a42// formatted string that contains the redirect URL. The formatted string starts with "REDIRECT:"43// and it's followed with the redirect URL (e.g. REDIRECT:https://www.boku.com)44var response = HTTPRequester.performGetRequest(URL(string: url))4546if response!.range(of:"REDIRECT:") != nil {47// 1. Get the redirect URL by getting rid of the "REDIRECT:" substring48let redirectRange = response!.index(response!.startIndex, offsetBy: 9)...49let redirectLink = String(response![redirectRange])5051// 2. Make a request to the redirect URL52response = requestHelper(url: redirectLink)53}5455return response!56}
Execute the EVURL as shown in the code sample below. Please note the EVURL will change and must be created each time.
1override func viewDidLoad() {2super.viewDidLoad()34let EVURL = "http://boku-url/cimi/evurl?SKEY=BEHBuKkD3yxt6dD6NgEHKhjBLZTPwQgT2Yb06NMnCilwuVgEetIlH7lUL%2BgmAEY%2FlaFVkoxzfdndPlVmP9FBRycx%2BhKZeLAo1gmvBP9qdb0%3D"56_ = requestEvurlWithCellularData(evurl: EVURL)7}
EVURLs are unique to each request, do not hard code one. EVURLs can be created manually using the Create an EVURL endpoint.