I'm very new to working with backend server stuff and nodejs. I'm trying to set up Stripe with my app and now trying to create a Connected account with stripe. Was following this https://stripe.com/docs/connect/collect-then-transfer-guide but I don't understand enough to make it work. How do I get information from the server or send it through to make the account.
this is what I got so far
binding.connectWithStripe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String redirect = "https://www.example.com/connect-onboard-redirect";
String url = "https://connect.stripe.com/express/oauth/authorize" +
"?client_id=" + "ca_Hdth53g5sheh4w4hwhw5h4weh5" +
"&state=" + 1234 +
"&redirect_uri=" + redirect;
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(view.getContext(), Uri.parse(url));
}
});
const express = require('express');
const app = express();
app.use(express.json());
const { resolve } = require("path");
const stripe = require('stripe')('sk_test_xxxx');
app.get("/", (req, res) => {
// Display landing page.
const path = resolve("./index.html");
res.sendFile(path);
});
app.get("/connect/oauth", async (req, res) => {
const { code, state } = req.query;
// Assert the state matches the state you provided in the OAuth link (optional).
if(!stateMatches(state)) {
return res.status(403).json({ error: 'Incorrect state parameter: ' + state });
}
// Send the authorization code to Stripe's API.
stripe.oauth.token({
grant_type: 'authorization_code',
code
}).then(
(response) => {
var connected_account_id = response.stripe_user_id;
saveAccountId(connected_account_id);
// Render some HTML or redirect to a different page.
return res.status(200).json({success: true});
},
(err) => {
if (err.type === 'StripeInvalidGrantError') {
return res.status(400).json({error: 'Invalid authorization code: ' + code});
} else {
return res.status(500).json({error: 'An unknown error occurred.'});
}
}
);
});
const stateMatches = (state_parameter) => {
// Load the same state value that you randomly generated for your OAuth link.
const saved_state = 'sv_53124';
return saved_state == state_parameter;
}
const saveAccountId = (id) => {
// Save the connected account ID from the response to your database.
console.log('Connected account ID: ' + id);
}
app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
The sign up page opens and can enter the test info but after submiting it's not actually creating the account in Stripe dashboard. Any help would be much appreciated
enter image description here
After you complete the Express account sign up, Stripe redirects your customer to the redirect URI you specified on your Connect OAuth url (looks like yours is https://www.example.com/connect-onboard-redirect).
You should redirect to a real page of yours here. The redirect URL will append query params containing the authorization code e.g. https://www.example.com/connect-onboard-redirect?code=ac_1234
where ac_1234 is the OAuth authorization code.
You need to parse out that authorization code and send it to your backend and complete the OAuth connection to actually connect that Express account to your Platform: https://stripe.com/docs/connect/oauth-express-accounts#token-request
Got the last piece of my puzzle. Didn't know how to communicate with nodejs and use the GET method. I used volley with this piece of code
RequestQueue queue = Volley.newRequestQueue(getContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, "http://10.0.2.2:4242" + "/connect/oauth",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(">>>>>>>>CONNECTED?", ">>>CONNECTED!!!<<<");
// enjoy your response
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(">>>>>>>>>>ERRRRRRROR", error.toString());
// enjoy your error status
}
});
queue.add(stringRequest);
Hope that helps anyone else starting to learn nodejs :)
Related
I am working in an application : Java Backend and Angular frontend. I am using angular Fromly, data is coming to service, but from the service it is not going to server.
lets share the code snipts:
Service Code:
export class RecommendationRequestService {
readonly ROOT_URL = environment.apiUrl + '/am/v1/recommendation-requests';
constructor(private http: HttpClient, private configService: RecommenderConfigService) {
}
updateData(interviewStatus: InterviewStatusRecommendation): Observable<any> {
console.log(interviewStatus);
return this.http.put<any>(this.ROOT_URL, interviewStatus);
}
}
This line is printing intended data set : console.log(interviewStatus);
The server is running.
The code from where the service is being called :
onSubmit() {
this.model.recommendationRequest.agentInitiationId = this.agentInitiationId;
const subs = this.service.updateData(this.model).subscribe(response => {
console.log('------' + response);
if (response === 'OK') {
this.notify.success('Request Recommendation Update success.');
} else {
this.notify.error('Request Recommendation Update fail.');
}
},
err => {
if (err.error.hasOwnProperty('code') && err.error.code === 1000) {
this.notify.error(CommonEnum.VALIDATION_ERROR);
}
});
subs.unsubscribe();
}
console.log('------' + response); this line should print at least -----, But nothing.
I have checked the network monitor from the browser, no call is going.
What might be the possible issue, any thing from fromly?
You are doing it incorrect as Aldin Bradaric also updated in the comment, as soon as you make the call on the very next moment you are unsubscribing it. This is what you should do :
public subs: [] = [];
onSubmit() {
this.model.recommendationRequest.agentInitiationId = this.agentInitiationId;
const subs = this.service.updateData(this.model).subscribe(response => {
console.log('------' + response);
if (response === 'OK') {
this.notify.success('Request Recommendation Update success.');
} else {
this.notify.error('Request Recommendation Update fail.');
}
},
err => {
if (err.error.hasOwnProperty('code') && err.error.code === 1000) {
this.notify.error(CommonEnum.VALIDATION_ERROR);
}
});
//subs.unsubscribe(); // remove it and add it to the lifecycle hooks
this.subs.push(subs);
}
ngOnDestroy() {
// create an array of subscription
this.subs.forEach(sub => sub.unsubscribe() )
}
I want to send broadcast messages from server (using laravel) to clients (using java).
What I'm using
Pusher as boradcast driver.
laravel passport for api authentication.
What I've done in server side
I've configured my Pusher credentials in .env file.
Uncommented App\Providers\BroadcastServiceProvider::class line in config/app.php file.
In config/auth.php file I've added the following:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'devices' => [
'driver' => 'session',
'provider' => 'devices',
],
'api' => [
'driver' => 'passport',
'provider' => 'devices',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
// using devices table to authenticate over api guard
'devices' => [
'driver' => 'eloquent',
'model' => App\Device::class,
],
],
In App\Providers\BroadcastServiceProvider class I added the following to boot() function:
Broadcast::routes(['prefix' => 'api', 'middleware' => 'auth:api']);
In routes/channels.php I added the following:
Broadcast::channel('device.{device_id}', function ($device, $device_id) {
return $device->id === $device_id;
});
Created an event AdvertisementAdded by running php artisan make:event AdvertisementAdded, added implements ShouldBroadcast then added the following to its broadcastOn() method:
return new PrivateChannel('device.'.$this->device_id);
What I've done in client side
Because I'm just testing now, I got my access_token and device_id by sending a login request from postman
I copied that accessToken to my java client and stored it in accessToken variable as String, here's the code:
String accessToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImY3ZTVlMTAzZWE3MzJjMTI5NzY1YTliMmMzOTM0N2ZhOGE4OTU5MjRjNDA5ZjgyOTA4ZDg5NTFjZTBkOGZlNTA2M2M1YTI1MDBlOTdhZDdiIn0.eyJhdWQiOiIxIiwianRpIjoiZjdlNWUxMDNlYTczMmMxMjk3NjVhOWIyYzM5MzQ3ZmE4YTg5NTkyNGM0MDlmODI5MDhkODk1MWNlMGQ4ZmU1MDYzYzVhMjUwMGU5N2FkN2IiLCJpYXQiOjE1NTkwOTYyNDgsIm5iZiI6MTU1OTA5NjI0OCwiZXhwIjoxNTkwNzE4NjQ3LCJzdWIiOiI3Iiwic2NvcGVzIjpbXX0.FKeE9Z-wv2yUNQPl-qsbu9baYGTdbQ6DuzaI1R8azR6l1CIP9uRI4hCaoWvgx0GXWWLPRNhfQl-YD3KP2YOraW16-h4ie_95B9VQrpFxXnlqKojsfh1xSrSNSl5HncslMWQPVjoesBpM5y_cpG19PGgu-SWo0W6s9Fiz_Nm70oyyZB9mSqU8PVQvAOSNr6TMR0aC3iMLFfkyZkTSwj8EoRyD2LGW6v4PFriqx8JLbZASCOiUYBlYnunWrTFDOAenZcoa5Sw7u7kbSvYehjDKRwKjQM6zmPfi0A3Mp0CHjHE599OXb-NG2IMH-wmlT0vEZjP2U97hxmsNW1RtHNXWaRKFL9T-WVmZbJf3fH5hXqTv495L3MQfq_m5YFHyc5NuIqK4K4xMJB956a33ICnH8DmvPmJgderNAhqEX1JHUAsR63K7xbZxRBDS8OlQYcEf-_v75X0kT1s067enSvI8Vs212AVnI6k0FmgQNM8DfJUq6YduD0m2F2ZWpKPrwdd6PdW5ZlZTEv-D8dYIEQ_CwOWohNoENATmTqxDpPBxK5c723MEt8S7Sa9MEGAo56HW3-9pbazbEdY1GqPWKVkov7K_6eBFcWsV67AgJpoKFt6RiBfRvokgiH96WG89qBB_Ucpm8uBahX93FaOXhVLW0VjJH2LQKrGw0bb5LS8Ql5o";
String deviceId = "7";
Map<String, String> authHeaders = new HashMap();
authHeaders.put("Authorization", accessToken);
HttpAuthorizer authorizer = new HttpAuthorizer("http://localhost:8000/api/broadcasting/auth");
authorizer.setHeaders(authHeaders);
PusherOptions options = new PusherOptions();
options.setAuthorizer(authorizer).setCluster(PUSHER_CLUSTER);
Pusher pusher = new Pusher(PUSHER_APP_KEY, options);
pusher.subscribePrivate("private-device." + deviceId, new PrivateChannelEventListener() {
#Override
public void onEvent(String channelName, String eventName, final String data) {
System.out.println(String.format("Received event on channel [%s]", channelName));
}
#Override
public void onSubscriptionSucceeded(String string) {
System.out.println(String.format("Subscribed to channel [%s]", string));
}
#Override
public void onAuthenticationFailure(String string, Exception excptn) {
System.out.println(string);
}
});
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
System.out.println("State changed to " + change.getCurrentState() +
" from " + change.getPreviousState());
}
#Override
public void onError(String message, String code, Exception e) {
System.out.println("There was a problem connecting!");
}
});
// Keeping main thread alive
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
When running the code above, it outputs the following on console:
State changed to CONNECTING from DISCONNECTED
State changed to CONNECTED from CONNECTING
java.io.IOException: Server returned HTTP response code: 403 for URL: http://localhost:8000/api/broadcasting/auth
I'm sure that auth:api middleware is working as I expect on other requests.
Here's a snippet from my routes/api.php:
Route::middleware('auth:api')->group(function () {
Route::prefix('advertisements')->group(function () {
Route::get('/request', 'AdvertisementsController#getDeviceAdvertisements')
->name('advertisements.getDeviceAdvertisements');
});
});
And here's a test to that route from postman (with the same access token as above):
And here's a test to api/broadcasting/auth route from postman (with the same access token as above):
What's the problem? Why all api routes under auth:api middleware working properly but not api/broadcasting/auth route??
Note
I tried working with public channels with no problems.
After a whole day of searching, finally It's solved.
The error happens when authorizing the channel, not when authenticating the request using auth:api middleware.
My private channel authorizing function in routes/channels.php always returns false meaning it will reject all subscribing requests to private-device.{device_id} channel:
Broadcast::channel('device.{device_id}', function ($device, $device_id) {
// this always return false, because of inequality of types
return $device->id === $device_id;
});
Authorizing function above always return false, because of inequality of types between $device->id (which is of type int) and $device_id (which is of type string).
So, in order to solve the problem, I cast both of them to int and then checked for equality.
Here's the code I used to solve the problem:
Broadcast::channel('device.{device_id}', function ($device, $device_id) {
return (int) $device->id === (int) $device_id;
});
First I'm use Typescript to write cloud functions to create an account with Firebase authentication. After creating new account, tried to add custom claims to the account and add the user info to the Firebase real-time database these steps complete successfully.
The problem appears when adding already existing account. The error prints in functions log but I cant throw it to Android
My firebase cloud functions log
cloud functions code:.
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import { User } from './model/User';
admin.initializeApp();
const db = admin.database();
exports.createSellerAccount = functions.https.onCall((data, context) => {
const userEmail = data.email;
const userPassword = data.password;
const user: User = new User();
const newUserData = JSON.parse(data.newUser);
user.setFirstName(newUserData.firstName);
user.setLastName(newUserData.lastName);
user.setMobileNumber(newUserData.mobileNumber);
admin.auth().createUser({
email: userEmail,
password: userPassword
}).then(function (userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
const additionalClaims = {
sellerAccount: true
};
admin.auth().setCustomUserClaims(userRecord.uid, additionalClaims)
.then(function (customToken) {
// Send token back to client
console.log("Successfully token created new user:", userRecord.uid);
})
.catch((error) => {
console.log("Error creating custom token:", error);
});
db.ref("Users/" + userRecord.uid).set(user)
.then(() => {
console.log("seller info inserted successfully");
})
.catch(function (error) {
console.log("Error while inserting seller info:", error);
});
}).catch(function(error) {
// console.log("Error creating new user:", error);
throw new functions.https.HttpsError('already-exists',error);
});
})
Android code:.
private void createAccount() {
ekhtarSeller.showProgressDialog(this);
newUser.setFirstName(tietFirstName.getText().toString().trim());
newUser.setLastName(tietLastName.getText().toString().trim());
newUser.setMobileNumber(tietMobileNumber.getText().toString().trim());
HashMap<String, Object> data = new HashMap<String, Object>();
data.put("email", tietEmail.getText().toString().trim());
data.put("password", tietPassword.getText().toString().trim());
data.put("newUser", new Gson().toJson(newUser));
mFunctions
.getHttpsCallable("createSellerAccount")
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
ekhtarSeller.getProgressDialog().cancel();
String result = (String) task.getResult().getData();
Toast.makeText(CreateAccountActivity.this, result, Toast.LENGTH_SHORT).show();
return result;
}
});
}
It's happened you aren't using the values listed in a linked document in firebase for code parameter You get Error codes for Google APIs "failed-auth" or "invalid-email"
Please visit
functions.https.HttpsError
I am trying to fetch google contacts for a user via oAuth2 mechanism. I am following this tutorial - https://developers.google.com/identity/sign-in/web/server-side-flow
I have javascript code that calls start() on pageload -
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'SOME_CLEINT_ID',
scope: 'https://www.googleapis.com/auth/contacts.readonly'
});
});
}
and
auth2.grantOfflineAccess().then(signInCallback);
and then -
function signInCallback(authResult) {
if (authResult['code']) {
var callback = function(data){
data = JSON.parse(data);
console.log(data);
};
callAjax({action: 'saveGmailAuth', gaccesscode: authResult['code']}, callback, true);
} else {
// There was an error.
}
}
This front end code calls my backend Java web servlet, which tries to get access token -
String authCode = request.getParameter("gaccesscode");
String REDIRECT_URI = "";
String CLIENT_SECRET_FILE = "G:/eclipse_proj/GoogleContacts/CLIENT_JSON_FILE.json";
GoogleClientSecrets clientSecrets;
try {
clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(),
new FileReader(CLIENT_SECRET_FILE));
REDIRECT_URI = clientSecrets.getDetails().getRedirectUris().get(0);
GoogleAuthorizationCodeTokenRequest tokenRequest = new GoogleAuthorizationCodeTokenRequest(new NetHttpTransport(),
JacksonFactory.getDefaultInstance(), "https://www.googleapis.com/oauth2/v3/token",
clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret(), authCode,
REDIRECT_URI);
GoogleTokenResponse tokenResponse = tokenRequest.execute();
String accessToken = tokenResponse.getAccessToken();
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Every time I try this java code, every time it gives me error at tokenRequest.execute() -
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "redirect_uri_mismatch",
"error_description" : "Bad Request"
}
With REDIRECT_URI as empty string, it give another error saying - redirect_uri_not_provided.
I tried it with both "https://www.googleapis.com/oauth2/v3/token" and "https://www.googleapis.com/oauth2/v4/token"
I need help figuring this out. What am I doing wrong here?
My redirect URI is - http://localhost:8080/GoogleContacts/Callback in both json file and in developer console for oauth2.
For redirect_uri in using Google APIs,go to your Google Dev console and type what you see as is:
//you can use any port you want
http:localhost:8080/oauth2callback
oauth2callback is the key ingredient.
I'm trying to implement "Twitter" login for my web application. I use scribe to simplify things a bit.
My implementation relies of GWT RPC mechanism to get the Authorization url back to the client so the client can call a popup window to redirect to the Autorization Url.
However, when the URL is opened to the new tab and user log in with Twitter account, the page provides the PIN number (from this site: https://api.twitter.com/oauth/authorize) that needs to be typed back into the org.scribe.model.Modifier
This kind of approach will be cumbersome to users. What is needed is that when the user typed in the Twitter username/password that should be it. Or at least automate all the other process.
Am I missing something?
Here's my code:
twitterLogin.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
TwitterService.Util.getInstance().getAuthorizationUrl(new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
if (result != null)
Window.open(result, "__blank", null);
}
#Override
public void onFailure(Throwable caught) {
}
});
}
});
To authenticate with OAuth, you need to send out 2 requests to the authenticating server:
- First to get the "Request Token"
- Then to get the "Access Token"
Twitter does open the authentication page in a new window where they can type their Twitter username/password, so that's to be expected.
if (req.getRequestURI().equals("/twitter")) {
Token requestToken = service.getRequestToken();
System.out.println("Got the Request Token!" + requestToken.getToken());
session = request.getSession(true);
session.setAttribute("TOKEN", requestToken);
response.sendRedirect(service.getAuthorizationUrl(requestToken));
} else if (req.getRequestURI().equals("/twitter/callback")) {
String code = request.getParameter("oauth_verifier");
System.out.println("Verifier :: " + code);
System.out.println("service.getRequestToken()" + service.getRequestToken());
session = request.getSession(false);
Token requestToken = (Token) session.getAttribute("TOKEN");
System.out.println("requestToken from Session " + service.getRequestToken().getToken() + " Secr" + service.getRequestToken().getSecret());
if (code != null && !code.isEmpty()) {
Verifier verifier = new Verifier(code);
Token accessToken = service.getAccessToken(requestToken, verifier);
OAuthRequest req = new OAuthRequest(Verb.GET, OAUTH_PROTECTED_URL);
service.signRequest(accessToken, req);
Response res = req.send();
response.setContentType("text/plain");
response.getWriter().println(res.getBody());
}
}