kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add RedeemReceiptRequest object and DonationService.
rodzic
891dfc1b68
commit
7f3ba1978d
|
@ -48,6 +48,7 @@ import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
|||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.services.DonationsService;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
|
@ -104,6 +105,7 @@ public class ApplicationDependencies {
|
|||
private static volatile GiphyMp4Cache giphyMp4Cache;
|
||||
private static volatile SimpleExoPlayerPool exoPlayerPool;
|
||||
private static volatile AudioManagerCompat audioManagerCompat;
|
||||
private static volatile DonationsService donationsService;
|
||||
|
||||
@MainThread
|
||||
public static void init(@NonNull Application application, @NonNull Provider provider) {
|
||||
|
@ -590,6 +592,17 @@ public class ApplicationDependencies {
|
|||
return audioManagerCompat;
|
||||
}
|
||||
|
||||
public static @NonNull DonationsService getDonationsService() {
|
||||
if (donationsService == null) {
|
||||
synchronized (LOCK) {
|
||||
if (donationsService == null) {
|
||||
donationsService = provider.provideDonationsService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return donationsService;
|
||||
}
|
||||
|
||||
public interface Provider {
|
||||
@NonNull GroupsV2Operations provideGroupsV2Operations();
|
||||
@NonNull SignalServiceAccountManager provideSignalServiceAccountManager();
|
||||
|
@ -625,5 +638,6 @@ public class ApplicationDependencies {
|
|||
@NonNull GiphyMp4Cache provideGiphyMp4Cache();
|
||||
@NonNull SimpleExoPlayerPool provideExoPlayerPool();
|
||||
@NonNull AudioManagerCompat provideAndroidCallAudioManager();
|
||||
@NonNull DonationsService provideDonationsService();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
|||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.services.DonationsService;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||
|
@ -301,6 +302,15 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
|
|||
return AudioManagerCompat.create(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull DonationsService provideDonationsService() {
|
||||
return new DonationsService(provideSignalServiceNetworkAccess().getConfiguration(context),
|
||||
new DynamicCredentialsProvider(context),
|
||||
BuildConfig.SIGNAL_AGENT,
|
||||
provideGroupsV2Operations(),
|
||||
FeatureFlags.okHttpAutomaticRetry());
|
||||
}
|
||||
|
||||
private @NonNull WebSocketFactory provideWebSocketFactory(@NonNull SignalWebSocketHealthMonitor healthMonitor) {
|
||||
return new WebSocketFactory() {
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.whispersystems.signalservice.api.services;
|
||||
|
||||
import org.signal.zkgroup.receipts.ReceiptCredentialPresentation;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.internal.EmptyResponse;
|
||||
import org.whispersystems.signalservice.internal.ServiceResponse;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
||||
|
||||
import io.reactivex.rxjava3.core.Scheduler;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* One-stop shop for Signal service calls related to donations.
|
||||
*/
|
||||
public class DonationsService {
|
||||
private final PushServiceSocket pushServiceSocket;
|
||||
|
||||
public DonationsService(
|
||||
SignalServiceConfiguration configuration,
|
||||
CredentialsProvider credentialsProvider,
|
||||
String signalAgent,
|
||||
GroupsV2Operations groupsV2Operations,
|
||||
boolean automaticNetworkRetry
|
||||
) {
|
||||
this.pushServiceSocket = new PushServiceSocket(configuration, credentialsProvider, signalAgent, groupsV2Operations.getProfileOperations(), automaticNetworkRetry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a user to redeem a given receipt they were given after submitting a donation successfully.
|
||||
*
|
||||
* @param receiptCredentialPresentation Receipt
|
||||
* @param visible Whether the badge will be visible on the user's profile immediately after redemption
|
||||
* @param primary Whether the badge will be made primary immediately after redemption
|
||||
*/
|
||||
public Single<ServiceResponse<EmptyResponse>> redeemReceipt(ReceiptCredentialPresentation receiptCredentialPresentation, boolean visible, boolean primary) {
|
||||
return Single.fromCallable(() -> {
|
||||
try {
|
||||
pushServiceSocket.redeemDonationReceipt(receiptCredentialPresentation, visible, primary);
|
||||
return ServiceResponse.forResult(EmptyResponse.INSTANCE, 200, null);
|
||||
} catch (Exception e) {
|
||||
return ServiceResponse.<EmptyResponse>forUnknownError(e);
|
||||
}
|
||||
}).subscribeOn(Schedulers.io());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package org.whispersystems.signalservice.internal;
|
||||
|
||||
/**
|
||||
* Indicates that no data is returned from a given service call.
|
||||
*/
|
||||
public enum EmptyResponse {
|
||||
INSTANCE
|
||||
}
|
|
@ -25,6 +25,7 @@ import org.signal.zkgroup.profiles.ProfileKeyCredentialRequest;
|
|||
import org.signal.zkgroup.profiles.ProfileKeyCredentialRequestContext;
|
||||
import org.signal.zkgroup.profiles.ProfileKeyCredentialResponse;
|
||||
import org.signal.zkgroup.profiles.ProfileKeyVersion;
|
||||
import org.signal.zkgroup.receipts.ReceiptCredentialPresentation;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
import org.whispersystems.libsignal.logging.Log;
|
||||
|
@ -134,7 +135,6 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -233,6 +233,8 @@ public class PushServiceSocket {
|
|||
private static final String SUBMIT_RATE_LIMIT_CHALLENGE = "/v1/challenge";
|
||||
private static final String REQUEST_RATE_LIMIT_PUSH_CHALLENGE = "/v1/challenge/push";
|
||||
|
||||
private static final String DONATION_REDEEM_RECEIPT = "/v1/donation/redeem-receipt";
|
||||
|
||||
private static final String REPORT_SPAM = "/v1/messages/report/%s/%s";
|
||||
|
||||
private static final String SERVER_DELIVERED_TIMESTAMP_HEADER = "X-Signal-Timestamp";
|
||||
|
@ -862,6 +864,11 @@ public class PushServiceSocket {
|
|||
makeServiceRequest(SUBMIT_RATE_LIMIT_CHALLENGE, "PUT", payload);
|
||||
}
|
||||
|
||||
public void redeemDonationReceipt(ReceiptCredentialPresentation receiptCredentialPresentation, boolean visible, boolean primary) throws IOException {
|
||||
String payload = JsonUtil.toJson(new RedeemReceiptRequest(Base64.encodeBytesToBytes(receiptCredentialPresentation.serialize()), visible, primary));
|
||||
makeServiceRequest(DONATION_REDEEM_RECEIPT, "PUT", payload);
|
||||
}
|
||||
|
||||
public List<ContactTokenDetails> retrieveDirectory(Set<String> contactTokens)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException
|
||||
{
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.signal.zkgroup.receipts.ReceiptCredentialPresentation;
|
||||
import org.whispersystems.libsignal.util.guava.Preconditions;
|
||||
|
||||
/**
|
||||
* POST /v1/donation/redeem-receipt
|
||||
*
|
||||
* Request object for redeeming a receipt from a donation transaction.
|
||||
*/
|
||||
class RedeemReceiptRequest {
|
||||
|
||||
private final byte[] receiptCredentialPresentation;
|
||||
private final boolean visible;
|
||||
private final boolean primary;
|
||||
|
||||
/**
|
||||
* @param receiptCredentialPresentation base64-encoded no-newlines standard-character-set with-padding of the bytes of a {@link ReceiptCredentialPresentation} object
|
||||
* @param visible boolean indicating if the new badge should be visible or not on the profile
|
||||
* @param primary boolean indicating if the new badge should be primary or not on the profile; is always treated as false if `visible` is false
|
||||
*/
|
||||
@JsonCreator
|
||||
RedeemReceiptRequest(
|
||||
@JsonProperty("receiptCredentialPresentation") byte[] receiptCredentialPresentation,
|
||||
@JsonProperty("visible") boolean visible,
|
||||
@JsonProperty("primary") boolean primary) {
|
||||
|
||||
Preconditions.checkArgument(receiptCredentialPresentation.length == ReceiptCredentialPresentation.SIZE);
|
||||
|
||||
this.receiptCredentialPresentation = receiptCredentialPresentation;
|
||||
this.visible = visible;
|
||||
this.primary = primary;
|
||||
}
|
||||
|
||||
public byte[] getReceiptCredentialPresentation() {
|
||||
return receiptCredentialPresentation;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
public boolean isPrimary() {
|
||||
return primary;
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue