Shopify - Making an API request to update user's email - shopify

Using the Shopify Admin API - I've been able to update a user's email address.
I've tested it with Postman, passing in a private app secret key.
Now I want to have this functionality on an actual page however have some questions:
I can't exactly store those private app keys on the JS code of the page itself as anyone would see. Neither can I make send a request with it as again anyone would have visbility.
Is it possible to create some sort of intermediary where I could make some sort of endpoint like POST /update/useremail sending across a customer ID
If the above is possible - I'm not sure how I could avoid any random person hitting that endpoint and updating other user's email addresses.
Has anyone had any experience/ideas/suggestions for a simply way to do this?
Any help appreciated.
Thanks.

Issue: Your issue is here that you want to verify if the email change request is a valid call or not? Then if you find it valid then you make the API call to update it.
My Solution
Create a page in Shopify with your form to update email. Show the page only to logged in users. When a user lands in the page show them the form to pass the new email they want. This where you need to add a few things so as to validate the requests. When the page loads create a hashed string from the Shopify Backend like below.
{% if customer != nil %}
{% assign timestamp = 'now' | date: "%s" %} //epoch time stamp
token = {{ customer.email | append: '<random_string>' | append: timestamp | sha256 }}
{% endif %}
Whenever a request is made for a change of email validate the SHA256 code at your end by creating a hash at your server. If the hash is valid update the email. Make sure you pass the timestamp and old email in the request you make.
Security issues you need to take care of -
You need to validate timestamp always For eg. It should not be 10 secs in the future or 10 secs in the past.
Your random string can also be brute forced. So keep updating the random string regularly using Assets API. It is very unlikely but why take the risk.

Related

How to show product variant inventory quantity per location on Shopify product Page using Admin API?

I would like to show the product variant quantity on the product page like this:
Location 1: 5 in stock
Location 2: 2 in stock
Location 3: 63 in stock
Location 4: 5 in stock
and so on...
Is it possible to do this using the admin API from Shopify?
Thanks in advance.
It is not recommended to use the Shopify admin API directly in the store front as you could be exposing the API username and keys in your JS code.
You should use a backend service or something similar where your frontend will send a request to the backend. The backend will then fetch the records using the Shopify rest admin APIs and return the data back.
If you prefer to go the custom code route below are a few things for you to keep in mind
Shopify has API rate limits. You most likely will be hitting these if you fetch every time a product page is loaded. Limits mentioned here
As an option for the rate limits, you could query the backend every x mins, save them in the database and serve the inventory levels from the DB. Or you could try to cache your request for a certain time limit instead of saving in the DB.
If you just want to how much is available across all inventory locations, you can use the below liquid/JS code.
<script>
var variantStock = {};
{% for variant in product.variants %}
variantStock[{{- variant.id -}}] = {{ variant.inventory_quantity }};
{% endfor %}
console.log(variantStock);
</script>
In the above code, you will have the available inventory quantity for each variant in the variantStock object. You can then write some extra code to display the stock levels when the user changes variants accordingly.
Check the liquid object document for variants here
Having said the above, another option is to use an app that will do the above for you. There are many apps in the Shopify app store that does exactly what you want.

Slack API - Don't notify user when parsing user id

In this message formatting doc: https://api.slack.com/docs/message-formatting, you can use special control sequence characters < and > to perform server-side parsing (server-side as in Slack API's server-side).
So using <#U024BE7LH> in your chat.postMessage() call will get parsed to something like #bob or whatever the username associated with that ID is, in the actual text that shows up in slack.
Unfortunately, this will cause a notification for the person you're referring to. How do I make it so that it doesn't notify the person? I've tried to enclose in a code block, i.e.:
`<#U024BE7LH>`
or
```
<#U024BE7LH>
```
But it still pings. I'm thinking the only way is to get a list of users and parse the name from the ID.
According to this, backticks should work but empirically it hasn't for me. The Slack employee says to just convert the user ID to their name and use that without the templating.
https://forums.slackcommunity.com/s/question/0D73a000005n0OXCAY/detail?language=en_US&fromEmail=1&s1oid=00Dj0000001q028&s1nid=0DB3a000000fxl3&s1uid=0053a00000Ry9cX&s1ext=0&emkind=chatterCommentNotification&emtm=1667894666436&emvtk=fH.W2M01lq9W1cf31RSROPwB7LYs.och8RgbVTqoNlg%3D&t=1667931570045

Using query string parameter in Kentico marketing automation process

I am trying to set up a marketing automation process that is kicked off when a user visits a particular web page on my site. The URL to that web page is going to be included in an email blast to a set of Kentico contacts.
I was hoping to be able to add a query string parameter to the end of the URL so that I can capture the e-mail address of the contact and store it in the Contact Email field,
i.e. http://example.com/mypage?email=xx#xxx.com.
My first attempt at this was setting up a marketing automation workflow that is triggered when the user visits the page, then using a 'Set Contact Property' step to set the contact's email address to the query string value, but I can't seem to be able to get the value of the query string parameter. I've tried {? email?}, {% QueryString.email%}, etc. with no luck.
Anyone have any ideas?
You are very close. Try this:
{% QueryString["nameOfQueryString"] %}
So if my URL were http://www.exmaple.com/mypage?email=testEmail#example.com, and I wanted to resolve the query string called "email" I would write:
{% QueryString["email"] %}
And it would resolve "testEmail#example.com".
Side Note: I would not recommend using your users' emails as the query string. I would use a GUID to build the URL and associate the user's email with a GUID in a SQL table.
So, if the email address "testEmail#exaple.com" was associated to the guid 25892e17-80f6-415f-9c65-7395632f0223, you would build a URL like this:
http://www.exmaple.com/mypage?id=25892e17-80f6-415f-9c65-7395632f0223
Then when the user visits this page, you can tell who they are by comparing the GUID to their email.

How Do I Make a SagePay BuyNow Button?

With PayPal, I can create a BuyNow button pretty easily, containing my merchant info, price, tax, shipping, etc. Is this possible in SagePay?
The desired system is called SagePay Form as far as similarity to PayPal's BuyNow button + PDT process. First, you need to create a FORM like so:
<form action="https://live.sagepay.com/gateway/service/vspform-register.vsp" method="POST" id="SagePayForm" name="SagePayForm">
<input type="hidden" name="VPSProtocol" value="2.23" />
<input type="hidden" name="TxType" value="PAYMENT" />
<input type="hidden" name="Vendor" value="<?= $YOUR_VENDOR_LOGIN_NAME ?>" />
<input type="hidden" name="Crypt" value="<?= $PAYMENT_CRYPT ?>">
<input type="image" src="images/buynow-sagepay.png" />
</form>
(One can swap the live URL with a test one here: https://test.sagepay.com/gateway/service/vspform-register.vsp)
As for the $PAYMENT_CRYPT, you have to first create a string like so:
VendorTxCode=406227821909
&Amount=32.00
&Currency=USD
&Description=1 ACME Widget
&SuccessURL=http://example.com/success.php
&FailureURL=http://example.com/fail.php
&BillingSurname=Smith
&BillingFirstnames=John
&BillingAddress1=123 Main Street
&BillingCity=Anywhere
&BillingPostCode=29555
&BillingCountry=USA
&DeliverySurname=Smith
&DeliveryFirstnames=John
&DeliverAddress1=123 Main Street
&DeliveryCity=Anywhere
&DeliveryPostCode=29555
&DeliveryCountry=USA
It's kind of dumb why they need some of this information when PayPal doesn't, but oh well. The docs clearly say that the thing will error out if they don't receive legitimate values like a real postal code that validates for that city and country, and is also used for problem dispute arbitration.
Note in my example that there's no tax or shipping breakout as PP has, so you'll need to display that as necessary before showing this BuyNow buton, or perhaps on your confirmation page or confirmation email you send. They do have a "&Basket=" parameter where the tax can be specified, but it's redundant to what you can display on your form page yourself and not necessary. Therefore, the &Amount value must be the gross value, not net. There is also no quantity value (which the &Basket parameter could be used to specify). More than likely you'll find the &Basket parameter just redundant to what you can already display on your own form during the checkout process. So, that's why my example didn't include it.
As for the VendorTxCode, that's something you create so that you can track the order back to the appropriate customer.
This $PAYMENT_CRYPT is then encrypted using XOR + Base64 encoding, using the encryption password provided by SagePay. They have an AES + Binhex encryption option, but it's overkill and your server has to have the mcrypt library enabled. Some shared hosting plans STILL don't have the enabled yet!
They provide an XOR example, but it's the typical one you see countless times in Computer Science courses where you repeatedly loop through each ASCII code of the password and each ASCII code of the data and take the complement bit of the other (the XOR process). Once done, feed it through Base64 encoding for safe POST transfer. The Base64 encoding uses the built-in function from PHP.
The response from this is more like PayPal's PDT process than PayPal's IPN process. They do direct someone to success.php and fail.php along with an encrypted URL response via GET that you can unencrypt and parse (base64 decode + XOR), but the difficulty is that the customer can close the form before waiting for the page to redirect. In that case, one will see this in their control panel in SagePay and have to fulfill the transaction manually for the customer.
On the success.php and fail.php it's up to you what you want to do. Once the query string &crypt parameter is unencrypted, you'll be able to parse out whether the transaction is complete or not by looking at Status parameter being "OK".
Note that you don't have to go direct to success.php. You can make it be like success.php?custom=value to pass extra information on the transaction that you can parse. Their code will automatically figure this out and tack on the &crypt= parameter on the end. The same goes with fail.php.
They do have ways to make SagePay send emails to the customer and to the vendor, but it's really overkill because you can do the same thing in your own PHP code with the mail() statement when doing the order.
REFERENCE: Note that the following doc URL may change in the future. To get the latest version of the doc, visit the website, enroll as a developer (a 1 minute process), and search on "form protocol".
http://www.sagepay.com/sites/default/files/downloads/sagepayformprotocolandintegrationguidelines_0.pdf
EDIT: New Link (25th Oct 2017) - https://www.sagepay.co.uk/file/25041/download-document/FORM_Integration_and_Protocol_Guidelines_270815.pdf

How to POST new product in shopify store via api from a private app?

i'm using shopify_app gem and i was able to read to my shop. but then i can't write to it. i have set up the read/write credentials while installing my app so i'm sure the problem's not there. here's what i did to POST a new product in my shop:
product = ShopifyAPI::Product.new
product.title= "Nike Bag"
product.price_range = "27.00"
product.save
but it doesn't save.
Thank you so much. I need this badly.
It looks like this problem has already been solved in the shopify api google group, but just posting it here just in case somebody else finds it useful.
The product above can't be saved because not all required fields are specified. Check the sample in the shopify api docs for a list of required fields. Also check product.errors if save fails, which should give an idea of why it failed.
This should work:
product = ShopifyAPI::Product.new
product.product_type = "Snowboard"
product.title = "Burton Custom Freestlye 151"
product.body_html = "<strong>Good snowboard!</strong>"
product.vendor = "Burton"
product.variants = [ShopifyAPI::Variant.new(:price =>10)]
product.save