/*
* Copyright (C) 2014 Nullbyte <http://nullbyte.eu>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.liato.bankdroid.banking.banks.ica;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liato.bankdroid.banking.Account;
import com.liato.bankdroid.banking.Bank;
import com.liato.bankdroid.banking.Transaction;
import com.liato.bankdroid.banking.banks.ica.model.LoginError;
import com.liato.bankdroid.banking.banks.ica.model.Overview;
import com.liato.bankdroid.banking.exceptions.BankChoiceException;
import com.liato.bankdroid.banking.exceptions.BankException;
import com.liato.bankdroid.banking.exceptions.LoginException;
import com.liato.bankdroid.legacy.R;
import com.liato.bankdroid.provider.IBankTypes;
import com.liato.bankdroid.utils.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import android.content.Context;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Base64;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import eu.nullbyte.android.urllib.CertificateReader;
import eu.nullbyte.android.urllib.Urllib;
public class ICA extends Bank {
private static final String API_URL = "https://api.ica.se/api/";
private static final String AUTHENTICATION_TICKET_HEADER = "AuthenticationTicket";
private static final String SESSION_TICKET_HEADER = "SessionTicket";
private static final String LOGOUT_KEY_HEADER = "LogoutKey";
private ObjectMapper mObjectMapper = new ObjectMapper();
private Map<String, String> mHeaders = new HashMap<String, String>();
public ICA(Context context) {
super(context, R.drawable.logo_ica);
url = "http://mobil.ica.se/";
inputTypeUsername = InputType.TYPE_CLASS_PHONE;
inputTypePassword = InputType.TYPE_CLASS_PHONE;
inputHintUsername = "ÅÅMMDDXXXX";
mHeaders.put(AUTHENTICATION_TICKET_HEADER, null);
mHeaders.put(SESSION_TICKET_HEADER, null);
mHeaders.put(LOGOUT_KEY_HEADER, null);
}
@Override
public int getBanktypeId() {
return IBankTypes.ICA;
}
@Override
public String getName() {
return "ICA";
}
public ICA(String username, String password, Context context)
throws BankException, LoginException, BankChoiceException, IOException {
this(context);
this.update(username, password);
}
public Urllib login() throws LoginException, BankException, IOException {
urlopen = new Urllib(context, CertificateReader.getCertificates(context, R.raw.cert_ica));
urlopen.addHeader("Accept", "application/json;charset=UTF-8");
urlopen.addHeader("Content-Type", "application/json;charset=UTF-8");
urlopen.addHeader("Authorization", "Basic " + Base64.encodeToString(
StringUtils.getBytes(getUsername() + ":" + getPassword()), Base64.NO_WRAP));
try {
HttpResponse httpResponse = urlopen.openAsHttpResponse(API_URL + "login",
new ArrayList<NameValuePair>(), false);
if (httpResponse.getStatusLine().getStatusCode() == 401) {
LoginError le = readJsonValue(httpResponse, LoginError.class);
if (le != null && "UsernamePassword".equals(le.getMessageCode())) {
if (!TextUtils.isEmpty(le.getMessage())) {
throw new LoginException(le.getMessage());
} else {
throw new LoginException(context.getText(
R.string.invalid_username_password).toString());
}
} else {
throw new BankException(context.getText(
R.string.invalid_username_password).toString());
}
}
for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
Header header = httpResponse.getFirstHeader(entry.getKey());
if (header == null || TextUtils.isEmpty(header.getValue())) {
throw new BankException(context.getString(
R.string.unable_to_find).toString() + " " + entry.getKey());
}
mHeaders.put(entry.getKey(), header.getValue());
}
urlopen.addHeader(AUTHENTICATION_TICKET_HEADER,
mHeaders.get(AUTHENTICATION_TICKET_HEADER));
httpResponse = urlopen.openAsHttpResponse(API_URL + "user/minasidor",
new ArrayList<NameValuePair>(), false);
Overview overview = readJsonValue(httpResponse, Overview.class);
if (overview == null) {
throw new BankException(context.getString(R.string.unable_to_find) + " overview.");
}
if (!TextUtils.isEmpty(overview.getAccountName())) {
Account account = new Account(overview.getAccountName(),
BigDecimal.valueOf(overview.getAvailableAmount()),
overview.getAccountNumber());
balance = balance.add(account.getBalance());
accounts.add(account);
List<Transaction> transactions = new ArrayList<Transaction>();
for (com.liato.bankdroid.banking.banks.ica.model.Transaction t : overview
.getTransactions()) {
transactions.add(new Transaction(t.getTransactionDate(), t.getDescription(),
BigDecimal.valueOf(t.getAmount())));
}
account.setTransactions(transactions);
}
for (com.liato.bankdroid.banking.banks.ica.model.Account a : overview.getAccounts()) {
Account account = new Account(a.getName(),
BigDecimal.valueOf(a.getAvailableAmount()), a.getAccountNumber());
balance = balance.add(account.getBalance());
accounts.add(account);
List<Transaction> transactions = new ArrayList<Transaction>();
for (com.liato.bankdroid.banking.banks.ica.model.Transaction t : a
.getTransactions()) {
transactions.add(new Transaction(t.getTransactionDate(), t.getDescription(),
BigDecimal.valueOf(t.getAmount())));
}
account.setTransactions(transactions);
}
Account account = new Account("Erhållen bonus i år",
BigDecimal.valueOf(overview.getAcquiredBonus()), "bonus");
account.setType(Account.OTHER);
accounts.add(account);
account = new Account("Årets totala inköp på ICA",
BigDecimal.valueOf(overview.getYearlyTotalPurchased()), "totalpurchased");
account.setType(Account.OTHER);
accounts.add(account);
if (accounts.isEmpty()) {
throw new BankException(res.getText(R.string.no_accounts_found).toString());
}
urlopen.addHeader(LOGOUT_KEY_HEADER, mHeaders.get(LOGOUT_KEY_HEADER));
httpResponse = urlopen.openAsHttpResponse(API_URL + "logout",
new ArrayList<NameValuePair>(), false);
httpResponse.getStatusLine();
} catch (JsonParseException e) {
throw new BankException(e.getMessage(), e);
}
return urlopen;
}
@Override
public void update() throws BankException, LoginException,
BankChoiceException, IOException {
super.update();
if (getUsername().isEmpty() || getPassword().isEmpty()) {
throw new LoginException(res.getText(
R.string.invalid_username_password).toString());
}
login();
super.updateComplete();
}
private <T> T readJsonValue(HttpResponse response, Class<T> valueType) throws BankException {
try {
return readJsonValue(response.getEntity().getContent(), valueType);
} catch (IOException e) {
return null;
}
}
private <T> T readJsonValue(InputStream is, Class<T> valueType) throws BankException {
try {
return mObjectMapper.readValue(is, valueType);
} catch (Exception e) {
return null;
}
}
}