在 Mozilla,我们一直在努力将支付引入网络。我们认为开发者应该拥有一个轻松的应用程序货币化方式。这也给了我们机会提供更深层的平台集成,允许使用运营商计费等方式,除了信用卡/借记卡之外。
我们之前在 navigator.mozPay() 用于网页支付 中讨论过应用内支付,但这是一篇从应用开发者角度概述的文章。这篇文章还包括一些更新,例如 Firefox 应用商店中的真实支付现已上线。支付不同于仅仅是付费应用,付费应用在首次购买时向用户收取一次费用。应用内支付是一种不同的流程,允许你为应用内的特定商品向客户收费。
架构概述
目前,支付仅在 Firefox OS 设备上启用。我们正在努力在其他平台上启用支付,甚至在桌面 Firefox 上启用,但这还需要一段时间。在本文的其余部分,我们将假设使用 Firefox OS 环境。
有关应用内支付的 MDN 页面 对流程进行了很好的概述,但这里有一个更简短的概述。你需要一个服务器来生成支付请求,因为否则黑客可以轻松地将价格改为 0。服务器创建 JWT 令牌,将其传递给你的应用,你的应用使用该令牌调用 navigator.mozPay
。用户将被带到内置支付流程,完成后,你的服务器将收到通知。之前关于支付的 Hacks 文章 更深入地探讨了更低级别的机制和支付的理由。
剩下的工作流程由你处理:在成功购买商品后更新应用程序,将购买与帐户关联等。
获取模拟密钥
为了使用支付,你需要使用应用商店为你生成的应用密钥和密钥。如果你只想模拟支付,你可以轻松地 获取测试密钥和密钥。你只需要创建一个帐户(如果你还没有帐户的话)。
你只能使用该密钥模拟支付。当你准备使用真钱时,你需要将你的应用提交到应用商店,设置支付,并获取真实的密钥和密钥。所有这些内容将在下面详细说明。
设置服务器端代码
你需要做的第一件事是设置服务器端代码。在 几种不同的语言 中存在一个 “mozpay” 模块,它为你实现了支付流程。如果你的编程语言中不存在它,你需要使用 JWT 模块 并进行更多操作。查看 mozpay-js 中相当 简单的代码,以了解你需要做什么的示例。
我为 Firefox OS 写了一个名为 Webfighter 的游戏,它使用 node.js 作为后端,因此我在服务器端使用了 mozpay-js。Webfighter 是一款带有商店的射击游戏,你可以在商店里购买更多武器和飞船,它对于开发者来说是一个很好的参考,可以查看使用支付的实际代码。下面的示例取自 Webfighter。 你可以在这里查看 Webfighter 的源代码。
首先,需要并配置 mozpay 模块
var pay = require('mozpay');
var settings = require('settings');
pay.configure({
mozPayKey: settings.payKey,
mozPaySecret: settings.paySecret,
mozPayAudience: 'marketplace.firefox.com',
mozPayType: 'mozilla/payments/pay/v1',
mozPayRoutePrefix: '/mozpay'
});
settings
模块只是一个包含 JSON 的文件,它指定了应用的配置。将配置分隔开以便于你轻松地在不同的环境(如开发环境和生产环境)中进行切换,这样很不错。
使用你从应用商店获取的密钥和密钥。如果你使用的是 Mozilla 以外的支付服务器,你应该只更改 audience 和 type 选项。routePrefix 是可选的,它指定了支付服务器回传的 URL 前缀。
接下来,你需要定义一个路由,用于创建支付交易中使用的数据。客户端是执行实际支付请求的人(这样你就不必处理信用卡详细信息,甚至可以通过运营商计费进行收费)。你只需要创建一个表示购买的对象。本示例使用 express.js 作为 http 服务器。
var purchaseQueue = {};
app.post('/sign-jwt', function(req, res) {
var token = 'o' + Date.now();
var item = getItem(req.body.name);
var jwt = pay.request({
id: item.name,
name: item.name,
description: item.description,
icons: { '64': settings.url + item.icon },
pricePoint: item.price,
productData: token,
postbackURL: settings.url + 'mozpay/postback',
chargebackURL: settings.url + 'mozpay/chargeback',
simulate: { result: 'postback' }
});
// Keep track of which JWT objects we are waiting on
purchaseQueue[token] = 'processing';
res.send(JSON.stringify({
jwt: jwt,
token: token
});
});
再次注意 settings
对象;它只是一个 dict,它包含有关我们的应用的一些配置属性。settings.url
是我们的应用托管的基本 URL,因此所有传入的 URL 都是绝对的。
我们调用 getItem
来获取有关商品的详细信息(我们在这里不定义它)。我发现定义一个包含所有可用商品信息的 JSON 文件是最容易的。你可以在 GitHub 上看到 Webfighter 中可用商品的 JSON。
对于购买请求,有 几个字段。id
只是一个唯一的标识符,我们简单地使用产品名称。其他字段描述了产品,例如 icons
,它列出了各种尺寸的图标。pricePoint
是一个数字,它映射到每个可用地区的特定价格,你应该查看 价格点表 找到你需要的那一个。例如,价格点为 10 表示在美国的价格为 0.99 美元。
simulate
参数告诉支付系统只模拟请求。如果传递了该参数,则不会进行实际收费,你将经历模拟流程。这对开发非常有用。**请记住**,在生产环境中要删除此标志。
你可以在 productData
中存储任何想要的内容,你可以在处理事件时使用它。这里我生成了一个用于跟踪请求的任意令牌,并将其存储在全局对象 purchaseQueue
中。我们在处理事件时使用它。
接下来,订阅 mozpay 模块的 postback
事件
pay.on('postback', function(data) {
// the payment was successful
var req = data.request;
purchaseQueue[req.productData] = 'success';
});
你也可以订阅 chargeback
事件。当客户对收费提出争议并退回款项时,就会发生退款。这可能会在一个月后发生,并且难以处理。Webfighter 会跟踪退款,但应用程序不会检查它们并撤销商品。你需要定期或在启动时检查用户是否仍然拥有对所有已购买商品的访问权限。
pay.on('chargeback', function(data) {
var req = data.request;
purchaseQueue[req.productData] = 'chargeback';
});
服务器端的代码就这些。
在客户端使用 mozPay
在客户端,你需要发布到 /sign-swt
并使用 mozPay
启动购买。在下面的代码中,我们检查 mozPay
是否可用,如果不可用,我们只是将商品提供给用户。请记住,这只是一个测试应用程序!一旦购买启动,我们就开始轮询服务器,直到我们收到成功的购买信息。
function buy(name) {
// Purchase an item by requesting a JWT object from the
// server, and posting it to the mozPay API
$.post('/sign-jwt', { name: name }, function(res) {
if(navigator.mozPay) {
var req = navigator.mozPay([res.jwt]);
req.onerror = function() {
console.log('mozPay error: ' + this.error.name);
clearPolling();
};
// Poll to see when the payment is complete
startPolling();
}
else {
alert('in-app payments unavailable, so giving it to you for free');
onPurchase(name);
}
});
}
以下是轮询函数,它们等待服务器响应成功的购买信息。请注意,我们只检查成功的购买信息。用户将在本机支付屏幕中收到任何错误的通知,当他们关闭屏幕时,mozPay
请求对象上会触发一个错误事件,我们处理该事件并停止轮询。查看上面的代码,其中包含 req.onerror
。
function pollQueue(token, name) {
// Poll the server every second to see the status of our
// payment request
$.get('/purchaseQueue?token=' + token, function(res) {
if(res == 'success') {
onPurchase(name);
clearPolling();
}
});
}
var pollTimer;
function startPolling() {
pollTimer = setInterval(function() { pollQueue(res.token, name); }, 1000);
}
function clearPolling() {
if(pollTimer) {
clearInterval(pollTimer);
}
pollTimer = null;
}
当成功购买商品并且应为用户启用商品时,我们调用 onPurchase
。你应该创建该函数并编写你的应用特定的代码。
真实支付:将应用提交到 Firefox 应用商店
当你准备运行真实支付时,在服务器创建支付请求时删除 simulate
字段,并将 你的应用提交 到 Firefox 应用商店。你需要提交应用,以便你能够连接真实支付。
获得报酬:配置银行账户详细信息和支付选项
你的应用提交后,编辑你的应用,点击左侧的 “兼容性和支付”,选择 “付费/应用内”。在 “支付账户” 下,添加你的银行账户。困扰我的一件事是需要我的银行的 SWIFT 代码。将来,应用商店有望自动填写它,但目前,你可以在 theswiftcodes.com 上查找它。
在 “价格和国家/地区” 下,你可以设置你的应用的价格。你可能只想设置 “免费,含应用内购买”,这就是 Webfighter 的设置方式。此外,你可以选择性地选择你的应用可用的区域。带有支付的应用只在启用了支付的区域可用。
使用真实的密钥和密钥
现在点击左侧边栏中的 “应用内支付” 链接。你将看到一个屏幕,你可以在其中获取用于真实支付的新密钥和密钥。在服务器上的 configure
调用中使用它们。不要分享你的密钥。
在撰写本文时,运营商计费只在特定国家/地区可用。查看 支付状态页面,了解它在哪些地方可用。如果它不可用,用户将看到信用卡屏幕。
使用你的应用赚点钱吧!
我们希望你能够成功地参与到应用程序生态系统和经济中。请告诉我们你的体验!我们很乐意在 应用商店邮件列表 上回答任何问题。
关于 kumar303
Kumar 为各种项目开发 Mozilla 网络服务和工具,例如支持 Firefox 扩展 的工具。他也开发很多 随机开源项目。
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道师和编辑。他经常发表演讲和撰写博客,主题包括 HTML5、JavaScript 和开放网络。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直从事 Web 前端开发工作,分别在瑞典和纽约市。他还在 http://robertnyman.com 上定期发布博客,热爱旅行和结识新朋友。
17 条评论