背景
ストライプ支払いを自分のサイトに統合しようとしています。プライベートストライプキーを使用してストライプユーザーを作成する必要があります。このキーをサーバーに保存し、サーバーメソッドを呼び出してユーザーを作成しています。たぶんこれを達成する別の方法がありますか?これがストライプAPIです(便宜上、以下にコピーします): https://stripe.com/docs/api/node#create_customer
//stripe api call
var Stripe = StripeAPI('my_secret_key');
Stripe.customers.create({
description: 'Customer for [email protected]',
card: "foobar" // obtained with Stripe.js
}, function(err, customer) {
// asynchronously called
});
私の試みと結果
同じクライアントコードと異なるサーバーコードを使用しています。すべての試行は、クライアントのconsole.log(...)で未定義になりますが、サーバーの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
Meteor.wrapAsync
から http://docs.meteor.com/#meteor_wrapasync 関数とオプションでコンテキストを渡す必要があることがわかりますが、2回の試行では呼び出しの結果を渡しています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イベントループ内で実行されます)。
API関数(Meteor.wrapAsync
)と共に関数コンテキスト、つまりAPI funcの本体内のthis
(この場合はStripe.customers.create
)と共にStripe.customers
に渡す必要があります。
編集:
エラーを取得する方法
従来のノードスタイルのAPI関数は、通常、最後の引数としてコールバックを受け取り、必要なタスクが完了すると最終的に呼び出されます。このコールバックは、エラーとデータの2つの引数を取ります。呼び出しの結果に応じて、どちらか1つがnullになります。
Meteor.wrapAsync
によって返される同期ラップ関数を使用して、エラーオブジェクトにアクセスするにはどうすればよいですか?
エラーの場合、非同期関数コールバックの最初の引数として渡されるのではなく、同期関数によってスローされるため、try/catchブロックの使用に依存する必要があります。
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
ではなくStripe.customers
であることを意味します。
ブラウザコンソールでこのモックコードをコピーして、自分でテストできます。
Stripe={
customers:{
create:function(){
console.log(this==Stripe.customers);
}
}
};
そして、次のようにブラウザコンソールでスタブ関数を呼び出します。
> Stripe.customers.create();
true
別のオプションはこれです package これは同様の目標を達成します。
meteor add meteorhacks:async
パッケージのREADMEから:
Async.wrap(function)
非同期関数をラップし、コールバックなしで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;
}
});
まず、@ saimeuntの回答に感謝します。これにより、いくつかの難しい概念が明確になります。しかし、エラーと結果の両方をクライアントに表示する古典的な非同期コールバック(err、結果)が必要な問題があったため、ブラウザで情報メッセージを提供できます。
私はこのように解決しました:
サーバーコード:
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には未解決のバグがあります( https://github.com/meteor/meteor/issues/2774 を参照)。これは呼び出し元に適切なエラーを復元しないためです。 Faceyspaceyと呼ばれる天才はMeteor.makeAsync()と呼ばれる置換を書きました。これは私が言及したバグページにありますが、結果ORエラーを 'result'変数に返し、 'error'変数を未定義のままにしておきます。今のところは、これで問題ありません。少なくとも、適切なエラーオブジェクトにフックできました。
MakeAsync()を使用する場合、次のようにFutureをインポートする必要があります。
Meteor.startup(function () {
//this is so that our makeAsync function works
Future = Npm.require('fibers/future');
});
ほぼすべての関数をAsyncでラップする必要があるため、このパッケージを使用する必要がありますhttps://atmospherejs.com/copleykj/stripe-sync
WrapAsyncを使用してすべてのストライプ関数を事前にラップし、作業を簡単にし、コードを簡潔にします。