Redeeming Push Notifications
-
Similar Topics
-
By Samsung Newsroom
Samsung Wallet provides an e-wallet service to its customers through wallet cards, as well as offering features designed to enhance user engagement and drive business growth for partners. Sending push notifications to users is such a feature. Partners can send push notifications to users' wallet cards directly, using pre-approved message templates.
These notifications can be used to send promotional messages or alert users about important updates. This article demonstrates a complete implementation of the Send Notification API.
In the example scenario, we send a notification to a user's wallet card from a partner's server using this API.
System requirements
The Notification API has the following prerequisites:
Complete the onboarding procedure to obtain the required security certificates if you are new to Samsung Wallet.
Now create your wallet card. Follow the Step 1 - Create Wallet Card Template section of the documentation.
Create your notification template and request for approval. Follow the Notification Workflow Overview to complete this step. Remember to check the template to detect prohibited content. No additional approval is required if it passes.
Get permission from Samsung to use the Send Notification API. Reach out to Samsung Developer Support for further support. API fundamentals
As an authorized partner, you can send notifications to the users linked to your card, using the Send Notification API from your server.
Endpoint: The endpoint below processes the notification requests.
URL https://tsapi-card.walletsvc.samsung.com/{cc2}/wltex/cards/{cardId}/notifications/{templateId}/send Headers: Header information is required to ensure secure communication between the Samsung server and the partner server.
Authorization: Bearer token for authentication. Refer to JSON Web Token documentation for specifications. x-smcs-partner-id: Unique partner identifier required for API access. x-request-id: A unique UUID string that identifies each request. Body: A payload including a parameter named ndata possessing a JWT token that contains the relevant data to identify the card user.
See the official documentation for detailed API specifications.
API implementation process
The Send Notification API allows you to send personalized push notifications to users. Download the sample source code and follow the step-by-step process below for a better understanding of the implementation of the API.
Step 1: Managing cryptographic keys
Cryptographic keys are needed for authorization purposes. In this step, use the certificate you obtained during the onboarding process to extract the necessary keys. These keys are needed for JWT token generation.
Extracting the public keys
Extract the public keys from the partner.crt and samsung.crt certificate files.
def getPublicKey(crt_path): try: with open(crt_path, "rb") as f: crt_data = f.read() certificate = x509.load_pem_x509_certificate(crt_data, default_backend()) public_key = certificate.public_key() public_key_pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) return public_key_pem except Exception as error: print(f"Error reading public key from {crt_path}: {error}") return None Extracting the private key
Extract the private key from the .pem file generated during the onboarding process.
def getPrivateKey(pem_path): try: with open(pem_path, "rb") as data: private_key = serialization.load_pem_private_key( data.read(), password=None, backend=default_backend() ) return private_key except Exception as error: print(f"Error reading private key from {pem_path}: {error}") return None Step 2: Constructing the authorization token
An authorization token is needed to validate the API request. Construct an authorization header with AUTH as the payload content type and include the certificate and partner IDs. Retrieve these IDs from My account > Encryption Management in the Wallet Partner Portal, then build the payload and construct the authorization token.
The following code snippet implements the actions described.
def generateAuthToken(partnerId, certificateId, utcTimestamp, privateKey, cardId, cc2, templateId): auth_header = { "cty": "AUTH", "ver": 3, "certificateId": certificateId, "partnerId": partnerId, "utc": utcTimestamp, "alg": "RS256" } auth_payload = { "API": { "method": "POST", "path": f"/wltex/cards/{cardId}/notifications/{templateId}/send" }, } auth_token = jwt.encode( payload=auth_payload, key=privateKey, algorithm='RS256', headers=auth_header ) return auth_token Step 3: Constructing the notification data token
The request payload requires the ndata parameter, which is a JWT token that contains information about the notification data and the cards’ identifiers. Follow these steps to construct the ndata token.
Defining the notification object
The notification object is a JSON structured data object containing a list of reference IDs and the data. The reference IDs identify the specific cards to send the push notification to. You can use a list of reference IDs to send the push notification to multiple recipients at a time. The data contains the name-value pairs used in the notification template. In our sample notification template, we used two name-value pairs (name and insert_end_date).
notifcationObject = { "refIds": [ "4afb049c-efef-43ca-8f03-1df55243477c" ], "data": { "name": "Premium", "insert_end_date": "12/12/2026" } } Constructing the notification data JWT token
Next, construct the JWT token for notification data (ndata). You can get more information about the JWT format in the "Card Data Token" section of this documentation.
def generateCDataToken(partnerId, samsungPublicKey, partnerPrivateKey, certificateId, utcTimestamp, data): jwe_header = { "alg": "RSA1_5", "enc": "A128GCM" } jwe_token = jwe.encrypt( data, samsungPublicKey, encryption=jwe_header["enc"], algorithm=jwe_header["alg"] ) print(f"jwe_token: \n{jwe_token}\n") jws_header = { "alg": "RS256", "cty": "NOTIFICATION", "ver": 3, "certificateId": certificateId, "partnerId": partnerId, "utc": utcTimestamp, } jws_token = jws.sign( jwe_token, key=partnerPrivateKey, algorithm='RS256', headers=jws_header ) print(f"jws_token: \n{jws_token}\n") return jws_token Step 4: Building and executing the POST request
Construct the HTTP POST request to send the push notification using the following code structure.
# --- Prepare JSON body (Python dictionary) --- payload = { "ndata": nData } # --- Build HTTP Request --- headers = { "Authorization": "Bearer " + authToken, "x-smcs-partner-id": partnerId, "x-request-id": requestId, "Content-Type": "application/json" } # --- Execute HTTP Request --- try: response = requests.post(endpoint, json=payload, headers=headers) response.raise_for_status() print("Wallet Card Template Notificatiom: " + json.dumps(response.json())) except requests.exceptions.RequestException as e: print("Failed to notify the Wallet Card user:") print(f"Error: {e}") if response: print("Response body:", response.text) Running the sample application
Once the four steps described above are implemented, open the sample project and do the following:
Update the partner_id, certificate_id, card_id, and template_id values in src/main.py with your actual values. Place your partner.crt, samsung.crt and private_key.pem files in the /cert directory. Install all dependent libraries listed in the requirements.txt file. Run the main script in the terminal. After the script is executed successfully, a push notification is sent to the user's wallet.
Conclusion
Now that you have implemented the Send Notification API sample application successfully, you can implement this API with your server to send customized push notifications.
Additional resources
For more information on this topic, consult the following resources:
Complete source code Official Samsung Wallet API documentation View the full blog at its source
-
By Samsung Newsroom
In-App purchases are crucial for many applications, and the Samsung In-App Purchase (IAP) service helps developers manage purchases, subscriptions, and refunds efficiently. To keep your server in sync with user transactions, Samsung IAP Instant Server Notification (ISN) sends real-time notifications to your backend server when purchase-related events occur.
ISN for Samsung IAP is a method used by Samsung's system to notify your server about user activities related to in-app items and subscriptions. When a change occurs, Samsung sends a notification to your server. A list of all events that trigger a notification is available here.
In this article, we will build a Spring Boot server that handles these notifications.
Prerequisites
To implement ISN for Samsung IAP, it is important to focus on the requirements that helps you to most easily implement the process:
Create an IAP public key in the Seller Portal. This key is used to authenticate the notifications you receive and verify that they are from the Samsung IAP ISN system. The steps you need to follow are outlined in the Create an IAP public key in Seller Portal documentation. Create an in-app item in the Seller Portal. Follow the related documentation to create an in-app item. ISN Structure
The ISN for Samsung IAP service sends a notification to the application developer server. The structure of the notification is always a base64-encoded JSON Web Token (JWT) and consists of three parts. The three parts are:
Header Payload Signature Header
The JWT uses a JOSE (JavaScript Object Signing and Encryption) header. Similar to the envelope of a letter, the header indicates the type of notification being sent. For additional information, refer to the Samsung IAP ISN Header article.
Example encoded header:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSXXXXXXXX Example decoded header:
{ "alg" : "RS256", "typ" : "JWT" } Payload
The payload is the actual content of the message, like the letter inside the envelope. This part contains the crucial information you need, like the user’s subscription details, the product they have subscribed to, and the current status of the subscription.
More details about the payload check are available in the following documentation and Data claims section.
Example encoded payload:
eyJpc3MiOiJpYXAuc2Ftc3VuZ2FwcHMuY29tIiwic3ViIjoiRVZFTlRfTkFNRSIsImF1ZCI6WyJjb20ucGFja2FnZS5uYW1lIl0sIm5iZiI6MTcxNzIwNCwiaWF0IjoxNzE3MjA0LCJkYXRhIjp7InNlbGxlck5hbWUiOm51bGwsIm NvbnRlbnROYW1lIjoiTWFydGluZSJ9LCJ2ZXJzaW9uIjoXXXXXXXX Example decoded payload:
{ "iss": "iap.samsungapps.com", "sub": "EVENT_NAME", "aud": ["com.package.name"], "nbf": 1717XXXXXX, "iat": 1717XXXXXX, "data": {..}, "version": "X.0" } Signature
The signature is the security feature that acts as a digital stamp to prove the message is genuine and hasn’t been tampered with. You can use this signature to verify that the data in the payload is authentic and was created by Samsung.
Further information is provided in the signature documentation.
Now that we know the structure of the ISN for Samsung IAP, we can configure the server to handle it.
Server Configuration
According to the ISN for Samsung IAP requirements, you must set up a server to receive the notifications.
Below, we create a Spring Boot server. Use your preferred IDE (Integrated Development Environment) or online Spring Initializr to create a Spring Boot server. Follow the steps below to set up your own server.
Step 1: Set Up a Spring Boot Project
Use the Spring Initializr tool to create a new project. Choose the following dependency: Spring Web Generate and download the project. Step 2: Import the Project into IDE
Open the project in the IDE (IntelliJ, Eclipse, etc.) Step 3: Set Up ISN Endpoint
Create a controller for ISN Notifications in the IDE after importing the Spring Boot project. The controller receives POST requests (Subscription, Refund and Cancel) sent from Samsung’s IAP server.
Add necessary dependencies in the build.gradle file:
{ implementation 'com.auth0:java-jwt:4.0.0' //For JWT verifier implementation 'org.json:json:20230227' // For JSON parsing } Load the public key detailed in the prerequisite section: private String loadPublicKey(String fileName) throws IOException { ClassPathResource resource = new ClassPathResource(fileName); StringBuilder contentBuilder = new StringBuilder(); try (InputStream inputStream = resource.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { contentBuilder.append(line).append("\n"); } } return contentBuilder.toString(); } Remove headers, footers, and whitespace from the public key and convert it to the RSAPublicKey format. private RSAPublicKey getRSAPublicKeyFromPEM(String pem) throws Exception { String publicKeyPEM = pem .replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); // Remove headers, footers, and whitespace byte[] encoded = Base64.getDecoder().decode(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } Create a JWT verifier with RSAPublicKey and, finally, verify the JWT. If the verification is successful, decode the JWT to retrieve the decoded JSON payload. The decoded payload contains the message of the notification. private void verifyToken(String token, RSAPublicKey publicKey) { try { // Create JWT verifier with RSA public key Algorithm algorithm = Algorithm.RSA256(publicKey, null); // Verify the JWT token JWTVerifier verifier = JWT.require(algorithm) .withIssuer("iap.samsungapps.com") .build(); DecodedJWT jwt = verifier.verify(token); // Decode the JWT token String payloadJson = new String(Base64.getDecoder().decode(jwt.getPayload())); JSONObject jsonObject = new JSONObject(payloadJson); //Print decoded JSON payload System.out.println("Payload as JSON: " + jsonObject.toString(4)); } catch (JWTVerificationException e) { System.out.println("Invalid token: " + e.getMessage()); } } In this sample project, we have only printed the payload data to the console. You can use this according to your requirements.
Step 4: Deploy the Server
The server needs a publicly accessible URL to receive ISN notifications. In our project, we have used CodeSandbox to get the publicly accessible URL for the server. Once you deploy the project on CodeSandbox, you will get a publicly accessible URL that looks like this: https://abcde-8080.csb.app/iap/isn.
Testing with Seller Portal
Test your server with Samsung Galaxy Store Seller Portal:
Set the CodeSandbox URL as the ISN URL in Seller Portal.
Go to the In-App Purchase section and create items with the required details. In the "ISN URL" field, set the publicly accessible server URL. After setting the URL, click the Test button. A notification will be sent to the specified server immediately. You will also receive a notification on the server that you just deployed in the CodeSandbox.
Figure 1: Testing with Seller Portal Testing with a Sample Application
Now it is time to test the ISN for Samsung IAP from the user application. Further details are provided in the Integrate the Samsung In-App Purchase Orders API with Your Application article. Download the sample application from this blog and then follow the instructions until you reach the "Implementation of Item Subscription" section.
In the sample application, after clicking the "Buy" button, startPayment() is called. The onPayment() callback returns an indication of whether the purchase succeeds or fails. If the purchase is successful, the IAP server sends a notification to your server.
iapHelper.startPayment(itemId, String.valueOf(1), new OnPaymentListener() { @Override public void onPayment(@NonNull ErrorVo errorVo, @Nullable PurchaseVo purchaseVo) { if (purchaseVo != null) { Log.d("purchaseId" , purchaseVo.getPurchaseId().toString()); // Purchase successfull }else { Log.d("purchaseError" , errorVo.toString()); } } }); Example Response
After successfully purchasing an item, a JSON response is returned. For more information on each parameter, you can check the Item purchased documentation.
Example JSON response:
"data" : { "itemId": "example_item_id", "orderId": "XXXX40601KRA00XXXXX", "purchaseId": "XXXXX7245d57cc1ba072b81d06e6f86cd49d3da63854538eea689273787XXXXX", "testPayYn": "N", "betaTestYn": "N", "passThroughParam": null } NoteFor different event types, it sends different data claims. For more detailed information regarding data claims, see Data claims. Conclusion
By implementing the ISN for Samsung IAP with your server, you can easily and securely stay in sync with user in-app purchases.
Integrating ISN for Samsung IAP helps you improve your application management experience and grow your application’s revenue. Following this guide will help you smoothly set up the system and provide a better way to manage your application.
References
For additional information on this topic, see the resources below:
Download the sample Spring Boot server Samsung IAP Instant Server Notification documentation Integrate the Samsung In-App Purchase Orders API with Your Application View the full blog at its source
-
-
By Samsung Newsroom
Push notifications have a terrible reputation but if done well can give your users a positive experience.
You know that thing where you go to a web site then, before you can do anything, you have to acknowledge the push notification request. Do you hate that? Yeah, me too.
Jo Franchetti even wrote an entire article about the crisis of websites bombarding people with permission requests and dialogs when they first arrive on the page.
A Crisis of Permissions
That’s just one of the many ways it’s easy to upset your users with push notifications, this article will try to detail some ways to do them better.
A bad example of requesting for push notifications on first load
Failing before you even begin
Push Notifications on the Web are one of the most maligned APIs on the Web and this is one of the reasons why. It’s possible to give a bad impression before you even send a single notification.
Just like you wouldn’t ask to move in with someone on the first date, do not ask to send notifications on the very first user engagement.
Assume your users do not want push notifications. Prove the worth of your web app with it’s high quality information and delightful user experience. Make the users want push notification before you prompt them, the best way to do this is to have a checkbox to enable push notifications in context.
This makes it clear not only what the push notification request is for but how they can turn them off when they do not want them.
In this example app users can turn on notifications for particular information channels with the “notify me on updates” checkbox:
If they check the checkbox then we will call pushManager.subscribe() which will prompt the user to enable notifications. The users are more likely to enable push notifications because they chose to be prompted through their own intuition.
On a related note app install banners:
In some browsers, app install banners, pop up in a similar way to poorly done notification requests. It is not in response to a user action and are unrelated to your app’s content and not part of your apps user interface.
It is possible to integrate this into your app interface, letting you hide this banner and letting you provide your own install button.
Do this in the beforeInstallPrompt event:
window.addEventListener('beforeinstallprompt', handleInstallPrompt); You can use this event to integrate an App Install Button into your app. If you get this event then you can show the button which allows the content to be installed. In the below image I put a subtle bubble at the bottom of the homepage for installing it. It’s easy to find and access but won’t intrude on the user’s app experience.
The user pays the cost of notification, don’t be expensive.
The user doesn’t pay a cost in money but they do in attention.
Each notification is a weight upon the user’s mind. A notification to a user when their attention is at their limit could be the motivation the user needs to block all notifications from the entire web browser.
Each notification should bring joy to the user. How do you bring joy?
Be timely If you could’ve given this information earlier or could show it later why bother interrupting the user right now.
Be efficient Opening an app or web page is comparatively slow, it can take a few seconds which is a long time to someone who is busy cooking dinner or watching Netflix or at work.
If you can put all the information in the notification without them opening the app then do that. If all the response you need is a simple Option-A/Option-B question such as yes/no then add those buttons.
When the user presses the button update the notification to acknowledge the button press but don’t open the app.
Be clear There are many options to change the appearance of the notification use as many as possible to make it clear where the app is from, what it’s about and what action is expected from the user.
Use the badge and icon for your app icon. Use the title to give a summary of what action the user needs to take, use the body and image to give relevant information and context.
The next section describes how to customise your notificaition.
DO NOT WASTE THE USER’S TIME Don’t push ads, don’t use them to beg users to return, don’t push boring notifications to remind the user your web app exists.
I know it’s tempting and you have quotas to meet but it will only have an adverse effect on how the user views your app and notifications as a whole. The user probably does not love your app as much as you do and will be a lot less forgiving.
Fully Customising Push Notifications
Here is an example notification where as much as possible has been configured:
{ body: "Awkward Zombie - Disagree to Agree", icon: "/icons/appicon.png", image: "https://example.com/previewimage.jpg", badge: "data:image/png;base64,iVBORw0KGgoAAA...", vibrate: [100, 50, 100], data: data, tag: data.url, actions: [ { action: "Read now", title: "Open" }, { action: "close", title: "Close" }, ], }; self.registration.showNotification(title, options); If assets take too long to load they get ignored. The most important icon is the badge icon since it’s the one which gets put into the status. It’s also very small so is ideal to be URL encoded and is kept in a constant in the Service Worker file, to ensure it is loaded reliably.
For the icon we use the app icon so it’s extra clear where the notification is from. This is a locally loaded PNG to be sure it loads quickly.
The image is loaded from the third party site the being loaded from the RSS feed we don’t need to have it store local it’s okay for these to be from somewhere else. It adds good context but it isn’t essential so if it does not load in time then it’s not an absolute problem.
These examples of action buttons I’ve done here are probably not totally necessary since notifications can be closed by some other means and we can just listen for notification clicks. Better examples would be something like “Open” and “Remind me Later”, defaulting to “Open” if neither button is clicked.
Detailing the different parts of the notification
Combining notifications
You can’t guarantee a user will check their device in between notifications. New notifications by default do not replace the the old ones so this can result in an overwhelming flood of notifications if they arrive in short succession.
If you set the tag property then notifications which share the same tag can overwrite each other. In this example the tag is set to the RSS feed’s URL, so that notifications from the same RSS feed overwrite each other.
This is better since we don’t get flooded but now if a second notification comes through we lose the first one. It’s probably a good idea to check to see if you are replacing a notification and if you are concatenate them together.
const existingNotifications = await self.registration.getNotifications({ tag: data.url, }); if (existingNotifications.length) { const oldNotification = existingNotifications[0]; options.body = oldNotification.body + '\n' + options.body; } There is a limited amount of text that can be fit into a notification body. An alternative solution would be to replace the notification with one that just says ‘You have N notificaitons’ then when the user taps on it open your Web App’s notification interface.
Updating Notifications
This can also be a good way to update the user in notification only interfaces. Once they have click on the notification to perform an action make, the request to the server to perform that action. Once the request completes then show a new notification acknowledging it’s completion.
self.addEventListener("notificationclick", async function (e) { const notification = e.notification; const action = e.action; if (action === "close") { notification.close(); } if (action === "respond") { // close the old notification notification.close(); const response = await fetch('/api/respond.json') .then(r => r.json()); // Let the user know if it succeeded or not if (response.ok) { self.registration.showNotification("Success", options); } else { self.registration.showNotification(response.error, options); } } }); By having the user interact only through push notifications the user can complete their task and have a positive interaction with your app without needing to dedicate much mental energy to it giving a positive experience.
Together we can use push notifications to enrich people’s lives and make users have a positive association to push notifications.
View the full blog at its source
-
-
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.