AndroidアプリにPAY.JPのカードトークン取得機能を組み込む必要があったのですが、PAY.JP側のライブラリではAndroidに対応していませんでした。
Java用ライブラリは用意されているのですが、下記ランタイムエラーが発生するためAndroidでは利用できません。
Caused by: java.lang.
at jp.pay.net.
既存プロジェクトでは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); } }