I'm trying to accept payment but getting this error in callback of sdk.
Code:
val params = cardInputWidget.paymentMethodCreateParams
if (params != null) {
val confirmParams =
ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams(params, clientSecret)
stripe = Stripe(
applicationContext,
PaymentConfiguration.getInstance(applicationContext).publishableKey)
stripe.confirmPayment(this, confirmParams)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
stripe.onPaymentResult(requestCode, data, object : ApiResultCallback<PaymentIntentResult> {
override fun onSuccess(result: PaymentIntentResult) {
val paymentIntent = result.intent
val status = paymentIntent.status
if (status == StripeIntent.Status.Succeeded) {
val gson = GsonBuilder().setPrettyPrinting().create()
showToast("Payment succeeded " + gson.toJson(paymentIntent))
} else {
showToast("Payment Error: "+paymentIntent.lastPaymentError?.message ?: "")
}
}
override fun onError(e: Exception) {
showToast("Payment failed "+e.message)
}
})
}
onError is getting always called!
This is internal code of sdk:
You are using confirmPayment method instead of confirmSetupIntent method. One is used for confirming payment intents with client secret, and the other one is used for confirming setup intents with client secret. Checkout the stripe documentation for saving and reusing payment methods: https://stripe.com/docs/payments/save-and-reuse
Related
i'm actually new to Kotlin android development. I'm making an app that uses Google sheets as a database. My app can successfully run after Google sign in. In fact I want my user to sign in to app, if their email ID is present in the Emails sheet in the Google sheet. So I have done following steps in my code so far.
Sign in user with Google Sign In
Retrieve data from "Emails" sheet in my Google Spreadsheet
Then store them in to a data class (Customers data class in Shipment.kt)
Then I check whether signed in user's email ID available in the data class or not. This is where I need help. It's giving me this error
"Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly."
Can someone help me on this?
Below is my data class in Shipment.kt
package com.example.demoonlinesheet
data class Shipments(
val shipperName:String,
val volume:String,
val eta:String,
val etd:String)
data class Customers(
val companyName:String,
val customerName:String,
val emailID:String)
Below is the code that I have written so far in MainActivity.kt
const val RC_SIGN_IN = 123
const val EXTRA_MESSAGE = "com.example.demoonlinesheet.MESSAGE"
const val EXTRA_MESSAGE2 = "com.example.demoonlinesheet.MESSAGE"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build()
// Build a GoogleSignInClient with the options specified by gso.
var mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
sign_in_button.setOnClickListener{
val signInIntent = mGoogleSignInClient.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
val acct = GoogleSignIn.getLastSignedInAccount(this)
if (acct != null) {
startActivity(Intent(this, SecondActivity::class.java).apply{
putExtra(EXTRA_MESSAGE, acct.displayName)
//putExtra(EXTRA_MESSAGE2, acct.email)
} )
}
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
// The Task returned from this call is always completed, no need to attach
// a listener.
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
handleSignInResult(task)
}
}
private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
val companyList= arrayListOf<Customers>()
val url="https://sheets.googleapis.com/v4/spreadsheets/{sheetID}/values/{sheetName}?alt=json&key={APIKey}"
val queue = Volley.newRequestQueue(this)
val jsonObjectRequest = JsonObjectRequest(Request.Method.GET, url, null,
{
fun onResponse(response: JSONObject) {
try {
// val feedObj = response.getJSONObject("")
val entryArray = response.getJSONArray("values")
for (i in 2 until entryArray.length()) {
val entryObj = entryArray.getJSONArray(i)
val companyName = entryObj[0].toString()
val customerName = entryObj[1].toString()
val emailID = entryObj[2].toString()
// entryObj.getJSONObject("gsx\$lastname").getString("\$t")
companyList.add(Customers(companyName, customerName, emailID))
}
} catch (e: JSONException) {
e.printStackTrace()
}
}
}, {
fun onErrorResponse(error: VolleyError?) {
Toast.makeText(this#MainActivity, "Fail to get data..", Toast.LENGTH_SHORT)
.show()
}
})
queue.add(jsonObjectRequest)
fun checkUser() {
val getAccount = completedTask.getResult(ApiException::class.java)
val emailLoggedIn = getAccount.email.toString()
val companies = listOf<Customers>()
//this is where I get the error message "Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly."
if (emailLoggedIn in companies){
//do something here
}
try {
val account = completedTask.getResult(ApiException::class.java)
val loggedname = account.displayName
//startActivity(Intent(this#MainActivity, SecondActivity::class.java))
val intent = Intent(this, SecondActivity::class.java).apply {
putExtra(EXTRA_MESSAGE, loggedname)
}
startActivity(intent)
} catch (e: ApiException) {
}
}
}
From your code:
if (emailLoggedIn in companies) {
//do something here
}
emailLoggedIn is a String, companies is a List<Customers>.
How does List know how to compare String and Customers? :)
You need something like this:
if (companies.any { it.emailID == emailLoggedIn }){
//do something here
}
I should also mention that you can leave the if condition unchanged and add the following code that overloads the in keyword:
operator fun List<Customers>.contains(email: String): Boolean {
return this.any { it.emailID == email }
}
But, in my opinion, this overload looks terrible and confusing :)
I try to make an storage where i can save my image in firebase storage but everytime i upload a new image it will replace the old one,i want evertime a new image will be save on storage,i am on android studio using kotlin,Is my code is wrong?here is my code
class Activity2 : AppCompatActivity() {
var curFile: Uri? = null
val imageRef = Firebase.storage.reference
private val userCollection = Firebase.firestore.collection("persons")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity2)
//here where a button to get an image from gallery
tvpilihfoto.setOnClickListener {
Intent(Intent.ACTION_GET_CONTENT).also {
it.type = "image/*"
val REQUEST_CODE_IMAGE_PICK = 0
startActivityForResult(it, REQUEST_CODE_IMAGE_PICK)
}
//this button for an upload activity to send the image to database firebase
btnupload.setOnClickListener {
uploadImageToStorage("my image")
}
}
private fun uploadImageToStorage(filename : String) = CoroutineScope(Dispatchers.IO).launch {
try {
curFile?.let {
imageRef.child("images/$filename").putFile(it).await()
withContext(Dispatchers.Main) {
Toast.makeText(this#Activity2,"Foto anda telah dipilih",
Toast.LENGTH_LONG).show()
}
}
} catch (e : Exception) {
withContext(Dispatchers.Main) {
Toast.makeText(this#Activity2,e.message,Toast.LENGTH_LONG).show()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val REQUEST_CODE_IMAGE_PICK = 0
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGE_PICK) {
data?.data?.let {
curFile = it
ivfoto.setImageURI(it)
//this where my image get or display in app
}
}
}
}
Since you're always calling uploadImageToStorage("my image"), the image will alway be called my image. So each time you make that call, it will overwrite the previous my image in storage.
To always add a new image, generate a unique filename in your code. For example:
uploadImageToStorage(UUID.randomUUID().toString())
I get this output on firebase: "Cannot determine payment method"
Note: I don't have too much knowledge on JavaScript and Firebase functions and can't get this to work.
I have been following Braintree's guide to setting up the payment method. This is the flow of events:
Step 1
Your front-end requests a client token from your server and initializes the client SDK.
Step 2
Your server generates and sends a client token back to your client using the server SDK.
Step 3
The customer submits payment information, the client SDK communicates that information to Braintree and returns a payment method nonce.
Step 4
Your front-end sends the payment method nonce to your server.
Step 5
Your server code receives the payment method nonce and then uses the server SDK to create a transaction.
So far I've been stuck at step 5. The nonce gets posted to my Firebase database in the following format:
-nonce
-LsHNQLklFEX48oiSt1H:"tokencc_bc_vbmypn_dvn4gy_xy47fw_th6vv9_bq6"
-LsHn2hilKlmVeT1g1Ow: tokencc_bf_8qrjsk_j7bg44_p8kk88_qz7vn2_vk6"
How would i go about step 5?
Functions code:
'use strict';
const functions = require('firebase-functions');
const express = require('express');
const app = express();
const braintree = require('braintree');
const admin = require('firebase-admin');
admin.initializeApp();
var clientToken;
var nonceFromTheClient;
var transaction;
var gateway = braintree.connect({
environment: braintree.Environment.Sandbox,
merchantId:"",
publicKey: "",
privateKey: ""
});
exports.createToken = functions.https.onRequest((request, response) => {
gateway.clientToken.generate({}, function (err, response) {
if (err){
console.log('inside error',err);
} else {
clientToken = response.clientToken;
}
});
response.send(clientToken);
});
exports.createTransaction = functions.https.onRequest((req, res) => {
app.post("/nonce", function (req, res) {
nonceFromTheClient = req.body.payment_method_nonce;
console.log("nonce" + nonceFromTheClient)
});
gateway.transaction.sale({amount: '10.00', paymentMethodNonce: nonceFromTheClient, options: {submitForSettlement: true}}, function (err, result) {
if (err) {
console.error(err);
return;
}
if (result.success) {
console.log('Transaction status: ' + result.transaction.status);
} else {
console.error(result.message);
}
});
res.send(transaction);
});
Activity code:
if (cardPayment.isChecked) {
val client = AsyncHttpClient()
client.get(
"https://.../createToken",
object : TextHttpResponseHandler() {
override fun onFailure(
statusCode: Int,
headers: Array<out Header>?,
responseString: String?,
throwable: Throwable?
) {
}
override fun onSuccess(
statusCode: Int,
headers: Array<Header>,
clientToken: String
) {
mClientToken = clientToken
onBraintreeSubmit(it)
}
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CODE && data != null) {
if (resultCode == Activity.RESULT_OK) {
val result =
data.getParcelableExtra<DropInResult>(DropInResult.EXTRA_DROP_IN_RESULT)
val nonce = result.paymentMethodNonce?.nonce
if (nonce != null) {
FirebaseShoppingCartDatabase.postNonceToDatabase(nonce)
val client = AsyncHttpClient()
client.get(
"https://..../createTransaction",
object : TextHttpResponseHandler() {
override fun onFailure(
statusCode: Int,
headers: Array<out Header>?,
responseString: String?,
throwable: Throwable?
) {
}
override fun onSuccess(
statusCode: Int,
headers: Array<Header>,
clientToken: String
) {
}
})
}
} else if (resultCode == RESULT_CANCELED) {
} else {
// handle errors here, an exception may be available in
val error = data.getSerializableExtra(DropInActivity.EXTRA_ERROR) as Exception
System.out.println("eroare " + error)
}
}
}
fun onBraintreeSubmit(v: View) {
val dropInRequest = DropInRequest()
.clientToken(mClientToken)
dropInRequest
.disablePayPal()
startActivityForResult(dropInRequest.getIntent(context), REQUEST_CODE)
}
}
Got it to work. I was passing the nonce to the server incorrectly. (using a different URL)
I'm trying to use AWS Cognito user pools in combination with the AWS API Gateway.
Logging in works fine, when entering the credentials the success handler is called and I can see the credentials. When verifying the JWT token at jwt.io I can also see that the user is correct.
However, when calling the API Gateway using the ApiClientFactory I always receive an error: com.amazonaws.mobileconnectors.apigateway.ApiClientException: Basic (classic) flow is not supported with RoleMappings, please use enhanced flow. (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: InvalidParameterException; Request ID: 1a61f1fd-91d8-11e8-82bc-675071b1c307) (Service: null; Status Code: 0; Error Code: null; Request ID: null)
Please see my code below:
Main activity:
AWSMobileClient.getInstance().initialize(this) {
// Obtain the reference to the AWSCredentialsProvider and AWSConfiguration objects
// Use IdentityManager#getUserID to fetch the identity id.
IdentityManager.getDefaultIdentityManager().getUserID(object : IdentityHandler {
override fun onIdentityId(identityId: String) {
Log.d("MainActivity", "Identity ID = " + identityId)
}
override fun handleError(exception: Exception) {
Log.d("MainActivity", "Error in retrieving the identity" + exception)
}
})
}.execute()
LoginFragment:
val authenticationHandler = object : AuthenticationHandler {
override fun getAuthenticationDetails(continuation: AuthenticationContinuation, userID: String) {
val authDetails = AuthenticationDetails(inputUsername.text.toString(), inputPassword.text.toString(), null)
// Now allow the authentication to continue
continuation.setAuthenticationDetails(authDetails)
continuation.continueTask()
}
override fun onSuccess(userSession: CognitoUserSession, newDevice: CognitoDevice?) {
progressLoader.visibility = View.GONE
(activity as? OnboardingActivity)?.proceedAfterLogin()
}
override fun onFailure(exception: Exception) {
progressLoader.visibility = View.GONE
val snackbar = Snackbar.make(view, R.string.ERR_GENERAL, Snackbar.LENGTH_LONG)
snackbar.show()
progressLoader.visibility = View.GONE
}
override fun getMFACode(continuation: MultiFactorAuthenticationContinuation) {
continuation.continueTask()
}
override fun authenticationChallenge(continuation: ChallengeContinuation) {
continuation.continueTask()
}
}
loginButton.setOnClickListener {
val userPool = CognitoUserPool(context, AWSMobileClient.getInstance().configuration)
val user = userPool.getUser(inputUsername.text.toString())
progressLoader.visibility = View.VISIBLE
user.getSessionInBackground(authenticationHandler)
}
Api client:
val factory = ApiClientFactory().credentialsProvider(AWSMobileClient.getInstance().credentialsProvider)
val = factory.build(MyClient::class.java)
try {
val request = GetChallengesRequest("", nextPageKey)
val response = client.getRunningChallenges(request)
} catch (t: Throwable) {
// This catch is allways called with the error
}
The config is loaded using the awsconfiguration.json which is stored in the raw resource folder.
When setting a breakpoint in AWS4Signer sign method I can see the sign method is called with AnonymousAWSCredentials but I really can't figure out why, as I call the method after logging in.
I hope someone can help me resolve this weird issue, it's been bugging me for days!
I am able to upload to google drive using accounts added in Android phone .I followed steps as told in http://www.youtube.com/watch?v=Ied1CjJ0iP0 . What i actually want to do is to upload to a single account from multiple phones via a service as a background process .How can i do it .
I did this by first logging in using the normal method from my fragment
private fun upload() {
Log.i(TAG, "Start sign in")
val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.build()
val googleSignInClient = GoogleSignIn.getClient(this.requireActivity(), signInOptions)
startActivityForResult(googleSignInClient.signInIntent, MyFragment.REQUEST_CODE_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
MyFragment.REQUEST_CODE_SIGN_IN -> {
if (resultCode == Activity.RESULT_OK) {
Log.i(TAG, "Signed into drive ok.")
//Create an intent for starting the service
//Add whatever data you need to the intent
val intent = Intent(context, UploadService::class.java)
requireContext().startService(intent)
}
}
}
Then in the UploadService
override fun onHandleIntent(intent: Intent?) {
if (intent == null) {
return
}
val lastSignedInAccount = GoogleSignIn.getLastSignedInAccount(this) ?: throw IllegalStateException("Not logged in")
val driveClient = Drive.getDriveClient(this, lastSignedInAccount)
val driveResourceClient = Drive.getDriveResourceClient(this, lastSignedInAccount)
.... Do what you need to do here
}
Remember to add the service to your AndroidManifest.xml
<service
android:name=".UploadService"
android:enabled="true"
android:exported="false" />