Braintree Node.js cannot get transaction.sale to work - javascript

I am building a reactjs app that among others will include Braintree Dropin UI integration. So far, I have managed to make the UI show up and send a payload to the back end. However, I cannot get the gateway.transaction.sale() part to work. Here is my code's relevant parts:
When the user clicks the pay button, this is fired:
instance.requestPaymentMethod().then(function (payload) {
console.log(payload);
completePayment(amount, payload.nonce, userId, sessionId).then((result) => {
console.log( result );
});
}).catch(function (err) {
alert(err.message);
});
And this is the code that should handle the transaction:
return gateway.transaction.sale({
amount: amount,
paymentMethodNonce: nonce,
customFields: {
session_id: sessionId,
user_id: userId
},
options: {
submitForSettlement: true
}
}).then(function (result) {
if (result.success) {
console.log('Transaction ID: ' + result.transaction.id);
} else {
console.error(result.message);
}
}).catch(( error ) => {
alert(error);
});
Every time this function is fired, I get this error from catch:
TypeError: can't assign to property "success" on :not an object
Can anyone point me in the right direction?
Please note that I am not very familiar with react, node etc so my code may not be the best thing around...

Check these points:
make sure you assigned your environment to the sandbox (braintree.Environment.Sandbox);
double check (merchantId, publicKey, and privateKey).

Related

Posting result data to a website (like API or a telegram bot) after a test on Cypress

I've finished writing my first Cypress test. Everything is good except I'm struggling to post the result data to a website. Because I want to send the result data and also if any errors occurs the result screenshot to our coworker telegram group.
For the last two days I've tried everything and couldn't find any solution.
I've tried those in my test script (cypress/integration/test.js);
Cypress.on('test:after:run', (test, runnable) => {
console.log('test,runnable', test, runnable)
const details = {
projectKey: Cypress.env('zephyr-project-key'),
testName: test.invocationDetails.relativeFile,
status: test.status,
error: runnable.err.message,
retries: runnable.retries.length,
duration: test.wallClockDuration,
startTime: test.wallClockStartedAt
}
cy.request('POST', 'http://mywebsite.com/notify.php', { body: details })
fetch('http://mywebsite.com/notify.php')
})
Also this didn't work (cypress/plugins/index.js);
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on('after:run', (results) => {
if (results) {
// results will be undefined in interactive mode
console.log(results.totalPassed, 'out of', results.totalTests, 'passed')
fetch('http://mywebsite.com/notify.php');
}
})
}
Edit: This is day 3 and I still couldn't solve this. What I've seen from Cypress help page is that cy.task() calls do not fire in 'test:after:run' event block;
https://github.com/cypress-io/cypress/issues/4823
I've seen some telegram groups who can do what I'm trying to do. All I need is to be able to get the results and post it to my website.
The third parameter to cy.request() is body, you don't have to wrap it.
Cypress.on('test:after:run', (test, runnable) => {
const details = {
projectKey: Cypress.env('zephyr-project-key'),
testName: test.invocationDetails.relativeFile,
status: test.status,
error: runnable.err?.message, // need err?.message if there is no error
retries: runnable.retries.length,
duration: test.wallClockDuration,
startTime: test.wallClockStartedAt
}
cy.request('POST', 'http://mywebsite.com/notify.php', details) // don't wrap details
.then(res => expect(res.status).to.eq(201)) // confirm result
})

Stripe Payment Element and one page checkout - what is the correct payment flow?

I want to upgrade my simple Stripe one-page checkout to use the new Payment Element that unifies a lot of different payment methods under one component. By simple I mean, the customer chooses between a few variants of one product, provides needed info and submits the order. Collect money, send emails, fulfil the order etc. Just vanilla HTML/CSS/JS and a bit of PHP. Using Payment Intents API to process the payments, was on Charges API before.
I love the premise of this unified element so I decided to give it a go. It turns out I have trouble understanding what to do with both stripe.confirmPayment method and return_url parameter.
I guess the return_url should be my checkout page? Also, is there a way to redirect without hard refresh? Ideally, I would be able to do some server-side stuff before redirect happens, but it seems that stripe.confirmPayment automatically redirects if resolved successfully.
Here is my code. I am a designer btw, so guess I am missing something obvious as always.
// init Stripe elements
fetch('/config.php', {
method: 'get',
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => {
return response.json();
})
.then((response) => {
return setupElements(response.publishableKey)
})
var setupElements = function (publishableKey) {
stripe = Stripe(publishableKey);
// create payment intent to setup payment element
fetch('/setup-elements.php', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(order)
})
.then(function (response) {
return response.json()
})
.then(function (data) {
const appearance = {
theme: 'none',
labels: 'floating',
// etc.....
};
elements = stripe.elements({
clientSecret: data.clientSecret,
fonts: [{
cssSrc: 'https://use.typekit.net/hly2qug.css'
}, ],
appearance
});
const paymentElement = elements.create("payment", {
fields: {
billingDetails: {
email: 'never',
address: {
line1: 'never',
city: 'never',
state: 'never',
country: 'never',
postalCode: 'never'
}
}
}
});
paymentElement.mount("#payment-element");
})
}
form.addEventListener('submit', function (e) {
e.preventDefault();
var isFormValid = validate.validateAll(form);
if (isFormValid.length < 1) {
loading(true);
collectFormInfo();
confirmPayment();
}
})
var confirmPayment = function () {
stripe.confirmPayment({
elements,
confirmParams: {
return_url: 'checkout-page?',
payment_method_data: {
billing_details: {
email: order.customer.email,
address: {
line1: order.delivery.address,
city: order.delivery.city,
state: order.delivery.state,
country: order.delivery.country,
postal_code: order.delivery.postcode
}
}
}
}
})
.then(function (result) {
// This is where I get stuck. How to do stuff after
// payment is confirmed
// and not get redirected immediately? If
//redirected, where to and is it
// possible to do so asynchronously?
if (result.error.type === "card_error" || result.error.type === "validation_error") {
showMessage(result.error.message);
} else {
// get client secret
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);
// bail if no client secret
if (!clientSecret) {
return;
} else {
stripe.retrievePaymentIntent(clientSecret).then(function (response) {
switch (response.paymentIntent.status) {
case "succeeded":
showMessage("Payment succeeded!");
break;
case "processing":
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
showMessage("Payment failed. Please try another payment method.");
break;
default:
showMessage("Something went wrong.");
break;
}
});
}
}
})
}
Nudge in the right direction is all I need, at least I hope so
Yes the return_url should be your own page that Stripe will automatically redirect after your customer completed the Payment: Stripe Doc. 'checkout-page?' doesn't look like a valid URL. Normally you would want something like 'http://localhost:4242/success'
This action is done automatically on client and you can't intercept it. Any action you want to perform on server should be handled via webhook, at Step 6 "Handle post-payment events" at the same article above.

EasyPaisa MA Transaction Error: Incomplete merchant information

I am trying to initiate an MA transaction using easy paisa api. The response error I get after executing the following code is as follows.
'RESPOSNE: '{"orderId": "XYZ123", "responseCode": "0017", "responseDesc": "Incomplete merchant information", "storeId": "xxxxx"}
The response code "0017" is not even mentioned in the documentation.
This is my code
const otcTransaction = async () => {
try {
let url = `https://easypaystg.easypaisa.com.pk/easypay-service/rest/v4/initiate-ma-transaction`
let body = {
emailAddress: 'example#gmail.com',
mobileAccountNo: '03xxxxxxxxx',
orderId: 'XYZ123',
storeId: XXXXX,
transactionAmount: 10.0,
transactionType: 'MA',
}
const response = await axios.post(
url,
body,
{
headers: {
'Credentials': 'base64(username:password)'
},
})
console.log('RESPOSNE: ', response.data)
} catch (error) {
console.log(error.message)
}
}
Let me know if anyone has worked on EasyPaisa MA Transaction
Thanks in advance!
Ask for store Id from EasyPaisa,
I have checked its working fine with proper payload
I got in contact with the easypaisa team and i found out that the code i have written is fine. What needed to be done was that since i was in development and using development credentials i could only use the test phone number provided to me by easypaisa.
(PS keep in mind in test mode we can only make a transaction of Rs 10.0)

Sequelize afterValidate hook called twice when updating

I'm using Sequelize in a Node backend to access a MySQL database and I realized that, depending on how you update an object, the afterValidate hook is called once or twice. I'll explain it better with an example:
We have a Shop entity defined by the following Sequelize model:
module.exports = (sequelize, DataTypes) => {
const Shop = sequelize.define('Shop', {
name: DataTypes.STRING,
address: DataTypes.STRING
}, {
freezeTableName: true,
hooks: {
afterValidate: (shop, options) => {
shop.name += '_HOOKED!'; // Just for testing
}
}
});
};
I've added a couple of shops using db.Shop.create() that have id 1 and 2. Now, I'm trying these 2 options that Sequelize provides to update a shop object:
Option 1
db.Shop.update({ name: 'Coffee Shop TEST' },
{ where: { id: shop.id } }).then((data) => {
console.log("All good!!");
}).catch((error) => {
console.log("No good: ", error);
});
Option 2
db.Shop.findOne({ where: { id: 1 } }).then((shop) => {
shop.update({ name: 'Coffee Shop TEST' }).then((data) => {
console.log("All good!!: ");
}).catch((error) => {
console.log("No good: ", error);
});
}).catch((error) => {
console.error("Error al actualizar: ", error);
});
If I use the first option, the shop is updated correctly and the afterValidate hook is called once, so the name now is: Coffee Shop TEST_HOOKED!.
However, if I use the second option, the hook is called twice so the name is set incorrectly to Coffee Shop TEST_HOOKED!_HOOKED!.
Why is this happening? Thanks in advance,
I might be a little late but for anyone who comes across this problem, here is the solution:
You can set options.validate = false in the beforeUpdate hook in your model.
For some reason, Sequelize runs the afterValidate hook twice when updating objects...
I tried to update an object that doesn't have any associations with other models and I got the same result: option 1 calls afterValidate hook once and option 2 calls it twice. Also, I tried to go back to sequelize version 5.1.0 and nothing changed.
So, it seems that sequelize works this way for whatever reason. I'll keep in mind that, if I want to update an object that has hooks on it, I'll use the code in option 1 to avoid problems like hashing the password twice.
Cheers,

Getting values from my web chat call in my website using backchannel

I'm trying to integrate the backchannel and getting the values.
https://github.com/Microsoft/BotFramework-WebChat/tree/master/samples/15.d.backchannel-send-welcome-event
I also tried this. Get URL Referer and Origin header from Microsoft Bot Framework
I also tried deserializing the values still not able to get the data.
how can i get the language values?
here's my sample code:
var userinfo = {
id: 'user-id',
name: 'user name',
locale: 'es'
};
var botConnection = new BotChat.DirectLine({
token: 'mytoken',
user: userinfo,
locale: 'es'
});
BotChat.App({
botConnection : botConnection,
user: userinfo,
bot: { id: 'bot-id', name: 'bot name' },
}, document.getElementById('botDiv'));
botConnection
.postActivity({
from: userinfo,
name: 'ConversationUpdate',
type: 'event',
value: '',
})
.subscribe(function (id) {
console.log('"trigger ConversationUpdate" sent');
});
The purpose of this I want to pass the locale to my bot from my website.
just like in the emulator.
Thanks!
I would recommend adding the locale to the back channel event's channel data. That way on the bot side you can simply access the locale in the incoming activity without having to deserialize any JSON objects when you receive the event. Note, you can also use text or value in place of channelData. See the code snippets below.
BotChat Back Channel Event
// Send back channel event
botConnection.postActivity({
from: userinfo,
name: 'setLocale',
type: 'event',
channelData: "es"
}).subscribe(id => console.log(id));
Bot - C#
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
if (turnContext.Activity.Type == ActivityTypes.Message)
{
...
} else if (turnContext.Activity.Type == "event") {
// Check for `setLocale` events
if (turnContext.Activity.Name == "setLocale") {
await turnContext.SendActivityAsync($"Your locale is set to {turnContext.Activity.ChannelData}");
}
}
else
{
await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected");
}
}
Hope this helps!

Categories