I have integrated Paypal smart button to my page and it works. 3 days ago Do not pass Pay-xxx directly gave an error and told me to send a token instead. This time, when I make a reference to it, it gives an error: Expected an order id to be passed. What should I do?
The following code raises an error: Expected an order id to be passed
var CREATE_PAYMENT_URL = '/api/create-payment';
var checkBox = document.getElementById("ship_to_different");
var note = $("#ordernote").val();
if (checkBox.checked == true) {
var body = $("#checkoutt, #data").serializeArray();
} else {
$('input[name=note]').val(note);
var body = $("#data").serializeArray();
}
$("#wait").show();
return fetch(CREATE_PAYMENT_URL, {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
body: body
})
}).then(function (res) {
return res.json();
}).then(function (data) {
console.log(data);
let token;
for (let link of data.links) {
if (link.rel === 'approval_url') {
token = link.href.match(/EC-\w+/)[0];
}
}
return data.token;
});
The following code raises an error:
Do not pass PAY-XXX or PAYID-XXX directly into createOrder. Pass the EC-XXX token instead
var CREATE_PAYMENT_URL = '/api/create-payment';
var checkBox = document.getElementById("ship_to_different");
var note = $("#ordernote").val();
if (checkBox.checked == true) {
var body = $("#checkoutt, #data").serializeArray();
} else {
$('input[name=note]').val(note);
var body = $("#data").serializeArray();
}
$("#wait").show();
return fetch(CREATE_PAYMENT_URL, {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
body: body
})
}).then(function (res) {
return res.json();
}).then(function (data) {
console.log(data);
let token;
for (let link of data.links) {
if (link.rel === 'approval_url') {
token = link.href.match(/EC-\w+/)[0];
}
}
return data.id;
});
I am not able to understand what is going on.
If you are using .net, then in your create payment api call, return an object that contains the order id instead of returning the BraintreeHttp.HttpResponse
[HttpPost]
public async Task<Order> Post()
{
try
{
var request = new OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(BuildRequestBody());
//3. Call PayPal to set up a transaction
var response = await PayPalClient.client().Execute(request);
Order order = new Order();
var result = response.Result<Order>();
if (result?.Status?.Trim()?.ToLower() == "created")
{
order.OrderId = result.Id;
}
return order;
}
catch (Exception ex)
{
string m = ex.Message;
throw;
}
}
then on my js
paypal.Buttons({
createOrder: function () {
return fetch('/api/paypal', {
method: 'post',
headers: {
'content-type': 'application/json'
}
}).then(function(res) {
return res.json();
}).then(function (data) {
return data.orderId; // the data is the order object returned from the api call, its not the BrainTree.Response object
});
}
Sorry for sloppy code, I was still in the process of trying to figure out the problem. Hope you get the gist of the solution
I also faced this issue, and I resolved easily.
paypal.Buttons({
createOrder: function () {
return fetch('/api/create_payment/', {
method: "POST",
headers: {
'content-type': 'application/json',
'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val()
}
}
)
.then(function(res) {
return res.json();
}).then(function(res) {
return res['orderId'];
});
},
onApprove: function (data, actions) {
// Do something after approved...
}
}).render('#paypal-container');
Here important is, on the back-end, I created order with Paypal V2 api endpoint - https://developer.paypal.com/docs/api/orders/v2/#orders_create
You need to send the Token of the payment and not the ID of the payment.
If you use php, use this :
// Instance of your ApiPayment
$payment = new ApiPayment();
$payment->getToken();
Your first code should work. My subjection is to check your browser console whether there are any errors or not.
Ref:
https://developer.paypal.com/docs/checkout/reference/upgrade-integration/?mark=Ec%20token#4-set-up-the-transaction
Code:
createOrder: function(data, actions) {
return fetch('{{ route('create-payment') }}', {
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
method: 'post',
body: JSON.stringify({
body:body
})
}).then(function(res) {
return res.json();
}).then(function(orderData) {
console.log(orderData);
// If you don't use ES2015 or higher replace 'let' with 'var'
var token;
for (link of orderData.links) {
if (link.rel === 'approval_url') {
token = link.href.match(/EC-\w+/)[0];
}
}
return token;
});
},
If you are using paypal sdk then make sure you are returning the order
createOrder={(data, actions) => {
return this.createOrder(cartState, actions)
}}
In your first JS code example, try returning the token variable instead of data.token. Data.token in that example is just going to return an object (which when I ran your code, it return the entire payment object). If you return simply the token variable, it will return the required orderID value (EC-XXXXX). I've adjusted your code example below.
var CREATE_PAYMENT_URL = '/api/create-payment';
var checkBox = document.getElementById("ship_to_different");
var note = $("#ordernote").val();
if (checkBox.checked == true){
var body = $("#checkoutt, #data").serializeArray();
}else{
$('input[name=note]').val(note);
var body = $("#data").serializeArray();
}
$("#wait").show();
return fetch(CREATE_PAYMENT_URL, {
method: 'post',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
body:body
})
}).then(function (res) {
return res.json();
}).then(function (data) {
console.log(data);
let token;
for (let link of data.links) {
if (link.rel === 'approval_url') {
token = link.href.match(/EC-\w+/)[0];
}
}
return token;
});
},
I was getting this because of a return false inside of the createorder function. Cart value input was not there, missed uploading a file.
Might be helpful :)
createOrder: function (data, actions) {
var cartVal = $("body").find("#cartVal").val();
if (typeof cartVal === 'undefined')
return false;
});
Related
At the moment I am working on an Electron app that is supplied with data via an API. The renderer calls a "backend function", which first gets the API key via Keytar and then executes the API call via axios.
The problem here is that Keytar always returns null/undefined, even if a similar function with the same functionality works without any problems, also because this point can only be reached if a valid API key is stored at all and this will also be queried by Keytar.
I am new to async/await-functions, maybe I didn't get something.
btw: Maybe the title doesn't fit too well, but I was a bit at a loss about this one.
(keytarService, username, baseUrl are globals)
Here is my code:
// Api-calling function
async function makeCall(method_type, url_path, data_array) {
keytar.getPassword(keytarService, username).then((apiKey) => {
if (apiKey == null || apiKey == undefined) {
return false;
}
axios({
method: method_type,
url: baseUrl + url_path,
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: data_array,
}).then(
(response) => {
return response.data;
},
(error) => {
return false;
}
);
});
}
//index_renderer.js
webContents.on('dom-ready', () => {
apiMain
.makeCall('GET', 'user/self')
.then((data) => {
console.log(data);
document.getElementById('username_text').innerText =
data.firstName + '' + data.lastName;
})
.catch((err) => console.log(err));
});
Similar function which is working:
async function isAuthenticated() {
apiKey = await keytar.getPassword(keytarService, username);
if (apiKey == null || apiKey == undefined) {
return false;
}
axios({
method: 'GET',
url: baseUrl + '/api/isAuthenticated',
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: {},
}).then(
(response) => {
console.log(response);
if (!response.data.authenticated) {
logout();
}
return response;
},
(error) => {
console.log(error);
logout();
return error;
}
);
}
// call of the working function in main.js
if (authProcess.isAuthenticated()) {
mainwin.loadFile('index.html');
} else {
mainwin.loadFile('login.html');
}
Thanks in advance.
You are missing important returns in MakeCall().
Try:
function makeCall(method_type, url_path, data_array) {
// return this promise to MakeCall
return keytar.getPassword(keytarService, username).then((apiKey) => {
if (apiKey == null || apiKey == undefined) {
return false;
}
// return this promise to keytar.getPassword then()
return axios({
method: method_type,
url: baseUrl + url_path,
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: data_array,
}).then(
(response) => {
return response.data;
},
(error) => {
return false;
}
);
});
}
when user wants to to POST somthing he must be singed in(without username & pass).
Problem is i'm trying to make when CreatePost() invoked it will call SingUser() and based on SingUser() fetch request it will call CreatePost() again to let user post after he sign in.
this is in createpost component
CreatePost(){
fetch(url ,{
method :'POST',
headers:{
Accept:'application/json',
'Content-Type' :'application/json',
},
body: JSON.stringify(post)
}).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status =='inactive'){
//SignUser
}else{
//post
}
}).catch((error)=>{ //later
});
}
here is SingUser() in other file
async function SignUser() {
try{
User.vtoken = await AsyncStorage.getItem('vtoken');
var userTemp={
vtoken: User.vtoken,
ntoken : User.ntoken
}
fetch(url,{
method :'POST',
headers:{
Accep : 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(userTemp)
}).then((response)=> response.json()).
then((responseJson)=>{
if(responseJson.path == 2){
Save(responseJson, userTemp);}
else return;
}).catch((error)=>{
});
}catch(error){}
}
async function Save(result , userTemp){
try{
await AsyncStorage.setItem('vtoken', result.vtoken);
User.vtoken = result.vtoken;
userTemp.vtoken = result.vtoken;
fetch(url,{
method :'POST',
headers:{
Accep : 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(userTemp)
}).then((response)=>response.json()).
then((responseJson)=>{
return 'done';
}).catch((error)=>{})
}
catch(error){}
}
export {SignUser}
i hope u understand what im trying to do if there is better way to do it thnx:(
You can do something like this:
const errorCodeMap = {
USER_INACTIVE: 10,
}
const statusMap = {
INACTIVE: `inactive`
}
const METHOD = `POST`
const APPLICATION_JSON = `application/json`
const headerDefault = {
Accept: APPLICATION_JSON,
'Content-Type': APPLICATION_JSON,
}
const who = `post`
async function createPost(payload, options) {
try {
const {
url = ``,
fetchOptions = {
method: METHOD,
headers: headerDefault,
},
} = options
const {
post,
} = payload
const response = await fetch(url, {
...fetchOptions,
body: JSON.stringify(post)
})
const {
status,
someUsefulData,
} = await response.json()
if (status === statusMap.INACTIVE) {
return {
data: null,
errors: [{
type: who,
code: errorCodeMap.USER_INACTIVE,
message: `User inactive`
}]
}
} else {
const data = someNormalizeFunction(someUsefulData)
return {
data,
errors: [],
}
}
} catch (err) {
}
}
async function createPostRepeatOnInactive(payload, options) {
try {
const {
repeat = 1,
} = options
let index = repeat
while (index--) {
const { data, errors } = createPost(payload, options)
if (errors.length) {
await signUser()
} else {
return {
data,
errors,
}
}
}
} catch (err) {
}
}
solve it, I did little adjustments
async CreatePost(){
try{
var response = await fetch(url ,{
method :'POST',
headers:{
Accept:'application/json',
'Content-Type' :'application/json',
},
body: JSON.stringify(post)});
var responseJson = await response.json();
if(responseJson.status =='inactive' && postRepeat == true){
postRepeat == false;
await SignUser();
this.CreatePost();
}
else{
//posted
}
}catch(err){}
}
I have a JavaScript loop iterating over an array. For every item, I perform a fetch request to insert the object. If the server response indicates it is an already inserted object, I try an update operation with another fetch call.
As the requests are asynchronous, the loop sets the request object to the next insert item before I try the update operation, so I end up requesting an update for an object it's not yet inserted.
Is there any way I can access the request object used for this fetch operation, so I can use that object instead of the loop var?
I've tried with this within the promise method, but it returns a reference to the window object: console.log(this) ==> > Window http://localhost
My code:
for (var i = 0; i < expectedRows; i++) {
var row = myArray[i];
customerCode = row['customer_code'];
customerName = row['customer_name'];
customerBalance = row['customer_balance'];
// Build body call
var callBody = {
user: 'USER',
code: customerCode,
name: customerName,
balance: customerBalance
};
var fetchOptions = {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "error",
referrer: "ux-import",
body: JSON.stringify(callBody),
};
// Call
var epurl = baseEP + '/customer/create';
fetch(epurl, fetchOptions)
.then(response => response.json())
.then(response => {
console.log(this) // <== Window object reference
if (response.error === 0) {
console.log('insert ok');
insertRows++;
} else {
if (response.error == 2) {
console.log('insert error => update');
var updateEP = baseEP + '/customer/update';
fetch(updateEP, fetchOptions) // <== Not what you expect
.then(updResponse => updResponse.json())
.then(updResponse => {
if (updResponse.error === 0) {
console.log('update ok.')
updateRows++;
} else {
console.log('update error: ' + updResponse.msg)
errorMessages.push(updResponse.msg);
}
})
.catch(error => {
console.log('update failure');
errorMessages.push(error);
});
} else {
console.log('insert error.');
errorMessages.push(response.msg);
}
}
})
.catch(error => {
console.log('insert failure.');
errorMessages.push(error);
});
}
I need some way to access this fetch call request object to achieve something like this:
var updFetchOptions = {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "error",
referrer: "ux-import",
body: this.request.body, // this as a reference to this fetch's request
}
fetch(updateEP, updFetchOptions)...
:
:
Can you try this.
for (let i = 0; i < expectedRows; i++) {
let row = myArray[i];
customerCode = row['customer_code'];
customerName = row['customer_name'];
customerBalance = row['customer_balance'];
// Build body call
let callBody = {
user: 'USER',
code: customerCode,
name: customerName,
balance: customerBalance
};
let fetchOptions = {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "error",
referrer: "ux-import",
body: JSON.stringify(callBody),
};
// Call
let epurl = baseEP + '/customer/create';
fetch(epurl, fetchOptions)
.then(response => response.json())
.then(response => {
console.log(this) // <== Window object reference
if (response.error === 0) {
console.log('insert ok');
insertRows++;
} else {
if (response.error == 2) {
console.log('insert error => update');
let updateEP = baseEP + '/customer/update';
fetch(updateEP, fetchOptions) // <== Not what you expect
.then(updResponse => updResponse.json())
.then(updResponse => {
if (updResponse.error === 0) {
console.log('update ok.')
updateRows++;
} else {
console.log('update error: ' + updResponse.msg)
errorMessages.push(updResponse.msg);
}
})
.catch(error => {
console.log('update failure');
errorMessages.push(error);
});
} else {
console.log('insert error.');
errorMessages.push(response.msg);
}
}
})
.catch(error => {
console.log('insert failure.');
errorMessages.push(error);
});
}
Basically, defining variables with var is not a good method as it doesn't maintain its state with each iteration of loop. But using let maintains the variable state for each iteration and you can use the variable even after doing some async task like fetch in your case.
You can achieve this by explicitly creating the RequestInit-Object and wrapping your handler functions like this:
const initObject = {
method: 'POST',
something: 1234
};
fetch('/test.json', initObject)
.then(r => r.json())
.then(((initObject) => {
return json => {
console.log({json, initObject})
}
})(initObject));
I'm working on a project that works with the Spotify API to allow users to search for and add songs/playlists to their account. I'm coding it all in react, and I get to the point where there's no compiler errors, the only error being:
Warning: Each child in an array or iterator should have a unique "key" prop.
Yet nothing on the application seems to work, you can't add songs to playlist, search the playlist, etc. I'm trying to figure out if something is wrong with my API module, because that's the only thing I can think of that has an issue and doesn't throw any errors. The module follows below, or you can view the repo And here is the Spotify API Authorization Document That we were told to use
function Spotify() {
function getAccessToken() {
if(accessToken !== '') {
return accessToken;
} else if (window.location.href.match(/access_token=([^&]*)/) != null){
accessToken = window.location.href.match(/access_token=([^&]*)/);
expiresIn = window.location.href.match(/expires_in=([^&]*)/);
window.setTimeout(() => accessToken = '', expiresIn * 1000);
window.history.pushState('Access Token', null, '/');
} else {
window.location = `https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectURI}`;
}
async function search(term) {
accessToken=getAccessToken();
try {
let response = await fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`
}
});
if (response.ok) {
let jsonResponse = await response.json();
let tracks = jsonResponse.map(track => ({
id: track.id,
name: track.name,
artist: track.artists[0].name,
album: track.album.name,
uri: track.uri
}));
return tracks;
}
} catch (error) {
console.log(error);
}
}
function savePlaylist(name, trackURIs) {
if (name === undefined || trackURIs === undefined) {
return;
} else {
let userAccessToken = getAccessToken();
let headers = {Authorization: userAccessToken};
let userId = findUserId(headers);
let playlistID;
fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": 'application/json'
},
body: {
name: name
}
}).then(response => {return response.json()}
).then(playlist => {
playlistID = playlist.id;
});
}
}
function findUserId(headers) {
accessToken = getAccessToken();
let id;
fetch(`https://api.spotify.com/v1/me`, {headers: headers}
).then(response => {return response.json()}
).then(jsonResponse => {
id = jsonResponse[0].id;
});
return id;
}
}
}
export default Spotify;
There are some problems with your code:
The handleTermChange method in SearchBar.js reads the value from the input incorrectly, it should be: this.setState({term: event.target.value});
The search button is only a link, you have to bind the onClick event, something like this: <a onClick={this.search}>SEARCH</a>
Something is not right in Spotify.js, currently the getAccessToken method encapsulates everything else.
If you inspect your playlist with React Dev Tools, you can see, that there is no id property on track in TrackList.js, so it will be always null. This is why you get the warning.
I'm trying to pass the promise value in headers but am not able to do so.
class test{
constructor(auth_key,auth_secret){
this.auth_key = auth_key;
this.auth_secret = auth_secret;
console.log("============In class test============");
this.authtoken = this.init().then(function(value){
return value;
});
}
init(){
console.log("============In init function============"+this.auth_key);
let postData = {};
return this.requestStt('test','POST',postData).then((response) => {
if (response.status == 200) {
return response.body.then((response) => {
//console.log(response.token);
let apiResp = {stt_token:response.token}
return apiResp;
});
}else {
console.log(response)
}
});
}
gettoken(){
console.log(this.authtoken)
var reqHeaders = new Headers({
"Accept":"application/json",
"Content-Type": "application/json; charset=UTF-8",
"token":this.authtoken,
});
}
}
Getting error because this.authtoken is a promise object.
Can anyone please help me out.
if you rewrite gettoken like follows:
gettoken(){
return this.authtoken.then(function(token) {
return new Headers({
"Accept":"application/json",
"Content-Type": "application/json; charset=UTF-8",
"token":token,
});
})
}
then of course, to use those headers, you would need to do something like
xxx.gettoken().then(function(headers) {
// whatever you do with headers goes here
});