如何使用stripe
本文由Stamplay赞助。 感谢您支持使SitePoint成为可能的赞助商。
作为前端开发人员,我经常发现自己使用Angular和React之类的框架为自己的副项目创建了丰富的UI,但是有时候您的应用需要数据,持久性,业务逻辑,电子邮件以及其他通常是后端开发人员的领域。 Stamplay是一项服务,旨在使应用程序开发的这些方面像填写表格一样容易。
让我们通过使用Stamplay构建一个“后端”来充实一个简单的Book Club应用程序。 用户将能够对阅读过的书进行评分。 他们还可以投票其他评论。 我们会向用户收取对读书俱乐部的访问权限,并在他们注册时通过电子邮件向他们发送欢迎礼包。
我已经为Book Club应用程序创建了一个前端外壳。 在学习本教程时,我们将使用Stamplay填补空白。
首先,您需要克隆以下存储库 :
git clone [email protected]:bradbarrow/sp-stamplay.git
在项目目录中,检出starter
分支:
git checkout starter
然后运行以下命令:
bower install
这将安装:
我们还包括了StripeJavaScript客户端。
要运行该应用程序,您需要安装http服务器。 我喜欢使用lr-http-server
,您可以通过运行以下命令进行安装:
npm install -g lr-http-server
然后在您的项目目录中,只需运行lr-http-server -p 8080
。
Stamplay入门很容易。 只需访问他们的注册页面 ,然后单击“ 创建新帐户”按钮即可获得一个帐户。
在Stamplay编辑器中,为您的新应用指定唯一的名称,然后单击“创建”按钮。 我们称我们的App Bookclub
现在,您将进入此应用程序的仪表板。 请注意此页面,因为它具有一些有关将前端连接到Stamplay的重要信息。
为了使用Stamplay,我们需要将我们的应用程序连接到Stamplay的API。 Stamplay为此提供了一个npm软件包。 继续并安装stamplay-cli软件包。
npm install -g stamplay-cli
现在,您可以在项目目录中运行stamplay init
来生成stamplay.json
文件。
您将需要应用程序的APP ID和API KEY ,如上所述,它们都可以在应用程序仪表板上找到。
如果我们要有一个读书俱乐部,我们将需要书籍。 我们的应用程序已经在index.html
有一个书单,在scripts/app.js
已经有一个BooksController
。 让我们转到Stamplay并设置Book CustomObject,然后再将其连接到我们的应用程序中。
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
在应用的信息中心上,点击左侧菜单中的对象链接,然后点击+添加 。 在“对象名称”字段中enter
book
,然后按enter
键以开始填写其属性。
我们将只添加一个名为“ title”的字符串属性。
Stamplay具有一个API控制台,可帮助您与应用程序进行交互。 它使您可以执行API操作来获取/设置数据,并查看您的应用程序如何响应。
让我们使用控制台添加我们的第一本书(稍后我们将使用自己的应用添加图书)。
单击Stamplay编辑器左侧菜单中的API Console。
从“操作”菜单中,选择“创建对象”。
在“ API URL”字段中,从下拉列表中选择“ book”。
将出现一个表格,询问您要添加的书的标题。 让我们添加“杀死一只嘲笑的鸟”。 点击发送按钮。
当请求发送到您应用的API时,我们将看到该请求,最终我们将得到响应。 一切顺利,应该是200 OK。
让我们将“操作”更改为“获取所有对象”,然后再次选择“预订”。 再次点击发送,我们应该返回一个包含“杀死一只嘲笑鸟”的响应。
现在是时候将该数据放入我们的前端了。
打开scripts/app.js
在文件的最上方添加以下行:
Stamplay.init('YOURAPPID');
这是使用Stamplay
全球从Stamplay SDK我们包括index.html
。 初始化函数标识我们的应用程序,以便我们其余的调用转到正确的应用程序。
接下来,我们将创建一个Book服务,以从Stamplay获取我们的图书。 如下更新app.js
:
Stamplay.init("bookclub");
var app = angular.module('stamplay', ['ngStamplay']);
app.controller('BooksController', function($scope, $rootScope, $stamplay, Book){
$scope.books = [];
Book.all().then(function(books){
$scope.books = books;
});
});
app.factory('Book', function($q, $stamplay){
function all() {
var deferred = $q.defer();
var BookCollection = $stamplay.Cobject('book').Collection;
BookCollection.fetch().then(function() {
deferred.resolve(BookCollection.instance);
});
return deferred.promise;
}
return {
all: all
}
});
您会注意到我们在这里使用
$stamplay
。 由于我们已包含ngStamplay模块,因此该功能可用。
我们在这里正在使用Angular Stamplay SDK来获取我们的藏书。 我们使用all()
方法创建了一个简单的Book服务。
all方法在内部调用Stamplay书籍Collection上的fetch()
,并返回promise 。 解决后,将填充BookCollection。 (请记住,Stamplay模型和集合本质上是Backbone.js结构。
在BooksController中,我们只需注入我们的服务并调用all()
方法即可在范围内填充books数组。
在index.html中,我们需要将{{book.title}}行更改为{{book.instance.title}},以符合Stamplay的数据结构。 您也可以调用book.get('title')。
现在,当您在浏览器中查看应用程序时,您应该在书单中看到“杀死一只模仿鸟”。
让我们添加从应用程序创建新书的功能。 首先,我们将在图书清单的顶部创建一个表单:
Books
{{book.instance.title}}
然后,我们将一个名为add
的新方法添加到Book服务中:
app.factory('Book', function($q, $stamplay){
function all() {
...
}
function add(book) {
var deferred = $q.defer();
var BookModel = $stamplay.Cobject('book').Model;
BookModel.set('title', book.title);
BookModel.save().then(function() {
deferred.resolve(BookModel);
});
return deferred.promise;
}
return {
all: all,
add: add
}
});
在这里,您可以看到我们使用自定义对象的模型而不是集合。 我们创建一本新的空书,为其分配书名然后保存。 然后,我们使用保存的实例实例来解决我们的承诺。
剩下的就是我们的BooksController处理表单提交:
app.controller('BooksController', function($scope, $rootScope, $stamplay, Book){
...
$scope.newBook = { title: '' }; // Empty book for form
$scope.addBook = function() {
Book.add($scope.newBook).then(function(savedBook){
$scope.books.push(savedBook); // Immediate UI response
});
$scope.newBook.title = ''; // Blank out the form
}
});
如果您填写表格,应该会看到您的书已添加到列表中。 刷新页面,它应该仍然存在。 我们刚刚使用Stamplay在应用程序中添加了持久性。 容易吧?
目前,我们网站的任何访问者都可以添加书籍。 假设我们只希望注册用户能够将新书添加到列表中。
Stamplay使登录变得容易。 首先,在Stamplay编辑器的左侧菜单中单击“用户”,然后单击“身份验证”。
在这里,您可以为Stamplay应用程序选择一系列身份验证解决方案。 今天,我们将使用Google Plus。
您可以在此处找到有关此过程的说明。 这非常容易,只需几分钟。
拥有Google Plus应用ID和密码后,请点击Stamplay身份验证部分中的Google Plus徽标,然后输入您的详细信息,然后点击保存。
就本教程而言,我们还将设置对公共应用的权限,这样我们就不必担心谁登录以及谁可以做什么。 也就是说,Stamplay中的角色和权限系统功能强大,可以轻松处理应用程序中复杂的用户权限设置。
要将权限设置为公共,请单击“用户”菜单下的“权限”,然后单击“公共”选项卡。
既然我们已经连接了Google Plus,那么登录就很简单了。
我们将创建一个User服务,该服务允许我们登录和注销以及获取有关当前登录用户的信息:
app.factory('User', function($q, $stamplay){
function login() {
var deferred = $q.defer();
var User = $stamplay.User().Model;
User.login('google').then(function(){
deferred.resolve(User);
});
}
function active() {
var deferred = $q.defer();
var User = $stamplay.User().Model;
User.currentUser().then(function() {
deferred.resolve(User);
}).catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
function logout() {
var User = $stamplay.User().Model;
User.logout();
}
return {
active: active,
logout: logout,
login: login
};
});
只需调用User.login('google')
,Stamplay将在返回用户登录之前通过OAuth流程发送我们的用户。
我们将向NavBar添加一个登录链接,但首先让我们创建一个NavController来处理操作:
app.controller('NavController', function($scope, User, $rootScope){
$scope.login = function(){
User.login().then(function(user){
// Add their details to root scope
$rootScope.$emit('User::loggedIn', {user: user});
});
}
$scope.logout = function(){
User.logout();
}
});
登录成功后,我们将发出一个包含用户详细信息的事件。 让我们为该事件设置一个侦听器:
app.run(function($rootScope, User){
// Listen for login events
$rootScope.$on('User::loggedIn', function(event, data){
$rootScope.loggedIn = true;
$rootScope.user = data.user;
});
// Check if there's a user logged in already
User.active().then(function(activeUser){
if(activeUser.isLogged()){
// Add their details to rootScope
$rootScope.$emit('User::loggedIn', {user: activeUser});
}
});
});
在Angular的run()
函数中,我们将为登录事件设置一个侦听器。 如果您以前没有使用过run()
函数,那么它基本上是一个在应用程序引导后立即运行的函数。
当用户登录时,我们将存储已登录用户的事实,并存储其详细信息。
下一节将检查是否有活动用户,如果他们已经登录,则会发出登录事件。 这是在这里,以便当已经登录的用户访问您的站点时,其详细信息将放回到$rootScope
。
现在我们知道某人是否已登录,并且有了登录和注销的方法,我们可以向导航栏添加一些链接:
如果您在浏览器中打开它并进行尝试,您会注意到的第一件事是,单击链接会将您转到http://localhost/auth/v1/google/connect
或类似的网站。 由于Google(出于安全原因)希望使用真实的网址来处理身份验证,因此无法使用此功能。 幸运的是,Stamplay使我们可以轻松地将应用程序部署到真实URL。
只需在项目目录中运行stamplay deploy
。
完成后,您可以在http://yourappid.stamplayapp.com
看到您的应用程序。 现在,登录/注销过程也应正常工作。
最后,我们仅在用户登录后显示“添加书”表单:
让我们向新用户发送欢迎电子邮件。 单击Stamplay左侧菜单中“任务”下的“管理”,然后单击“新建任务”。 我们将选择:“当用户注册时,电子邮件–发送电子邮件”
单击“继续”进入第3步,您可以在其中使用右侧的值来填充您的电子邮件。
再次“继续”,给您的任务起一个名字。 新用户注册后,他们现在会收到您的电子邮件:)
我们将允许我们的用户对他们阅读的书发表评论。 为此,我们在Stamplay中创建的审阅对象将连接到该审阅将要涉及的书对象,以便我们可以使用该关联。 我们还将把评论与登录的用户相关联。
在Stamplay编辑器中,让我们回到“对象”选项卡并添加一个名为“ review”的新自定义对象:
添加一个名为“ text”的字符串属性,该属性将保存评论内容。
现在,转到Stamplay编辑器中的book对象。 我们将向book对象添加一个字段,该字段是其评论的数组。
在书对象上创建一个名为“评论”的新字段,然后选择“对象关系–评论”作为类型。
现在,我们已经在Stamplay上设置了评论,我们需要添加将评论写到我们的应用程序的功能。
首先,让我们创建一个服务来处理“评论”的一些任务:
app.factory('Review', function($q, $stamplay, Book, $rootScope){
function all() {
var deferred = $q.defer();
var ReviewCollection = $stamplay.Cobject('review').Collection;
ReviewCollection.fetch().then(function() {
deferred.resolve(ReviewCollection.instance);
});
return deferred.promise;
}
function add(review) {
var deferred = $q.defer();
var ReviewModel = $stamplay.Cobject('review').Model;
ReviewModel.set('text', review.text); // The review text
ReviewModel.set('owner', $rootScope.user.instance.id); //Associate with logged in user
// Save the review
ReviewModel.save().then(function() {
// If it saves, update the book
Book.find(review.bookId).then(function(BookToUpdate){
// Store the saved review on the book
var currentReviews = BookToUpdate.get('reviews') || [];
currentReviews.push(ReviewModel.get('_id'));
BookToUpdate.set('reviews', currentReviews)
BookToUpdate.save().then(function(){
// We're done
deferred.resolve(ReviewModel);
});
});
});
return deferred.promise;
}
return {
all: all,
add: add,
}
});
这里重要的是:
我们需要在我们的Book服务中添加find()
方法:
function find(id) {
var deferred = $q.defer();
var BookModel = $stamplay.Cobject('book').Model;
BookModel.fetch(id).then(function() {
deferred.resolve(BookModel);
}).catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
然后将其添加到服务的导出中:
return {
all: all,
add: add,
find: find // Now we can use Book.find()
}
fetch()
方法使用ID进行搜索。
现在我们有了一项可以处理评论的服务,让我们为表单创建一个控制器:
app.controller('ReviewController', function($scope, Book, $rootScope, Review){
$scope.bookOptions = [];
Book.all().then(function(books){
$scope.bookOptions = books;
});
$scope.newReview = {
bookId: null,
text: '',
};
$scope.leaveReview = function() {
Review.add($scope.newReview).then(function(savedReview){
$rootScope.$emit('Review::added', {review: savedReview});
$scope.newReview.text = '';
$scope.newReview.bookId = null;
});
}
});
在此控制器中需要注意一些事项。 首先,我们获得要显示在下拉列表中的书籍列表,以便用户可以选择要阅读的书籍。 当用户留下评论时,我们将使用评论服务来添加它,完成后,我们将发出一个事件来通知其余应用程序。
让我们在书本表单上方为评论添加一个新表单(仅在登录时显示):
Add a review
现在,我们需要能够看到我们创建的评论。 让我们将它们放在它们所属的书下面。
首先,在获取书时,我们需要告诉Stamplay,我们还希望响应中包含所有相关的对象(评论)。 为此,我们在获取图书时将{populate: true}
指定为fetch方法。 如下更新您的图书服务:
app.factory('Book', function($q, $stamplay){
function all() {
var deferred = $q.defer();
var BookCollection = $stamplay.Cobject('book').Collection;
BookCollection.fetch({populate: true}).then(function() {
deferred.resolve(BookCollection.instance);
});
return deferred.promise;
}
...
});
现在,在我们的BooksController中,一旦我们加载了这些书,我们还可以访问每本书的评论。
每当我们添加新书和每次添加新评论时,我们都希望刷新我们的书数据。 因此,让我们听这些事件,并在发生这些事件时再次加载它们。
app.controller('BooksController', function($scope, $rootScope, $stamplay, Book, Review, User){
$scope.books = [];
var loadBooks = function(){
Book.all().then(function(books){
$scope.books = books;
});
}
$scope.newBook = {
title: ''
};
$scope.addBook = function() {
Book.add($scope.newBook).then(function(savedBook){
$scope.books.push(savedBook);
// Emit new book was added
$rootScope.$emit('Book::added');
});
$scope.newBook.title = '';
}
$rootScope.$on('Book::added', function(data){
loadBooks();
});
$rootScope.$on('Review::added', function(data){
loadBooks();
});
loadBooks();
});
我们将对图书清单的布局进行一些调整以适应评论,如下所示:
{{book.instance.title}}
{{review.text}}
如果您现在启动浏览器,则应该可以添加新评论,并且保存后,它应该显示在正确的书下。
太好了,现在只剩下一件事了-很高兴在用户的评论中显示其姓名。
对于每条评论,我们都会要求提供所有者的信息,并将其存储在评论中,以便我们可以在视图中将其获取。
首先,我们需要在用户服务上使用find方法:
app.factory('User', function($q, $stamplay){
function find(id) {
var deferred = $q.defer();
var User = $stamplay.User().Model;
User.fetch(id).then(function() {
deferred.resolve(User);
}).catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
...
});
将此添加到出口以为您提供服务:
return {
active: active,
logout: logout,
login: login,
find: find
};
然后,我们将在BooksController中使用它:
app.controller('BooksController', function($scope, $rootScope, $stamplay, Book, Review, User){
$scope.books = [];
var loadBooks = function(){
Book.all().then(function(books){
$scope.books = books;
$scope.books.forEach(function(book){
var reviews = book.instance.reviews || [];
reviews.forEach(function(review){
if(review.owner){
User.find(review.owner).then(function(user){
review.user = user.get('displayName');
});
} else {
review.user = 'Anonymous';
}
});
})
});
}
...
});
我们将在每次评论之前显示此新用户属性:
{{review.user}} {{review.text}}
我们终于得到它了。 我们创建了一个表单,用于发布新评论,这些评论将显示在带有评论所有者姓名的正确书籍下。
现在可能是使用几个不同帐户部署和测试应用程序的好时机。
Stamplay为我们提供了各种即插即用功能。 让我们在UI中添加一些元素,以使我们的应用程序感觉功能丰富:
通常,当您留下评论时,您还会给星级。 Stamplay具有对项目进行评分的内置功能。 让我们现在使用它。 首先,我们将在评分表单中添加一个新字段:
然后,当我们将评论保存在评论服务中时,我们只需要执行其他操作即可对书进行评分:
// Save the review
ReviewModel.save().then(function() {
// If it saves, update the book
Book.find(review.bookId).then(function(BookToUpdate){
// Rate it
BookToUpdate.rate(review.rating);
// Store the saved review on the book
var currentReviews = BookToUpdate.get('reviews') || [];
currentReviews.push(ReviewModel.get('_id'));
BookToUpdate.set('reviews', currentReviews)
BookToUpdate.save().then(function(){
// We're done
deferred.resolve(ReviewModel);
});
});
});
现在,我们可以使用action对象在视图中显示这些附加信息(以星标表示):
{{book.instance.title}}
{{review.user}} {{review.text}}
即使评论不好,评论也可能会很受欢迎……因此,让我们允许用户对喜欢的评论进行评论。
让我们增加我们的评论服务,以便它可以发布评论
app.factory('Review', function($q, $stamplay, Book){
function all() {
...
}
function upvote(review) {
var deferred = $q.defer();
var ReviewModel = $stamplay.Cobject('review').Model;
ReviewModel.fetch(review.id).then(function(){
ReviewModel.upVote().then(function(){
deferred.resolve(ReviewModel);
});
}).catch(function(err){
deferred.resolve(err);
});
return deferred.promise;
}
});
然后加:
return {
all: all,
add: add,
upvote: upvote
}
我们会在每个评论中添加一个按钮,以允许投票:
{{review.user}} {{review.text}}
然后,将upvote()
方法添加到BooksController中以保存upvote
$scope.upvote = function(review){
Review.upvote(review).then(function(){
$rootScope.$emit('Review::upvoted');
});
}
$rootScope.$on('Review::upvoted', function(data){
loadBooks();
});
现在,当您单击upvote按钮时,您会看到计数增加。 用户的评论每次只能投票一次。 尝试以其他人身份登录并发表评论。
我们的读书俱乐部非常棒,让我们向访客收取一个帐户的费用。 您需要此部分的Stripe帐户。
我们首先需要设置Stripe组件。 在Stamplay编辑器的任务菜单下,单击“组件”,然后单击“条纹”图标。
单击绿色的大连接按钮,系统将要求您登录您的Stripe帐户。 如果您没有,则可以在stripe.com上创建一个。 尽管我们在本教程中仅使用测试模式,但是您将需要输入银行详细信息(以便人们付款)。
按照提示登录并连接您的Stripe帐户。
完成后,您应该会看到一个绿色按钮,显示“组件已激活”
回到Stripe组件页面,您应该看到自己的详细信息(测试键等)。 确保禁用实时模式。
现在,我们需要创建一个任务,以便在用户注册时为他们创建新的Stripe客户。 单击任务菜单下的管理,然后单击“新任务”。
从下拉列表中,我们将选择“当用户注册时”,然后选择“剥离-添加客户”。
单击“下一步”,在步骤3中,确保您正在传递{{user._id}}
。
单击下一步,为您的任务命名,例如“创建客户”,然后单击“保存”。
现在,当用户注册时,我们将在Stripe中创建一个新的客户。
现在我们已经拥有与用户相关联的客户,我们可以对已登录的用户收费,然后他们才能访问该应用程序。
首先,我们首先将一个变量paid
设置为false,并使用它隐藏应用程序,直到用户付款为止。 我们还将在稍后设置一个对登录用户paid
的属性,因此我们也在此处进行检查:
app.run(function($rootScope, User){
$rootScope.paid = false;
// Listen for login events
$rootScope.$on('User::loggedIn', function(event, data){
$rootScope.loggedIn = true;
$rootScope.paid = data.user.instance.paid || false; // Has the user already paid?
$rootScope.user = data.user;
});
// Check if there's a user logged in already
User.active().then(function(activeUser){
...
});
});
当前在使用ng-show="loggedIn"
我们还要添加一张付款支票:
例如
Books