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.
Related
I am trying to integrate stripe terminal code with my android app build using kotlin, unfortunately I am getting the following run time error which I could not able to fix
java.lang.IllegalStateException: initTerminal must be called before attempting to get the instance
The code I have added is used below
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pay_screen)
onDiscoverReaders()
}
fun onDiscoverReaders() {
val config = DiscoveryConfiguration(
timeout = 0,
discoveryMethod = DiscoveryMethod.LOCAL_MOBILE,
isSimulated = false,
location = "xxxxxxxxxxxxxxx"
)
// Save this cancelable to an instance variable
discoveryCancelable = Terminal.getInstance().discoverReaders(config,
discoveryListener = object : DiscoveryListener {
override fun onUpdateDiscoveredReaders(readers: List<Reader>) {
}
}
, object : Callback {
override fun onSuccess() {
println("Finished discovering readers")
}
override fun onFailure(e: TerminalException) {
e.printStackTrace()
}
})
}
I have added this to one of my activity and my intention is to check if my phone is supporting stripe tap on mobile
I guess the issue could be calling onDiscoverReaders() from a wrong place, someone please help me to fix this issue
Thanks in advance
In stripe docs you can check
// Create your listener object. Override any methods that you want to be notified about
val listener = object : TerminalListener {
}
// Choose the level of messages that should be logged to your console
val logLevel = LogLevel.VERBOSE
// Create your token provider.
val tokenProvider = TokenProvider()
// Pass in the current application context, your desired logging level, your token provider, and the listener you created
if (!Terminal.isInitialized()) {
Terminal.initTerminal(applicationContext, logLevel, tokenProvider, listener)
}
// Since the Terminal is a singleton, you can call getInstance whenever you need it
Terminal.getInstance()
might be you missed to initialise terminal before getting Instance so try add above code before onDiscoverReaders()
The error speaks for itself - first you need to initialize the api terminal, and then call the terminal instance.
Based on the documentation, we follow the following steps to get started with the api terminal:
Initialize the terminal application in the application class of the
application
class App : Application() {
override fun onCreate() {
super.onCreate()
TerminalApplicationDelegate.onCreate(this)
}
}
We request the necessary permissions for correct work with the
terminal search (bluetooth, geolocation), if everything is provided,
we call the init terminal with parameters like that:
Terminal.initTerminal(
context = context,
logLevel = LogLevel.VERBOSE,
tokenProvider = TokenProvider(),
listener = object : TerminalListener {
override fun onUnexpectedReaderDisconnect(reader: Reader) {
Log.d("log", "onUnexpectedReaderDisconnect")
}
override fun onConnectionStatusChange(status: ConnectionStatus) {
super.onConnectionStatusChange(status)
Log.d("log", "onConnectionStatusChange")
}
override fun onPaymentStatusChange(status: PaymentStatus) {
super.onPaymentStatusChange(status)
Log.d("log", "onPaymentStatusChange")
}
}
)
After this initialization, you can call the terminal instance and
work with it.
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.
Converting my own http calls to KTor (& therefore coroutines) is a bit hollow, or at least not terribly satisfying, without also being able to convert Play Store API calls and their callbacks to use suspend functions.
This general answer, with specific example of a different API, is fabulous and I've managed to use it to produce something for "startBillingClient", as follows
private suspend fun BillingClient.startConnection(value: Int) =
suspendCoroutine<Unit> { cont ->
val callback = object: BillingClientStateListener {
override fun onBillingSetupFinished(billingResult:
BillingResult) {
isServiceConnected = true
}
override fun onBillingServiceDisconnected() {
isServiceConnected = false
startConnection(this)
}
}
startConnection(callback)
}
but now I'm struggling with producing something similar for querySkuDetailsAsync, which seems to be due to needing to pass parameters in. Should be easy, but...
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.