How should be the correct http request url in flutter to fetch data from the shopify store? - flutter

How should be the correct HTTP request URL in a flutter to fetch data from the Shopify store?
Any idea or material, how to integrate payment method with Shopify in a flutter when the user clicks the buy button?
I am trying with this line for HTTP requests, but not working
getUserData() async {
var response = await http.get(Uri.https(
'{apikey}:{password}#{hostname}.myshopify.com',
'/admin/api/{version}/{resource}.json'));
var jsonData = jsonDecode(response.body);
print(jsonData);
}
getUserData() async {
var response = await http.get(Uri.https(
'c948656b86f9a9e0bf8beffad653e484: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#verdenapp310.myshopify.com',
'/admin/api/2021-07/graphql.json'));
var jsonData = jsonDecode(response.body);
print(jsonData);
}
print output: I/flutter (31610): {errors: Not Found}

You are going to have to do some work. Study the architecture of the Shopify platform and then decide the correct API to use. In your brief example, you are choosing the Admin API, which is completely wrong for retrieving data from a store, unless you are an App installed in the store, to benefit the merchant experience. Usually, Admin API has nothing to do with customers.
Buy Button has a direct line to Shopify checkout. You do not get to install your own payment gateway through that button. The merchant has to select or install the payment gateway they want to use from their Shop. Note that it is possible to provide for custom payment gateways in Shopify but that is far outside the scope of your SO request here. Again, they have documentation for that too.

Related

Flutter use api and webhook

i wanna work with this api in my flutter app
https://dev.chargily.com/docs/epay-api/
i have done the first part 1.Make Payment
but the second part 2. Payment confirmation i don't know how to do it because it contain webhook
(i wanna get the response sent via webhook_url)
this is the first part 1. Make Payment
final response = await dio
.post(
'http://epay.chargily.com.dz/api/invoice',
options: Options(headers: {
'X-Authorization':
'["API-KEY"]',
'Accept': 'application/json',
}),
data: jsonEncode(params),
)
.then((value) async {
log(value.data['checkout_url']);
var url = await value.data['checkout_url'];
work perfectly
i need the second part 2. Payment confirmation
Webhooks are a fancy word to describe a server calling another server's Web Api Endpoint. so, it's not meant to be used in the frontend.
you can't verify / get payment confirmation directly from a flutter app, you have to host your own backend / serverless function to act as a webhook and report back to the frontend environment.

Authentication flow with Oauth2 in flutter communicating with own api

After some hours of research in vain I stay confused how to do the following:
I have a flutter app which authenticates via OAuth2 to Google (google_sign_in) and Facebook. For Facebook this is the code:
final LoginResult loginResult = await FacebookAuth.instance.login();
final userData = await FacebookAuth.instance.getUserData();
print(userData);
Which prints: {email: john.doe#email.com, id: 123456, name: John Doe}
I already have a webpage with OAuth2 authentication built in Flask/Python. Now I want my users to be able to both use Web and App and share the preferences/data/etc.
How would I achieve that? In my Flask webapp I'm just creating a user in my database if it doesn't exist and then use some authentication headers in subsequent calls. So I thought with the app I could…
send what I got from OAuth to the api and create the user if it does not yet exist
return some sort of token (with a TTL?)
verify the tokens being sent by the app
But this is a lot of custom boilerplate code, I'm sure that this is existing somewhere/somehow. Additionally: How can I be sure someone is not "tampering" my app via decompile, proxying or just plainly calls my api and claiming to be someone else?
My security requirements are medium: The app will eventually have messaging but won't be used for things like money transfer.
I'm considering these options:
PKCE but this looks like the OAuth2 flow would go through my flask api and that sounds too complex (I had a hard time already getting OAuth2 to work in flutter alone)
Resource Owner Password Credentials Grant which sounds like I can somehow pass the results of OAuth2 to my api, get back a token and use this in subsequent requests. However this seems like an outdated protocol (top google results are articles from oracle)
firebase implementation: they use the same flow: first OAuth2 authentication and then passing the credentials into their servers api. On the first time they pass the credentials a user is created and stored in the database, etc. But my reverse engineering skills are not good enough to figure out how it's done.
using a webview and use the oauth2 of my flask website. I'm shying back from this because it would be not a nice mobile experience plus I would not know how to read/store these credentials
After a lot of reading I found a good article on auth0 , in essence there are two options:
Resource Owner Password Flow - use this if you totally trust your app, e.g. when you deploy it to a closed group of users for which you have device management in place. This situation doesn't apply for me and also Auth0 doesn't recommend it. Still, it would have been relatively easy to implement.
PKCE (Proof Key for Code Exchange) - use this when the client cannot be trusted (IMO 99.9% of mobile apps). But this needs some fancy protocol between the mobile app and the server and alone by looking at the flowchart diagram I got headaches
As PKCE looks too complicated to implement myself I decided to go with Firebase, which helps small projects such as mine where you don't want to go through the pain to code the whole PKCE flow yourself.
What I did was:
adding firebase authentication to my flask app, using flask-firebase - this was worth it since it decreased the lines of python code by 40%. Because the module lacks good documentation I wrote this blog post which explains how to use it
adding firebase authentication to flutter. This is very well documented e.g. here
The whole flow then works like this:
flutter triggers the oauth flow for e.g. google
flutter gets back the auth details, including email address, name, etc. (depends on oauth provider)
the auth details are sent to firebase which creates the user if it doesn't exist yet, enriches it with a user id and packs it into an encrypted token
the token is sent to flask, which verifies the token against firebase
flask logs the user in (via flask_login) and returns a session cookie
the session cookie is stored in flutter (using requests) and used for subsequent api calls
to preserve the user logged in even after app close, the session is stored in apps preferences (using shared_preferences)
In essence, this is the code needed (google social login example):
Future<String?> signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
final GoogleSignInAuthentication? googleAuth =
await googleUser?.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
UserCredential userCredentials =
await FirebaseAuth.instance.signInWithCredential(credential);
return userCredentials.user?.getIdToken();
}
…
var cookies = await Requests.getStoredCookies('example.com');
SharedPreferences? prefs;
if (!cookies.keys.contains('session')) {
prefs = await SharedPreferences.getInstance();
if (prefs.containsKey('session')) {
print('cookie not set, load session from prefs');
await Requests.addCookie(
'example.com', 'session', prefs.getString('session')!);
}
}
cookies = await Requests.getStoredCookies('example.com');
if (!cookies.keys.contains('session')) {
print('cookie not set, prefs contain no session, signing in');
String? idToken = await signInWithGoogle();
if (idToken != null) {
await Requests.post('https://example.com/auth/sign-in',
body: idToken,
headers: {'Content-Type': 'application/jwt'},
bodyEncoding: RequestBodyEncoding.PlainText);
var cookies = await Requests.getStoredCookies('example.com');
prefs?.setString('session', cookies['session']!.value);
}
}
var r = await Requests.get('https://example.com/api/something_which_requires_login');
The important part happens with Requests.post: this posts the idToken of firebase to flask, which in turn then verifies the token, calls login_user and returns response with the session cookie header. This cookie is stored by requests and is added to subsequent http requests.
Because this is some mouthful I created this blogpost which explains this in more detail.

Using Stripe API with Flutter Dio package Flutter to Add Cards, Payment Methods, Accounts

Noobish Dev here. I'm developing an app that involves processing payments between customers and a particular service, the app would take a fee and pay the service provider directly to their bank accounts. Looking for advice really or perhaps a better implementation.
Anyway, after watching some tutorials online I developed the app to use my own form to handle a customers card data and send directly to Stripes API with curl request. In this instance to attach the card to a customer account. I find that stripe requires the apps/websites be PCI compliant when handling data and to not use custom form handling for fear of retaining card data, that leaves me stuck as this particular method we use by directly interacting with the API (I'm using Dio) is not recommended by Stripe as advised below.
App screenshot :
The snippet of code (works fine by the way):
Future<void> addCard(
{int cardNumber,
int month,
int year,
int cvc,
String stripeId,
String userId,
String cardHolderName,
String email}) async {
Map body = {
"type": "card",
"card[number]": cardNumber,
"card[exp_month]": month,
"card[exp_year]": year,
"card[cvc]": cvc,
"billing_details[name]": cardHolderName,
"billing_details[email]": email
};
dynamic stripeResponse;
try {
print('Successfully added payment method id $paymentMethodUrl');
Dio dio = Dio();
await dio
.post(paymentMethodUrl,
data: body,
options: Options(
contentType: Headers.formUrlEncodedContentType,
headers: headers))
.then((response) {
print(response.data);
stripeResponse = response;
String paymentId = response.data['id'];
Map stripeCustomer = {"customer": UserData.stripeID};
try {
dio
.post('$paymentMethodUrl/$paymentId/attach',
data: stripeCustomer,
options: Options(
contentType: Headers.formUrlEncodedContentType,
headers: headers))
.then((response) {
print(response.data);
print('Attached successfully');
});
} on DioError catch (e) {
print('Error attaching card to customer: ${e.response.data['error']['message']}');
}
});
} on DioError catch (e) {
print(stripeResponse);
print('Error adding card: ${e.response.data['error']['message']}');
}
}
https://stripe.com/docs/security#pci-dss-guidelines
The easiest way to be PCI compliant is as advised by Stripe:
Use one of our recommended payments integrations to collect payment information, which is securely transmitted directly to Stripe without it passing through your servers
Serve your payment pages securely using Transport Layer Security (TLS) so that they make use of HTTPS
Anyway I would appreciate it if anyone could give me some advice on this or maybe I'm misunderstanding something when it comes to compliance. I might just instead use Apple pay and Google pay if this option is not viable as I don't want to get into trouble if I'm not PCI compliant due to handing card data.
Thanks in advance.
As stated in thisSO post:
The sensitive information governed by PCI (i.e. raw card data) is sent
directly from the client to Stripe. Stripe creates a Payment Method to
represent that data (pm_) and returns that to the client so it can be
referenced from there.
However, Payment Intents must be created server-side in a secure
context with a secret or restricted API key, then the Payment Intent's
client secret should be sent to the client to allow for client-side
confirmation.
The section about validating your PCI compliance in Stripe's integration security guide has more information.
And as mentioned in the comment, you can explore using the plugins to provide all the functions you need for your app. I suggest to look into this flutter_stripe which was published by flutterstripe.io. You can also check out this blog(https://flutterstripe.medium.com/announcing-the-flutter-sdk-for-stripe-1ba2b3ee667c) where it was mentioned about the security feature that the package could offer:
Secure by default
SCA-Ready: The SDK automatically performs native 3D Secure authentication if needed
to comply with Strong Customer
Authentication
regulation in Europe.
PCI compliant: as the plugin does not handle sensitive information (such as credit card credentials) the plugin is PCI
compliant by default. You can find out more about PCI compliance and
why it’s important here.

Flutter oAuth : how to get started with OAuth and Stripe connect

I am trying to implement stripe connect in my flutter app. Here are the steps I need to implement. Can anyone please navigate me on how I could achieve this in Flutter?
I am able to create a button with the endpointUrl but that's all..
Thanks
I found out this myself using firebase cloud functions:
first you create an https function in the firebase cloud function
then you add the link created by the function to your stripe dashboard
then you write the following logic to your function
obtain the the authorisation code
fetch data from stripe
save the response somewhere (in my case in realtime database)
Here is the function
exports.connectStripeStandardAccount = functions.https.onRequest((req, res) => {
let authCode = req.query.code;
return stripe.oauth.token({
grant_type: 'authorization_code',
code: authCode,
}).then(async response => {
await admin.database()
.ref(`/accounts/${authCode}`)
.set(response);
return res.send("Well done, account integration is completed. You can now close the window and go back to the app");
});
});
The answer selected is not completely correct:
If you dont assign the account_id to a user then it's of no use.
The only way to pass the user_id (fUser.uid) is to pass it using the state parameter.
exports.StripePI = functions.https.onRequest(async (req, res) => {
// console.log('accountIdq ' + req.query.error);
// console.log('accountIdq ' + req.query.state);
// return;
// if(!req.query.code)
// return res.send("An Error has occured please try again");
const response = await stripe.oauth.token({
grant_type: 'authorization_code',
code: req.query.code,
}).then(async response => {
var connected_account_id = response.stripe_user_id;
await admin.firestore().collection('Registration').doc(req.query.state)
.update({customer_id : connected_account_id});
return res.send("Well done, account integration is completed. You can now close the window and go back to the app");
});
});
If you want to create an in-app stripe connect account registration with flutter you will need these:
A server or service to complete the OAuth like Firebase Functions or Integromat (I used Integromat)
A link that will redirect to your app (I used Firebase Dynamic Link)
STEPS TO CREATE THE REGISTRATION FLOW
INTEGROMAT/FIREBASE FUNCTIONS SETUP
I decided to use Integromat instead of Firebase Functions because is easier to set up, doesn't need any code, and decreases my server load.
If you want to create it on Firebase Functions you will need to have a Blaze Plan
If you don't know it, Integromat will automate processes that you currently handle manually, via webhooks. It is not only capable of connecting apps (like GoogleCloud, Facebook, AWS...) but can also transfer and transform data.
Create a new scenario and add a Custom Webhook. Click on it and click on add, name it, and save it. It will now create a custom link to your webhook.
Close and click on the semi-sphere next to the webhook, to add the new module.
Select HTTP and Make a Request.
In the URL section insert https://connect.stripe.com/oauth/token.
Method POST.
Body Type Application/x-www-form-urlencoded.
Create now those fields :
Key client_secret - value your stripe client secret You can find it on your stripe dashboard. I advise you to first use the test mode and after that, change the value to the live key.
Key grant_type - value authorization_code
Key code - leave the value blank. We will add it later.
Save and close
For Firebase Functions you can create a new HTTPS function (I didn't test this)
var stripe = require("stripe")(*your stripe client secret*);
exports.connectStripeStandardAccount = functions.https.onRequest((req, res) =>{
let authCode = req.query.code;
return stripe.oauth.token({
grant_type: 'authorization_code',
code: authCode,
});
});
Remember to install stripe package npm install stripe
STRIPE SETUP
If you are in the test mode go to this link
If you are in the live mode go to this link
Go on the bottom and activate oAuth for standard accounts or for Express Account.
Click on Add URI and add the webhook link of Integromat that you created or the link related to your Firebase function.
If you used Firebase add this link https://us-central1-<project-id>.cloudfunctions.net/connectStripeStandardAccount
For Integromat you will need to create the structure. To do this click on Test OAuth, copy the link, and open it in incognito mode. Open your Integromat scenario and click on your webhook. Now click on Re-determine data structure.
Return to your stripe registration page and click on Ignore account form at the top.
Return on Integromat and select the HTTPS request, modify the field code, and insert the variable code (will open a dialog with all queries from the webhook). Confirm and save.
Now click on the play button and reopen the stripe registration link in incognito mode and click on Ignore account form. Return in Integromat and add a JSON module after the HTTPS request. In the JSON string insert the Data variable and save. Create a Webhook Response module after the JSON module.
In the status put 301, then click on Ok.
DEEP LINK SETUP
It's time to set up the redirect link that will return the user to our flutter app or on our website if the user hasn't it installed.
I used Firebase Dynamic Link You can follow this tutorial for set up.
Go to the dashboard and create a new Link prefix and a new dynamic link, remember to select to redirect your users to the right app.
Click on the three dots in your dynamic link row and click on Link Details. Copy the extended link.
Open Integromat and select the last module you created (Webhook Response). Click on Show advanced settings and on the Header add :
Key Location - value the extended dynamic link that you copied.
If you want your app to elaborate data from the stripe OAuth response you can modify the extended dynamic link by adding ? on the link parameter: link=https://test.page.link?stripe_user_id={{14.stripe_user_id}}
And select the variable parsed from the JSON module. Remember to click on the save icon to save your scenario.
On Firebase Functions you can do this when the function stripe.oauth.token finish (I didn't test it):
res.setHeader('Location', your dynamic link);
res.status(301).send();
Remember to deploy it.
FLUTTER APP SETUP
The code here is very simple. To initialize the connect account registration you only need to set up a button that will launch the stripe connect URL. You can use launch(url);
You can find that URL here. Remember to be logged in to your stripe account to get the right stripe client id. You can easily get it in the same section you added the webhook link in your stripe connect settings.
Delete &redirect_uri=https://sub2.example.com on the URL.
Now you can test your app and will see that when you complete your stripe connect registration/login you will be redirected to your app.
If you want to have an in-app web view you can use this package
To handle the response, you need to have installed the package firebase_dynamic_links
Set your Main widget Stateful and on the initState run the method getDynamic() :
void getDynamic() {
FirebaseDynamicLinks.instance.getInitialLink().then((value) {
if (value != null) {
_connect(value);
}
});
FirebaseDynamicLinks.instance.onLink(onSuccess: (value) async {
if (value != null) {
_connect(value);
}
}, onError: (error) async {
debugPrint('DynamicLinks onError $error');
});
}
void _connect(value) {
Uri deepLink = value.link;
print("Link :" + deepLink.path);
print("Query :" + deepLink.queryParameters.toString());
String stripeUserId = deepLink.queryParameters["stripe_user_id"];
}
You need to have both of them to handle dynamic links when your app is running and when it's closed.

How to access response from Paypal Express Checkout?

I am integrating PayPal Express Checkout as shown here.
https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/basic-integration/
I am processing the payment successfully, when the transaction has been authorized I am using actions.payment.get(); to get the information about the transaction.
This returns an object called SyncPromise with all the data I want to use.
console screenshot here
I have tried:
var response = actions.payment.get();
response.value
But I get undefined.
Does anyone how can I access the object element?
You need to call like so:
actions.payment.get().then(function(data) {
console.log(data);
});