Encode string in base64 into Shopify - base64

How can I encode a string to base 64 in Shopify?
I need to encrypt into base64 the the buyer email ({{customer.email}}) and the order ({{order_name}})
The scope if for adding the trustedbadge*.de button into the email, and they are requesting the fallow url format:
www . trustedshops/buyerrating/rate_XFD9974BBC558C007CD46
431D056DF230.html&buyerEmail="[base64 buyerEmail]: "&
shopOrderID=" [base64 Order] "&channel=cmF0ZW5vd2J1dHRvbg"
Is there any way to convert those two values in base64?
Thank you for your time!

Base64 is not encryption -- it's known as an encoding.
There is no shopify liquid filter for base64 that I'm aware of, so you'll have to do this in javascript.
Liquid:
HTML:
<a href="#" onclick="window.open('https://www.trustedshops/buyerrating/rate_XFD9974BBC558C007CD46431D056DF230.html&buyerEmail=' + encodeURIComponent(btoa({{ order.email | json }})) + '&shopOrderID=' + encodeURIComponent(btoa('{{ order.order_number }}')) + '&channel=cmF0ZW5vd2J1dHRvbg')">
Open order on trustedshops.com
</a>
And this code just explains the javascript in that onclick.
Javascript:
// The btoa function is the javascript function to encode a string as base64
// Since base64 encoded strings can't go directly in a url, we then
// need to use encodeURIComponent to make it ok to use in a url.
var encodedEmail = encodeURIComponent(btoa('hello#example.com')); // aGVsbG9AZXhhbXBsZS5jb20%3D
var encodedOrderId = encodeURIComponent(btoa('1234567890')); // MTIzNDU2Nzg5MA%3D%3D
// we can now construct the full url
var url = 'https://www.trustedshops/buyerrating/rate_XFD9974BBC558C007CD46431D056DF230.html&buyerEmail=' + encodedEmail + '&shopOrderID=' + encodedOrderId + '&channel=cmF0ZW5vd2J1dHRvbg';
// use window.open to open the url in a new tab
window.open(url);
// or use window.location.href = url if you'd like it
// to be the same tab

Related

rendering returned html code to be shown as a view

so i'm saving the current Date in a cookie and I try to show the value of this cookie in a html web page using a template engine. The problem is when i send my new template which contains the Date, i get a HTML text instead of a view.
router.get('/', (req, res) => {
let template = fs.readFileSync(indexFile, 'utf8');
var dataToShow = {"cookie_data": 'Letzte Besuch: ' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds()};
template = mustache.render(template, dataToShow);
res.send(template);
})
And in my HTML page i have the following :
<p>{{cookie_data}}</p>
I expect to have a view instead of html-code
Please try using
<p>{{{cookie_data}}}</p>
Please refer this doc: http://handlebarsjs.com/#html-escaping
Please use
res.render('page', 'params')

Cheerio how to ignore elements of a certain tag

I am scraping the body of the webpage:
axios.get(url)
.then(function(response){
var $ = cheerio.load(response.data);
var body = $('body').text();
});
The problem is, I want to exclude contents from the <footer> tag. How do I do that?
cheerio creates a pseudo-DOM when it parses the HTML. You can manipulate that DOM similar to how you would manipulate the DOM in a browser. In your specific case, you could remove items from the DOM using any number of methods such as
.remove()
.replaceWith()
.empty()
.html()
So, the basic idea is that you would use a selector to find the footer element and then remove it as in:
$('footer').remove();
Then, fetch the text after you've removed those elements:
var body = $('body').text();

Instagram: Get oEmbed using Media ID

Say, I have a media ID (eg. 1075297042445691366_195350057). How to get the Embed HTML using the oEmbed API?
This API accepts only shortcode (which is different from media ID).
Or How to get the shortcode of an media ID?
Any media object returned by the API has a field called 'link' that is the URL representation of the media. You can use this link as 'url' parameter of the oembed endpoint.
If anyone finds this question in the future I spent quite a while trying to solve it.
This implementation deserves 99.9% credit to this answer by Nick Hanshaw. All I did was include a CDN link to the BigInteger.js library which is required, but not part of Nick's code. This is currently working for me right now by passing the Media ID as a string into the function, then returning the full string of the Instagram photo URL:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/big-integer/1.6.40/BigInteger.min.js"></script>
<script type="text/javascript">
function getInstagramUrlFromMediaId(media_id) {
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
var shortenedId = '';
media_id = media_id.substring(0, media_id.indexOf('_'));
while (media_id > 0) {
var remainder = bigInt(media_id).mod(64);
media_id = bigInt(media_id).minus(remainder).divide(64).toString();
shortenedId = alphabet.charAt(remainder) + shortenedId;
}
return 'https://www.instagram.com/p/' + shortenedId + '/';
}
</script>

Get filename as a request parameter

I try to load a file with node.js.
In my view, I've got a button :
doctype 5
html(ng-app="lineApp")
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
p filename: #{filename}
button(onclick="location.href='/app/#{filename}'") click me
The page display a paragraph with filename: C:\users\username\my filename.txt.
When I click on the button, the URL is something like http://localhost:8080/app/C:usersusernamemy%20filename.txt
So when I try to retrieve the parameter
exports.appli = function (req, res) {
var filename = req.params.filename;
//....
});
};
with the server side call :
app.get('/app/:filename?', routes.appli);
I got an invalid filename. My question is then, how to pass a file path as a parameter in URL ?
This is a problem with the slashes acting as escape characters.
The first time you pass the string to the client, any escaped slashes (ex: c:\\users\\username\\my file.txt) are converted to single slashes.
When you use href.location, the slashes act as escape characters a second time...which is why they drop out when you try to call the server using it.
You could:
Create two variables to pass to the jade template, one the filename as-is and the other an HTML encoded string
pass the variables to the jade template:
For example, based upon your original jade:
body
p filename: #{filename}
button(onclick="location.href='/app/#{encodedFilename}'") click me

How to sign Amazon Simple Pay button in node.js / Javascript

I've spent the past 6 hours trying to follow Amazon's instructions for signing a Simple Pay button form in node.js. I can't get it to the accept the sig and I've tried every permutation of the confusing instructions. Can anyone help me out of my misery?
The error I get is
Input parameter signature is invalid
Here is my procedure
var params={
"returnUrl": "[confidential]",
"ipnUrl": "[confidential]",
"processImmediate": "1",
"accessKey" :"[AWS key]",
"collectShippingAddress" :"0",
"isDonationWidget" :"0",
"amazonPaymentsAccountId" :"[the button generator creates this but there is no mention in the docs]",
"referenceId" :ref,
"cobrandingStyle" :"logo",
"immediateReturn" :"1",
"amount" :"USD "+amount,
"description" : desc,
"abandonUrl" :"[confidential]",
"signatureMethod": "HmacSHA256", //docs not clear if signatureMethod and signatureVersion should be included, but I've tried all permutations and can't get it to work
"signatureVersion" :"2"
}
//Docs say it should confirm to
/*
StringToSign = HTTPVerb + "\n" +
ValueOfHostHeaderInLowercase + "\n" +
HTTPRequestURI + "\n" +
CanonicalizedQueryString <from the preceding step>
*/
//sort parameters (natural byte order)
var p=_.pairs(params);
var psorted=_.sortBy(p, function(p) { return p[0];});
//start to construct the form
var input='';
for(var i=0; i<psorted.length;i++) {
input+="<input type='hidden' name='"+psorted[i][0]+"' value='"+psorted[i][1]+"'>";
}
//prepare the string to be signed
var qstring='POST'+'\n';
qstring+='https://authorize.payments.amazon.com'+'\n';
qstring+='/pba/paypipeline'+'\n';
for(var i=0; i<psorted.length;i++) {
psorted[i][0]=encodeURI(psorted[i][0]);
psorted[i][1]=encodeURI(psorted[i][1]);
qstring+=psorted[i][0]+'='+psorted[i][1];
if (i<psorted.length-1) {qstring+='&';}
};
console.log(qstring+'\n\n');
var sig=crypto.createHmac("SHA256", "[AWS Secret Key") 6
.update(qstring)
.digest('base64');
input+="<input type='hidden' name='signature' value='"+sig+"'>"; //doesn't matter whether or not i url encode this
console.log(input);
That converts the parameters into
POST
authorize.payments.amazon.com
/pba/paypipeline
abandonUrl=XXXX&accessKey=XXXXX&amazonPaymentsAccountId=XXXXXX&amount=USD%203&cobrandingStyle=logo&collectShippingAddress=0&description=sadasdd&immediateReturn=1&ipnUrl=XXXXXx&isDonationWidget=0&processImmediate=1&referenceId=324324&returnUrl=XXXXXXXX&signatureMethod=HmacSHA256&signatureVersion=2
I concatenate and paste the the output to this form for testing
<form action="https://authorize.payments.amazon.com/pba/paypipeline" method="POST">
<input type='hidden' name='abandonUrl' value='[confidential]'>
<input type='hidden' name='accessKey' value='[confidential]'>
<input type='hidden' name='amazonPaymentsAccountId' value='[confidential]'>
<input type='hidden' name='amount' value='USD 3'>
<input type='hidden' name='cobrandingStyle' value='logo'>
<input type='hidden' name='collectShippingAddress' value='0'>
<input type='hidden' name='description' value='sadasdd'>
<input type='hidden' name='immediateReturn' value='1'>
<input type='hidden' name='ipnUrl' value='[confidential]'>
<input type='hidden' name='isDonationWidget' value='0'>
<input type='hidden' name='processImmediate' value='1'>
<input type='hidden' name='referenceId' value='324324'>
<input type='hidden' name='returnUrl' value='[confidential]'>
<input type='hidden' name='signatureMethod' value='HmacSHA256'>
<input type='hidden' name='signatureVersion' value='2'>
<input type='hidden' name='signature' value='fHSA+p37r5ooOJOUnjYBdhNFe/pAEg/KunAEOudUvGs='>
<input type="submit">
</form>
Here are the Amazon docs
http://docs.aws.amazon.com/AmazonSimplePay/latest/ASPAdvancedUserGuide/Sig2CreateSignature.html
How to Generate a Signature
To create the signature
Create the canonicalized query string that you need later in this
procedure:
Sort the UTF-8 query string components by parameter name with natural
byte ordering.
The parameters can come from the GET URI or from the POST body (when
Content-Type is application/x-www-form-urlencoded).
URL encode the parameter name and values according to the following
rules:
Do not URL encode any of the unreserved characters that RFC 3986
defines.
These unreserved characters are A-Z, a-z, 0-9, hyphen ( - ),
underscore ( _ ), period ( . ), and tilde ( ~ ).
Percent encode all other characters with %XY, where X and Y are hex
characters 0-9 and uppercase A-F.
Percent encode extended UTF-8 characters in the form %XY%ZA....
Percent encode the space character as %20 (and not +, as common
encoding schemes do).
Note Currently all AWS service parameter names use unreserved
characters, so you don't need to encode them. However, you might want
to include code to handle parameter names that use reserved
characters, for possible future use. Separate the encoded parameter
names from their encoded values with the equals sign ( = ) (ASCII
character 61), even if the parameter value is empty.
Separate the name-value pairs with an ampersand ( & ) (ASCII code 38).
Create the string to sign according to the following pseudo-grammar
(the "\n" represents an ASCII newline).
StringToSign = HTTPVerb + "\n" + ValueOfHostHeaderInLowercase + "\n" +
HTTPRequestURI + "\n" + CanonicalizedQueryString The HTTPRequestURI component is the HTTP absolute path
component of the URI up to, but not including, the query string. If
the HTTPRequestURI is empty, use a forward slash ( / ).
Calculate an RFC 2104-compliant HMAC with the string you just created,
your Secret Access Key as the key, and SHA256 or SHA1 as the hash
algorithm.
For more information, go to http://www.ietf.org/rfc/rfc2104.txt.
Convert the resulting value to base64.
Use the resulting value as the value of the Signature request
parameter.
Important The final signature you send in the request must be URL
encoded as specified in RFC 3986 (for more information, go to
http://www.ietf.org/rfc/rfc3986.txt). If your toolkit URL encodes your
final request, then it handles the required URL encoding of the
signature. If your toolkit doesn't URL encode the final request, then
make sure to URL encode the signature before you include it in the
request. Most importantly, make sure the signature is URL encoded only
once. A common mistake is to URL encode it manually during signature
formation, and then again when the toolkit URL encodes the entire
request. For information on the high-level process for creating a
button, see Creating Button Forms Dynamically .
In the following examples, new lines have been inserted to make the
examples easier to read. Explicit '\n' is used wherever new line is
required.
The following is an example Amazon Simple Pay request using POST.
The following is an example of a string to use for
StringToSign in the preceding example.
POST\n authorize.payments-sandbox.amazon.com\n /pba/paypipeline\n
SignatureMethod=HmacSHA256 &SignatureVersion=2
&accessKey=YourCallerKey &amount=USD%201.1 &cobrandingStyle=logo
&description=Test%20Widget &immediateReturn=0
&ipnUrl=http%3A%2F%2Fyourwebsite.com%2Fipn &processImmediate=1
&referenceId=YourReferenceId
&returnUrl=http%3A%2F%2Fyourwebsite.com%2Freturn.html For more
examples of generating a signature, see Appendix: Sample Code.
For information on signing your button form correctly, see How to Sign
your Button Form Correctly.
For posterity, here is the solution:
1) Don't mess with Simple Pay Buttons - use FPS instead
2) Of the myriad overlapping documents, I found this to be the simplest and clearest: http://docs.aws.amazon.com/AmazonFPS/latest/FPSBasicGuide/SendingaCBUIRequest.html
3) Use encodeURIComponent not encodeURI - this was my biggest most frustrating mistake
This code will correctly sign an Amazon FPS request (assumes crypto for hmac and nconf for configuration)
var crypto = require('crypto');
var _ = require('underscore');
var nconf = require('nconf').argv().env().file({
file: "./config.json"
});
exports.azPayRequest=function (amount, desc,ref) {
var params={
"returnUrl": nconf.get("awsPayments:returnURL"), //callback
"callerKey" : nconf.get("awsPayments:callerKey"), //aws id
"callerReference": ref,
"pipelineName":"SingleUse",
"cobrandingStyle" :"logo",
"currencyCode" :"USD",
"transactionAmount" : amount,
"paymentReason" : desc,
"signatureMethod": "HmacSHA256",
"signatureVersion" :"2"
}
/*
StringToSign = HTTPVerb + "\n" +
ValueOfHostHeaderInLowercase + "\n" +
HTTPRequestURI + "\n" +
CanonicalizedQueryString <from the preceding step>
*/
//sort parameters
var p=_.pairs(params);
var psorted=_.sortBy(p, function(p) { return p[0];});
//method, host, path
var method='GET';
var host=nconf.get('awsPayments:host'); // e.g., authorize.payments.amazon.com;
var path=nconf.get('awsPayments:path'); //e.g. /cobranded-ui/actions/start;
//url encode parameters
var qstring='';
for(var i=0; i<psorted.length;i++) {
psorted[i][0]=encodeURIComponent(psorted[i][0]);
psorted[i][1]=encodeURIComponent(psorted[i][1]);
qstring+=psorted[i][0]+'='+psorted[i][1];
if (i<psorted.length-1) {qstring+='&';}
};
//calculate hmac
var nl=String.fromCharCode(10);
var encode_request=method+nl+host+nl+path+nl+qstring;
console.log("STRING TO ENCODE\n"+encode_request+'\n\n');
var sig=crypto.createHmac("SHA256", nconf.get("awsPayments:awsSecretAccessKey"))
.update(encode_request)
.digest('base64');
var url="https://"+host+path+"?"+qstring+'&signature='+encodeURIComponent(sig);
return url;
}

Resources