カテゴリー
Android

Androidアプリ内にてPAY.JPのカードトークン作成

AndroidアプリにPAY.JPのカードトークン取得機能を組み込む必要があったのですが、PAY.JP側のライブラリではAndroidに対応していませんでした。

Java用ライブラリは用意されているのですが、下記ランタイムエラーが発生するためAndroidでは利用できません。
Caused by: java.lang.NoClassDefFoundError: javax.xml.bind.DatatypeConverter
at jp.pay.net.LivePayjpResponseGetter.getHeaders(LivePayjpResponseGetter.java:85)

既存プロジェクトではvolleyを使っていたので、直接PAY.JPのRestAPIにリクエストを投げることで対応するに至りました。

以下サンプルとなります。

final String apiKey = "pk_test_123456789012345678901234";//PAY.JPの公開APIキー
String url = "https://api.pay.jp/v1/tokens";
Map<String,String> params = new HashMap<>();
params.put("card[number]",number);
params.put("card[name]",name);
params.put("card[cvc]",cvc);
params.put("card[exp_month]",expMonth);
params.put("card[exp_year]",expYear);
JsonObjectRequestHashMapPost request = new JsonObjectRequestHashMapPost(Request.Method.POST, url, params,
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                try{
                    //トークン取得して後続処理を呼ぶ
                    token = jsonObject.getString("id");
                }catch(Exception e){
                    //正常にトークンが発行されなかった
                    e.printStackTrace();
                }
            }
        },
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                //エラー処理
                switch(volleyError.networkResponse.statusCode){
                    case 400:
                        //不正なパラメータなどのリクエストエラー
                        break;
                    case 401:
                        //APIキーの認証エラー
                        break;
                    case 402:
                        //カード認証・支払いエラー
                        break;
                    case 500:
                        //PAY.JPや決済ネットワークでの障害
                        break;
                    default:
                }
            }
        }
){
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();
        // Add BASIC AUTH HEADER
        Map<String, String> newHeaders = new HashMap<String, String>();
        newHeaders.putAll(headers);
        // APIキーにコロンを追加
        String userString = apiKey+":";
        // APIキーをBase64でエンコード
        String user = String.format("Basic %s", Base64.encodeToString(userString.getBytes(), Base64.URL_SAFE| Base64.NO_WRAP));
        newHeaders.put("Authorization", user);
        return newHeaders;
    }
};
//Queueに追加(JSON取得処理)
RequestQueue mQueue = Volley.newRequestQueue(this);
mQueue.add(request);

ポイントはオーバーライドしているpublic Map<String, String> getHeadersで、コロン(:)を追加したapiキーをBase64でエンコードし、HttpリクエストヘッダーのAuthorizationとして追加するところ。

 

ちなみにJsonObjectRequestHashMapPostはその名の通り、HashMapをPostするためにRequestを拡張したクラスです。こちらも参考までに。

public class JsonObjectRequestHashMapPost extends Request<JSONObject> {
    private Listener<JSONObject> listener;
    private Map<String, String> params;

    public JsonObjectRequestHashMapPost(String url, Map<String, String> params,
                         Listener<JSONObject> responseListener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = responseListener;
        this.params = params;
    }

    public JsonObjectRequestHashMapPost(int method, String url, Map<String, String> params,
                         Listener<JSONObject> responseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = responseListener;
        this.params = params;
    }

    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return params;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        listener.onResponse(response);
    }
}

参考

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください