Make a subscription purchase with a developer payload using com.android.billingclient.api - play-billing-library

I'm working on migrating from https://github.com/serso/android-checkout lib to com.android.billingclient.api, the Checkout API allowed me to start the purchase flow by providing a develop payload as a parameter. like is shown below
/**
* #see #startPurchaseFlow(String, String, String, RequestListener)
*/
public void startPurchaseFlow(Sku sku, #Nullable String payload, RequestListener<Purchase> listener) {
startPurchaseFlow(sku, payload, null, listener);
}
Later I would be able to retrieve the same developer payload while getting Purchase History.
Now working with com.android.billingclient.api I see that I can provide the a developer payload, looking at the code I see that in the BillingClientImpl of com.android.billingclient.api class the payload just provide as a null value
futureBuyIntentBundle =
executeAsync(
new Callable<Bundle>() {
#Override
public Bundle call() throws Exception {
return mService.getBuyIntent(
/* apiVersion */ 3,
mApplicationContext.getPackageName(),
newSku,
skuType,
/* developerPayload */ null);
}
});
I'm wondering if it's a bug, or there is another way to store a developer payload within a purchase record.

You're right. Play Billing Library didn't support developer payload in prior 2.0 version. See https://issuetracker.google.com/issues/69079764.
Since 2.0, this is added back, but is moved to consume/acknowledge phase:
https://developer.android.com/google/play/billing/billing_library_releases_notes#2_0_payload

Related

How to use libmosquitto to make a request and get response using MQTT v5?

I'm trying to use libmosquitto to make a request (publish to a 'test/topic' topic) and I want to get a response based on the client (sender) id. So that means the client will publish to 'test/topic' and it will automatically subscribe 'test/topic/<client_id>'
The server has already subscribed on 'test/topic' and when it becomes the message, it will send a response (publish) to 'test/topic/<client_id>', which the client subscribed to receive that response in the first place.
The challenge here is how do I get the <client_id>, right. I already done this in python and js, where the client will send metadata or properties in the payload, which the server can unpack to get the client_id. However, I'm using C++ now and it's frustrating because I can't figure out how to get these properties.
Here is an example of how to do this in python. I just want to do the same with c++
I'm using the libmosquitto as I mentionned. I don't even have an example to show because I didn't find how to do this. There is literally no example on how to do this with the mosquitto c++ lib (which is confusing since mosquitto is a famous lib I guess).
I hope someone had a similar problem or can post an example for c++ and mosquitto lib. Thanks in advance.
When in doubt, look at the tests:
const char *my_client_id = ...;
mosquitto_property *proplist = NULL;
mosquitto_property_add_string_pair(&proplist, MQTT_PROP_USER_PROPERTY, "client_id", my_client_id);
mosquitto_publish_v5(mosq, &sent_mid, "test/topic", strlen("message"), "message", 0, false, proplist);
mosquitto_property_free_all(&proplist);
Since you asked in the comments, you can retrieve these properties from published messages by first setting an on_message callback using mosquitto_message_v5_callback_set and the implementing it like so:
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message, const mosquitto_property *props) {
std::string topic{message->topic};
if (topic == "test/topic") {
const char *client_id = nullptr;
mosquitto_property_read_string_pair(props, MQTT_PROP_USER_PROPERTY, nullptr, &client_id, false);
if (client_id) {
/* client_id contains a client id. */
}
}

Setting JMSMessageID on stubbed jms endpoints in camel unit tests

I have a route that I am testing. I use stub://jms:queue:whatever to send/receive messages and extending CamelTestSupport for my test classes. I am having an issue with one of the routes that has a bean that uses an idempotent repo to store messages by "message id" for which it reads and stores the JMSMessageID property from exchange.
The problem I run into is that I can't figure out a way to set this property on messages sent on stubbed endpoints. Every time the method that requires this prop is called, the id returns null and i have to handle it as a null pointer. I can do this but the cleanest approach would be to just set the header on the test message. I tried includeSentJMSMessageId=true on endpoint, I tried using sendBodyAndHeader on producer and passing "JMSMessageID", "ID: whatever" in arguments, doesn't appear to work? I read that the driver/connectionfactory is supposed to set the header, but I'm not too familiar with how/where to do this. And since I am using a stubbed end points, I'm not creating any brokers/connectionfactories in my uts.
So dont stud out the JMS component replace it with a processor and then add the preferred JMSMessageID in the processor.
Something like this code:
#Test
void testIdempotency() throws Exception {
mockOut.expectedMinimumMessageCount(1);
//specify the route to test
AdviceWithRouteBuilder.adviceWith(context, "your-route-name", enrichRoute -> {
//replace the from with a end point we can call directly.
enrichRoute.replaceFromWith("direct:start");
//replace the jms endpoint with a processor so it can act as the JMS Endpoint.
enrichRoute.weaveById("jms:queue:whatever").replace().process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
//Set that ID to the one I want to test
exchange.getIn().setHeader("JMSMEssageID", "some-value-to-test");
}
});
// add an endpoint at the end to check if received a mesage
enrichRoute.weaveAddLast().to(mockOut);
});
context.start();
//send some message
Map<String,Object> sampleMsg = getSampleMessageAsHashMap("REQUEST.json");
//get the response
Map<String,Object> response = (Map<String,Object>)template.requestBody("direct:start", sampleMsg);
// you will need to check if the response is what you expected.
// Check the headers etc.
mockOut.assertIsSatisfied();
}
The JMSMessageID can only be set by the provider. It cannot be set by a client despite the fact that javax.jms.Message has setJMSMessageId(). As the JavaDoc states:
This method is for use by JMS providers only to set this field when a message is sent. This message cannot be used by clients to configure the message ID. This method is public to allow a JMS provider to set this field when sending a message whose implementation is not its own.

What should be the best way to filter the kafka message

I'm consuming data from a kafka topic which includes the area code. I have to filter the data only for certain area codes. Can any one suggest be the best approach to solve this.
Here is my listener code looks like. Is it best practice to parse the data into object(as I mapped the payload to a TEST object) and filter the data based on the value which I need to filter or Does kafka provides any other libraries which I can make use of this filtering process.
Kafka Listener Method
#Service
public class Listener{
#KafkaListener(topics = "#{#topicName}")
public void listen(String payload) throws IOException {
LOGGER.info("received payload from topic='{}'", payload);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
TEST test = objectMapper.readValue(payload,TEST.class);
}
}
My Kafka Configuration class:
#Configuration
public class Config {
#Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> properties = new HashMap<>();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, applicationConfiguration.getKafkaBootStrap());
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, applicationConfiguration.getKafkaKeyDeserializer());
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, applicationConfiguration.getKafkaValueDeserializer());
properties.put(ConsumerConfig.GROUP_ID_CONFIG, applicationConfiguration.getKafkaGroupId());
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, applicationConfiguration.getKafkaAutoOffsetReset());
return properties;
}
#Bean
public ConsumerFactory<String, String> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}
#Bean
public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
#Bean
public Listener receiver() {
return new Listener();
}
}
See Filtering Messages.
The Spring for Apache Kafka project also provides some assistance by means of the FilteringMessageListenerAdapter class, which can wrap your MessageListener. This class takes an implementation of RecordFilterStrategy in which you implement the filter method to signal that a message is a duplicate and should be discarded. This has an additional property called ackDiscarded, which indicates whether the adapter should acknowledge the discarded record. It is false by default.
When you use #KafkaListener, set the RecordFilterStrategy (and optionally ackDiscarded) on the container factory so that the listener is wrapped in the appropriate filtering adapter.
/**
* Set the record filter strategy.
* #param recordFilterStrategy the strategy.
*/
public void setRecordFilterStrategy(RecordFilterStrategy<? super K, ? super V> recordFilterStrategy) {
this.recordFilterStrategy = recordFilterStrategy;
}
/**
* Implementations of this interface can signal that a record about
* to be delivered to a message listener should be discarded instead
* of being delivered.
*
* #param <K> the key type.
* #param <V> the value type.
*
* #author Gary Russell
*
*/
public interface RecordFilterStrategy<K, V> {
/**
* Return true if the record should be discarded.
* #param consumerRecord the record.
* #return true to discard.
*/
boolean filter(ConsumerRecord<K, V> consumerRecord);
}
What you did is alright.
If your payload has a lot of data besides the area code and you worry about long parsing, you can filter the messages before doing the whole parsing to TEST object by adding the area code as a header.
Later versions of Kafka (after 0.11) offers custom headers (KIP-82)
If you want to implement it by yourself (or if you use older version of Kafka), you can add the header to your message payload, lets say as the first 4 bytes of the message, they will represent the area code and can be extracted very fast prior to the parsing process.
New message payload:
([header-4-bytes],[original-payload-n-bytes])
So make your filter based on the header, and if you find out this is an area code you need, create your TEST object based on the rest of the message (cut the first 4 bytes to remove the header).
Kafka does not provide any filtering options that could help you, though it has the ability to send keyed messages in your Producer, so if your key is the area code Kafka guarantees that all messages with the same area codes goes to the same parition, maybe can help for your performance if used correctly.
The Producer can also send messages to a specific partitions, so if you knew you have fixed area code numbers you could also define the topic with partition number equal to the unique area codes count and send each area code to different partition, then use your Consumer to access only to the partitions with the area codes you are looking for, but, may be overkill for most cases.

TYPO3 Webservice/Rest API as Repository for Extbase Extension

I am developing an TYPO3 extbase extension to connect to my external application that has a REST-API. All I want is to retrieve the data from my REST-API and pass this data to the controller. Since I am quite new to extbase development, I didn't really find any resources about Repository interacting with a webservice. Only documentation about Repository that interacts with a database (MySQL, PostgreSQL, ..)
I would like to know, where should I place the cURL-Request Function to connect to the API? In the Model? In the Repository? How can the Controller in my Extension access that data? From Model or Repository?
What would be the best practice for retrieving the data from my external application/database ? (the data retrieved from the application is JSON-formatted)
thanks for any advice / help!
What we usually do is create a Service (in Classes/Service) and use that to connect to the webservice and fetch the data. If you want Models, you can create them there as well.
However, now that I think about it, technically it should be a Repository. It shouldn't matter where the Repository gets its data. Extbase shouldn't have any problem with a completely custom Repository (not extending any other class).
Lets take a simple list -> detail view and make it as simple as possible in order to get some results. Then you can add some helper classes and include them via namespaces etc.
ListAction (yourExtension/Classes/Controller/EventController)
/**
* action list
*
* #return void
*/
public function listAction()
{
$events = (some function which gets all the available events and results to a json output)
$decodedEvents = json_decode($events , true);
(in case you need to see what you got back)
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($decodedEvents);
$this->view->assign('events', $decodedEvents);
}
List HTML (yourExtension/Resources/Private/Templates/Event/List)
<f:for each="{events}" as="event">
<h2>{event.title}</h2>
</for>
Now if i am not wrong, every event has a uid or something that identifies it. So on the same template you can do the following:
<f:for each="{events}" as="event">
<h2>{event.title}</h2>
<f:link.action action="detail" arguments="{eventId: event.uid}">More</f:link.action>
</f:for>
What this does, is to generate a link which links to your detail action with an extra parameter, the eventId.
Bedore TYPO3 renders the detail page it will go through your detail action to get the information for this specific event in order to display them.
DetailAction (yourExtension/Classes/Controller/EventController)
/**
* action detail
*
* #return void
*/
public function detailAction()
{
$args = $this-request->getArguments();
$eventId = $args['eventId'];
$getEvent = (some function that gets a specific id and results to a json output)
$decodedEvent = json_decode($getEvent , true);
(in case you need to see what you got back)
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($decodedEvent );
$this->view->assign('event', $decodedEvent );
}
What this does, it to retrieve the argument that we specified in order to get the identifier of the event and include it on your api request to get the event back. Then we just just decode it to a normal array and we send the results to the FrontEnd.
Detail HTML (yourExtension/Resources/Private/Templates/Event/Detail)
<h2>{event.title}</h2>
Thats a simple list -> detail proccess on TYPO3. You will oft see that the detail view as show but is basically the same thing.
You can replace the variables with a dummy json values and play around. I tested the code while i was writing this answer and it works.
Classes/Service
As for the Classes/Service that mentioned by Rudy Gnodde, you can put your library in there (assuming that you already have coded some functions like getEvent, getAllEvents, getPersons etc.) and then call them in the controller.
use \Vendor\YourExtension\Service\RestApiClass;
/**
* action list
*
* #return void
*/
public function listAction()
{
$events = RestApiClass::getAllEvents();
$decodedEvents = json_decode($events , true);
(in case you need to see what you got back)
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($decodedEvents);
$this->view->assign('events', $decodedEvents);
}
/**
* action detail
*
* #return void
*/
public function detailAction()
{
$args = $this-request->getArguments();
$eventId = $args['eventId'];
$getEvent = RestApiClass::getEvents($eventId);
$decodedEvent = json_decode($getEvent , true);
(in case you need to see what you got back)
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($decodedEvent );
$this->view->assign('event', $decodedEvent );
}
If you need more information feel free to ask.
Best regards

Casablanca REST SDK C++ Listener

I have recently used Java Spring to create REST services. In it, there were annotations for binding each specific function to a different REST query. Lets not go too technical here, as a psuedo, it was like this:
/** list records */
#bind("/list", WebMethod.GET)
List<Record> getRecords()
{
}
/** get record */
#bind("/record", WebMethod.GET)
Record getRecord()
{
}
/** add record */
#bind("/record", WebMethod.POST)
void addRecord()
{
}
Now I am given a tesk to perform a REST with Casablanca SDK in C++, but in every tutorial I checked covers a single GET or POST request. Is it possible to bind multpile requests to custom targets similar to Spring in Casablanca SDK?
You can make a single get function where you capture all get requests, then just get the path from the query and use a switch to call different functions to process the request for that path.