背景
我正在尝试将条纹付款集成到我的网站中。我需要使用我的专用条纹密钥创建一个条纹用户。我将此密钥存储在服务器上,并调用服务器方法来创建用户。也许还有另一种方法可以做到这一点?
//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的情况。
在Meteor.wrapAsync您可以看到需要向其传递一个函数和一个可选的上下文,而在两次尝试中,您都传递了调用异步版本的结果Stripe.customers.create。
Meteor.wrapAsync
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); } });
Meteor.wrapAsync将异步函数转换为方便的同步外观函数,该函数允许编写顺序查找的代码。(底层仍然在异步Node.js事件循环中执行所有操作)。
我们需要将函数上下文与函数上下文一起传递给Meteor.wrapAsync我们的API函数(Stripe.customers.create),即this在API函数的主体内部(在本例中为)Stripe.customers。
this
Stripe.customers
编辑:
如何找回错误?
传统的节点样式API函数通常将回调作为最后一个参数,当所需的任务完成时,它将最终被调用。此回调采用2个参数:error和data,根据调用结果,其中任一个将为null。
我们如何使用返回的同步包装函数访问错误对象Meteor.wrapAsync?
我们必须依靠使用try / catch块,因为如果发生错误,它将由sync函数抛出,而不是作为异步函数回调的第一个参数传递。
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?
JavaScript没有“命名空间”概念,因此API开发人员使用了一种通用技巧,即定义充当API名称空间的全局对象,在此对象上定义的属性是API的“子模块”。这意味着它Stripe.customers是Stripe API的子模块,用于公开与客户相关的功能,因此这些功能this上下文Stripe.customers不是Stripe。
Stripe
您可以通过将以下模拟代码复制粘贴到浏览器控制台中来自己进行测试:
Stripe={ customers:{ create:function(){ console.log(this==Stripe.customers); } } };
然后像这样在浏览器控制台中调用存根函数:
> Stripe.customers.create(); true