How to figure out stripe issue for payout / transfer with Strapi - stripe-payments

I am going to implement transfer and payout functional with stripe between accounts using node js.
But I met one issue to implement this one.
Code:
const stripe = require('stripe')('****');
try {
cardInfo = await PayInfo.findOne({user_id: uid});
if (!cardInfo ) {
return ctx.badRequest(
null,
formatError({
id: 'PayInfo.create.findByUserId.error',
message: 'User is not available',
})
);
}
let targetId = cardInfo.account_id;
let payoutState = null;
try {
const payoutState = await stripe.transfers.create({
amount: 400,
currency: 'usd',
destination: targetId,
source_type: 'bank_account',
});
await record.create({
order_id: id,
user_id: user.id,
payment_id: payoutState.id,
transaction: 'transfer',
amount: 400,
state: payoutState.reversed ? 'failed' : 'succeeded',
});
} catch (error) {
return ctx.send(null, {
error,
payoutState,
});
}
} catch (e) {
return ctx.badRequest(
null,
{
error: e,
}
);
}
But I met this issue message from it.
If I delete stripe integration part then it works well. - so wired.
{
actual: false
code: "ERR_ASSERTION"
expected: true
generatedMessage: false
operator: "=="
}
I am not sure what I was wrong, would you let me know on it please?
Thanks.

Related

Razorpay not returning payment_id,order_id etc. upon successfull payment

I have one function that is responsible of creating order using razorpay and verify that order .
The code for that function is : -
const paymentMethod = async ()=>{
if(!isAuthenticated())
{
toast.error('Please signin to continue');
history.push('/signin')
// return <Redirect to='/signin' />
return;
}
try{
// console.log(JSON.stringify(total));
const obj = {
amount:total
}
let data = await fetch('http://localhost:3100/api/checkout',{
method:'POST',
headers:{
"content-type":"application/json",
Accept:"application/json"
},
body: JSON.stringify(obj)
})
let {order} = await data.json()
console.log(order)
console.log(order.amount)
const options = {
key: "rzp_test_cXj3ybg8fawS9Y",
amount: order.amount,
currency: "INR",
name: "YO! Merchandise",
description: "Pay Please",
image:yo,
order_id: order.id,
callback_url: "http://localhost:3100/api/paymentverification",
prefill: {
name: "Aakash Tiwari",
email: "tiwaryaakash00#gmail.com",
contact: "8750043604"
},
notes: {
address: "Razorpay Corporate Office"
},
theme: {
color: "#13C962"
}
};
let rzp1 = await new window.Razorpay(options);
rzp1.open();
}
catch(err){
console.log(err)
}
}
But this function when call callback_url upon successfull payment it is not passing the payment_id,order_id etc. other neccessary details.
when i try to console.log there the req.body is always empty.

How to find documents in array in mongoose

How can i use mongoose.find() method to find the below code.
Paid.find({info:{data:"status"}})
This is not working as it is returning empty array
info{
event: 'charge.success',
data: {
id: 1190118808,
domain: 'test',
status: 'success',
reference: 'T458573232919212',
amount: 100000,
message: null,
gateway_response: 'Successful',
paid_at: '2021-06-26T00:25:33.000Z',
created_at: '2021-06-26T00:25:24.000Z',
}
If you use mongoose, it should be as easy as doing YourModel.find({ data: { status: "success" } }), this is assuming info is not an actual property on the document
Full Example (including data structure (the Schema), simplified):
const schema1 = new mongoose.Schema({
data: {
status: String
}
});
const model1 = mongoose.model("model1", schema1);
(async () => {
// connect the connection before this part
await model1.create({ data: { status: "success" } });
await model1.create({ data: { status: "failure" } });
// this should only find & log the "success" one in the array
const found = await model1.find({ data: { status: "success" } }).exec();
console.log("found", found);
})()

Correct boom error not being returned in hapijs v17

API controller:
export const addPaymentCard = async (request: ICustomerAddPaymentCardRequest, h: ResponseToolkit) => {
try {
const { _id: customerId } = request.auth.credentials
const { cardToken } = request.payload
const customerInfo: ICustomer | null = await Customer.findOne({ _id: customerId })
if (!customerInfo) throw Boom.notFound("Customer not found")
if (!customerInfo.stripeId) {
const stripeCustomer = await createStripeCustomer({ email: customerInfo.email, metadata: { customerId: customerId.toString() } })
await Customer.findOneAndUpdate({ _id: customerInfo._id }, { stripeId: stripeCustomer.id }, { new: true })
customerInfo["stripeId"] = stripeCustomer.id
}
const card = await createStripeSource(customerInfo.stripeId, { source: cardToken })
return h.response({ statusCode: 200, message: "Success", data: card })
} catch (error) {
logger.error(`${request.method.toUpperCase()} ${request.url.pathname}, error=${error}`)
throw error
}
}
Boom error is thrown in this method:
export const createStripeSource = async (customerId: string, data: Stripe.CustomerSourceCreateParams) => {
try {
const source = await stripe.customers.createSource(customerId, data)
return source
} catch (error) {
logger.error(`create stripe payment methods incurred error=${error}`)
throw error
}
}
Expected error to be sent: like invalid card
Actual error being sent: Internal Server error
How can I get actual error returned by stripe?
This is also happening with other methods that are returning error when called inside any handler.
node v12
#hapi/hapi v20
#hapi/boom v9

Stripe "no such price"

I created a product with tiered pricing in my Stripe dashboard. I copied the price API IDs and put them in my app's frontend. When I run my code, the backend generates the error: No such price: 'PRICE_1HPYAGLJZYBC5S5KGBKT8UDY'. This price id matches one of the prices on my Stripe dashboard, but I never set the product so I'm wondering if that's the issue. Here is my client js:
function createSubscription({ customerId, paymentMethodId, priceId }) {
return (
fetch('/create-subscription', {
method: 'post',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({
customerId: customerId,
paymentMethodId: paymentMethodId,
priceId: priceId,
}),
})
.then((response) => {
return response.json();
})
// If the card is declined, display an error to the user.
.then((result) => {
if (result.error) {
// The card had an error when trying to attach it to a customer
throw result;
}
return result;
})
// Normalize the result to contain the object returned
// by Stripe. Add the addional details we need.
.then((result) => {
console.log("RETURNING SUBSCRIPTION")
return {
// Use the Stripe 'object' property on the
// returned result to understand what object is returned.
subscription: result,
paymentMethodId: paymentMethodId,
priceId: priceId,
};
})
);
}
And here is my backend code:
app.post('/create-subscription', async function(req, res) {
console.log(req.body);
User.findOne({"_id": req.session.auth_user._id}, async function(err, user) {
if (user.stripe_id) {
console.log("RETRIEVING CUSTOMER");
var customer = await stripe.customers.retrieve(user.stripe_id);
if (user.stripe_subscription) {
console.log("RETRIEVING SUBSCRIPTION");
var subscription = await stripe.subscriptions.retrieve(user.stripe_subscription);
update_customer(customer, subscription);
}
else {
console.log("CREATING SUBSCRIPTION");
var subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{
price: req.body.priceId,
}]
});
user.stripe_subscription = subscription.id;
user.save(function(err) {
update_customer(customer, subscription);
})
}
}
else {
console.log("CREATING CUSTOMER");
var customer = await stripe.customers.create({
email: req.body.email,
});
user.stripe_id = customer.id;
user.save( async function(err, user) {
if (user.stripe_subscription) {
console.log("RETRIEVING SUBSCRIPTION");
var subscription = await stripe.subscriptions.retrieve(user.stripe_subscription);
update_customer(customer, subscription);
}
else {
console.log("CREATING SUBSCRIPTION");
var subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{
price: req.body.priceId,
}]
});
user.stripe_subscription = subscription.id;
user.save(function(err) {
update_customer(customer, subscription);
});
}
});
}
});
async function update_customer(customer, subscription) {
const paymentMethod = await stripe.paymentMethods.attach(
req.body.paymentMethodId,
{customer: customer.id}
);
console.log(subscription);
res.send(subscription);
}
});
Check the price ID, it looks like something in your frontend converts all the string to uppercase. Usually price id start in lowercase ('price....') and then the string is a mix between numbers and lowercase and uppercase characters.
Incase anyone faces this issue in the future. I had the same issue, but mine was caused by the stripe secret being wrong.
It's wise to:
Double check the price,
Trim the string,
Check your config keys all through
Hope this helps someone 🚀
In my case I was following the docs and
the docs had it like this: Price = "{{price_1234}}"
So I changed it to this: Price = "price_1234" and it worked.
In my case, the API keys were not correct.
If like me, you just followed the tutorial from the docs, the API keys from the code snippets that are proposed are not correct.
You have to setup the ones from the dashboard page (for the test environment: https://dashboard.stripe.com/test/dashboard)

Stripe auth and capture charge with NODE.js

I'm having trouble with the pre-authorization described here https://stripe.com/docs/charges#auth-capture.
The auth goes successful (capture params to false), I can store the ID of the carghe on my databse and I can see the uncaptured charge from my Stripe Dashboard.
Problem comes when I try to capture the charge, because it fails with Error: No such charge: <CHARGE_ID>.
Here is the code:
constructor(){
this.stripe = require('stripe')('<sk_test_mysecretkey>');
}
async captureCharge(chargeId) {
try {
/**
* https://stripe.com/docs/api/charges/capture
*/
return this.stripe.charges.capture(chargeId)
.then((charge) => {
return {
error: false,
success: true,
message: 'ChargeSuccesful',
code: 200,
charge: charge,
};
},
(err) => {
console.log("CAPTURE CHARGE ERROR: ", err);
return {
success: false,
error: err.type,
code: err.statusCode,
};
}
);
} catch (e) {
console.log('ERROR CAPTURE', e);
}
}
Even if I try with a POST to https://api.stripe.com/v1/charges/<CHARGE_ID>/capture with auth: Bearer <sk_test_mysecretkey> i get the same error:
{
"error": {
"code": "resource_missing",
"doc_url": "https://stripe.com/docs/error-codes/resource-missing",
"message": "No such charge: <CHARGE_ID>",
"param": "charge",
"type": "invalid_request_error"
}
}
The uncaptured charge still exist on Stripe.
Thanks in advance.
UPDATE
I forgot to say that the charge isn't a simple charge, but it is a split payment with a shared customer. Stripe supports three approaches for processing split payment, I have choosed the direct charges:
async authorizationCharge(amount, merchantStripeId, billId, customerId) {
try {
var fee = 0.25;
/** Pre-Authorization Charge using a shared customer
* https://stripe.com/docs/charges#auth-capture
* https://stripe.com/docs/connect/shared-customers
*/
return this.stripe.tokens
.create(
{ customer: customerId },
{ stripe_account: merchantStripeId }
)
.then((oneTimeToken) => {
return this.stripe.charges
.create(
{
amount: Math.round(amount),
currency: 'eur',
application_fee: fee,
description: 'Bill ID: ' + billId,
source: oneTimeToken.id,
capture: false,
},
{ stripe_account: merchantStripeId }
)
.then((charge) => {
console.log('CHARGE: ', charge);
return {
error: false,
success: true,
code: 200,
charge: charge,
fee: fee,
};
},
(err) => {
// ERROR INFO:
// https://stripe.com/docs/api#error_handling
console.log('ERROR', err);
return {
success: false,
error: err.type,
code: err.statusCode,
};
}
);
},
(err) => {
// ERROR INFO:
// https://stripe.com/docs/api#error_handling
console.log('ERROR', err);
return { success: false, error: err.type, code: err.statusCode };
}
);
} catch (e) {
console.log(e);
}
}
Finally I understood the reason, I did not indicate the connected account (see the updated question).
return this.stripe.charges.capture(chargeId, { stripe_account: merchantStripeId }) <---- CONNECTED ACCOUNT
.then((charge) => {
...
}

Resources