背景
我正在尝试将条带付款整合到我的网站中。我需要使用私有条带密钥创建条带用户。我将此密钥存储在我的服务器上,并调用服务器方法来创建用户。也许有另一种方法可以实现这一目标?这是条纹api(为方便起见,下面复制): https://stripe.com/docs/api/node#create_customer
//stripe api call
var Stripe = StripeAPI('my_secret_key');
Stripe.customers.create({
description: 'Customer for test@example.com',
card: "foobar" // obtained with Stripe.js
}, function(err, customer) {
// asynchronously called
});
我的尝试和结果
我一直在使用不同服务器代码的相同客户端代码。所有尝试都会在客户端的console.log(...)上立即给出undefined,但在服务器console.log(...)上给出正确的响应:
//client
Meteor.call('stripeCreateUser', options, function(err, result) {
console.log(err, result);
});
//server attempt 1
var Stripe = StripeAPI('my_secret_key');
Meteor.methods({
stripeCreateUser: function(options) {
return Meteor.wrapAsync(Stripe.customers.create({
description: 'Woot! A new customer!',
card: options.ccToken,
plan: options.pricingPlan
}, function (err, res) {
console.log(res, err);
return (res || err);
}));
}
});
//server attempt 2
var Stripe = StripeAPI('my_secret_key');
Meteor.methods({
stripeCreateUser: function(options) {
return Meteor.wrapAsync(Stripe.customers.create({
description: 'Woot! A new customer!',
card: options.ccToken,
plan: options.pricingPlan
}));
}
});
我也尝试过没有Meteor.wrapAsync。
编辑 - 我也在使用这个包: https://atmospherejs.com/mrgalaxy/stripe
答案 0 :(得分:74)
从Meteor.wrapAsync
http://docs.meteor.com/#meteor_wrapasync你可以看到你需要传递一个函数和一个上下文,而在你的两次尝试中你传递的结果是调用{{1的异步版本}}
Stripe.customers.create
Meteor.methods({
stripeCreateUser: function(options) {
// get a sync version of our API async func
var stripeCustomersCreateSync=Meteor.wrapAsync(Stripe.customers.create,Stripe.customers);
// call the sync version of our API func with the parameters from the method call
var result=stripeCustomersCreateSync({
description: 'Woot! A new customer!',
card: options.ccToken,
plan: options.pricingPlan
});
// do whatever you want with the result
console.log(result);
}
});
将异步函数转换为方便的同步查找函数,该函数允许编写顺序查找代码。 (发动机故障仍然在异步Node.js事件循环中执行。)
我们需要传递Meteor.wrapAsync
我们的API函数(Meteor.wrapAsync
)以及函数上下文,即API函数体内的Stripe.customers.create
,在本例中为this
1}}。
编辑:
如何检索错误?
传统节点样式API函数通常将回调作为最后一个参数,最终将在所需任务完成时调用。这个回调有两个参数:错误和数据,根据调用的结果,其中一个将为null。
我们如何使用Stripe.customers
返回的同步包装函数来访问错误对象?
我们必须依赖于使用try / catch块,因为如果出现错误,它将被sync函数抛出而不是作为异步函数回调的第一个参数传递。
Meteor.wrapAsync
为什么Stripe不需要传递?
JavaScript没有“命名空间”概念,因此API开发人员使用定义充当API命名空间的全局对象的常用技巧,在此对象上定义的属性是API的“子模块”。
这意味着try{
var result=syncFunction(params);
console.log("result :",result);
}
catch(error){
console.log("error",error);
}
// is the equivalent of :
asyncFunc(params,function(error,result){
if(error){
console.log("error",error);
return;
}
console.log("result :",result);
});
是Stripe API的子模块,公开了与客户相关的功能,因此这些功能Stripe.customers
上下文为this
,而不是Stripe.customers
。
您可以通过在浏览器控制台中粘贴此模拟代码来自行测试:
Stripe
然后在浏览器控制台中调用存根函数,如下所示:
Stripe={
customers:{
create:function(){
console.log(this==Stripe.customers);
}
}
};
答案 1 :(得分:11)
另一种选择是package,它实现了类似的目标。
meteor add meteorhacks:async
来自自述文件包:
<强> Async.wrap(功能)强>
包装异步函数并允许它在没有回调的情况下在Meteor中运行。
//declare a simple async function
function delayedMessge(delay, message, callback) {
setTimeout(function() {
callback(null, message);
}, delay);
}
//wrapping
var wrappedDelayedMessage = Async.wrap(delayedMessge);
//usage
Meteor.methods({
'delayedEcho': function(message) {
var response = wrappedDelayedMessage(500, message);
return response;
}
});
答案 2 :(得分:7)
首先,感谢@saimeunt的回答,这使得一些困难的概念变得清晰。 但是我遇到了一个问题,即想要一个经典的异步回调(错误,结果),在客户端显示错误和结果,以便我可以在浏览器中提供信息性消息。
我这样解决了:
服务器代码:
var Stripe = StripeAPI(STRIPE_SECRET_KEY);
Meteor.methods({
createCust: Meteor.wrapAsync(Stripe.charges.create, Stripe.charges)
});
客户代码:
var stripeCallOptions = {
description: 'Woot! A new customer!',
card: ccToken,
plan: pricingPlan
};
Meteor.call('createCust', stripeCallOptions, function(error, result){
console.log('client error', error);
console.log('client result', result);
});
看起来很整洁。但是不幸的是,wrapAsync有一个开放的bug(参见https://github.com/meteor/meteor/issues/2774),因为它没有为调用者恢复正确的错误。一个名为Faceyspacey的天才编写了一个名为Meteor.makeAsync()的替代品,您可以在我提到的错误页面上找到它,但是它会将结果或错误返回给'result'变量,使'error'变量保持未定义状态。 我现在很好,至少我对正确的错误对象有一个钩子。
如果你使用makeAsync(),你需要像这样导入期货:
Meteor.startup(function () {
//this is so that our makeAsync function works
Future = Npm.require('fibers/future');
});
答案 3 :(得分:1)
由于你几乎需要在Async中包含几乎每个函数,你应该使用这个包https://atmospherejs.com/copleykj/stripe-sync
它使用WrapAsync预先包装所有条带函数,使你的生活更轻松,代码更清晰。