From 7320041cc5d83e76772d645fbce3e73e76c9a726 Mon Sep 17 00:00:00 2001 From: bu-tokumitsu Date: Wed, 3 Jun 2026 12:16:50 +0900 Subject: [PATCH 1/5] Reproduce crash --- gradle/libs.versions.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 40886507..7dd99395 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,6 +10,7 @@ kotlin = "2.0.0" browser = "1.6.0" leakcanaryAndroid = "2.14" okHttp3 = "3.12.13" +okHttp3NewVer = "4.12.0" moshi = "1.15.1" retrofit = "2.11.0" lifecycle = "2.6.2" @@ -55,7 +56,7 @@ kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = " kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutine" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutine" } leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanaryAndroid" } -okHttp3-core = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okHttp3" } +okHttp3-core = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okHttp3NewVer" } okHttp3-loggingInterceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okHttp3" } okHttp3-mockServer = { group = "com.squareup.okhttp3", name = "mockwebserver", version.ref = "okHttp3" } moshi-core = { group = "com.squareup.moshi", name = "moshi", version.ref = "moshi" } From ca74a46a88b08bb6d4c2f7d0afc1c14c2627e3a8 Mon Sep 17 00:00:00 2001 From: bu-tokumitsu Date: Wed, 3 Jun 2026 12:19:50 +0900 Subject: [PATCH 2/5] Unify okHttp3 version to 4.12.0 --- gradle/libs.versions.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7dd99395..3c100128 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,7 @@ junitKtx = "1.1.5" kotlin = "2.0.0" browser = "1.6.0" leakcanaryAndroid = "2.14" -okHttp3 = "3.12.13" -okHttp3NewVer = "4.12.0" +okHttp3 = "4.12.0" moshi = "1.15.1" retrofit = "2.11.0" lifecycle = "2.6.2" @@ -56,7 +55,7 @@ kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = " kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutine" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutine" } leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanaryAndroid" } -okHttp3-core = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okHttp3NewVer" } +okHttp3-core = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okHttp3" } okHttp3-loggingInterceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okHttp3" } okHttp3-mockServer = { group = "com.squareup.okhttp3", name = "mockwebserver", version.ref = "okHttp3" } moshi-core = { group = "com.squareup.moshi", name = "moshi", version.ref = "moshi" } From 865d575f77ec2fb36d51b2bd48c7926cbb4eaf24 Mon Sep 17 00:00:00 2001 From: bu-tokumitsu Date: Wed, 3 Jun 2026 16:29:23 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=E6=9C=80=E5=B0=8F=E8=A6=81=E4=BB=B6?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- build.gradle | 2 +- .../jp/pay/android/network/OkHttpTlsHelper.kt | 83 ---------------- .../android/network/Tls12SocketFactory.java | 94 ------------------- .../android/network/TokenApiClientFactory.kt | 3 - 5 files changed, 3 insertions(+), 183 deletions(-) delete mode 100644 payjp-android-core/src/main/kotlin/jp/pay/android/network/OkHttpTlsHelper.kt delete mode 100644 payjp-android-core/src/main/kotlin/jp/pay/android/network/Tls12SocketFactory.java diff --git a/README.md b/README.md index 8c310a92..7f243ffa 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Androidでの利用 | PAY.JP https://pay.jp/docs/mobileapp-android ## 動作環境 -- Android Studio 3.0以上 -- Android OS 4.1 (API Level 16) 以上 +- Android Studio Ladybug Feature Drop (2024.2.2) 以上 +- Android OS 5.0 (API Level 21) 以上 ## インストール diff --git a/build.gradle b/build.gradle index f6169bad..4950f7c1 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ tasks.named("dokkaHtmlCollector") { } ext { - minSdkVersion = 16 + minSdkVersion = 21 sdkVersion = 35 numberOfCommits = numberOfCommits() } diff --git a/payjp-android-core/src/main/kotlin/jp/pay/android/network/OkHttpTlsHelper.kt b/payjp-android-core/src/main/kotlin/jp/pay/android/network/OkHttpTlsHelper.kt deleted file mode 100644 index ffc3c9cf..00000000 --- a/payjp-android-core/src/main/kotlin/jp/pay/android/network/OkHttpTlsHelper.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Copyright (c) 2021 PAY, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package jp.pay.android.network - -import android.os.Build -import jp.pay.android.PayjpLogger -import okhttp3.ConnectionSpec -import okhttp3.OkHttpClient -import okhttp3.TlsVersion -import java.security.KeyStore -import java.util.Arrays -import javax.net.ssl.SSLContext -import javax.net.ssl.TrustManagerFactory -import javax.net.ssl.X509TrustManager - -/** - * Enable Tls ON Pre-Lollipop - * @link https://github.com/square/okhttp/issues/2372 - */ -internal object OkHttpTlsHelper { - - fun enableTls12OnPreLollipop( - builder: OkHttpClient.Builder, - logger: PayjpLogger - ): OkHttpClient.Builder { - return builder.takeIf { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && - Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1 - }?.apply { - try { - val trustManagerFactory = TrustManagerFactory.getInstance( - TrustManagerFactory.getDefaultAlgorithm() - ) - trustManagerFactory.init(null as KeyStore?) - val trustManagers = trustManagerFactory.trustManagers - check(!(trustManagers.size != 1 || trustManagers[0] !is X509TrustManager)) { - "Unexpected default trust managers:" + Arrays.toString(trustManagers) - } - val trustManager = trustManagers[0] as X509TrustManager - - val sslContext = SSLContext.getInstance("TLSv1.2") - .apply { init(null, null, null) } - - sslSocketFactory(Tls12SocketFactory(sslContext.socketFactory), trustManager) - - val cs = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) - .tlsVersions(TlsVersion.TLS_1_2) - .build() - - connectionSpecs( - mutableListOf( - cs, - ConnectionSpec.COMPATIBLE_TLS, - ConnectionSpec.CLEARTEXT - ) - ) - logger.v("apply TLSv1.2 for pre-Lollipop") - } catch (e: Exception) { - logger.e("error while setting TLS 1.2", e) - } - } ?: builder - } -} diff --git a/payjp-android-core/src/main/kotlin/jp/pay/android/network/Tls12SocketFactory.java b/payjp-android-core/src/main/kotlin/jp/pay/android/network/Tls12SocketFactory.java deleted file mode 100644 index 47d74eee..00000000 --- a/payjp-android-core/src/main/kotlin/jp/pay/android/network/Tls12SocketFactory.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Copyright (c) 2018 PAY, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package jp.pay.android.network; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; - -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; - -/** - * Enables TLS v1.2 when creating SSLSockets. - *

- * For some reason, android supports TLS v1.2 from API 16, but enables it by - * default only from API 20. - * - * @link https://developer.android.com/reference/javax/net/ssl/SSLSocket.html - * @link https://github.com/square/okhttp/issues/2372 - * @see SSLSocketFactory - */ -class Tls12SocketFactory extends SSLSocketFactory { - private static final String[] TLS_V12_ONLY = {"TLSv1.2"}; - - private final SSLSocketFactory delegate; - - public Tls12SocketFactory(SSLSocketFactory base) { - this.delegate = base; - } - - @Override - public String[] getDefaultCipherSuites() { - return delegate.getDefaultCipherSuites(); - } - - @Override - public String[] getSupportedCipherSuites() { - return delegate.getSupportedCipherSuites(); - } - - @Override - public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { - return patch(delegate.createSocket(s, host, port, autoClose)); - } - - @Override - public Socket createSocket(String host, int port) throws IOException, UnknownHostException { - return patch(delegate.createSocket(host, port)); - } - - @Override - public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { - return patch(delegate.createSocket(host, port, localHost, localPort)); - } - - @Override - public Socket createSocket(InetAddress host, int port) throws IOException { - return patch(delegate.createSocket(host, port)); - } - - @Override - public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { - return patch(delegate.createSocket(address, port, localAddress, localPort)); - } - - private Socket patch(Socket s) { - if (s instanceof SSLSocket) { - ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY); - } - return s; - } -} \ No newline at end of file diff --git a/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt b/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt index c138b6a8..ba5e70ef 100644 --- a/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt +++ b/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt @@ -73,9 +73,6 @@ internal object TokenApiClientFactory { ) } } - .let { - OkHttpTlsHelper.enableTls12OnPreLollipop(it, PayjpLogger.get(debuggable)) - } .dispatcher(Dispatcher(NetworkExecutorFactory.create())) .build() From 8419528cb167bfd78851c564af053d0805b86f7f Mon Sep 17 00:00:00 2001 From: bu-tokumitsu Date: Wed, 3 Jun 2026 16:36:06 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=E5=8F=A4=E3=81=84API=E5=88=86=E5=B2=90?= =?UTF-8?q?=E3=81=AE=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/jp/pay/android/verifier/ui/VerifierWebView.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/payjp-android-verifier/src/main/kotlin/jp/pay/android/verifier/ui/VerifierWebView.kt b/payjp-android-verifier/src/main/kotlin/jp/pay/android/verifier/ui/VerifierWebView.kt index b9982120..67d89792 100644 --- a/payjp-android-verifier/src/main/kotlin/jp/pay/android/verifier/ui/VerifierWebView.kt +++ b/payjp-android-verifier/src/main/kotlin/jp/pay/android/verifier/ui/VerifierWebView.kt @@ -160,9 +160,6 @@ internal class VerifierWebView @JvmOverloads constructor( domStorageEnabled = true @SuppressLint("SetJavaScriptEnabled") javaScriptEnabled = true - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { - savePassword = false - } } if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_ENABLE)) { WebSettingsCompat.setSafeBrowsingEnabled(settings, true) From 821061cce6a90192d1c477a850ad14dc673feae1 Mon Sep 17 00:00:00 2001 From: bu-tokumitsu Date: Wed, 3 Jun 2026 16:47:07 +0900 Subject: [PATCH 5/5] =?UTF-8?q?Test=E4=BF=AE=E6=AD=A3=E3=80=81robolectric?= =?UTF-8?q?=E3=81=AE=E5=AE=9F=E8=A1=8C=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=81=AE=E4=BF=AE=E6=AD=A3=E3=80=81API=2035=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E3=81=A7=E3=83=A9=E3=82=A4=E3=83=96=E3=83=A9=E3=83=AA?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=81=AE=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 2 +- .../src/test/resources/robolectric.properties | 2 +- .../main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt | 1 - payjp-android-core/src/test/resources/robolectric.properties | 2 +- .../src/test/resources/robolectric.properties | 2 +- .../src/test/resources/robolectric.properties | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3c100128..629fb707 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ recyclerview = "1.3.2" cardio = "5.5.1" androidxCore = "1.12.0" annotation = "1.8.1" -robolectric = "4.12.2" +robolectric = "4.14" swiperefreshlayout = "1.1.0" viewpager2 = "1.0.0" webkit = "1.8.0" diff --git a/payjp-android-cardform/src/test/resources/robolectric.properties b/payjp-android-cardform/src/test/resources/robolectric.properties index e7f67b67..b2cd4407 100644 --- a/payjp-android-cardform/src/test/resources/robolectric.properties +++ b/payjp-android-cardform/src/test/resources/robolectric.properties @@ -21,5 +21,5 @@ # SOFTWARE. # -sdk=19,34 +sdk=21,35 constants=jp.pay.android.BuildConfig \ No newline at end of file diff --git a/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt b/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt index ba5e70ef..815b8865 100644 --- a/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt +++ b/payjp-android-core/src/main/kotlin/jp/pay/android/network/TokenApiClientFactory.kt @@ -24,7 +24,6 @@ package jp.pay.android.network import com.squareup.moshi.Moshi import jp.pay.android.PayjpApi -import jp.pay.android.PayjpLogger import jp.pay.android.model.BundleJsonAdapter import jp.pay.android.model.CardBrand import jp.pay.android.model.ClientInfo diff --git a/payjp-android-core/src/test/resources/robolectric.properties b/payjp-android-core/src/test/resources/robolectric.properties index e7f67b67..b2cd4407 100644 --- a/payjp-android-core/src/test/resources/robolectric.properties +++ b/payjp-android-core/src/test/resources/robolectric.properties @@ -21,5 +21,5 @@ # SOFTWARE. # -sdk=19,34 +sdk=21,35 constants=jp.pay.android.BuildConfig \ No newline at end of file diff --git a/payjp-android-coroutine/src/test/resources/robolectric.properties b/payjp-android-coroutine/src/test/resources/robolectric.properties index 3bed9556..89636521 100644 --- a/payjp-android-coroutine/src/test/resources/robolectric.properties +++ b/payjp-android-coroutine/src/test/resources/robolectric.properties @@ -21,4 +21,4 @@ # SOFTWARE. # -sdk=19,34 \ No newline at end of file +sdk=21,35 \ No newline at end of file diff --git a/payjp-android-verifier/src/test/resources/robolectric.properties b/payjp-android-verifier/src/test/resources/robolectric.properties index 3bed9556..89636521 100644 --- a/payjp-android-verifier/src/test/resources/robolectric.properties +++ b/payjp-android-verifier/src/test/resources/robolectric.properties @@ -21,4 +21,4 @@ # SOFTWARE. # -sdk=19,34 \ No newline at end of file +sdk=21,35 \ No newline at end of file