package jp.webpay.android.token;
import android.net.Uri;
import android.os.AsyncTask;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import jp.webpay.android.token.model.AccountAvailability;
import jp.webpay.android.token.model.ErrorResponse;
import jp.webpay.android.token.model.RawCard;
import jp.webpay.android.token.model.Token;
public class WebPay {
private static final Uri BASE_URI = Uri.parse("https://api.webpay.jp/v1");
private final WebPayPublicClient client;
public WebPay(String publishableKey) {
client = new WebPayPublicClient(BASE_URI, publishableKey);
}
public void setLanguage(String language) {
client.setLanguage(language);
}
public void createToken(final RawCard rawCard, WebPayListener<Token> listener) {
if (rawCard == null) {
throw new IllegalArgumentException("rawCard must not be null");
}
new RequestTask<Token>(listener) {
@Override
WebPayPublicClient.Result sendRequest() throws IOException {
return client.request("POST", "tokens", rawCard.toJson().toString());
}
@Override
Token parseResponse(JSONObject json) throws JSONException {
return Token.fromJson(json);
}
}.execute();
}
public void retrieveAvailability(WebPayListener<AccountAvailability> listener) {
new RequestTask<AccountAvailability>(listener) {
@Override
WebPayPublicClient.Result sendRequest() throws IOException {
return client.request("GET", "account/availability", null);
}
@Override
AccountAvailability parseResponse(JSONObject json) throws JSONException {
return AccountAvailability.fromJson(json);
}
}.execute();
}
private abstract static class RequestTask<T> extends AsyncTask<Void, Void, TaskResult<T>> {
private final WebPayListener<T> listener;
private RequestTask(WebPayListener<T> listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
this.listener = listener;
}
abstract WebPayPublicClient.Result sendRequest() throws IOException;
abstract T parseResponse(JSONObject json) throws JSONException;
@Override
protected TaskResult<T> doInBackground(Void... params) {
try {
WebPayPublicClient.Result result;
try {
result = sendRequest();
} catch (IOException e) {
return new TaskResult<T>(e);
}
if (result.statusCode >= 200 && result.statusCode < 300) {
try {
return new TaskResult<T>(parseResponse(new JSONObject(result.responseBody)));
} catch (JSONException e) {
return new TaskResult<T>(e);
}
} else {
try {
ErrorResponse error = ErrorResponse.fromJson(result.statusCode, new JSONObject(result.responseBody));
return new TaskResult<T>(error);
} catch (JSONException e) {
return new TaskResult<T>(e);
}
}
} catch (RuntimeException e) {
return new TaskResult<T>(e);
}
}
@Override
protected void onCancelled() {
listener.onException(new RuntimeException("Communication task is not expected to be cancelled"));
}
@Override
protected void onPostExecute(TaskResult<T> result) {
if (result.model != null) {
listener.onCreate(result.model);
} else if (result.error != null) {
listener.onException(new ErrorResponseException(result.error));
} else if (result.cause != null) {
listener.onException(result.cause);
} else {
throw new AssertionError("Incomplete result");
}
}
}
private static class TaskResult<T> {
private final T model;
private final ErrorResponse error;
private final Throwable cause;
private TaskResult(T model) {
this.model = model;
this.error = null;
this.cause = null;
}
private TaskResult(ErrorResponse error) {
this.model = null;
this.error = error;
this.cause = null;
}
private TaskResult(Throwable cause) {
this.model = null;
this.error = null;
this.cause = cause;
}
}
}