Closed LucianoGanga closed 3 years ago
Async await would be MUCH cleaner, thanks for this suggestion!
I would also love for this package to use async await. Would make the writing the code so much cleaner. I'm having to write a wrapper around this package to use promises
@LucianoGanga @L-U-C-K-Y. After looking at the typescript declaration files and the code it turns out it does return a promise you just have to pass any value (even undefined) as a parameter to the request function, so maybe this could be an optional parameter?
const portalSession = await chargebee.portal_session.create({
redirect_url: 'MY_URL',
customer: {
id: 'customer-id'
}
}).request(undefined)
@LucianoGanga @L-U-C-K-Y. After looking at the typescript declaration files and the code it turns out it does return a promise you just have to pass any value (even undefined) as a parameter to the request function, so maybe this could be an optional parameter?
const portalSession = await chargebee.portal_session.create({ redirect_url: 'MY_URL', customer: { id: 'customer-id' } }).request(undefined)
Thanks @isaac-scarrott your workaround works for me.
@cb-navaneedhan how about making the .request
optional? Combined with #7 this would make the experience complete for me.
Edit:
I was facing issues when with async/await when the return is an array. In general, it seems that the response from the typescript library is returning an empty object (or array of empty objects), when console logging it. I also inspected it with the debugger, but it is empty.
When getting a list of something (for example payment sources) and there should be 1 entry, the return object just as a length of 1, but has empty contents.
Weird enough, when just accessing it, I am able to get the data.
For getting the payment sources I have used the following code:
/**
* Static function: Get payment sources list of a customer
* @param params
*/
static async getChargebeeCustomerPaymentSources(
params: _payment_source.payment_source_list_params,
): Promise<PaymentSource[]> {
const paymentSources: PaymentSource[] = [];
// get payment sources list from a customer
const paymentSourcesResponse = await chargebee.payment_source.list(params).request(undefined);
// if there are payment sources push to array
for (let i = 0; i < paymentSourcesResponse.list.length; i++) {
const payment_source: PaymentSource = paymentSourcesResponse.list[i].payment_source;
// if the payment source exists, push the payment source
if (payment_source) {
paymentSources.push(payment_source);
}
}
logger.info(
`getChargebeeCustomerPaymentSources - paymentSources array: ${JSON.stringify(
paymentSources,
null,
2,
)}`,
);
return paymentSources;
}
@L-U-C-K-Y I'm also getting an empty response Result {}
when creating a customer.
@L-U-C-K-Y I'm also getting an empty response
Result {}
when creating a customer.
You have to access the object in order to get the values out of it (not sure why).
This is the code I use for creating a subscription. Note that I explicitly access the result object to get the values out of it. You should be able to do the same thing with customer.
export interface ChargebeeCreateSubscriptionResponse {
subscription?: Subscription;
customer?: Customer;
card?: Card;
invoice?: Invoice;
unbilled_charges?: UnbilledCharge;
}
static async createChargebeeSubscription(params: _subscription.create_params): Promise<ChargebeeCreateSubscriptionResponse> {
// create subscription
const createdSubscription: ChargebeeCreateSubscriptionResponse = await chargebee.subscription
.create(params)
.request(undefined);
// log response
logger.info(`createSubscription - subscription: ${JSON.stringify(createdSubscription.subscription,null,2)}`);
logger.info(`createSubscription - customer: ${JSON.stringify(createdSubscription.customer, null, 2)}`);
logger.info(`createSubscription - card: ${JSON.stringify(createdSubscription.card, null, 2)}`);
logger.info(`createSubscription - invoice: ${JSON.stringify(createdSubscription.invoice, null, 2)}`);
logger.info(`createSubscription - unbilled_charges: ${JSON.stringify(createdSubscription.unbilled_charges,null,2)}`);
// explicitly access and return the response from the chargebee API
return {
subscription: createdSubscription.subscription,
customer: createdSubscription.customer,
card: createdSubscription.card,
invoice: createdSubscription.invoice,
unbilled_charges: createdSubscription.unbilled_charges,
};
}
If anyone else is getting an empty Result {}
using the proposed method (by @isaac-scarrott ) you can alternatively try this:
return await new Promise((resolve, reject) => chargebee.customer.create({
email,
id
}).request((error: any, result: any) => {
if (error) {
reject(error)
} else {
resolve(JSON.parse(JSON.stringify(`${result}`)))
}
})));
thanks @L-U-C-K-Y
@smashah The empty result is due to it return some sort of JSON that cannot be directly logged. Try the .toString() method to see the structure of the JSON and then you can access it's keys in a normal way.
This is also an issue that needs to be solved. This could be due to using the q library and not native Javascript Promises. If this is the case native promises should be used.
Yes, a Request {}
object is entirely unexpected and this is an issue that needs fixing asap.
What the hell is this library. I just had to JSON.parse the result twice for it to work as an object! In all of my years of JS, I've never seen this type of nonsense. Please fix this Chargebee. This is unacceptable when Stripe is already an option. Honestly.
return await new Promise((resolve, reject) => chargebee.customer.create({
email,
id
}).request((error: any, result: any) => {
if (error) {
reject(error)
} else {
resolve(JSON.parse(JSON.parse(JSON.stringify(`${result}`))))
}
})));
Also agree that this library does not meet standards one would except.
@L-U-C-K-Y I'm also getting an empty response
Result {}
when creating a customer.export interface ChargebeeCreateSubscriptionResponse { subscription?: Subscription; customer?: Customer; card?: Card; invoice?: Invoice; unbilled_charges?: UnbilledCharge; }
Thanks for the idea, though the types where also not exported as expected @L-U-C-K-Y
What the hell is this library. I just had to JSON.parse the result twice for it to work as an object! In all of my years of JS, I've never seen this type of nonsense. Please fix this Chargebee. This is unacceptable when Stripe is already an option. Honestly.
return await new Promise((resolve, reject) => chargebee.customer.create({ email, id }).request((error: any, result: any) => { if (error) { reject(error) } else { resolve(JSON.parse(JSON.parse(JSON.stringify(`${result}`)))) } })));
Did some testing and using the node package chargebee
seams to be better, you can still type the returned promise with putting together a type from the chargebee-typescript
. Its not the best case but feels more reliable then the broken typescript libray. As of writing using version chargebee@2.6.4 and chargebee-typescript@2.0.7
import chargebee from 'chargebee'
import { ChargeBee as ChargeBeeType } from 'chargebee-typescript'
type ChargebeeCreateSubscriptionResponse = {
subscription?: ChargeBeeType['subscription']
customer?: ChargeBeeType['customer']
card?: ChargeBeeType['card']
invoice?: ChargeBeeType['invoice']
unbilled_charges?: ChargeBeeType['unbilled_charge'][]
}
chargebee.configure({
site: 'XX,
api_key: 'XXX',
})
const yourFunctionForCreation = async () => {
const result = await (<ChargebeeCreateSubscriptionResponse>(
chargebee.subscription
.create({
plan_id: 'XXX',
customer: { email: 'john2@user.com' },
})
.request()
))
const { subscription, customer, card, invoice, unbilled_charges } = result
console.log(
'results spreaded',
subscription,
customer,
card,
invoice,
unbilled_charges,
)
}
Thanks for the helpful conversation.
Also agree that this library does not meet standards one would except.
This is sadly the issue with all their libraries. The quality is just bad ... and it's not getting any better. And don't get your hopes up. They are ignoring issues for 7 years and counting.
If you have the choice, stay away from Chargebee.
@rubas having an issue open that long would be embarrassing for me as a solo open source maintainer. I can't believe the issue you linked is still open, with open PRs as well?!?!, after so long on a repo of a handsomely funded company. I'm half way done with my stripe billing migration. Too bad. I really believed in chargebee.
I'm surprised they officially launched this (and included it in the official docs). It feels very much unfinished. Also, shocking that it still uses callback functions instead of just async/await. They're still even relying on the "Q" Promise library when it's not necessary!
I guess I'll go back to using the regular JS chargebee npm package. I'm also getting the empty Result {}
response, so for me, it's unusable.
The code examples in the docs also don't make sense:
import {
ChargeBee,
_estimate
} from 'chargebee-typescript';
var chargebee = new ChargeBee();
chargebee.configure({site : "{site}",
api_key : "{site_api_key}"});
chargebee.estimate.upcoming_invoices_estimate("__test__KyVnHhSBWl2pw2aa").request(function(error,result) {
if(error){
//handle error
console.log(error);
}else{
console.log(`${result}`);
var estimate: typeof chargebee.estimate = result.estimate;
}
});
Why import _estimate
if it's not used?
We have made callback param optional in v2.2.0
@LaszloDev @smashah Hi! Do you know if this issue is already fixed? Is the library working as expected? Otherwise, from your experience, what do you recommend? Would using the NodeJS library + hard-typing types from the typescript library be an option? Thanks in advance!
Hello!
I was wondering if you're thinking of adding async/await support to this client.
It will make the code much more readable and easier. For example, it will be nice to change this code:
To something like this:
But "request" forces a callback call with 2 parameters inside.
Thanks! Luciano