I create a payment through sofort, ideal, pass the specified parameters and every time I get an error-
Error from Stripe: Invalid Payment Intent client secret: src_client_secret_**********************
final paymentIntent = await Stripe.instance.confirmPayment(
paymentIntentClientSecret: clientSecret,
data: PaymentMethodParams.sofort(
paymentMethodData: PaymentMethodDataSofort(country: 'de'),
),
);
clientSecret-the key is generated without any problems
payment by card is fine
What am I doing wrong?
I am using the latest versions of the libraries: flutter_stripe: ^7.0.0
I looked through all the information in the library and couldn't find anything
Related
I need a callback URL so that when a mobile money API completes a payment transaction, my app can receive a message about the transaction status. I'm building a flutter app. I have seen that cloud functions may be the answer. So, I need help on how to get started on creating this callback URL.
I'm yet to try anything because all the material I have seen talks about JavaScript and websites. I need material on doing this in the flutter mobile app.
look at this snippet I hope it helps
// await for your first function t
await moneyFuntion()
.whenComplete(() async => await anotherAPIFuntion())
.onError((error, stackTrace) {
log("$error");
I use the latest version of sign_in_with_apple using the following code to allow signing in with Apple to my Flutter app on Android.
final credential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
webAuthenticationOptions: WebAuthenticationOptions(
clientId: '***Service Identifier***',
redirectUri:
// For web your redirect URI needs to be the host of the "current page",
// while for Android you will be using the API server that redirects back into your app via a deep link
kIsWeb ? Uri.parse('https://${window.location.host}/') : Uri.parse('https://***Backend***/callback'),
),
nonce: nonce,
);
I have taken the code for the backend from the package README.md:
apple_router.post("/callback", (request, response) => {
console.log(">>> Apple callback received <<<");
console.log("Body:");
console.log(request.body);
console.log("Query:");
console.log(request.query);
console.log("Params:");
console.log(request.params);
const redirect = `intent://callback?${new URLSearchParams(
request.body
).toString()}#Intent;package=${process.env.ANDROID_PACKAGE_IDENTIFIER
};scheme=signinwithapple;end`;
console.log(`Redirecting to ${redirect}`);
response.redirect(307, redirect);
});
I have also configured everything at Apple with the correct domains, but on my backend, when I log into the app, only an empty request arrives:
>>> Apple callback received <<<
Body:
{}
Query:
{}
Params:
{}
Redirecting to intent://callback?#Intent;package=***Android package ID***;scheme=signinwithapple;end
Which is why it doesn't work properly in the app either:
E/flutter (27962): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: SignInWithAppleAuthorizationError(AuthorizationErrorCode.invalidResponse, parseAuthorizationCredentialAppleIDFromDeeplink: No `code` query parameter set))
I have checked everything several times and I no longer have any idea where this problem could come from. Does anyone have any ideas?
Using this sign_in_with_apple apple will provide you the email, fullName, etc. information only for the first authorizations.
So, you have to take few steps to apple authorization.
Flutter/client side code/mechanism
void loginSignUpWithApple() async {
SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName
],
).then((value) {
_socialLoginSignUp(value.authorizationCode, describeEnum(LoginMethod.APPLE));
}).catchError((e) {
showMessage("Something went wrong: $e", isError: true);
});
}
Backend side code/mechanism
Generate JWT using apple key id and private key
Get auth token from apple server by using generated jwt and clint sent authorizationCode then extract the IdToken from the auth token response
Decode the IdToken and get the IdTokenHeader
From the IdTokenHeader get the kId
Using the kId get the list of keys from apple server then extract the actual key
Using the actual key create apple key to public key
Using public key and IdToken get the claims then decode the claim to get the user email
After getting the user email you can store this email in your database or other place and you can trust this is mail as a valid apple mail.
You can see the backend implementation code which is we have implemented previously in java (spring boot).
Sample backend code for apple login (Try with VPN if link is not working)
I found the problem: if you are using express as your server, add
bodyParser.urlencoded({ extended: true })
as middleware for your callback handler and then request.body will not be empty.
Description
Using flutter_stripe package, version ^1.2.0, to perform payment on the front end, Google pay button wasn't displayed on the paymentSheet despite setting the flag googlePay: true in SetupPaymentSheetParameters while initializing the payment sheet using Stripe.instance.initPaymentSheet().
The examples project of the package doesn't provide information about configuring google pay in payment sheet other than setting the flag to true, so i followed these instructions form stripe's documentations to integrate google pay but the button still not displayed on the sheet.
My Code
stripe initialization
Stripe.publishableKey = dotenv.env['STRIPE_PUB_KEY'];
Stripe.instance.applySettings();
payment sheet methods
Future<void> initializePaymentSheet(
PaymentCredentials credentials,
) async {
Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
applePay: Stripe.instance.isApplePaySupported.value,
googlePay: true,
style: ThemeMode.dark,
testEnv: true,
merchantCountryCode: 'USA',
merchantDisplayName: 'Our App. Inc.',
customerId: credentials.clientId,
paymentIntentClientSecret: credentials.paymentIntent,
customerEphemeralKeySecret: credentials.eKey,
customFlow: false,
),
);
}
Future<void> presentPaymentSheet(String paymentIntent) async =>
Stripe.instance.presentPaymentSheet(
parameters: PresentPaymentSheetParameters(
clientSecret: paymentIntent,
confirmPayment: true,
),
);
What is missing to display this button on the sheet?
as #Romeo said in the comments above, Google pay button was displayed when gPay app is installed and there is at least one card available on it.
I was using separate google pay button on my app using pay plugin and it was displayed along with google pay sheet so i figured it should be shown on stripe's payment sheet as well.
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.
I have to integrate PayPal payments in Flutter and the only plugin that seems to have this kind of functionality is flutter_braintree. But the documentation there is not so detailed, so I am kind of confused how to use this plugin to have real payments. My mission is to have this kind of flow: click on a PayPal button in the app and then proceed with PayPal paying to a predefined IBAN. I tried to examine the PayPal and Braintree documentations, but since there is nothing mentioned for Flutter, I am a little bit confused.
Please help me what's the right direction to go in order to fulfil my requirements. I have the following questions:
How to use this plugin and make real payments? What do I need - a client token as far as I see, but I am going to generate this in Flutter?
Where should I put the IBAN that I want the money to be transferred to?
Am I supposed to use some kind of webviews for the PayPal, or this plugin is enough?
Thank you in advance, I am really stuck on this topic and can't find a solution.
Generate clientToken in php | nodejs see: https://developers.braintreepayments.com/reference/request/client-token/generate/php
$clientToken = $gateway->clientToken()->generate([
"customerId" => '21534539348326'//create customer in panel
]);`
Generate paymentNonce in app flutter:
BraintreePayment braintreePayment = new BraintreePayment();
var data = await braintreePayment.showDropIn(
nonce: clientNonce,
amount: "2.0",
inSandbox: true,
);
print("Response of the payment $data");
// exe: Generate transaction in php | nodejs see: https://github.com/braintree/braintree_php
$result = $gateway->transaction()->sale([
'amount' => '1000.00',
'paymentMethodNonce' => 'nonceFromTheClient',
'options' => [ 'submitForSettlement' => true ]
]);