Issue with google Reseller API sending batch requests - google-reseller-api

In a special scenario wherein the resold customer who is using Google Vault, GoogleDrive along with Google Apps for Business, and to transfer that customer, as per the documentation (Ref https://developers.google.com/admin-sdk/reseller/v1/how-tos/batch) we're supposed to use Batch Subscription Ordering.
Here is what we're observing so far:
When we try to transfer resold customer which has only one subscription “Google-Apps-For-Business”
a. Then the Batch Ordering (even though its not required) is working.
However when we have to transfer resold customer who has more than on subscription such as “Google-Apps-for-Business” and one or more of “Google Vault”, “Google drive”
a. If we send all features request with Batch Order, the call retunes Error Code: 500 (Internal Server Error)
b. If we send only one request (even though it is wrong as per the documentation) in the Batch Order (the Google-apps-for-business), the call returns expected Error Code: 412 (Precondition Failed): The domain has subscriptions which need to be transferred.
We also tried based on the Google Calendar API Example (Ref https://developers.google.com/admin-sdk/reseller/v1/how-tos/batch) but it also results in the same failure.
Both above suggests either the documentation is wrong or the API doesn't work as per the documentation.
Does anyone have a suggestion?
Here is the sample code
// based on https://code.google.com/p/google-api-java-client/wiki/Batch sample code
Reseller reseller = Reseller.Builder(httpTransport, jsonFactory, credential).setApplicationName("RedResellerAccountSample").build();
JsonBatchCallback<Subscription>; callback = new JsonBatchCallback<Subscription>() {
#Override
public void onSuccess(Subscription t,
HttpHeaders responseHeaders) throws IOException {
// TODO Auto-generated method stub
System.out.println("Success");
}
#Override
public void onFailure(GoogleJsonError e,
HttpHeaders responseHeaders) throws IOException {
// TODO Auto-generated method stub
System.out.println("Failure");
}
};
BatchRequest batchRequest = reseller.batch();
Subscription sub = new Subscription();
sub.setKind("subscriptions#subscription");
sub.setCustomerId("testdomain.com");
Subscription.Plan plan = new Subscription.Plan();
plan.setPlanName("TRIAL");
Seats seats = new Seats();
seats.setKind("subscriptions#seats");
seats.setMaximumNumberOfSeats(10);
sub.setPlan(plan);
sub.setSeats(seats);
sub.setSkuId("Google-Apps-For-Business");
reseller.subscriptions().insert("testdomain.com",sub).setCustomerAuthToken("B40D2EFF4316B703").queue(batchRequest, callback);
Subscription sub2 = new Subscription();
sub2.setKind("subscriptions#subscription");
sub2.setCustomerId("testdomain.com");
Subscription.Plan plan2 = new Subscription.Plan();
plan2.setPlanName("TRIAL");
Seats seats2 = new Seats();
seats2.setKind("subscriptions#seats");
seats2.setMaximumNumberOfSeats(10);
sub2.setPlan(plan);
sub2.setSeats(seats);
sub2.setSkuId("Google-Vault");
reseller.subscriptions().insert("testdomain.com",sub2).setCustomerAuthToken("B40D2EFF4316B703").queue(batchRequest, callback);
//System.out.println(new ObjectMapper().writeValueAsString(batchRequest);
// if we call it fail as we have more than one request queued in the
batchRequest.execute();

Related

Web Drop-in integration "advanced use case" redirect result

I'm trying to understand if it's possible to retrieve the redirectResult when the user is redirected to our redirectUrl to invoke the /payment/details API endpoint to speed up delivering virtual goods instead of waiting for the web hook (I'm aware it will not work for "async" payment methods).
Looking at https://docs.adyen.com/online-payments/web-drop-in/advanced-use-cases/redirect-result it should be possible, however, the returnUrl in CreateCheckoutSessionResponse returned from com.adyen.service.Checkout#sessions (adyen-java-api-library 17.2.0 - checkout api version v68) does not contain the aforementioned redirectResult param so the configuration we pass into the drop-in template is missing this data and does not seem to be available in the onPaymentCompleted callback either (only resultCode and sessionData).
#Override
public RedirectResponse handleRedirectToPartner(PaymentContext paymentContext) throws PartnerIntegrationException {
final Payment payment = paymentContext.getPayment();
final Amount amount = new Amount();
amount.setCurrency(payment.getCurrency().toUpperCase());
amount.setValue((long) payment.getPriceInCents());
final CreateCheckoutSessionRequest checkoutSessionRequest = new CreateCheckoutSessionRequest();
...
checkoutSessionRequest.setChannel(CreateCheckoutSessionRequest.ChannelEnum.WEB);
checkoutSessionRequest.setReturnUrl(getReturnUrl());
try {
CreateCheckoutSessionResponse checkoutSessionResponse = checkout().sessions(checkoutSessionRequest);
JSONObject params = new JSONObject();
params.put("environment", testMode ? "test" : "live");
params.put("clientKey", adyenClientKey);
JSONObject session = new JSONObject();
session.put("id", checkoutSessionResponse.getId());
session.put("sessionData", checkoutSessionResponse.getSessionData());
params.put("session", session);
params.put("urlKo", getFailureUrl());
params.put("urlOk", checkoutSessionResponse.getReturnUrl());
params.put("urlPending", getUrlPending(checkoutSessionResponse.getReturnUrl()));
return new RedirectResponse(RedirectResponse.Type.REDIRECT_CUSTOM_HTML_ADYEN, null, params);
} catch (ApiException | IOException e) {
throw new PartnerIntegrationException("Failed creating Adyen session", e);
}
}
protected Checkout checkout() {
return new Checkout(new Client(adyenApiKey, testMode ? Environment.TEST : Environment.LIVE,
testMode ? null : liveEndpointUrlPrefix));
}
(async () => {
let configuration = ${partnerJsonParameters?string};
configuration.onPaymentCompleted = function(result, component) {
console.info(result);
if (result.sessionData) {
console.info(result.sessionData);
}
if (result.resultCode) {
console.info(result.resultCode);
}
handleServerResponse(result, configuration);
};
configuration.onError = function(error, component) {
console.error(error, component);
handleServerResponse(result, configuration);
};
let checkout = await AdyenCheckout(configuration);
checkout.create('dropin').mount('#dropin-container');
})();
The sessions request does not perform the payment, but only initiates the payment session with all required parameters and configuration.
The Web drop-in takes care of 'talking' to the Adyen backend and eventually, the payment outcome can be obtained in the frontend using the onPaymentCompleted handler.
onPaymentCompleted: (result, component) => {
console.info("onPaymentCompleted: " + result.resultCode);
...
}
See Use the result code
On the server-side it is possible to get the payment result with a /payments/details call in addition to /sessions if needed.
// get redirectResult appended to the returnUrl
String redirectResult = request.getParameter("redirectResult");
var paymentDetails = new PaymentsDetailsRequest();
paymentDetails.setDetails(Collections.singletonMap("redirectResult", redirectResult));
// use paymentDetails() method
var paymentsDetailsResponse = checkout.paymentsDetails(paymentDetails);
String resultCode = paymentsDetailsResponse.getResultCode();
Note that a synchronous result is not always available, hence relying on the webhook is best.
I'm the (non-developer) colleague testing with PAL enable and sadly the delay is way too long with them as well. It is crucial for us to be able to get trustworthy authorisation and deliver the goods for the customers in (tens of) seconds, not minutes.
Is there any way to achieve fast and trustworthy credit card transactions with your web drop-in without notifications?
This is possible with your soon-to-be-obsoleted HPP integration and I find it unbelievable that you could have impaired, worsen the integration and user experience. So, there must be some kind of misunderstanding and communication breakdown somewhere (I hope). :)
Sorry, could not just comment as I don't have enough reputation...

How To Create Test Facebook Ads || How to Get Android Advertisement ID (AAID) programmatically?

How to create Test Device to Facebook Ads >> To Create Test Device you need Enter a device ID (IDFA, AAID):
sometimes we need to get the android advertisement id AAID for android device, when we place google ads or Facebook ads to our Android app or any other functions we need to place the unique AAID for testing purpose.
For Kotlin code
Thread{
AdvertisingIdClient.getAdvertisingIdInfo(activity).id?.let {
Log.i("myId",it)
}
}.start()
The first Step, get AdvertisingIdClient
public class AdvertisingIdClient extends Object
Helper library for retrieval of advertising ID and related information such as the limit ad tracking setting.
It is intended that the advertising ID completely replace existing usage of other identifiers for ads purposes (such as use of ANDROID_ID in Settings.Secure) when Google Play Services is available. Cases, where Google Play Services is unavailable, are indicated by a GooglePlayServicesNotAvailableException being thrown by getAdvertisingIdInfo().
Code >>>
#SuppressLint("StaticFieldLeak")
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String token = null;
AdvertisingIdClient.Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
} catch (IOException | GooglePlayServicesRepairableException | GooglePlayServicesNotAv
// ...
MessageLog.setLogCat("DEVICE_ID",""+e);
}
String android_id = adInfo.getId();
MessageLog.setLogCat("DEVICE_ID",android_id);
return android_id;
}
#Override
protected void onPostExecute(String token) {
MessageLog.setLogCat("DEVICE_ID","DEVICE_ID Access token retrieved:" + token);
}
};
task.execute();
Open Your Logcate of android studio
you will get Result like it
2020-07-23 19:32:37.225 19041-19093/com.packagename.example I/DEVICE_ID :: 1aaf7707-22b5-4627-xxx-xxxxxxxx
2020-07-23 19:32:37.738 19041-19041/com.packagename.example I/DEVICE_ID :: DEVICE_ID Access token retrieved:1aaf7707-22b5-4627-xxx-xxxxxxxx
1aaf7707-22b5-4627-xxx-xxxxxxxx is your device ID
Second Step: Open your Facebook Monetization Manager
write your device id in a device ID (IDFA, AAID): EditText and Write Name Device like the image.
The following code snippet might help lot of you in current cases.
Add this method in your code:
fun getIdThread() {
var adInfo: AdvertisingIdClient.Info? = null
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(this)
} catch (e: IOException) {
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (e: GooglePlayServicesAvailabilityException) {
// Encountered a recoverable error connecting to Google Play services.
} catch (e: GooglePlayServicesNotAvailableException) {
// Google Play services is not available entirely.
}
val id: String = adInfo?.id.orEmpty()
val isLAT: Boolean = adInfo?.isLimitAdTrackingEnabled?.orFalse() == true
}
And call from separate thread as like below.
Thread{
getIdThread()
}.start()
This simple snippet will give you the AD ID. Even if the user resets the advertising ID.
Note: [Don't forget to declare ad ID permission in your manifest]

laravel queue (retry jobs 5 times) & mark job as failed "manually"

I've got a queue running some callback requests to endpoint of my users.
Here's the code of my queue.
public function handle()
{
//send webrequest here....
//check the response of user backend
if ($res->getStatusCode() != 200 || $res->getBody()->getContents() != "*received*")
throw new Exception('callback url not reachable');
}
public function failed(Exception $exception)
{
//check tries and try again if needed
//check if job failed for 5 times
//if not ->retry again in 5 minutes, increment the times tried
//if yes ->disable API access, send email
Log::info("user email send, callback disabled!");
}
How to let the job fail (my current exception makes the whole job end), when webrequest answer is != "received" and check if the certain job failed 5 times?
If a job failed it should be tried again in 5 minutes.
I don't understand the doc regarding these points.
I know it's too late but yesterday I had the same problem with the queue and when I throw a new exception the queue run it again and again until my VM hanged up. actually, you did right the only thing you have to add to your code is define a tries variable to the public area of your job class and it should run only for example 5 times and pushed to failed job ;)
class NewCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;
.
.
.

Real Time Google Fit Sessions

I'm working on a fitness activity tracker app, and I have a couple questions regarding the Google Fit Sessions API.
From the Google Fit Session guide, if we want to create a session with real time data, we need to specify start-time using the method Session.Builder.setStartTime(long,TimeUnit), and then we call the method startSession.
Question 1: Can we set the end time for that session if we're using the real time data? If we've already defined the endTime, do we still need to call the stopSession method?
In the documentation, a sample session is created with a specified start-time and end-time, and then sample data are added to that session.
Question 2: How would you create a SessionInsertRequest on sessions with real time data? How can we get a real time recorded DataSet from the DataSource to use in the SessionInsertRequest.Builder.addDataSet(DataSet) method?
Question 3: I already have this method to find my DataSources; do I still need to create a new DataSource object to get a DataSet object (as answered in this thread: DataSet Object for the Google Fit API)?
The method:
private void findFitnessDataSources() {
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
.setDataSourceTypes(DataSource.TYPE_DERIVED)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
#Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_DELTA)
&& mListener == null) {
Log.i(TAG, "Data source for LOCATION_SAMPLE found! Registering.");
registerFitnessDataListener(dataSource,
DataType.TYPE_STEP_COUNT_DELTA);
}
}
}
});
//just temporarily return datasource for testing purpose
}
Question 4: How do I modify my method to return the dataSource(s) to use in the Session Builder?
Thank you.

How to count all HTTP requests sent, retries in?

Some use cases require being able to count the requests sent by the Apache API. For example, when massively requesting a web API, which API requires an authentication through an API key, and which TOS limits the requests count in time for each key.
Being more specific on the case, I'm requesting https://domain1/fooNeedNoKey, and depending on its response analyzed data, I request https://domain2/fooNeedKeyWithRequestsCountRestrictions. All sends of those 1-to-2-requests sequences, are performed through a single org.apache.http.impl.client.FutureRequestExecutionService.
As of now, depending on org.apache.httpcomponents:httpclient:4.3.3, I'm using those API elements:
org.apache.http.impl.client.FutureRequestExecutionService, to perform multi-threaded HTTP requests. It offers time metrics (how much time did an HTTP thread took until terminated), but no requests counter metrics
final CloseableHttpClient httpClient = HttpClients.custom()
// the auto-retry feature of the Apache API will retry up to 5
// times on failure, being also allowed to send again requests
// that were already sent if necessary (I don't really understand
// the purpose of the second parameter below)
.setRetryHandler(new StandardHttpRequestRetryHandler(5, true))
// for HTTP 503 'Service unavailable' errors, also retrying up to
// 5 times, waiting 500ms between each retry. Guessed is that those
// 5 retries are part of the previous "global" 5 retries setting.
// The below setting, when used alone, would allow to only enable
// retries for HTTP 503, or to get a greater count of retries for
// this specific error
.setServiceUnavailableRetryStrategy(new DefaultServiceUnavailableRetryStrategy(5, 500))
.build();, which customizes the Apache API retry behavior
Getting back to the topic :
A request counter could be created by extending the Apache API retry-related classes quoted before
Alternatively, an Apache API support unrelated ticket tends to indicate this requests-counter metrics could be available and forwarded out of the API, into Java NIO
Edit 1:
Looks like the Apache API won't permit this to be done.
Quote from the inside of the API, RetryExec not beeing extendable in the API code I/Os:
package org.apache.http.impl.execchain;
public class RetryExec implements ClientExecChain {
..
public CloseableHttpResponse execute(
final HttpRoute route,
final HttpRequestWrapper request,
final HttpClientContext context,
final HttpExecutionAware execAware) throws IOException, HttpException {
..
for (int execCount = 1;; execCount++) {
try {
return this.requestExecutor.execute(route, request, context, execAware);
} catch (final IOException ex) {
..
if (retryHandler.retryRequest(ex, execCount, context)) {
..
}
..
}
}
The 'execCount' variable is the needed info, and it can't be accessed since it's only locally used.
As well, one can extend 'retryHandler', and manually count requests in it, but 'retryHandler.retryRequest(ex, execCount, context)' is not provided with the 'request' variable, making it impossible to know on what we're incrementing a counter (one may only want to increment the counter for requests sent to a specific domain).
I'm out of Java ideas for it. A 3rd party alternative: having the Java process polling a file on disk, managed by a shell script counting the desired requests. Sure it will make a lot of disk read-accesses and will be a hardware killer option.
Ok, the work around was easy, the HttpContext class of the API is intended for this:
// optionnally, in case your HttpCLient is configured for retry
class URIAwareHttpRequestRetryHandler extends StandardHttpRequestRetryHandler {
public URIAwareHttpRequestRetryHandler(final int retryCount, final boolean requestSentRetryEnabled)
{
super(retryCount, requestSentRetryEnabled);
}
#Override
public boolean retryRequest(final IOException exception, final int executionCount, final HttpContext context)
{
final boolean ret = super.retryRequest(exception, executionCount, context);
if (ret) {
doForEachRequestSentOnURI((String) context.getAttribute("requestURI"));
}
return ret;
}
}
// optionnally, in addition to the previous one, in case your HttpClient has specific settings for the 'Service unavailable' errors retries
class URIAwareServiceUnavailableRetryStrategy extends DefaultServiceUnavailableRetryStrategy {
public URIAwareServiceUnavailableRetryStrategy(final int maxRetries, final int retryInterval)
{
super(maxRetries, retryInterval);
}
#Override
public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context)
{
final boolean ret = super.retryRequest(response, executionCount, context);
if (ret) {
doForEachRequestSentOnURI((String) context.getAttribute("requestURI"));
}
return ret;
}
}
// main HTTP querying code: retain the URI in the HttpContext to make it available in the custom retry-handlers code
httpContext.setAttribute("requestURI", httpGET.getURI().toString());
try {
httpContext.setAttribute("requestURI", httpGET.getURI().toString());
httpClient.execute(httpGET, getHTTPResponseHandlerLazy(), httpContext);
// if request got successful with no need of retries, of if it succeeded on the last send: in any cases, this is the last query sent to server and it got successful
doForEachRequestSentOnURI(httpGET.getURI().toString());
} catch (final ClientProtocolException e) {
// if request definitively failed after retries: it's the last query sent to server, and it failed
doForEachRequestSentOnURI(httpGET.getURI().toString());
} catch (final IOException e) {
// if request definitively failed after retries: it's the last query sent to server, and it failed
doForEachRequestSentOnURI(httpGET.getURI().toString());
} finally {
// restoring the context as it was initially
httpContext.removeAttribute("requestURI");
}
Solved.