diff --git a/dependencies.gradle b/dependencies.gradle index 13c1b886fb..70755d9c85 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -55,6 +55,7 @@ dependencyResolutionManagement { alias('google-libphonenumber').to('com.googlecode.libphonenumber:libphonenumber:8.12.17') alias('google-play-services-maps').to('com.google.android.gms:play-services-maps:16.1.0') alias('google-play-services-auth').to('com.google.android.gms:play-services-auth:16.0.1') + alias('google-play-services-wallet').to('com.google.android.gms:play-services-wallet:18.1.3') alias('google-zxing-android-integration').to('com.google.zxing:android-integration:3.1.0') alias('google-zxing-core').to('com.google.zxing:core:3.2.1') alias('google-ez-vcard').to('com.googlecode.ez-vcard:ez-vcard:0.9.11') diff --git a/donations/app/build.gradle b/donations/app/build.gradle new file mode 100644 index 0000000000..874fe929b0 --- /dev/null +++ b/donations/app/build.gradle @@ -0,0 +1,48 @@ +plugins { + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-kapt' + id 'witness' +} + +apply from: 'witness-verifications.gradle' + +android { + compileSdk COMPILE_SDK + + defaultConfig { + applicationId "org.signal.donations.app" + versionCode 1 + versionName "1.0" + multiDexEnabled true + + minSdk MINIMUM_SDK + targetSdk TARGET_SDK + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JAVA_VERSION + targetCompatibility JAVA_VERSION + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencyVerification { + configuration = '(debug|release)RuntimeClasspath' +} + +dependencies { + implementation libs.androidx.core.ktx + implementation libs.androidx.appcompat + implementation libs.material.material + implementation project(':donations') + implementation project(':core-util') +} diff --git a/donations/app/src/main/AndroidManifest.xml b/donations/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..51461435c7 --- /dev/null +++ b/donations/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/donations/app/src/main/java/org/signal/donations/app/MainActivity.java b/donations/app/src/main/java/org/signal/donations/app/MainActivity.java new file mode 100644 index 0000000000..3734f7dddd --- /dev/null +++ b/donations/app/src/main/java/org/signal/donations/app/MainActivity.java @@ -0,0 +1,92 @@ +package org.signal.donations.app; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import com.google.android.gms.wallet.PaymentData; + +import org.signal.core.util.logging.Log; +import org.signal.core.util.money.FiatMoney; +import org.signal.donations.GooglePayApi; + +import java.math.BigDecimal; +import java.util.Currency; +import java.util.Locale; + +import io.reactivex.rxjava3.disposables.Disposable; + +public class MainActivity extends AppCompatActivity implements GooglePayApi.PaymentRequestCallback { + + private static final String TAG = Log.tag(MainActivity.class); + + private View donateButton; + + private GooglePayApi payApi; + private Disposable isReadyToPayDisposable; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + donateButton = findViewById(R.id.donate_with_googlepay); + donateButton.setVisibility(View.GONE); + donateButton.setOnClickListener(v -> requestPayment()); + + payApi = new GooglePayApi(this, TestUtil.INSTANCE); + + isReadyToPayDisposable = payApi.queryIsReadyToPay().subscribe(this::presentGooglePayButton, this::presentException); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + payApi.onActivityResult(requestCode, resultCode, data, 1, this); + } + + @Override + protected void onDestroy() { + isReadyToPayDisposable.dispose(); + super.onDestroy(); + } + + private void presentGooglePayButton() { + Log.d(TAG, "Pay is available, displaying button"); + donateButton.setVisibility(View.VISIBLE); + } + + private void presentException(@NonNull Throwable throwable) { + Log.w(TAG, "Could not display pay button", throwable); + Toast.makeText(this, "Could not display pay button", Toast.LENGTH_LONG).show(); + } + + private void requestPayment() { + donateButton.setClickable(false); + + payApi.requestPayment(new FiatMoney(BigDecimal.valueOf(4.00), Currency.getInstance(Locale.getDefault())), "Test Purchase", 1); + } + + @Override + public void onSuccess(PaymentData paymentData) { + Toast.makeText(this, "SUCCESS", Toast.LENGTH_SHORT).show(); + donateButton.setClickable(true); + } + + @Override + public void onError() { + Toast.makeText(this, "ERROR", Toast.LENGTH_SHORT).show(); + donateButton.setClickable(true); + } + + @Override + public void onCancelled() { + Toast.makeText(this, "CANCELLED", Toast.LENGTH_SHORT).show(); + donateButton.setClickable(true); + } +} diff --git a/donations/app/src/main/java/org/signal/donations/app/TestUtil.kt b/donations/app/src/main/java/org/signal/donations/app/TestUtil.kt new file mode 100644 index 0000000000..a02a7620b6 --- /dev/null +++ b/donations/app/src/main/java/org/signal/donations/app/TestUtil.kt @@ -0,0 +1,22 @@ +package org.signal.donations.app + +import org.signal.donations.GooglePayApi + +object TestUtil : GooglePayApi.Gateway { + override fun getTokenizationSpecificationParameters(): Map { + return mapOf( + "gateway" to "example", + "gatewayMerchantId" to "exampleMerchantId" + ) + } + + override val allowedCardNetworks: List = listOf( + "AMEX", + "DISCOVER", + "INTERAC", + "JCB", + "MASTERCARD", + "VISA" + ) + +} \ No newline at end of file diff --git a/donations/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/donations/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000000..18c0565852 --- /dev/null +++ b/donations/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/donations/app/src/main/res/drawable/ic_launcher_background.xml b/donations/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..c71b77f4d2 --- /dev/null +++ b/donations/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/donations/app/src/main/res/drawable/ic_refresh_20.xml b/donations/app/src/main/res/drawable/ic_refresh_20.xml new file mode 100644 index 0000000000..915e0bbbca --- /dev/null +++ b/donations/app/src/main/res/drawable/ic_refresh_20.xml @@ -0,0 +1,9 @@ + + + diff --git a/donations/app/src/main/res/layout/activity_main.xml b/donations/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000..b07556fbe9 --- /dev/null +++ b/donations/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/donations/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/donations/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..9244248264 --- /dev/null +++ b/donations/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/donations/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/donations/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..9244248264 --- /dev/null +++ b/donations/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/donations/app/src/main/res/mipmap-hdpi/ic_launcher.png b/donations/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..a571e60098 Binary files /dev/null and b/donations/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/donations/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/donations/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000..61da551c55 Binary files /dev/null and b/donations/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/donations/app/src/main/res/mipmap-mdpi/ic_launcher.png b/donations/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..c41dd28531 Binary files /dev/null and b/donations/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/donations/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/donations/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000..db5080a752 Binary files /dev/null and b/donations/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/donations/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/donations/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..6dba46dab1 Binary files /dev/null and b/donations/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/donations/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/donations/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..da31a871c8 Binary files /dev/null and b/donations/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/donations/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/donations/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000..15ac681720 Binary files /dev/null and b/donations/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/donations/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/donations/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..b216f2d313 Binary files /dev/null and b/donations/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/donations/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/donations/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000..f25a419744 Binary files /dev/null and b/donations/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/donations/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/donations/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..e96783ccce Binary files /dev/null and b/donations/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/donations/app/src/main/res/values-night/themes.xml b/donations/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000000..469981c422 --- /dev/null +++ b/donations/app/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/donations/app/src/main/res/values/colors.xml b/donations/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000..09837df62f --- /dev/null +++ b/donations/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/donations/app/src/main/res/values/strings.xml b/donations/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000..704183733d --- /dev/null +++ b/donations/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + DonationsTest + \ No newline at end of file diff --git a/donations/app/src/main/res/values/themes.xml b/donations/app/src/main/res/values/themes.xml new file mode 100644 index 0000000000..00c51022b9 --- /dev/null +++ b/donations/app/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/donations/app/witness-verifications.gradle b/donations/app/witness-verifications.gradle new file mode 100644 index 0000000000..2c81c28b24 --- /dev/null +++ b/donations/app/witness-verifications.gradle @@ -0,0 +1,168 @@ +// Auto-generated, use ./gradlew calculateChecksums to regenerate + +dependencyVerification { + verify = [ + + ['androidx.activity:activity:1.0.0', + 'd1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d'], + + ['androidx.annotation:annotation-experimental:1.0.0', + 'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'], + + ['androidx.annotation:annotation:1.2.0', + '9029262bddce116e6d02be499e4afdba21f24c239087b76b3b57d7e98b490a36'], + + ['androidx.appcompat:appcompat-resources:1.2.0', + 'c470297c03ff3de1c3d15dacf0be0cae63abc10b52f021dd07ae28daa3100fe5'], + + ['androidx.appcompat:appcompat:1.2.0', + '3d2131a55a61a777322e2126e0018011efa6339e53b44153eb651b16020cca70'], + + ['androidx.arch.core:core-common:2.1.0', + 'fe1237bf029d063e7f29fe39aeaf73ef74c8b0a3658486fc29d3c54326653889'], + + ['androidx.arch.core:core-runtime:2.0.0', + '87e65fc767c712b437649c7cee2431ebb4bed6daef82e501d4125b3ed3f65f8e'], + + ['androidx.cardview:cardview:1.0.0', + '1193c04c22a3d6b5946dae9f4e8c59d6adde6a71b6bd5d87fb99d82dda1afec7'], + + ['androidx.collection:collection:1.1.0', + '632a0e5407461de774409352940e292a291037724207a787820c77daf7d33b72'], + + ['androidx.constraintlayout:constraintlayout-solver:2.0.1', + 'b23732edbb3511d937fea1ffef047b0e6c001b50c1921f0d959fc384d706ec6a'], + + ['androidx.constraintlayout:constraintlayout:2.0.1', + 'ec15b5d4a2eff07888bc1499ce2e2c6efe24c0ed60cc57b08c9dc4b6fd3c2189'], + + ['androidx.coordinatorlayout:coordinatorlayout:1.1.0', + '44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'], + + ['androidx.core:core-ktx:1.5.0', + '5964cfe7a4882da2a00fb6ca3d3a072d04139208186f7bc4b3cb66022764fc42'], + + ['androidx.core:core:1.5.0', + '2b279712795689069cfb63e48b3ab63c32a5649bdda44c482eb8f81ca1a72161'], + + ['androidx.cursoradapter:cursoradapter:1.0.0', + 'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'], + + ['androidx.customview:customview:1.0.0', + '20e5b8f6526a34595a604f56718da81167c0b40a7a94a57daa355663f2594df2'], + + ['androidx.documentfile:documentfile:1.0.0', + '865a061ef2fad16522f8433536b8d47208c46ff7c7745197dfa1eeb481869487'], + + ['androidx.drawerlayout:drawerlayout:1.0.0', + '9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1'], + + ['androidx.dynamicanimation:dynamicanimation:1.0.0', + 'ce005162c229bf308d2d5b12fb6cad0874069cbbeaccee63a8193bd08d40de04'], + + ['androidx.fragment:fragment:1.1.0', + 'a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496'], + + ['androidx.interpolator:interpolator:1.0.0', + '33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a'], + + ['androidx.legacy:legacy-support-core-utils:1.0.0', + 'a7edcf01d5b52b3034073027bc4775b78a4764bb6202bb91d61c829add8dd1c7'], + + ['androidx.lifecycle:lifecycle-common:2.1.0', + '76db6be533bd730fb361c2feb12a2c26d9952824746847da82601ef81f082643'], + + ['androidx.lifecycle:lifecycle-livedata-core:2.0.0', + 'fde334ec7e22744c0f5bfe7caf1a84c9d717327044400577bdf9bd921ec4f7bc'], + + ['androidx.lifecycle:lifecycle-livedata:2.0.0', + 'c82609ced8c498f0a701a30fb6771bb7480860daee84d82e0a81ee86edf7ba39'], + + ['androidx.lifecycle:lifecycle-runtime:2.1.0', + 'e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b'], + + ['androidx.lifecycle:lifecycle-viewmodel:2.1.0', + 'ba55fb7ac1b2828d5327cda8acf7085d990b2b4c43ef336caa67686249b8523d'], + + ['androidx.loader:loader:1.0.0', + '11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'], + + ['androidx.localbroadcastmanager:localbroadcastmanager:1.0.0', + 'e71c328ceef5c4a7d76f2d86df1b65d65fe2acf868b1a4efd84a3f34336186d8'], + + ['androidx.multidex:multidex:2.0.0', + 'c01700091072e0ff5d8ec2d00eac6b8f96ea18646080425e9ce3c6a7b5f66e33'], + + ['androidx.print:print:1.0.0', + '1d5c7f3135a1bba661fc373fd72e11eb0a4adbb3396787826dd8e4190d5d9edd'], + + ['androidx.recyclerview:recyclerview:1.1.0', + 'f0d2b5a67d0a91ee1b1c73ef2b636a81f3563925ddd15a1d4e1c41ec28de7a4f'], + + ['androidx.savedstate:savedstate:1.0.0', + '2510a5619c37579c9ce1a04574faaf323cd0ffe2fc4e20fa8f8f01e5bb402e83'], + + ['androidx.transition:transition:1.2.0', + 'a1e059b3bc0b43a58dec0efecdcaa89c82d2bca552ea5bacf6656c46e853157e'], + + ['androidx.vectordrawable:vectordrawable-animated:1.1.0', + '76da2c502371d9c38054df5e2b248d00da87809ed058f3363eae87ce5e2403f8'], + + ['androidx.vectordrawable:vectordrawable:1.1.0', + '46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26'], + + ['androidx.versionedparcelable:versionedparcelable:1.1.1', + '57e8d93260d18d5b9007c9eed3c64ad159de90c8609ebfc74a347cbd514535a4'], + + ['androidx.viewpager2:viewpager2:1.0.0', + 'e95c0031d4cc247cd48196c6287e58d2cee54d9c79b85afea7c90920330275af'], + + ['androidx.viewpager:viewpager:1.0.0', + '147af4e14a1984010d8f155e5e19d781f03c1d70dfed02a8e0d18428b8fc8682'], + + ['com.google.android.gms:play-services-base:17.5.0', + '198c9e2115f5ce5f91140cd9b481dc6d64dd634ac2d6c6525567dc5fe00065cb'], + + ['com.google.android.gms:play-services-basement:17.5.0', + '362301c0da1c765cbbdcf8ea866b6cb62bc130c86d2aa7cc9e9c18a6e51ea79d'], + + ['com.google.android.gms:play-services-identity:17.0.0', + '8987c6c303eaaa9c10c403822cf5ae188ee1ce61c3056eb3be2ca4aaecc80b5f'], + + ['com.google.android.gms:play-services-maps:17.0.0', + 'f9e479bc57ff423959c6dd9d08d463c677f440e29d90de795418ea27da6c67fb'], + + ['com.google.android.gms:play-services-tasks:17.2.0', + 'a131d126145dfe87de04fa904f9ce91753b2d3273851b7d084666a71255792a8'], + + ['com.google.android.gms:play-services-wallet:18.1.3', + 'e19d1f4650f51ce2202c092cbe174058860b6558cf26c8be37a732eff3ae1864'], + + ['com.google.android.material:material:1.3.0', + 'cbf1e7d69fc236cdadcbd1ec5f6c0a1a41aca6ad1ef7f8481058956270ab1f0a'], + + ['com.google.protobuf:protobuf-javalite:3.10.0', + '215a94dbe100130295906b531bb72a26965c7ac8fcd9a75bf8054a8ac2abf4b4'], + + ['com.squareup.okhttp3:okhttp:3.12.10', + '3cb8e21cd3ab10d390448f5a475c960732efab583a09c39f06f866a7ed819ebc'], + + ['com.squareup.okio:okio:1.15.0', + '693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2'], + + ['io.reactivex.rxjava3:rxjava:3.0.13', + '598abaf71dbc970dd0727e6d5f4f786dc999df5b972cbf261316a32e155b2c69'], + + ['org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32', + 'e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145'], + + ['org.jetbrains.kotlin:kotlin-stdlib:1.4.32', + '13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba'], + + ['org.jetbrains:annotations:13.0', + 'ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478'], + + ['org.reactivestreams:reactive-streams:1.0.3', + '1dee0481072d19c929b623e155e14d2f6085dc011529a0a0dbefc84cf571d865'], + ] +} diff --git a/donations/lib/build.gradle b/donations/lib/build.gradle new file mode 100644 index 0000000000..a771b27f54 --- /dev/null +++ b/donations/lib/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'com.android.library' + id 'witness' + id 'kotlin-android' + id 'kotlin-kapt' +} + +apply from: 'witness-verifications.gradle' + +android { + buildToolsVersion BUILD_TOOL_VERSION + compileSdkVersion COMPILE_SDK + + defaultConfig { + minSdkVersion MINIMUM_SDK + targetSdkVersion TARGET_SDK + multiDexEnabled true + } + + compileOptions { + coreLibraryDesugaringEnabled true + sourceCompatibility JAVA_VERSION + targetCompatibility JAVA_VERSION + } + + kotlinOptions { + jvmTarget = '1.8' + } + + lintOptions { + disable 'InvalidVectorPath' + } +} + +dependencyVerification { + configuration = '(debug|release)RuntimeClasspath' +} + +dependencies { + lintChecks project(':lintchecks') + + implementation project(':core-util') + + coreLibraryDesugaring libs.android.tools.desugar + + implementation libs.androidx.core.ktx + implementation libs.androidx.annotation + implementation libs.androidx.appcompat + + api libs.google.play.services.wallet + api libs.square.okhttp3 + api libs.rxjava3.rxjava + + kapt libs.androidx.annotation +} diff --git a/donations/lib/src/main/AndroidManifest.xml b/donations/lib/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..af79577bd4 --- /dev/null +++ b/donations/lib/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/donations/lib/src/main/java/org/signal/donations/GooglePayApi.kt b/donations/lib/src/main/java/org/signal/donations/GooglePayApi.kt new file mode 100644 index 0000000000..d8fbe24ebc --- /dev/null +++ b/donations/lib/src/main/java/org/signal/donations/GooglePayApi.kt @@ -0,0 +1,193 @@ +package org.signal.donations + +import android.app.Activity +import android.content.Intent +import com.google.android.gms.common.api.ApiException +import com.google.android.gms.tasks.Task +import com.google.android.gms.wallet.AutoResolveHelper +import com.google.android.gms.wallet.IsReadyToPayRequest +import com.google.android.gms.wallet.PaymentData +import com.google.android.gms.wallet.PaymentDataRequest +import com.google.android.gms.wallet.PaymentsClient +import com.google.android.gms.wallet.Wallet +import com.google.android.gms.wallet.WalletConstants +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Single +import io.reactivex.rxjava3.schedulers.Schedulers +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import org.signal.core.util.logging.Log +import org.signal.core.util.money.FiatMoney + +/** + * Entrypoint for Google Pay APIs + * + * @param activity The activity the Pay Client will attach itself to + * @param gateway The payment gateway (Such as Stripe) + */ +class GooglePayApi(private val activity: Activity, private val gateway: Gateway) { + + private val paymentsClient: PaymentsClient + + init { + val walletOptions = Wallet.WalletOptions.Builder() + .setEnvironment(PAYMENT_ENVIRONMENT) + .build() + + paymentsClient = Wallet.getPaymentsClient(activity, walletOptions) + } + + /** + * Query the Google Pay API to determine whether or not the device has Google Pay available and ready. + * + * @return A completable which, when it completes, indicates that Google Pay is available, or when it errors, indicates it is not. + */ + fun queryIsReadyToPay(): Completable = Completable.create { emitter -> + try { + val request: IsReadyToPayRequest = buildIsReadyToPayRequest() + val task: Task = paymentsClient.isReadyToPay(request) + task.addOnCompleteListener { completedTask -> + if (!emitter.isDisposed) { + try { + val result: Boolean = completedTask.getResult(ApiException::class.java) ?: false + if (result) { + emitter.onComplete() + } else { + emitter.onError(Exception("Google Pay is not available.")) + } + } catch (e: ApiException) { + emitter.onError(e) + } + } + } + } catch (e: JSONException) { + emitter.onError(e) + } + }.subscribeOn(Schedulers.io()) + + /** + * Launches the Google Pay sheet via an Activity intent. It is up to the caller to pass + * through the activity result to onActivityResult. + */ + fun requestPayment(price: FiatMoney, label: String, requestCode: Int) { + val paymentDataRequest = getPaymentDataRequest(price, label) + val request = PaymentDataRequest.fromJson(paymentDataRequest.toString()) + AutoResolveHelper.resolveTask(paymentsClient.loadPaymentData(request), activity, requestCode) + } + + /** + * Checks the activity result for payment data and fires off the corresponding callback. Does nothing if + * the request code is not the expected request code. + */ + fun onActivityResult( + requestCode: Int, + resultCode: Int, + data: Intent?, + expectedRequestCode: Int, + paymentRequestCallback: PaymentRequestCallback + ) { + if (requestCode != expectedRequestCode) { + return + } + + when (resultCode) { + Activity.RESULT_OK -> { + data?.let { intent -> + PaymentData.getFromIntent(intent)?.let { paymentRequestCallback.onSuccess(it) } + } ?: paymentRequestCallback.onError() + } + Activity.RESULT_CANCELED -> paymentRequestCallback.onCancelled() + AutoResolveHelper.RESULT_ERROR -> { + AutoResolveHelper.getStatusFromIntent(data)?.let { + Log.w(TAG, "loadPaymentData failed with error code ${it.statusCode}") + paymentRequestCallback.onError() + } + } + } + } + + private fun getPaymentDataRequest(price: FiatMoney, label: String): JSONObject { + return baseRequest.apply { + put("merchantInfo", merchantInfo) + put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod())) + put("transactionInfo", getTransactionInfo(price, label)) + put("emailRequired", false) + put("shippingAddressRequired", false) + } + } + + private fun getTransactionInfo(price: FiatMoney, label: String): JSONObject { + return JSONObject().apply { + put("currencyCode", price.currency.currencyCode) + put("countryCode", "US") + put("totalPriceStatus", "FINAL") + put("totalPrice", price.defaultPrecisionString) + put("totalPriceLabel", label) + put("checkoutOption", "COMPLETE_IMMEDIATE_PURCHASE") + } + } + + private fun buildIsReadyToPayRequest(): IsReadyToPayRequest { + val isReadyToPayJson: JSONObject = baseRequest.apply { + put("allowedPaymentMethods", JSONArray().put(baseCardPaymentMethod())) + } + + return IsReadyToPayRequest.fromJson(isReadyToPayJson.toString()) + } + + private fun gatewayTokenizationSpecification(): JSONObject { + return JSONObject().apply { + put("type", "PAYMENT_GATEWAY") + put("parameters", JSONObject(gateway.getTokenizationSpecificationParameters())) + } + } + + private fun baseCardPaymentMethod(): JSONObject { + return JSONObject().apply { + val parameters = JSONObject().apply { + put("allowedAuthMethods", allowedCardAuthMethods) + put("allowedCardNetworks", JSONArray(gateway.allowedCardNetworks)) + put("billingAddressRequired", false) + } + + put("type", "CARD") + put("parameters", parameters) + } + } + + private fun cardPaymentMethod(): JSONObject { + val cardPaymentMethod = baseCardPaymentMethod() + cardPaymentMethod.put("tokenizationSpecification", gatewayTokenizationSpecification()) + + return cardPaymentMethod + } + + companion object { + private val TAG = Log.tag(GooglePayApi::class.java) + + private const val PAYMENT_ENVIRONMENT: Int = WalletConstants.ENVIRONMENT_TEST + private const val MERCHANT_NAME = "Signal Foundation" + + private val merchantInfo: JSONObject = + JSONObject().put("merchantName", MERCHANT_NAME) + + private val allowedCardAuthMethods = JSONArray(listOf("CRYPTOGRAM_3DS")) + + private val baseRequest = JSONObject().apply { + put("apiVersion", 2) + put("apiVersionMinor", 0) + } + } + + interface Gateway { + fun getTokenizationSpecificationParameters(): Map + val allowedCardNetworks: List + } + + interface PaymentRequestCallback { + fun onSuccess(paymentData: PaymentData) + fun onError() + fun onCancelled() + } +} \ No newline at end of file diff --git a/donations/lib/src/main/java/org/signal/donations/GooglePayPaymentSource.kt b/donations/lib/src/main/java/org/signal/donations/GooglePayPaymentSource.kt new file mode 100644 index 0000000000..2198efc58f --- /dev/null +++ b/donations/lib/src/main/java/org/signal/donations/GooglePayPaymentSource.kt @@ -0,0 +1,12 @@ +package org.signal.donations + +import com.google.android.gms.wallet.PaymentData +import org.json.JSONObject + +class GooglePayPaymentSource(private val paymentData: PaymentData) : StripeApi.PaymentSource { + override fun parameterize(): JSONObject { + val jsonData = JSONObject(paymentData.toJson()) + val paymentMethodJsonData = jsonData.getJSONObject("paymentMethodData") + return paymentMethodJsonData.getJSONObject("tokenizationData") + } +} \ No newline at end of file diff --git a/donations/lib/src/main/java/org/signal/donations/StripeApi.kt b/donations/lib/src/main/java/org/signal/donations/StripeApi.kt new file mode 100644 index 0000000000..4d0b787ff6 --- /dev/null +++ b/donations/lib/src/main/java/org/signal/donations/StripeApi.kt @@ -0,0 +1,307 @@ +package org.signal.donations + +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Single +import io.reactivex.rxjava3.schedulers.Schedulers +import okhttp3.FormBody +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okio.ByteString +import org.json.JSONObject +import org.signal.core.util.money.FiatMoney +import java.io.IOException +import java.math.BigDecimal +import java.util.Locale + +class StripeApi(private val configuration: Configuration, private val paymentIntentFetcher: PaymentIntentFetcher, private val okHttpClient: OkHttpClient) { + + sealed class CreatePaymentIntentResult { + data class AmountIsTooSmall(val amount: FiatMoney) : CreatePaymentIntentResult() + data class AmountIsTooLarge(val amount: FiatMoney) : CreatePaymentIntentResult() + data class CurrencyIsNotSupported(val currencyCode: String) : CreatePaymentIntentResult() + data class Success(val paymentIntent: PaymentIntent) : CreatePaymentIntentResult() + } + + fun createPaymentIntent(price: FiatMoney, description: String? = null): Single = Single.fromCallable { + if (Validation.isAmountTooSmall(price)) { + CreatePaymentIntentResult.AmountIsTooSmall(price) + } else if (Validation.isAmountTooLarge(price)) { + CreatePaymentIntentResult.AmountIsTooLarge(price) + } else if (!Validation.supportedCurrencyCodes.contains(price.currency.currencyCode.toUpperCase(Locale.ROOT))) { + CreatePaymentIntentResult.CurrencyIsNotSupported(price.currency.currencyCode) + } else { + CreatePaymentIntentResult.Success( + paymentIntentFetcher.fetchPaymentIntent( + price, description + ) + ) + } + }.subscribeOn(Schedulers.io()) + + fun confirmPaymentIntent(paymentSource: PaymentSource, paymentIntent: PaymentIntent): Completable = Completable.fromAction { + val paymentMethodId = createPaymentMethod(paymentSource).use { response -> + val body = response.body() + if (body != null) { + val paymentMethodObject = body.string().replace("\n", "").let { JSONObject(it) } + paymentMethodObject.getString("id") + } else { + throw IOException("Failed to parse payment method response") + } + } + + val parameters = mapOf( + "client_secret" to paymentIntent.clientSecret, + "payment_method" to paymentMethodId + ) + + postForm("payment_intents/${paymentIntent.id}/confirm", parameters) + }.subscribeOn(Schedulers.io()) + + private fun createPaymentMethod(paymentSource: PaymentSource): Response { + val tokenizationData = paymentSource.parameterize() + val parameters = mapOf( + "card[token]" to JSONObject((tokenizationData.get("token") as String).replace("\n", "")).getString("id"), + "type" to "card" + ) + + return postForm("payment_methods", parameters) + } + + private fun postForm(endpoint: String, parameters: Map): Response { + val formBodyBuilder = FormBody.Builder() + parameters.forEach { (k, v) -> + formBodyBuilder.add(k, v) + } + + val request = Request.Builder() + .url("${configuration.baseUrl}/$endpoint") + .addHeader("Authorization", "Basic ${ByteString.encodeUtf8("${configuration.publishableKey}:").base64()}") + .post(formBodyBuilder.build()) + .build() + + val response = okHttpClient.newCall(request).execute() + + if (response.isSuccessful) { + return response + } else { + throw IOException("postForm failure: ${response.code()}") + } + } + + object Validation { + private val MAX_AMOUNT = BigDecimal(99_999_999) + + fun isAmountTooLarge(fiatMoney: FiatMoney): Boolean { + return fiatMoney.amount > MAX_AMOUNT + } + + fun isAmountTooSmall(fiatMoney: FiatMoney): Boolean { + return fiatMoney.amount < BigDecimal(minimumIntegralChargePerCurrencyCode[fiatMoney.currency.currencyCode] ?: 50) + } + + private val minimumIntegralChargePerCurrencyCode: Map = mapOf( + "USD" to 50, + "AED" to 200, + "AUD" to 50, + "BGN" to 100, + "BRL" to 50, + "CAD" to 50, + "CHF" to 50, + "CZK" to 1500, + "DKK" to 250, + "EUR" to 50, + "GBP" to 30, + "HKD" to 400, + "HUF" to 17500, + "INR" to 50, + "JPY" to 50, + "MXN" to 10, + "MYR" to 2, + "NOK" to 300, + "NZD" to 50, + "PLN" to 200, + "RON" to 200, + "SEK" to 300, + "SGD" to 50 + ) + + val supportedCurrencyCodes: List = listOf( + "USD", + "AED", + "AFN", + "ALL", + "AMD", + "ANG", + "AOA", + "ARS", + "AUD", + "AWG", + "AZN", + "BAM", + "BBD", + "BDT", + "BGN", + "BIF", + "BMD", + "BND", + "BOB", + "BRL", + "BSD", + "BWP", + "BZD", + "CAD", + "CDF", + "CHF", + "CLP", + "CNY", + "COP", + "CRC", + "CVE", + "CZK", + "DJF", + "DKK", + "DOP", + "DZD", + "EGP", + "ETB", + "EUR", + "FJD", + "FKP", + "GBP", + "GEL", + "GIP", + "GMD", + "GNF", + "GTQ", + "GYD", + "HKD", + "HNL", + "HRK", + "HTG", + "HUF", + "IDR", + "ILS", + "INR", + "ISK", + "JMD", + "JPY", + "KES", + "KGS", + "KHR", + "KMF", + "KRW", + "KYD", + "KZT", + "LAK", + "LBP", + "LKR", + "LRD", + "LSL", + "MAD", + "MDL", + "MGA", + "MKD", + "MMK", + "MNT", + "MOP", + "MRO", + "MUR", + "MVR", + "MWK", + "MXN", + "MYR", + "MZN", + "NAD", + "NGN", + "NIO", + "NOK", + "NPR", + "NZD", + "PAB", + "PEN", + "PGK", + "PHP", + "PKR", + "PLN", + "PYG", + "QAR", + "RON", + "RSD", + "RUB", + "RWF", + "SAR", + "SBD", + "SCR", + "SEK", + "SGD", + "SHP", + "SLL", + "SOS", + "SRD", + "STD", + "SZL", + "THB", + "TJS", + "TOP", + "TRY", + "TTD", + "TWD", + "TZS", + "UAH", + "UGX", + "UYU", + "UZS", + "VND", + "VUV", + "WST", + "XAF", + "XCD", + "XOF", + "XPF", + "YER", + "ZAR", + "ZMW" + ) + } + + class Gateway(private val configuration: Configuration) : GooglePayApi.Gateway { + override fun getTokenizationSpecificationParameters(): Map { + return mapOf( + "gateway" to "stripe", + "stripe:version" to configuration.version, + "stripe:publishableKey" to configuration.publishableKey + ) + } + + override val allowedCardNetworks: List = listOf( + "AMEX", + "DISCOVER", + "JCB", + "MASTERCARD", + "VISA" + ) + } + + data class Configuration( + val publishableKey: String, + val baseUrl: String = "https://api.stripe.com/v1", + val version: String = "2018-10-31" + ) + + interface PaymentIntentFetcher { + fun fetchPaymentIntent( + price: FiatMoney, + description: String? = null + ): PaymentIntent + } + + data class PaymentIntent( + val id: String, + val clientSecret: String + ) + + interface PaymentSource { + fun parameterize(): JSONObject + } +} \ No newline at end of file diff --git a/donations/lib/src/main/res/drawable-ar/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-ar/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..079fd572c7 --- /dev/null +++ b/donations/lib/src/main/res/drawable-ar/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-bg/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-bg/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..c23c990df9 --- /dev/null +++ b/donations/lib/src/main/res/drawable-bg/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-ca/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-ca/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..b2a8fd40d8 --- /dev/null +++ b/donations/lib/src/main/res/drawable-ca/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-cs/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-cs/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..7c55839e8e --- /dev/null +++ b/donations/lib/src/main/res/drawable-cs/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-da/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-da/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..622d3198de --- /dev/null +++ b/donations/lib/src/main/res/drawable-da/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-de/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-de/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..c3d4c5347b --- /dev/null +++ b/donations/lib/src/main/res/drawable-de/donate_with_googlepay_button_content.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-el/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-el/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..cd7adc3857 --- /dev/null +++ b/donations/lib/src/main/res/drawable-el/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-es/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-es/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..1d5461166f --- /dev/null +++ b/donations/lib/src/main/res/drawable-es/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-et/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-et/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..367cec333e --- /dev/null +++ b/donations/lib/src/main/res/drawable-et/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-eu/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-eu/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..083062e8fd --- /dev/null +++ b/donations/lib/src/main/res/drawable-eu/donate_with_googlepay_button_content.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-fi/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-fi/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..c0022bfc21 --- /dev/null +++ b/donations/lib/src/main/res/drawable-fi/donate_with_googlepay_button_content.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-fr/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-fr/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..2cf102c30a --- /dev/null +++ b/donations/lib/src/main/res/drawable-fr/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-hdpi/googlepay_button_background_image.9.png b/donations/lib/src/main/res/drawable-hdpi/googlepay_button_background_image.9.png new file mode 100755 index 0000000000..7091d810af Binary files /dev/null and b/donations/lib/src/main/res/drawable-hdpi/googlepay_button_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-hdpi/googlepay_button_no_shadow_background_image.9.png b/donations/lib/src/main/res/drawable-hdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100755 index 0000000000..4f9bc6ba76 Binary files /dev/null and b/donations/lib/src/main/res/drawable-hdpi/googlepay_button_no_shadow_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-hr/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-hr/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..5934099041 --- /dev/null +++ b/donations/lib/src/main/res/drawable-hr/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-id/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-id/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..b7f195bc92 --- /dev/null +++ b/donations/lib/src/main/res/drawable-id/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-it/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-it/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..6ffa94b4dc --- /dev/null +++ b/donations/lib/src/main/res/drawable-it/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-ja/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-ja/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..5909abc9c6 --- /dev/null +++ b/donations/lib/src/main/res/drawable-ja/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-ko/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-ko/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..a54b6d3191 --- /dev/null +++ b/donations/lib/src/main/res/drawable-ko/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-mdpi/googlepay_button_background_image.9.png b/donations/lib/src/main/res/drawable-mdpi/googlepay_button_background_image.9.png new file mode 100755 index 0000000000..a60464a360 Binary files /dev/null and b/donations/lib/src/main/res/drawable-mdpi/googlepay_button_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-mdpi/googlepay_button_no_shadow_background_image.9.png b/donations/lib/src/main/res/drawable-mdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100755 index 0000000000..d0be7ed2d5 Binary files /dev/null and b/donations/lib/src/main/res/drawable-mdpi/googlepay_button_no_shadow_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-ms/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-ms/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..18c0936d5f --- /dev/null +++ b/donations/lib/src/main/res/drawable-ms/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-nl/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-nl/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..4a3dc7bfbc --- /dev/null +++ b/donations/lib/src/main/res/drawable-nl/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-no/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-no/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..622d3198de --- /dev/null +++ b/donations/lib/src/main/res/drawable-no/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-pl/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-pl/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..2916f90b14 --- /dev/null +++ b/donations/lib/src/main/res/drawable-pl/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-pt/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-pt/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..e910854870 --- /dev/null +++ b/donations/lib/src/main/res/drawable-pt/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-ru/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-ru/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..bea5a08460 --- /dev/null +++ b/donations/lib/src/main/res/drawable-ru/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-sk/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-sk/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..78e03f8add --- /dev/null +++ b/donations/lib/src/main/res/drawable-sk/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-sl/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-sl/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..b1a8d5a0d2 --- /dev/null +++ b/donations/lib/src/main/res/drawable-sl/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-sr/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-sr/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..59f17d2936 --- /dev/null +++ b/donations/lib/src/main/res/drawable-sr/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-sv/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-sv/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..abf8cfe800 --- /dev/null +++ b/donations/lib/src/main/res/drawable-sv/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-th/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-th/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..666202619e --- /dev/null +++ b/donations/lib/src/main/res/drawable-th/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-tr/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-tr/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..3c9dd5e5dd --- /dev/null +++ b/donations/lib/src/main/res/drawable-tr/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-uk/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-uk/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..a92ff95972 --- /dev/null +++ b/donations/lib/src/main/res/drawable-uk/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable-v21/googlepay_button_background.xml b/donations/lib/src/main/res/drawable-v21/googlepay_button_background.xml new file mode 100755 index 0000000000..4873ef2428 --- /dev/null +++ b/donations/lib/src/main/res/drawable-v21/googlepay_button_background.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/donations/lib/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml b/donations/lib/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml new file mode 100755 index 0000000000..d44e9eb62d --- /dev/null +++ b/donations/lib/src/main/res/drawable-v21/googlepay_button_no_shadow_background.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/donations/lib/src/main/res/drawable-xhdpi/googlepay_button_background_image.9.png b/donations/lib/src/main/res/drawable-xhdpi/googlepay_button_background_image.9.png new file mode 100755 index 0000000000..40f767d533 Binary files /dev/null and b/donations/lib/src/main/res/drawable-xhdpi/googlepay_button_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-xhdpi/googlepay_button_no_shadow_background_image.9.png b/donations/lib/src/main/res/drawable-xhdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100755 index 0000000000..969cc52a94 Binary files /dev/null and b/donations/lib/src/main/res/drawable-xhdpi/googlepay_button_no_shadow_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-xxhdpi/googlepay_button_background_image.9.png b/donations/lib/src/main/res/drawable-xxhdpi/googlepay_button_background_image.9.png new file mode 100755 index 0000000000..91035e2a41 Binary files /dev/null and b/donations/lib/src/main/res/drawable-xxhdpi/googlepay_button_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-xxhdpi/googlepay_button_no_shadow_background_image.9.png b/donations/lib/src/main/res/drawable-xxhdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100755 index 0000000000..dda66dfd0d Binary files /dev/null and b/donations/lib/src/main/res/drawable-xxhdpi/googlepay_button_no_shadow_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-xxxhdpi/googlepay_button_background_image.9.png b/donations/lib/src/main/res/drawable-xxxhdpi/googlepay_button_background_image.9.png new file mode 100755 index 0000000000..ab905289bc Binary files /dev/null and b/donations/lib/src/main/res/drawable-xxxhdpi/googlepay_button_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-xxxhdpi/googlepay_button_no_shadow_background_image.9.png b/donations/lib/src/main/res/drawable-xxxhdpi/googlepay_button_no_shadow_background_image.9.png new file mode 100755 index 0000000000..e67fdaf516 Binary files /dev/null and b/donations/lib/src/main/res/drawable-xxxhdpi/googlepay_button_no_shadow_background_image.9.png differ diff --git a/donations/lib/src/main/res/drawable-zh/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable-zh/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..06ee8ed6ba --- /dev/null +++ b/donations/lib/src/main/res/drawable-zh/donate_with_googlepay_button_content.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable/donate_with_googlepay_button_content.xml b/donations/lib/src/main/res/drawable/donate_with_googlepay_button_content.xml new file mode 100755 index 0000000000..ee9b8f7428 --- /dev/null +++ b/donations/lib/src/main/res/drawable/donate_with_googlepay_button_content.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable/googlepay_button_background.xml b/donations/lib/src/main/res/drawable/googlepay_button_background.xml new file mode 100755 index 0000000000..b81005b06f --- /dev/null +++ b/donations/lib/src/main/res/drawable/googlepay_button_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/donations/lib/src/main/res/drawable/googlepay_button_content.xml b/donations/lib/src/main/res/drawable/googlepay_button_content.xml new file mode 100755 index 0000000000..b2cdb1d52b --- /dev/null +++ b/donations/lib/src/main/res/drawable/googlepay_button_content.xml @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/donations/lib/src/main/res/drawable/googlepay_button_no_shadow_background.xml b/donations/lib/src/main/res/drawable/googlepay_button_no_shadow_background.xml new file mode 100755 index 0000000000..9543c4bcb6 --- /dev/null +++ b/donations/lib/src/main/res/drawable/googlepay_button_no_shadow_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/donations/lib/src/main/res/drawable/googlepay_button_overlay.xml b/donations/lib/src/main/res/drawable/googlepay_button_overlay.xml new file mode 100755 index 0000000000..70c7a92271 --- /dev/null +++ b/donations/lib/src/main/res/drawable/googlepay_button_overlay.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/donations/lib/src/main/res/layout/donate_with_googlepay_button.xml b/donations/lib/src/main/res/layout/donate_with_googlepay_button.xml new file mode 100755 index 0000000000..797bf8fc52 --- /dev/null +++ b/donations/lib/src/main/res/layout/donate_with_googlepay_button.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/donations/lib/src/main/res/values/googlepay_strings.xml b/donations/lib/src/main/res/values/googlepay_strings.xml new file mode 100755 index 0000000000..81d01c2b74 --- /dev/null +++ b/donations/lib/src/main/res/values/googlepay_strings.xml @@ -0,0 +1,12 @@ + + + Google Pay + Buy with Google Pay + Donate With Google Pay + Pay With Google Pay + Subscribe With Google Pay + Book With Google Pay + Checkout With Google Pay + Order With Google Pay + View In Google Pay + \ No newline at end of file diff --git a/donations/lib/witness-verifications.gradle b/donations/lib/witness-verifications.gradle new file mode 100644 index 0000000000..e9e3cc120f --- /dev/null +++ b/donations/lib/witness-verifications.gradle @@ -0,0 +1,123 @@ +// Auto-generated, use ./gradlew calculateChecksums to regenerate + +dependencyVerification { + verify = [ + + ['androidx.activity:activity:1.0.0', + 'd1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d'], + + ['androidx.annotation:annotation:1.2.0', + '9029262bddce116e6d02be499e4afdba21f24c239087b76b3b57d7e98b490a36'], + + ['androidx.appcompat:appcompat-resources:1.2.0', + 'c470297c03ff3de1c3d15dacf0be0cae63abc10b52f021dd07ae28daa3100fe5'], + + ['androidx.appcompat:appcompat:1.2.0', + '3d2131a55a61a777322e2126e0018011efa6339e53b44153eb651b16020cca70'], + + ['androidx.arch.core:core-common:2.1.0', + 'fe1237bf029d063e7f29fe39aeaf73ef74c8b0a3658486fc29d3c54326653889'], + + ['androidx.arch.core:core-runtime:2.0.0', + '87e65fc767c712b437649c7cee2431ebb4bed6daef82e501d4125b3ed3f65f8e'], + + ['androidx.collection:collection:1.1.0', + '632a0e5407461de774409352940e292a291037724207a787820c77daf7d33b72'], + + ['androidx.core:core-ktx:1.5.0', + '5964cfe7a4882da2a00fb6ca3d3a072d04139208186f7bc4b3cb66022764fc42'], + + ['androidx.core:core:1.5.0', + '2b279712795689069cfb63e48b3ab63c32a5649bdda44c482eb8f81ca1a72161'], + + ['androidx.cursoradapter:cursoradapter:1.0.0', + 'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'], + + ['androidx.customview:customview:1.0.0', + '20e5b8f6526a34595a604f56718da81167c0b40a7a94a57daa355663f2594df2'], + + ['androidx.drawerlayout:drawerlayout:1.0.0', + '9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1'], + + ['androidx.fragment:fragment:1.1.0', + 'a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496'], + + ['androidx.interpolator:interpolator:1.0.0', + '33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a'], + + ['androidx.lifecycle:lifecycle-common:2.1.0', + '76db6be533bd730fb361c2feb12a2c26d9952824746847da82601ef81f082643'], + + ['androidx.lifecycle:lifecycle-livedata-core:2.0.0', + 'fde334ec7e22744c0f5bfe7caf1a84c9d717327044400577bdf9bd921ec4f7bc'], + + ['androidx.lifecycle:lifecycle-livedata:2.0.0', + 'c82609ced8c498f0a701a30fb6771bb7480860daee84d82e0a81ee86edf7ba39'], + + ['androidx.lifecycle:lifecycle-runtime:2.1.0', + 'e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b'], + + ['androidx.lifecycle:lifecycle-viewmodel:2.1.0', + 'ba55fb7ac1b2828d5327cda8acf7085d990b2b4c43ef336caa67686249b8523d'], + + ['androidx.loader:loader:1.0.0', + '11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'], + + ['androidx.savedstate:savedstate:1.0.0', + '2510a5619c37579c9ce1a04574faaf323cd0ffe2fc4e20fa8f8f01e5bb402e83'], + + ['androidx.vectordrawable:vectordrawable-animated:1.1.0', + '76da2c502371d9c38054df5e2b248d00da87809ed058f3363eae87ce5e2403f8'], + + ['androidx.vectordrawable:vectordrawable:1.1.0', + '46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26'], + + ['androidx.versionedparcelable:versionedparcelable:1.1.1', + '57e8d93260d18d5b9007c9eed3c64ad159de90c8609ebfc74a347cbd514535a4'], + + ['androidx.viewpager:viewpager:1.0.0', + '147af4e14a1984010d8f155e5e19d781f03c1d70dfed02a8e0d18428b8fc8682'], + + ['com.google.android.gms:play-services-base:17.5.0', + '198c9e2115f5ce5f91140cd9b481dc6d64dd634ac2d6c6525567dc5fe00065cb'], + + ['com.google.android.gms:play-services-basement:17.5.0', + '362301c0da1c765cbbdcf8ea866b6cb62bc130c86d2aa7cc9e9c18a6e51ea79d'], + + ['com.google.android.gms:play-services-identity:17.0.0', + '8987c6c303eaaa9c10c403822cf5ae188ee1ce61c3056eb3be2ca4aaecc80b5f'], + + ['com.google.android.gms:play-services-maps:17.0.0', + 'f9e479bc57ff423959c6dd9d08d463c677f440e29d90de795418ea27da6c67fb'], + + ['com.google.android.gms:play-services-tasks:17.2.0', + 'a131d126145dfe87de04fa904f9ce91753b2d3273851b7d084666a71255792a8'], + + ['com.google.android.gms:play-services-wallet:18.1.3', + 'e19d1f4650f51ce2202c092cbe174058860b6558cf26c8be37a732eff3ae1864'], + + ['com.google.protobuf:protobuf-javalite:3.10.0', + '215a94dbe100130295906b531bb72a26965c7ac8fcd9a75bf8054a8ac2abf4b4'], + + ['com.squareup.okhttp3:okhttp:3.12.10', + '3cb8e21cd3ab10d390448f5a475c960732efab583a09c39f06f866a7ed819ebc'], + + ['com.squareup.okio:okio:1.15.0', + '693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2'], + + ['io.reactivex.rxjava3:rxjava:3.0.13', + '598abaf71dbc970dd0727e6d5f4f786dc999df5b972cbf261316a32e155b2c69'], + + ['org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32', + 'e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145'], + + ['org.jetbrains.kotlin:kotlin-stdlib:1.4.32', + '13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba'], + + ['org.jetbrains:annotations:13.0', + 'ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478'], + + ['org.reactivestreams:reactive-streams:1.0.3', + '1dee0481072d19c929b623e155e14d2f6085dc011529a0a0dbefc84cf571d865'], + ] +} diff --git a/settings.gradle b/settings.gradle index a707d93496..4c304474f8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,8 @@ include ':device-transfer' include ':device-transfer-app' include ':image-editor' include ':image-editor-app' +include ':donations' +include ':donations-app' project(':app').name = 'Signal-Android' project(':paging').projectDir = file('paging/lib') @@ -24,6 +26,9 @@ project(':libsignal-service').projectDir = file('libsignal/service') project(':image-editor').projectDir = file('image-editor/lib') project(':image-editor-app').projectDir = file('image-editor/app') +project(':donations').projectDir = file('donations/lib') +project(':donations-app').projectDir = file('donations/app') + rootProject.name='Signal' apply from: 'dependencies.gradle'