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) => {
...
}
Related
I have a payment system with stripe payment intents and I want to create a succesfull paymnent . but once i payment then show this eorror in server side
C:\Project_Programing_hero\assainment-list\assainment-12\best-tech-server\node_modules\stripe\lib\Error.js:40
return new StripeInvalidRequestError(rawStripeError);
^
StripeInvalidRequestError: This value must be greater than or equal to 1.
on client side in checkoutFrom.js
useEffect(() => {
console.log(typeof (totalPrice));
fetch('http://localhost:5000/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ price: parseInt(totalPrice) }),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
const dataClientSecret = data?.clientSecret;
if (dataClientSecret) {
setClientSecret(dataClientSecret)
}
})
}, [totalPrice])
const handleSubmit = async (event) => {
event.preventDefault()
if (!stripe || !elements) {
return;
}
const card = elements.getElement(CardElement);
if (card == null) {
return;
}
const { error, paymentMethod } = await stripe.createPaymentMethod({
type: 'card',
card,
});
if (error) {
console.log('[error]', error);
setCardError(error.message)
} else {
console.log('[PaymentMethod]', paymentMethod);
setCardError('')
}
// confirm card payment
setCardSuccess('')
setProcessing(true)
const { paymentIntent, error: intentError } = await stripe.confirmCardPayment(
`${clientSecret}`,
{
payment_method: {
card: card,
billing_details: {
name: customerName,
email: email
},
},
},
);
if (intentError) {
setCardError(intentError?.message)
setProcessing(false)
} else {
setCardError('')
setTransitionId(paymentIntent.id)
console.log(paymentIntent);
setCardSuccess('Congrats,Your payment is compiled')
// store payment to database
const payment = {
order: _id,
transitionId: paymentIntent.id
}
axios.patch(`http://localhost:5000/order/${_id}`, payment)
.then(res => {
setProcessing(false)
console.log(res.data);
})
}
}
“This value must be greater than or equal to 1” error shows that the amount [0] param set in the payment intent creation request is smaller than 1. In the endpoint /create-payment-intent at your server, you will need to ensure request.price is greater than or equal to 1, and correctly assign into amount param. For example,
const paymentIntent = await stripe.paymentIntents.create({
amount: request.price,
currency: 'usd',
automatic_payment_methods: {enabled: true},
});
Apart from the server side, you should also make sure that the totalPrice at frontend is greater than or equal to 1 before passing to server.
body: JSON.stringify({ price: parseInt(totalPrice) }),
[0] https://stripe.com/docs/api/payment_intents/create#create_payment_intent-amount
When i get the string from my discord bot, i make a post request to my api
axios.post(`http://localhost:8080/api/post/ban/${discord_id}`, {}, {
headers: {
key: key
}
}).then((response) => {
console.log(response.data)
})
But when its submitted the event isnt activated
When i sent string the length of 17 or less or length of 19 or more it worked but not when string length is 18
app.post('/api/post/ban/:discord_id/', async function (req, res) {
let id = req.params.discord_id
let header = req.headers;
if(isNaN(id)) return res.send({
"error": {
"message": "USER_ID_MUST_BE_NUMBER",
"code": "400"
}
});
if(id.length < 19 || id.length > 19) return res.send({
"error": {
"message": "ID_IS_NOT_VALID",
"code": "400"
}
});
if(header.key != key) return res.send({
"error": {
"message": "OWNER_ONLY",
"code": "none"
}
});
await banModel.findByIdAndUpdate(banID, {
$addToSet: { "bannedUsers": `${id}`}
});
return res.send({
"success": {
"message": "ADDED_USER_TO_BANS",
"code": "201"
}
});
});`
i fixed it heres the answer:
axios.post(`http://localhost:8080/api/post/ban/${discord_id}/`,{},{
headers: {
key: key
}
})
.then(function (response) {
console.log(response.data)
if(response.data.error) {
switch(response.data.error.code) {
case "404":
return interaction.reply("Channel not found!");
case "422":
return interaction.reply("Invalid parameters!");
case "400":
return interaction.reply("Invalid types of objects!");
case "409":
return interaction.reply("U already exist on our Database!");
case "none":
switch(response.data.error.message) {
case "INVALID_VIDEO_URL":
return interaction.reply("Invalid video url")
case "OWNER_ONLY":
return interaction.reply("Owner only API")
}
break;
}
}
if(response.data.success) return interaction.reply("Succesfully added your video!")
})
.catch(function (error) {
console.log(error);
});
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.
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
there related but without response:
How to fix Error: Require at least one aggregateby? - fitness api
const fitness = google.fitness({ version: 'v1', auth });
fitness.users.dataset.aggregate(
{
aggregateBy: [
{
dataSourceId:
'derived:com.google.step_count.delta:com.google.android.gms:estimated_steps'
}
],
bucketByTime: {
durationMillis: 86400000
},
userId: 'me',
startTimeMillis: 1584891702214,
endTimeMillis: 1584978102214
},
(err, res, aa) => {
if (err) return console.log('The API returned an error: ' + err);
console.log(res.data);
const events = res.data.items;
resolve(events);
}
);
and got
The API returned an error: Error: Require at least one aggregateby
How I can repair that?
solved:
https://github.com/googleapis/google-api-nodejs-client/issues/1749
correct version:
fitness.users.dataset.aggregate(
{
userId: 'me',
resource: {
aggregateBy: [
{
dataSourceId:
'derived:com.google.step_count.delta:com.google.android.gms:estimated_steps'
}
],
bucketByTime: {
durationMillis: 86400000
},
startTimeMillis: 1584891702214,
endTimeMillis: 1584978102214
}
},
(err, res, aa) => {
if (err) return console.log('The API returned an error: ' + err);
console.log(res.data);
const events = res.data.items;
resolve(events);
}
);