Very often, we can find mobile applications which provide in-app purchase store credit card details, allowing users to buy things in a convenient manner. I am planning to implement the same mechanism on the client side. The following points are what I can think of.
First, there are several variables involved:
credit_card_number
The credit card number used for the purchase.
cvc
The CVC of the credit card being used.
expiry_date
The expiry date of the credit card being used.
card_info_key
The key used to encrypt and decrypt the credit card information stored in the client device.
Is it viable to save card_info_key on the server, then use it to encrypt and decrypt credit card information on the client device as follows?
// credit card information entered by user
var credit_card_number = '1234123412341234';
var cvc = '789';
var expiry_date = '12-2020';
// the key is retrieved from server
var card_info_key = getCardInfoKeyFromServer(current_user);
var card_info = {
'number': credit_card_number,
'cvc': cvc,
'expiry': expiry_date
};
// an encrypted token is expected
var encryptedCardInfo = encryptCardInfo(card_info, card_info_key);
// an object containing the same data as card_info should be returned
var decryptedCardInfo = decryptCardInfo(encryptedCardInfo, card_info_key);
Besides, what encryption and decryption algorithm should I use?
This is not a technical issue because you simply aren't allowed to implement such a functionality (unless you make the app PC-DSS compliant).
See How to save credit card data in a database? for more info and links.
Related
We have a requirement to provide UPI payments for our users, we tried the google pay APIs, but it shows the pay button, and also it supports only google pay, we need to support other payment apps as well.
I was planning to generate a QR code with the amount pre-filled.
for example: If I buy a sandwich, the bill might be 100 rs, and the QR code must be generated for that only.
You can generate QR code by creating the QR for specific intent.
upi://pay?pa=&pn=&am=&cu=&tn=
where:
pa = Payee address or business virtual payment address (VPA).
pn = Payee name or business name.
am = Transaction amount.
cu = Currency Code.
tn = Transaction note.
Converting this to QR will enable to make payments using any UPI App.
Eg:
upi://pay?pa=anything%40payu&pn=Foody&tn=Order&am=100.34&cu=INR
Javascript code to generate links:
let upi = {
pa: "anything#payu",
pn: "Foody",
tn: "Order",
am: "100.34",
cu: "INR"
}
let upiLink = new URLSearchParams(upi).toString();
I built action on google using dialogflow for experience sampling purpose.
It's idea is: it asks specific users about their mood 3 times per day.
It sends these users then every week a weekly overview about their mood after it has been analysed by researchers.
So I need to save each user info with his mood entries on a database so they can be accessed later by researchers, analysed and sent back to users.
I'm using dialogflow fulfilment with index.js to connect to Firebase database to save the entries.
This agent should be integrated as action on google
On the database I get users names and moods but they are not related to each other so I cannot know which user entered which mood and, also I cannot do the userID check.
I would really appreciate if anybody could help me with the functions since I am totally unfamiliar with node.js or databases but I have to do it that way.
here is my code.
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
//initialise DB connection
const admin = require('firebase-admin');
admin.initializeApp();
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function saveName(agent) {
const nameParam = agent.parameters.name;
const context = agent.getContext('awaiting_name_confirm');
const name = nameParam || context.parameters.name;
agent.add('Hi ' + name + ' Are you ready to answer my question?' || 'Hi' + name + 'Have you got a moment for me? ' );
//agent.add('Hi' + name + 'Have you got a minute for me? ');
return admin.database().ref('/names').push({name: name}).then((snapshot)=>
{
console.log('database write sucessful: ' + snapshot.ref.toString());
});
}
function saveMood(agent) {
const moodParam = agent.parameters.mood;
const mood = moodParam;
agent.add('That is good! keep it up. Thanks for sharing with me! Bye ');
//agent.add('Hi' + name + 'Have you got a minute for me? ');
return admin.database().ref('/moods').push({mood: mood}).then((snapshot)=>
{
console.log('database write sucessful: ' + snapshot.ref.toString());
});
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Get Name', saveName);
intentMap.set('Confirm Name Yes', saveName);
// intentMap.set('Confirm Name Yes', getName);
intentMap.set('attentiveness', saveMood);
agent.handleRequest(intentMap);
});
You have a few issues in your code and approach that you'll need to address:
You need to design your database so that you can associate the user's mood with their account. (And possibly other user information, such as their name or email address, while you're at it.)
You need a unique identity for the person.
A person's name isn't a unique identity. Two people may have the same name, or the system may hear the name differently each time, so you need to have a way to know who you're talking to.
You also need to know their email address and possibly other information, so you can send them their report at the end of the week.
You need to make sure you have their identity between calls to your Action during the same conversation.
Fortunately, you do one thing that is typically missed - you make your calls to the database using Promises. So that part works.
Unique Identity
Your example code asks the user for their name, which it sounds like you intend to use as their identity. Unfortunately, this is a bad idea for a few reasons:
The name isn't an identity. What happens if two people with the same name access your Action?
Names are easily discoverable, so other people could use it and report misleading information. This may not be too serious in your case, but it can still have trustworthiness implications.
Names can be Personally Identifiable Information (PII), so may be covered by additional privacy laws.
Users might want to terminate their account, and can't do this without "changing" their name.
Additionally, you may need other identity information later, such as their email address, and asking for that every time may become troublesome.
You have a few ways to deal with this:
If you're developing for the Google Assistant, you can also use Google Sign In for Assistant which will tell you the user's Google identifier, which you can use as a unique ID. You also get their email address and name as part of their profile.
You can ask for this information (name, email, etc) and save it against a user ID that you generate or a user name the user provides. This ID becomes the identifier. If you're developing for the Google Assistant, you can save this ID in the user's private storage - only you and the user have access to it or can delete it. If not, you may need to use the database to look up the ID. More on this later.
You may wish to use variants on this later point, depending what information you're getting and how you want the user to identify themselves every time. But the important part is that they need to identify themselves with something unique and that you can easily capture.
Use identity in the same session
If you're using Google Sign In, you don't have to worry about this. You'll get the same ID each session and for each call during a session.
If you're using the user's private storage with the Google Assistant, you'll have this as part of the userStore object.
But if you're not, you need to make sure that you get the user's ID in an early intent, and saving this as part of a Context so it is preserved in between calls to your webhook. In subsequent handlers, you can get the ID out of the context and then use it to access other information.
You don't need to store it in the database at this point. All you have is an identifier - this becomes the key that you will use for other information. You just need to remember it for later parts of the conversation.
So in your saveName() function, it might look something like
function saveName(agent) {
const nameParam = agent.parameters.name;
agent.add('Hi ' + nameParam + ' Are you ready to answer my question?');
agent.setContext({
name: 'user',
lifespan: 99,
parameters: {
id: nameParam
}
};
}
As an aside - your handler seems to try to determine if this is the user saying their name, or confirming their name. This is probably better handled as separate intents and separate handlers. Trying to combine them will confuse things.
Structuring and Accessing your Database
We have an ID. We have the user reporting the data. How do we associate the two?
There are a lot of ways to structure the data, and Firebase goes into some detail depending on how you intend to use it, access it, and make it available to the users or others.
In this case, it seems pretty straightforward that you want to store records about the user. Each record can use their ID as a key, and then contain some information about the user, including their mood.
One nice thing about the Firebase database is that you can (mostly) treat it like a Javascript object. If we think about it this way, it might look something like
{
"user": {
"id1":{...},
"id2":{...},
"id3":{
"moods": [
{"mood":"good"},
{"mood":"tired"}
]
},
"id4":{...}
}
}
And so forth. With Firebase, we would reference the moods of user "id3" with a path such as user/id3/moods. If we have the user id in a variable name, we might use the following code to get that reference
var ref = admin.database().ref('user').ref(name).ref('moods');
and then use code such as this to push an object with the mood onto the array (and return the Promise that we need to do):
var obj = {
mood: mood
};
return ref.push( obj ).then( snapshot => {
// Do stuff, including acknowledge to the user you saved it.
});
Keep in mind that you may want to also use this to store more information about each user (such as their name or email) on the user level, or more about the moods (such as a timestamp) in the mood object.
I want to send multiple locations pinned on a single map into telegram-bot, by using send location function. is there a way to send multiple locations to telegram bot? I try and just can send one location to telegram bot.
As I understood you want to send multiple locations to the user so you don't want to put numbers in the SendLocation method. If the locations that need to be sent are some fixed locations you can save them in an array or in a DB and use a loop to send them.
But if they're not fixed you have to send them to the bot first and then force the bot to send to a user or anywhere else.(channel or group) The code below may help you:
//Send the location like: latitude=xxx&longtitude=yyy;
if(update.Message.Text.Contains("latitude") && update.Message.Text.Contains("longtitude"))
{
string latitude = text.Split('&').First();
string longtitude = text.Split('&').Last();
//splites the input text into two parts first part is latitude=xxx and second or last part is longtitude=yyy. because the string is splited based on & sign
float latitue_num = float.Parse(latitude.Split('=').Last());
float longtitude_num = float.Parse(longtitude.Split('=').Last());
//does the same action for "latitude=xxx" and "longtitude=yyy" after that the number xxx is stored in latitude_num and yyy is stored in longtitude_num
var req = new SendLocation(update.Message.Chat.Id, latitue_num, longtitude_num);
await bot.MakeRequestAsync(req);
}
Of course if the number of locations is too big, it's better to use a database and send them to bot from the DB.
And if you want to send the locations from a user to the bot(not from bot to a user) you can use:
if(update.Message.Location != null)
{
.
.
.
//here you can do whatever you want every time bot receives a location. no matter how many locations are sent to the bot the bot will receive them one by one and do the action(s) listed in this method.
}
I hope these will help you, your question was not clear therefore I explained this way.
You Can't.
This method Just send point on the map.
Check Telegram Bot API (https://core.telegram.org/bots/api#sendlocation)
MVC 2FA sometimes generates the same OTP (I have set to 6 numericals) and when you generate multiple OTPs, one can use the previous OTP.
Is there a way to generate unique OTPs and disable the previous generated OTP?
string code = await UserManager.GenerateTwoFactorTokenAsync(user.Id, provider);
This is the time set before the OTP expires
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(2));
I just stumbled across this post today and found a simple solution to the problem.
https://www.stevejgordon.co.uk/asp-net-core-identity-token-providers
This link describes the fact that the SecurityTokenStamp is used in the verification process. So for me it was a simple matter of updating it each time I sent out an SMS token for the user. Effectively invalidating the original one.
if(await userManager.UpdateSecurityStampAsync(user.Id) != IdentityResult.Success)
{
// https://www.stevejgordon.co.uk/asp-net-core-identity-token-providers
// we update it to effectively reset all the token validation stuff
return IdentityResult.Failed("failed to update the security stamp");
}
// Send token - this may throw but thats ok as we just rollback
string code = await userManager.GenerateTwoFactorTokenAsync(user.Id, "twilio");
await userManager.SmsService.SendAsync(new Microsoft.AspNet.Identity.IdentityMessage
{
Destination = user.UserName,
Body = "Your security code is: " + code
});
The OTP which is generating via UserManager.GenerateTwoFactorTokenAsync is not a One Time Password even though we called it OTP. It is a TOTP ( Time based one time password).
https://en.wikipedia.org/wiki/Time-based_One-Time_Password
Therefore in a particular time period the generated passwords can be slimier.
For SMS and Email I have noticed that the time period is around 90 seconds. That means within 90 seconds it generates the same password.
For authenticator app also there is this default time period.
By doing lot of researches around this, What I have noticed is, to change this default time period we need to create a custom 2FA token provider.
OTP are time based and not recorded anywhere. If you generate 2 OTPs within a short period of time, you'll get identical strings. And this is how algorithm is working and there is no easy way around it.
Just wondering if it is at all possible in classic ASP/VBScript to launch a new window of the default mail client.
I have tried the following:
set objOutlk = createobject("Outlook.Application")
set objMail = objOutlk.createitem(olMailItem)
But got nothing but an error: ActiveX cannot create object: Outlook.Application.
Any advice is much appreciated.
Rob.
If you want to provide a simple way to open the default mail client message of a user viewing your (asp) page just add a mailto: hyperlink:
Send Msg
The mailto: will trigger the browser to open the default (or configured) mail client.
You can append a query string defining the subject line and the mail body - in my example the subject is "Hello World" and the body text is "Hi there".
Notice the blanks are url-encoded to %20
After a little thought (thanks to some of you guys for the prompt) it made sense to run this client side and I used the following JScript:
<script type="text/javascript">
function send() {
alert("clicked")
var recpt = "info#example.ccTLD"
var subj = "FASTER BETTER SOONER: Look at Monash Rowville rail now"
var text = "<Enter your name and address here> %0D%0DMelbourne is growing and more people need transport. With concern about climate change and rising petrol prices, Melbourne's growth is not sustainable without more and better public transport.%0D%0DVictorians want more people catching public transport, cycling and walking; fewer trucks on our roads, more freight on rail; and fewer kilometres travelled by car and truck.%0D%0DPublic transport should: be fast, frequent, reliable, affordable and safe; grow as Melbourne grows; be available to all Melbournians; and be managed as an integrated, co-ordinated network.%0D%0DThis means bringing forward existing public transport projects, committing to new projects and accelerating programs to move freight off our roads and onto rail.%0D%0DIt also means looking very closely at the impact on greenhouse gas emissions of any new transport projects like tunnels and freeways.%0D%0DWe especially urge you to look at a feasibility study for a Monash Rowville rail line. %0D%0DAs Melbourne's population grows, better public transport will both reduce traffic congestion and provide a much needed antidote to spiralling petrol prices. "
var bcc = "people#example.ccTLD"
var content = new Array()
content[0] = "mailto:"
content[1] = recpt
content[2] = "?subject="
content[3] = subj
content[4] = "&body="
content[5] = text
content[6] = "&bcc="
content[7] = bcc
content = content.join("")
window.location = content
}
This seems to the results I expected.
Rob