I am developing an android application which includes in-app Paypal payments for buying coins.
I am using the official sdk https://github.com/paypal/android-checkout-sdk with latest version 0.3.0.
I am facing the following error when clicking Paypal Button in LIVE mode
I have the following configuration in my code
val environment: Environment = if (resources.getBoolean(R.bool.production)) Environment.LIVE else Environment.SANDBOX
val config = CheckoutConfig(
this,
getString(R.string.paypal_client_id), environment,
"by.the.way://paypalpay", CurrencyCode.USD, UserAction.PAY_NOW,
SettingsConfig(
true,
false
)
)
setConfig(config)
This is the code for buying coins:
btnPaymentPayPal.setup(object : CreateOrder {
override fun create(createOrderActions: CreateOrderActions) {
val purchaseUnits = ArrayList<PurchaseUnit>()
purchaseUnits.add(
PurchaseUnit.Builder()
.amount(
Amount.Builder()
.currencyCode(CurrencyCode.USD)
.value(coinsPakageModel.price.toString())
.build()
)
.description(coinsPakageModel.name)
.build()
)
val order: Order = Order.Builder().appContext(
AppContext.Builder()
.userAction(UserAction.PAY_NOW)
.build()
).intent(OrderIntent.CAPTURE)
.purchaseUnitList(purchaseUnits).build()
createOrderActions.create(order)
}
},
object : OnApprove {
override fun onApprove(approval: Approval) {
approval.orderActions.capture(object : OnCaptureComplete {
override fun onCaptureComplete(result: captureOrderResult) {
//...
}
})
}
},
object : OnCancel {
override fun onCancel() {
//...
}
},
object : OnError {
override fun onError(errorInfo: ErrorInfo) {
//...
}
}
)
And this is my Paypal Configuration in developers dashboard. My account is a business account :
Actually I was trying to get Paypal integration to work in PRODUCTION mode, so you need enable email and full name in live mode, but first you need to pass the paypal review process.
Related
I'm trying to fetch list of Client in my App.
I made Ktor backend and put clients there. Im using Retrofit for fetching and Hilt for DI.
In my android app i made api:
#GET("/clients")
fun getAllClients(): List<Client>
In clientListRepoImpl:
override fun getAllClients(): List<Client> {
return clientTrackerApi.getAllClients()
}
In ViewModel I call interface clientRepository:
init {
viewModelScope.launch {
val clients = clientsRepository.getAllClients()
}
}
In listScreen:
val viewModel = hiltViewModel<ClientListViewModel>()
val myContext = LocalContext.current
LaunchedEffect(key1 = myContext) {
viewModel.viewModelScope.launch {
Log.d(TAG, "ClientsListScreen:")
}
}
I also got this error:
java.lang.IllegalArgumentException: Unable to create call adapter for
java.util.List<android.tvz.hr.clienttracker.data.domain.model.Client
I checked that ktor is returning Client e.g. of 1 Client:
[
{
"id": 1,
"name": "Ronnie",
"age": 23,
"picture": "content://com.android.providers.media.documents/document/image%3A18",
"aboutUser": "something"
}
]
EDIT:
client model:
data class Client(
val id: Int,
val name: String,
val age: Int,
val picture: String? = null,
val aboutUser: String? = null,
)
Im trying to fetch list of Client from my backend to show it in LazyList in Compose.
You either need to make getAllClients() suspended function or return Call<List<Client>>. The second one will make your code look like this:
val call = clientsRepository.getAllClients()
call.enqueue(object: Callback<PlacesFoo>() {
override fun onResponse(Call<List<Client>> call,
Response<List<Client>>response) {
}
override fun onFailure(Call<List<Client>> call, Throwable t) {
}
})
Also use auto completion by android studio don't copy paste this, there could be a mistake.
I followed this guide https://developers.google.com/admob/ump/android/quick-start and my code looks like this:
private fun checkForConsent() {
/*
val debugSettings = ConsentDebugSettings.Builder(this)
.setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
.addTestDeviceHashedId("69887E2CBBE5346EC3B54A3FD207AB41")
.build()
val params = ConsentRequestParameters.Builder()
.setConsentDebugSettings(debugSettings)
.build()
*/
Log.d("adstuff", "check Consent")
val params = ConsentRequestParameters.Builder().build()
// Set tag for under age of consent. Here false means users are not under age
//Log.d("adstuff", params.isTagForUnderAgeOfConsent.toString())
consentInformation = UserMessagingPlatform.getConsentInformation(this)
//consentInformation.reset();
consentInformation.requestConsentInfoUpdate(
this,
params,
object : ConsentInformation.OnConsentInfoUpdateSuccessListener {
override fun onConsentInfoUpdateSuccess() {
// The consent information state was updated.
// You are now ready to check if a form is available.
Log.d("adstuff", "Is consentform available")
Log.d("adstuff", consentInformation.isConsentFormAvailable.toString())
if (consentInformation.isConsentFormAvailable) {
Log.d("adstuff", "Consentform is available")
loadForm()
}
}
},
object : ConsentInformation.OnConsentInfoUpdateFailureListener {
override fun onConsentInfoUpdateFailure(formError: FormError) {
// Handle the error.
Log.d("adstuff", "content info update failure")
Log.d("adstuff", formError.toString())
}
})
}
However, consentInformation.isConsentFormAvailable returns false. I made an AdMob account and a Funding Choices account where I created and published a message of type Consent TCF. I have also added the ca-app-pub ID to the Android Manifest.
Thanks
Edit: If I set the location to the EEA using the debug settings, like in the commented code, the consent info update fails.
In your phone go to Settings > Privacy > Advanced > Ads and toggle off "Opt out of Ads Personalization"
Docusign Android SDK useTemplate Offline mode does not work.
I'm trying to use useTemplate function with isOffline = false, but when I call the function
useTemplate, it does not respond, neither successful nor error.
Here is the useTemplate function:
private fun useTemplate() {
templateDelegate.useTemplate(context, templateId, envelopeDefaults, false, object : DSUseTemplateListener {
override fun onComplete(envelopeId: String) {
Log.e(DOCUSIGN_TAG, "useTemplate template has been successfully signed")
}
override fun onCancel(templateId: String, envelopeId: String?) {
Log.e(DOCUSIGN_TAG, "useTemplate the signing ceremony is cancelled")
}
override fun onError(exception: DSTemplateException) {
Log.e(DOCUSIGN_TAG, "useTemplate error using the template or during signing")
}
})
}
If 'isOffline' parameter is passed as false in useTemplate api, it should launch Online Signing. Online Signing in SDK is not supported yet and will be available in future releases. We currently have support for Offline Signing. So, you can try passing true for 'isOffline' parameter which will launch Offline Signing mode.
templateDelegate.useTemplate(context, templateId, envelopeDefaults, true, ...)
Otherwise if you pass 'issOffline' parameter as true, it throws DSSigningException.
I am trying to implement MSAL in Android for logging in user using their Microsoft credentials.
On clean install, first time I am able to get the token, and use it further for accessing Microsoft Graph API.
As expiry time for MSAL token is 1 hour by default, after 1 hour if I try to re-start the app, I face token authentication exception.
Now I am stuck on how to refresh the token again ?
In MSAL I have followed the examples, but nowhere is there any mention of refreshing a token using Android SDK [we can use API calls otherwise to get and refresh token, but I am not using API approach, I am using SDK for handling all the flow.]
I am trying to get through this for some days now.
private val AUTHORITY = "https://login.microsoftonline.com/common"
private var mSingleAccountApp: ISingleAccountPublicClientApplication? = null
private var mActiveAccount: MultiTenantAccount? = null
fun startTokenProcess(
activity: LoginActivity,
preferenceManager: PreferenceManager
) {
this.mActivity = activity
this.mPreferences = preferenceManager
mSingleAccountApp = null
// Creates a PublicClientApplication object with res/raw/auth_config.json
PublicClientApplication.createSingleAccountPublicClientApplication(activity,
R.raw.auth_config,
object : IPublicClientApplication.ISingleAccountApplicationCreatedListener {
override fun onCreated(application: ISingleAccountPublicClientApplication?) {
// initialization of ISingleAccountPublicClientApplication object
mSingleAccountApp = application
// check for existence of any account linked in cache
mSingleAccountApp?.getCurrentAccountAsync(object :
ISingleAccountPublicClientApplication.CurrentAccountCallback {
override fun onAccountLoaded(activeAccount: IAccount?) {
if (activeAccount == null) {
// nothing found
// start new interactive signin
mSingleAccountApp?.signIn(mActivity, "", getScopes(),
object : AuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult?) {
mActiveAccount =
authenticationResult?.account as MultiTenantAccount?
// save access token in SP
authenticationResult?.accessToken?.let {
mPreferences.putString(
KEY_ACCESS_TOKEN,
it
)
}
callGraphAPI(authenticationResult?.accessToken)
}
override fun onCancel() {
Timber.d("Canceled")
}
override fun onError(exception: MsalException?) {
Timber.d(exception?.errorCode)
}
})
} else {
// Founded an valid account in cache
// get account token from SP, call Graph API
// todo: check if access token expired ? ask for new token, clear SP
mActiveAccount = activeAccount as MultiTenantAccount?
val accessToken = mPreferences.getString(KEY_ACCESS_TOKEN)
if (accessToken != null) {
callGraphAPI(accessToken)
}
}
}
override fun onAccountChanged(
priorAccount: IAccount?,
currentAccount: IAccount?
) {
Timber.d("Founded an account $priorAccount")
Timber.d("Founded an account $currentAccount")
}
override fun onError(exception: MsalException) {
Timber.e(exception)
}
})
}
override fun onError(exception: MsalException?) {
Timber.e(exception)
}
})
}
I have tried to get token Silently and Interactively again, but no success.
SILENTLY:
mSingleAccountApp?.acquireTokenSilentAsync(getScopes(), AUTHORITY, getAuthSilentCallback())
private fun getAuthSilentCallback(): SilentAuthenticationCallback {
return object : SilentAuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult) {
Timber.d("Successfully authenticated")
/* Successfully got a token, use it to call a protected resource - MSGraph */
callGraphAPI(authenticationResult?.accessToken)
}
override fun onError(exception: MsalException) {
/* Failed to acquireToken */
Timber.e("Authentication failed: $exception")
if (exception is MsalClientException) {
Timber.e("Exception inside MSAL, more info inside MsalError.java ")
} else if (exception is MsalServiceException) {
Timber.e("Exception when communicating with the STS, likely config issue")
} else if (exception is MsalUiRequiredException) {
Timber.e("Tokens expired or no session, retry with interactive")
}
}
}
}
OR
INTERACTIVELY:
if (activeAccount == null) {
mSingleAccountApp?.signIn(mActivity, "", getScopes(),
object : AuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult?) {
mActiveAccount =
authenticationResult?.account as MultiTenantAccount?
// save access token in SP
authenticationResult?.accessToken?.let {
mPreferences.putString(
KEY_ACCESS_TOKEN,
it
)
}
callGraphAPI(authenticationResult?.accessToken)
}
override fun onCancel() {
Timber.d("Canceled")
}
override fun onError(exception: MsalException?) {
Timber.d(exception?.errorCode)
}
})
}
Edit 1:
Exceptions I am geting:
CoreHttpProvider[sendRequestInternal] - 414Graph service exception Error code: InvalidAuthenticationToken
CoreHttpProvider[sendRequestInternal] - 414Error message: Access token has expired.
CoreHttpProvider[sendRequestInternal] - 414SdkVersion : graph-java/v1.9.0
CoreHttpProvider[sendRequestInternal] - 414Authorization : Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI[...]
CoreHttpProvider[sendRequestInternal] - 414Graph service exception Error code: InvalidAuthenticationToken
Throwable detail: com.microsoft.graph.http.GraphServiceException: Error code: InvalidAuthenticationToken
Error message: Access token has expired.
When I re-try to get token silently, I get the following exception:
l$getAuthSilentCallback: Authentication failed: com.microsoft.identity.client.exception.MsalServiceException: AADSTS700016: Application with identifier 'Some_ID' was not found in the directory 'Some_ID'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
Trace ID: 'Some_ID'
Correlation ID: 'Some_ID'
Timestamp: 2020-08-15 06:06:11Z
getAuthSilentCallback: Exception when communicating with the STS, likely config issue
Edit 2
As per exceptions I was getting regarding config issue, I got the issue, it was related to the Authority URL which I was using. msal-client-application-configuration
DIAGNOSING
Are there any error details you can provide? And have you traced the HTTPS token refresh message?
WHAT IT SHOULD LOOK LIKE
The MSAL library should be sending a Refresh Token Grant message, as in steps 15 and 16 of my blog post.
My app uses AppAuth libraries but MSAL will work the same way, since that is standard for a mobile app.
I am using Pusher Beams for sending notification to my users. It worked fine but today I got this error, and I don't know how to solve it.
PushNotificationsAPI: Failed to register device: NOKResponse(error=Unauthorized, description=The device token provided could not be validated against any known credentials)
This is my code:
private fun setPusherBeam() {
try {
val tokenProvider = BeamsTokenProvider(
BuildConfig.PUSHER_BEAM,
object : AuthDataGetter {
override fun getAuthData(): AuthData {
return AuthData(
headers = hashMapOf(
"Authorization" to getHawkString(AUTH_TOKEN)
),
queryParams = hashMapOf()
)
}
}
)
PushNotifications.setUserId(
DbHelper.getUser()?.user_id.toString(),
tokenProvider,
object : BeamsCallback<Void, PusherCallbackError> {
override fun onFailure(error: PusherCallbackError) {
Timber.i("BeamsAuth Could not login to Beams: ${error.message}")
}
override fun onSuccess(vararg values: Void) {
Timber.i("BeamsAuth Beams login success $values")
}
}
)
} catch (ex: Exception) {
Timber.i("BeamsAuth ex ${ex.localizedMessage}")
}
}
After 2days of struggling with this error, finally, it resolved due to these steps.
1-stop the API
PushNotifications.start(applicationContext, BuildConfig.INSTANCE_ID)
PushNotifications.stop()
PushNotifications.removeDeviceInterest("example")
PushNotifications.clearDeviceInterests()
2-clear android studio cash and reset it
3-remove the app from mobile and reinstall it
4-replace code from step1 with this
PushNotifications.start(applicationContext, BuildConfig.INSTANCE_ID)
PushNotifications.addDeviceInterest("example")
5-repeat 2 and 3
Delete the generated values.xml under app\build\generated\res\google-services\debug\values, then delete the app and build again. Took me a while to figure this out.