步骤 2 使用开票协议为用户创建订阅(节点示例)

为用户创建订阅的第二步是基于现有的激活计费计划创建和执行计费协议。此示例假定你已经完成并激活了上一个示例中的结算方案,并且在该示例中具有该结算方案的 ID 以供参考。

当你设置结算协议以为用户创建订阅时,你将遵循 3 个步骤,这可能会让人想起处理 PayPal 付款:

  1. 你可以创建结算协议,通过 ID 引用基础结算方案。
  2. 创建后,你将用户重定向到 PayPal(如果通过 PayPal 付款)以确认订阅。确认后,PayPal 会使用基础结算方案中提供的重定向将用户重定向回你的网站。
  3. 然后,你可以使用通过 PayPal 重定向提供的令牌执行结算协议。

此示例是设置基于 Express 的 HTTP 服务器以显示计费协议流程。

要开始这个例子,我们首先需要设置我们的配置。我们添加了四个要求,PayPal SDK,用于处理 JSON 编码体的 body-parser,用于简单服务器集成的 http 和用于 Express 框架的 express。然后,我们定义我们的客户端 ID 和秘密来创建应用程序,为沙箱配置 SDK,然后配置 bodyParser 来处理 JSON 主体。

var paypal = require('paypal-rest-sdk'),
    bodyParser = require('body-parser'),
    http = require('http'),
    app = require('express')();

var clientId = 'YOUR APPLICATION CLIENT ID';
var secret = 'YOUR APPLICATION SECRET';

paypal.configure({
  'mode': 'sandbox', //sandbox or live
  'client_id': clientId,
  'client_secret': secret
});

app.use(bodyParser.json());

我们在结算协议中的第一步是创建一条路线来处理创建结算协议,并将用户重定向到 PayPal 以确认该订阅。我们假设将结算方案 ID 作为查询字符串参数传递,例如通过使用上一个示例中的计划 ID 加载以下 URL:

http://localhost:3000/createagreement?plan=P-3N543779E9831025ECYGDNVQ

我们现在需要使用该信息来创建结算协议。

app.get('/createagreement', function(req, res){
    var billingPlan = req.query.plan;
    
    var isoDate = new Date();
    isoDate.setSeconds(isoDate.getSeconds() + 4);
    isoDate.toISOString().slice(0, 19) + 'Z';

    var billingAgreementAttributes = {
        "name": "Standard Membership",
        "description": "Food of the World Club Standard Membership",
        "start_date": isoDate,
        "plan": {
            "id": billingPlan
        },
        "payer": {
            "payment_method": "paypal"
        },
        "shipping_address": {
            "line1": "W 34th St",
            "city": "New York",
            "state": "NY",
            "postal_code": "10001",
            "country_code": "US"
        }
    };

    // Use activated billing plan to create agreement
    paypal.billingAgreement.create(billingAgreementAttributes, function (error, billingAgreement){
        if (error) {
            console.error(error);
            throw error;
        } else {
            //capture HATEOAS links
            var links = {};
            billingAgreement.links.forEach(function(linkObj){
                links[linkObj.rel] = {
                    'href': linkObj.href,
                    'method': linkObj.method
                };
            })

            //if redirect url present, redirect user
            if (links.hasOwnProperty('approval_url')){
                res.redirect(links['approval_url'].href);
            } else {
                console.error('no redirect URI present');
            }
        }
    });
});

我们首先从查询字符串中提取开票计划 ID,然后创建计划开始时的日期。

下一个对象定义 billingAgreementAttributes 由订阅的信息组成。它包含有关计划的可读信息,对计费计划 ID 的引用,付款方式和运输详细信息(如果订阅需要)。

接下来,调用 billingAgreement.create(...),传入我们刚刚创建的 billingAgreementAttributes 对象。如果一切都成功,我们应该将一个结算协议对象传回给我们,其中包含有关我们新创建的订阅的详细信息。该对象还包含许多 HATEOAS 链接,为我们提供了可以对这个新创建的协议采取的后续步骤。我们在这里关心的那个被标记为 approval_url

我们遍历所有提供的链接,将它们放入一个容易引用的对象中。如果 approval_url 是其中一个链接,我们会将用户重定向到该链接,即 PayPal。

此时,用户确认 PayPal 上的订阅,并重定向回基础计费计划中提供的 URL。除了该 URL,PayPal 还将沿着查询字符串传递令牌。该令牌是我们将用于执行(或开始)订阅的标记。

让我们在以下路线中设置该功能。

app.get('/processagreement', function(req, res){
    var token = req.query.token;
    
    paypal.billingAgreement.execute(token, {}, function (error, billingAgreement) {
        if (error) {
            console.error(error);
            throw error;
        } else {
            console.log(JSON.stringify(billingAgreement));
            res.send('Billing Agreement Created Successfully');
        }
    });
});

我们从查询字符串中提取令牌,然后调用 billingAgreement.execute,传递该令牌。如果一切都成功,我们现在拥有该用户的有效订阅。返回对象包含有关活动计费协议的信息。

最后,我们设置 HTTP 服务器来监听路由的流量。

//create server
http.createServer(app).listen(3000, function () {
   console.log('Server started: Listening on port 3000');
});