json 条带校验错误:一次性+订阅付款按钮在同一页上?

e37o9pze  于 2023-01-18  发布在  其他
关注(0)|答案(4)|浏览(134)

已更新我构建了一个定价页面,该页面使用Stripe Checkout来同时使用产品1的一次性付款按钮和产品2的订阅付款按钮。

我的目标是将一次性付款按钮重定向到一次性付款的Stripe Checkout,并单独将订阅付款重定向到定期付款的Checkout。

根据STRIPE,这可以通过在create-checkout-session.php的CheckoutSession中使用Subscription作为Mode来实现(示例项目):
结帐会话的模式。使用价格或设置模式时必需。如果结帐会话包括至少一个定期项目,则通过订阅。
与Stripe Docs相反,下面的代码行:'mode' => 'subscription',仅激活订阅付款,但不会重定向一次性付款。要使一次性付款生效,我必须将其更改为:'mode' => 'payment',,但订阅付款不起作用。
下面是问题中的php代码:

<?php
    
    require_once 'shared.php';
    
    $domain_url = $config['domain'];
    
    // Create new Checkout Session for the order
    // Other optional params include:
    // [billing_address_collection] - to display billing address details on the page
    // [customer] - if you have an existing Stripe Customer ID
    // [payment_intent_data] - lets capture the payment later
    // [customer_email] - lets you prefill the email input in the form
    // For full details see https://stripe.com/docs/api/checkout/sessions/create
    
    // ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param
    $checkout_session = \Stripe\Checkout\Session::create([
        'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}',
        'cancel_url' => $domain_url . '/canceled.html',
        'payment_method_types' => ['card'],
        'mode' => 'subscription',
        'line_items' => [[
          'price' => $body->priceId,
          'quantity' => 1,
      ]]
    ]);
    
    echo json_encode(['sessionId' => $checkout_session['id']]);

下面是javascript代码:

// Create a Checkout Session with the selected plan ID
var createCheckoutSession = function(priceId) {
  return fetch("./create-checkout-session.php", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      priceId: priceId
    })
  }).then(function(result) {
    return result.json();
  });
};

// Handle any errors returned from Checkout
var handleResult = function(result) {
  if (result.error) {
    var displayError = document.getElementById("error-message");
    displayError.textContent = result.error.message;
  }
};

/* Get your Stripe publishable key to initialize Stripe.js */
fetch("./config.php")
  .then(function(result) {
    return result.json();
  })
  .then(function(json) {
    var publishableKey = json.publishableKey;
    var subscriptionPriceId = json.subscriptionPrice;
    var onetimePriceId = json.onetimePrice;

    var stripe = Stripe(publishableKey);
    // Setup event handler to create a Checkout Session when button is clicked
    document
      .getElementById("subscription-btn")
      .addEventListener("click", function(evt) {
        createCheckoutSession(subscriptionPriceId).then(function(data) {
          // Call Stripe.js method to redirect to the new Checkout page
          stripe
            .redirectToCheckout({
              sessionId: data.sessionId
            })
            .then(handleResult);
        });
      });

    // Setup event handler to create a Checkout Session when button is clicked
    document
      .getElementById("onetime-btn")
      .addEventListener("click", function(evt) {
        createCheckoutSession(onetimePriceId).then(function(data) {
          // Call Stripe.js method to redirect to the new Checkout page
          stripe
            .redirectToCheckout({
              sessionId: data.sessionId
            })
            .then(handleResult);
        });
      });
      
  });

是否有可能在Stripe Checkout的同一页面上同时进行一次性付款和周期性付款?我该如何实现?
根据Bemn更新

$checkout_session = \Stripe\Checkout\Session::create([
  'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}',
  'cancel_url' => $domain_url . '/canceled.html',
  'payment_method_types' => ['card'],
  'mode' => $body->mode
    'line_items' => [[
    'price' => $body->price_xxx,
    // For metered billing, do not pass quantity
    'quantity' => 1,
  ]],

  'line_items' => [[
    'price' => $body->price_zzz,
    // For metered billing, do not pass quantity
    'quantity' => 1,
  ]]
]);

echo json_encode(['sessionId' => $checkout_session['id']]);

和JS:

// Create a Checkout Session with the selected plan ID
var createCheckoutSession = function(priceId, mode) {
  return fetch("./create-checkout-session.php", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      priceId: priceId,
      mode: mode // <-- passing the mode, e.g. 'payment' or 'subscription'
    })
  }).then(function(result) {
    return result.json();
  });
};

以及HTML:

<div data-stripe-priceid="pricexxx" data-stripe-mode="payment" id="onetime-btn" class="bold mt-2 d-inline-block w-100-after-md max-width-xxs py-2 btn btn-secondary">Ore Time</div>
    
<div data-stripe-priceid="pricexxx" data-stripe-mode="subscription" id="subscription-btn" class="bold mt-2 d-inline-block w-100-after-md max-width-xxs py-2 btn btn-secondary">Ore Time</div>
llew8vvj

llew8vvj1#

是否有可能在Stripe Checkout的同一页面上同时进行一次性付款和周期性付款?

是。关键是您应传递正确的选项以生成相应的条带检出会话ID。

我该如何实现这一点?

  • 后端:具有接受Stripe的价格ID支付模式作为输入并返回Stripe Checkout会话ID作为输出的功能。
  • 前台:将支付方式信息传递给/create-checkout-session.php(无法传递请参见备注)

详情

以下解假设:
1.您在后端生成一个StripeCheckoutSession ID,然后将该ID传递给jsfrontend中的.createCheckoutSession()
1.您有一个一次性产品(我们称之为 PAY)和一个定期订阅(我们称之为 SUB)。

前端

我想你已经接近了。你需要做的是把mode信息也传递给你的API端点:

// Create a Checkout Session with the selected plan ID
var createCheckoutSession = function(priceId, mode) { // <-- add a mode parameter
  return fetch("./create-checkout-session.php", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      priceId: priceId,
      mode: mode // <-- passing the mode, e.g. 'payment' or 'subscription'
    })
  }).then(function(result) {
    return result.json();
  });
};

如果是这样的话,页面中的每个结帐按钮都应该有对应的priceId和支付模式信息。您可以通过使用数据属性存储它们来做到这一点:

<div data-stripe-priceid="price_yyy" data-stripe-mode="subscription">Recurrent</div>
<div data-stripe-priceid="price_zzz" data-stripe-mode="payment">1-time</div>

如果是这样,您可以通过click事件等获取数据属性。

**注:**如果您无法添加额外的参数来指示模式,则需要确定给定的价格ID在后端是一次性产品还是重复产品。https://stripe.com/docs/api/prices/object?lang=php#price_object-type有关详细信息,请参阅www.example.com。

后端

以下是Stripe文档中的两个示例代码片段。直接复制它们不起作用

$checkout_session = \Stripe\Checkout\Session::create([
  'payment_method_types' => ['card'],
  'line_items' => [[
    'price_data' => [
      'currency' => 'usd',
      'unit_amount' => 2000,
      'product_data' => [
        'name' => 'Stubborn Attachments',
        'images' => ["https://i.imgur.com/EHyR2nP.png"],
      ],
    ],
    'quantity' => 1,
  ]],
  'mode' => 'payment',
  'success_url' => $YOUR_DOMAIN . '/success.html',
  'cancel_url' => $YOUR_DOMAIN . '/cancel.html',
]);

在您的示例中,可能不需要定义'price_data',而是应该使用'price',如下面的示例。

  • SUB* 的参考:https://stripe.com/docs/billing/subscriptions/checkout#create-session
$checkout_session = \Stripe\Checkout\Session::create([
  'success_url' => 'https://example.com/success.html?session_id={CHECKOUT_SESSION_ID}',
  'cancel_url' => 'https://example.com/canceled.html',
  'payment_method_types' => ['card'],
  'mode' => 'subscription',
  'line_items' => [[
    'price' => $body->priceId,
    // For metered billing, do not pass quantity
    'quantity' => 1,
  ]],
]);

1.看看这个参考:对于line_items,您只需使用'price'并传递价格ID(例如price_xxx),这意味着您的'line_items'将如下所示:

'line_items' => [[
  'price' => $body->priceId,
  'quantity' => 1,
]],

对于'mode',使用API请求中的值。它应该类似于:

'mode' => $body->mode

这意味着您最好在后端定义一个函数(例如generate_checkout_session)来:

  • 解析API请求中接收到的json主体
  • 从解析数据中获取priceIdmode
  • 使用\Stripe\Checkout\Session::create中的priceIdmode,以及
  • 返回checkout_session ID

希望这(和参考网址)能帮助你。

ki1q1bka

ki1q1bka2#

创建会话时,您可以传递订阅中收取的定期费用的价格和您要收取的一次性费用的价格。您可以将多个定期价格和一次性价格合并在一起。

$checkout_session = \Stripe\Checkout\Session::create([
    'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}',
    'cancel_url' => $domain_url . '/canceled.html',
    'payment_method_types' => ['card'],
    'mode' => 'subscription',
    'line_items' => [
      // Add a one-time Price for $10
      [
        'price' => 'price_123', 
        'quantity' => 1,
      ],
      // Add another one-time Price for $23
      [
        'price' => 'price_345', 
        'quantity' => 1,
      ],
      // Add a recurring Price for $100 monthly
      [
        'price' => 'price_ABC', 
        'quantity' => 1,
      ],
]);

上面的代码将创建一个具有3个行项目的会话。一个为每月$100,一个为$10仅一次,一个为$23仅一次。会话的第一次付款总额将为$133。它还将开始每月$100的订阅,未来的发票将为预期的$100。

wlp8pajw

wlp8pajw3#

我所得到的是,你只需要添加一个检查要么是一次性或订阅这里是你可以做的:

JS FILE CHANGES:

var createCheckoutSession = function(priceId, $mode) {
  return fetch("./create-checkout-session.php", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      priceId: priceId,
      paymentType: $mode, // This vary based on the button clicked either one-time or subscription.
    })
  }).then(function(result) {
    return result.json();
  });
};

/* Get your Stripe publishable key to initialize Stripe.js */
fetch("./config.php")
  .then(function(result) {
    return result.json();
  })
  .then(function(json) {
    var publishableKey = json.publishableKey;
    var subscriptionPriceId = json.subscriptionPrice;
    var onetimePriceId = json.onetimePrice;

    var stripe = Stripe(publishableKey);
    // Setup event handler to create a Checkout Session when button is clicked
    document
      .getElementById("subscription-btn")
      .addEventListener("click", function(evt) {
        createCheckoutSession(subscriptionPriceId, 'subscription').then(function(data) {
          // Call Stripe.js method to redirect to the new Checkout page
          stripe
            .redirectToCheckout({
              sessionId: data.sessionId
            })
            .then(handleResult);
        });
      });

    // Setup event handler to create a Checkout Session when button is clicked
    document
      .getElementById("onetime-btn")
      .addEventListener("click", function(evt) {
        createCheckoutSession(onetimePriceId, 'onetime').then(function(data) {
          // Call Stripe.js method to redirect to the new Checkout page
          stripe
            .redirectToCheckout({
              sessionId: data.sessionId
            })
            .then(handleResult);
        });
      });
      
  });

现在我们需要在PHP文件中进行更改:

PHP FILE CHANGES:

$checkout_session = \Stripe\Checkout\Session::create([
        'success_url' => $domain_url . '/success.html?session_id={CHECKOUT_SESSION_ID}',
        'cancel_url' => $domain_url . '/canceled.html',
        'payment_method_types' => ['card'],
        'mode' => $body->paymentType, // Here is what we have got from front-end
        'line_items' => [[
          'price' => $body->priceId,
          'quantity' => 1,
      ]]
    ]);
58wvjzkj

58wvjzkj4#

对于订阅,我们实际上需要设置间隔,这是不需要设置在一次钱包。可能这个错误发生的原因。添加重复可以解决重复的错误。

recurring: {
   interval: 'month' // 'month' | 'year'
}

相关问题