Stripe checkout with gwt not working - gwt

I'm trying to integrate Strip checkout flow in my gwt application. As per the documentation on
https://stripe.com/docs/checkout#integration-custom
we make the configure call and then add a payment completion event handler. But for some reason, the javascript is unable to find the callback function (token)
Uncaught TypeError: undefined is not a function
checkout.js:2 TokenCallback.trigger
checkout.js:2 __bindcheckout.js:2 (anonymous function)
checkout.js:2 IframeView.closed
checkout.js:2 __bindcheckout.js:1 RPC.processMessage
checkout.js:1 __bindcheckout.js:1 RPC.message
checkout.js:1 (anonymous function)
The hooks for opened/closed are getting called though
public class StripePaymentHandler {
public static void initialize(final String apiKey) {
if (!isInjected()) {
ScriptInjector.fromUrl("https://checkout.stripe.com/checkout.js").setWindow(ScriptInjector.TOP_WINDOW)
.setCallback(new Callback() {
#Override
public void onFailure(Exception e) {
Window.alert("Failed to load stripe");
}
#Override
public void onSuccess(Void aVoid) {
doInitialize(apiKey);
}
}).inject();
}
}
public static native void doInitialize(String apiKey) /*-{
console.log('initializing Stripe: '+apiKey);
$wnd.callback = function(token) {
console.log(token);
alert(token);
}
$wnd.handler = $wnd.StripeCheckout.configure({
key: 'key',
image: '/images/logo.png',
token: $wnd.callback
});
}-*/;
public static void completePayment(StripeCheckoutToken token) {
Window.alert(token.getId());
}
public static native void handlePaymentButtonClicked(String description, double price) /*-{
$wnd.handler.open({
name: 'Ziplly',
description: description,
amount: price,
key: 'key',
token: function(token) {
console.log(token);
alert(token);
},
opened: function() {
alert('opened');
}
});
}-*/;
public static native boolean isInjected() /*-{
return typeof $wnd.Stripe !== "undefined";
}-*/;
}
I was able to verify that $wnd.handler does exist after the configure method call. I also tried putting the callback in handler.open method but no luck. Any help on this will be appreciated.
EDIT 2
Here's button handler code that calls handler.open(). This works just fine but the callback from configure method (token) never gets called instead I get the error I described above. Does that make sense?
#Override
public void onSuccess(CheckBuyerEligibilityForCouponResult result) {
PaymentProviderName providerName = result.getPaymentSetupResponse().getProviderName();
switch (providerName) {
case GOOGLE:
handleGooglePayment(result.getPaymentSetupResponse());
break;
case STRIPE:
StripePaymentHandler.handlePaymentButtonClicked("Coupon purchase", 20);
}

I had to add the ID of the button to the StripeCheckout.configure() method to solve this problem. Here's how it would look for you:
$wnd.handler = $wnd.StripeCheckout.configure(
$wnd.myButton.id,
{
key: 'key',
image: '/images/logo.png',
token: $wnd.callback
});

Related

Xamarin.Auth: Using Facebook oauth, how to redirect to my app?

I've just started using Xamarin.Auth and I want to enable Facebook login via oauth.
Here is my config:
public static string ClientId = "client id";
public static string ClientSecret = "client secret";
public static string Scope = "email";
public static string AuthorizeUrl = "https://m.facebook.com/dialog/oauth";
public static string RedirectUrl = "https://www.facebook.com/connect/login_success.html";
public static string AccessTokenUrl = "https://m.facebook.com/dialog/oauth/token";
Code for initiating the authentication:
public class AuthenticationPageRenderer : PageRenderer
{
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear (animated);
var auth = new OAuth2Authenticator (
Constants.ClientId,
Constants.ClientSecret,
Constants.Scope,
new Uri (Constants.AuthorizeUrl),
new Uri (Constants.RedirectUrl),
new Uri (Constants.AccessTokenUrl)
);
auth.Completed += OnAuthenticationCompleted;
PresentViewController (auth.GetUI (), true, null);
}
async void OnAuthenticationCompleted (object sender, AuthenticatorCompletedEventArgs e)
{
Debug.WriteLine ("AUTH Completed!");
if (e.IsAuthenticated) {
}
}
}
Seems to work fine, but instead of redirecting the user to https://www.facebook.com/connect/login_success.html, I want to redirect him back to my app again. Any help much appreciated!
Best,
Sascha
You can "redirect back" to your app again by simply invoking your own method to display the app's page you want to show to your user like this.
async void OnAuthenticationCompleted (object sender, AuthenticatorCompletedEventArgs e)
{
Debug.WriteLine ("AUTH Completed!");
if (e.IsAuthenticated) {
//invoke the method that display the app's page
//that you want to present to user
App.SuccessfulLoginAction.Invoke();
}
}
In your App.cs
public static Action SuccessfulLoginAction
{
get
{
return new Action(() =>
{
//show your app page
var masterDetailPage = Application.Current.MainPage as MasterDetailPage;
masterDetailPage.Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(MainPage)));
masterDetailPage.IsPresented = false;
});
}
}
Assuming that MainPage is the page you wanted to show after successful login. I am using Xamarin.Forms with MasterDetailPage to display pages in my example which maybe different from your app but the concept is the same.
Just call DismissViewController (true, null) in your OnAuthenticationCompleted method. Or use the async equivalent:
async void OnAuthenticationCompleted(object sender, AuthenticatorCompletedEventArgs e)
{
Debug.WriteLine("AUTH Completed!");
await DismissViewControllerAsync(true);
if (e.IsAuthenticated)
{
}
}

How to integrate hockey App with Hybrid mobile app

I am trying to integrate my Hybrid Mobile App (Inonic + Cordova) with hockey App
but the problem is Hockey App is support Native apps (According to my info). So is there any guide available for that?
Hybrid App integration with Hockey app.
When I try to follow hockey app integration with android platform (hybrid app) it also said me to add some code in main activity so where i can find this
Main activity is inside Android platform... cordova/platforms/android/src/...
Put in onCreate method the Register...
There also some plugins for help in this task like https://github.com/peutetre/cordova-plugin-hockeyapp
Take into account that a lot of crash JavaScript problems do not crash in native world it would be helpful to use additional way to communicate controlled errors for example the saveException method, try to expose this by plugin into javascript, it will let store context information error: http://hockeyapp.net/help/sdk/android/3.0.1/net/hockeyapp/android/ExceptionHandler.html
I have tested the solution for Android only in a fork of the previous mentioned plugin:
https://github.com/m-alcu/cordova-plugin-hockeyapp
There are several actions available but yo only need to use "start" and "saveException" for controlled errors to be send to hockeyapps.
hockeyapp.js:
var exec = require('cordova/exec');
var hockeyapp = {
start:function(success, failure, token) {
exec(success, failure, "HockeyApp", "start", [ token ]);
},
feedback:function(success, failure) {
exec(success, failure, "HockeyApp", "feedback", []);
},
saveException:function(success, failure, description) {
exec(success, failure, "HockeyApp", "saveException", [ description ]);
}
};
module.exports = hockeyapp;
hockeyapp.java:
package com.zengularity.cordova.hockeyapp;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import android.widget.Toast;
import static net.hockeyapp.android.ExceptionHandler.saveException;
import net.hockeyapp.android.FeedbackManager;
import net.hockeyapp.android.CrashManager;
import net.hockeyapp.android.CrashManagerListener;
public class HockeyApp extends CordovaPlugin {
public static boolean initialized = false;
public static String token;
public static String description;
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
if (action.equals("start")) {
token = args.optString(0);
CrashManager.register(cordova.getActivity(), token, null);
initialized = true;
callbackContext.success();
return true;
} else if(action.equals("feedback")) {
token = args.optString(0);
FeedbackManager.register(cordova.getActivity(), token, null);
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
FeedbackManager.showFeedbackActivity(cordova.getActivity());
}
});
callbackContext.success();
return true;
} else if(action.equals("saveException")) {
description = args.optString(0);
if(initialized) {
Toast toast = Toast.makeText(cordova.getActivity(), "problem", Toast.LENGTH_SHORT);
toast.show();
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Exception e = new Exception("Send problem");
saveException(e, new CrashManagerListener() {
public String getDescription() {
return description;
}
});
}
});
callbackContext.success();
return true;
} else {
callbackContext.error("cordova hockeyapp plugin not initialized, call start() first");
return false;
}
}
else {
return false;
}
}
}
example of use this plugin in a hellowold example (index.js):
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
hockeyapp.start(
function() { alert('hockeyapp initialised'); },
function(msg) { alert(msg); },
'< your APP ID >');
hockeyapp.saveException(
function() { alert('hockeyapp saveException'); },
function(msg) { alert(msg); },
'Something wrong has happened: bla bla bla...');
}
};
app.initialize();
Hockey stores these controlled exceptions in the file directory of the app and asks to send it the next time user opens app:

Android load url in internal WebView issue

I have a problem with a specific site when loading in my apps internal webview.
In the LogCat i get these 2 lines (the tag is "chromium").
[INFO:CONSOLE(25)] "Uncaught TypeError: Cannot call method 'getItem' of null", source: http://m.ynet.co.il/Default_Ynet.aspx?type=3&id=4519238 (25)
[INFO:CONSOLE(73)] "Uncaught TypeError: Cannot call method 'push' of undefined", source: http://m.ynet.co.il/Default_Ynet.aspx?type=3&id=4519238 (73)
If i redirect to the external browser all is fine. Also it happens only with the above site (see in logcat)
public class WebActivity extends Activity {
WebView wv;
final Activity activity = this;
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setProgressBarIndeterminateVisibility(true);
setContentView(R.layout.activity_web);
wv = (WebView)findViewById(R.id.webView1);
Intent intent = getIntent();
final String url = intent.getStringExtra("url");
Log.i("webView", url);
wv.getSettings().setJavaScriptEnabled(true);
wv.getSettings().setBuiltInZoomControls(true);
wv.getSettings().setLoadWithOverviewMode(true);
wv.getSettings().setUseWideViewPort(true);
wv.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress)
{
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if(progress == 100)
activity.setTitle(R.string.app_name);
}
});
wv.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
});
wv.loadUrl(url);
}
Any ideas?
It turns out that there was a problem using the shouldOverrideUrlLoading method (below) with this particular site.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
Once this was deleted all was good...

Waiting until application return Sucess or Failure(AsyncCallBack)

Just for example, let's check the code below
private void loadUserFromServer() {
dispatchAsync.execute(new FindLoggedUserAction(),
new AsyncCallback<FindLoggerUserResult>() {
#Override
public void onFailure(Throwable caught) {
//do something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
//dosomething with user
result.getUser();
}
operationTwo();
}
My problem is, I have to execute operationTwo(); after some result of dipatcher(Success or failure).
This is just an example, let's assume I can't put operationTwo() inside the onSucess or onFailure()
My real PROBLEM
My GateKeeper of presenters that user must be login.
private UserDTO user;
#Override
public boolean canReveal() {
if(getUser() == null){
ShowMsgEvent.fire(eventBus,"Must Login first", AlertType.ERROR);
return false;
}
return true;
}
}
public UserDTO getUser()
{
if(user == null)
{
//call server
loadUserFromServer();
}
return user;
}
private void loadUsuarioFromServer() {
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
,new AsyncCallback<BuscarUsuarioLogadoResult>() {
#Override
public void onFailure(Throwable caught) {
//something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
if(!(result.getDto().equals(user)))
{
setUsuario(result.getDto(), false); //Set user UserDTO user
//event for update Presenter Login/Logout
// and Label with username
fireUserUpdateEvents();
}
else
{
setUsuario(result.getDto(), false);
}
}
});
As you can see, when a Presenter with that Gatekeeper is called and user is null,
getUser() is called, but when dispatch executes, the method doesn't wait until the return of Sucess or Failure
Result: getUser() returns null.
After the sucessful result of dispatch, getUser() returns a DTO. But, as you can see canReveal() already returned false.
Do not think that GateKeeper is a good approach to handle security in your case. You will not be able to reach stable work. Problem that you will have:
You are not handling network connection lost. If you code is already cached but you need to reload User it will be a big problem with double checking.
Sync calls are always problematic, specially with bad network connection. You will have tons of not responding messages.
To handle presenter access it will be better to use revealInParent method. Most of your presenter already overrides it and it looks like:
#Override
protected void revealInParent() {
RevealContentEvent.fire(...);
}
So you can just not fire Reveal event before you actually download user data. In your case the code will looks like:
#Override
protected void revealInParent() {
if(getUser() == null){
RevealContentEvent.fire(...);
return;
}
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
,new AsyncCallback<BuscarUsuarioLogadoResult>() {
#Override
public void onFailure(Throwable caught) {
//something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
if(!(result.getDto().equals(user)))
{
setUsuario(result.getDto(), false); //Set user UserDTO user
//event for update Presenter Login/Logout
// and Label with username
fireUserUpdateEvents();
}
else
{
setUsuario(result.getDto(), false);
}
RevealContentEvent.fire(...);
}
});
We have also encountered similar problems. Its better to use Async call chaining. Since you can't do that there are two options for your problem
Setup a timer which will check from time to time whether the user is null or not and return only after when user is populated.
Use JSNI (Native code) and make the synchronous call. But beware this is bad practice
Yes, as Abhijith mentioned in previous answer there are 2 options -
1) Synchronous calls - which GWT doesn't support. So it is ruled out.
2) Setting timer - unless user logs in control will not come out of the timer loop. So failed status will never return from the timer. This approach serves only half of your requierment(serving only success state).
To solve your problem you try the following code snippet -
private UserDTO user;
private CanRevealCallBack revealCallBack;
public interface CanRevealCallBack {
returnStatus(boolean status);
}
#Override
public void canReveal(CanRevealCallBack callBack) {
revealCallBack = callBack;
if(user == null){
loadUserFromServer();
}
else{
revealCallBack.returnStatus( true );
}
}
private void loadUsuarioFromServer() {
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
,new AsyncCallback<BuscarUsuarioLogadoResult>() {
#Override
public void onFailure(Throwable caught) {
//something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
if(!(result.getDto().equals(user)))
{
setUsuario(result.getDto(), false); //Set user UserDTO user
//event for update Presenter Login/Logout
// and Label with username
fireUserUpdateEvents();
}
else
{
setUsuario(result.getDto(), false);
}
if(result.getDto() == null){
revealCallBack.returnStatus( true );
}
else{
revealCallBack.returnStatus( false );
}
}
});
So, you have to pass a revealCallback to the canReveal method. CallBack gets executed and returns u the status on success of the async call. In returnStatus method of the callback you can program the logic with the correct user log-in status.

GWT : print button

I am trying to create a button that prints the current browser window.
This is my current code, that uses (or at least it tries to use) JSNI:
private Button print = new Button(constants.print(), new ClickHandler() {
#Override
public void onClick(final ClickEvent event) {
/*-{
if ($wnd.print) {
$wnd.print();
return true;
} else {
return false;
}
}-*/
}
});
But when I click the button, nothing happens. It is my first GWT application, so I am not sure about how to implement it.
new Button(constants.print(), new ClickHandler() {
#Override
public void onClick(final ClickEvent event) {
print();
}
private native boolean print( ) /*-{
if ($wnd.print) {
$wnd.print();
return true;
} else {
return false;
}
}-*/; });
Should work! Always place JSNI within a native method.
Since GWT version 1.5, there's a built-in print function:
import com.google.gwt.user.client.Window
public class PrintHandler implements ClickHandler {
public void onClick (ClickEvent event) {
Window.print()
}
}
Here is my 2 cents:
Create a re-usable class:
public class PrintHandler implements ClickHandler {
public void onClick (ClickEvent event) {
print();
}
private native boolean print ()
/*-{
if ($wnd.print) {
$wnd.print();
return true;
} else {
return false;
}
}-*/;
}
And use it anywhere you like:
new Button( constants.print(), new PrintHandler() )