Skip to main content
ArcBlock Community

Calling API with pages kit

Twelve
Support
pages-kitdiscussionfeature

你好,我想请问一下,是否可以在 Pages Kit 组件中直接调用 Payment Kit API(例如 /api/payment-kit/payment-links)? 我目前可以通过独立的 Node 服务器(proxy)来调用并创建支付链接,但想知道是否能在 Pages Kit 内直接使用 fetch() 访问这些接口,而不需要单独的服务器。 换句话说,Pages Kit 组件是否具备足够的权限和身份认证来调用 Blocklet 内部的 API(如 Payment Kit、DID Space 等)? 如果不行,请问正确的做法是什么?是否需要启用某种代理或配置 access key?

6 replies

Xiao Fang11 months ago

参考: https://community.arcblock.io/discussions/0f440b8b-9a9d-4219-8023-cd9d684f891b#84000e82-e10e-499e-8156-c68b7e547862 我们在调用前都必须先登录,并且保证登录账户有调用某些api的权限,如果前提条件满足,我们可以通过cookie读取csrf-token 和 登录凭证,添加到headers来调用fetch 配置 access key 其实也可以,但是这个代码是浏览器公开可访问的,所以不建议通过写入accessKey来访问;

Twelve10 months ago

Thanks for the clarification! I’m logged in and can see my DID from useSessionContext(), but my Pages Kit app isn’t issuing any csrf-token cookie or /api/csrf-token route — so the fetch call still throws a “CSRF token mismatch” even after login.

I didn’t build this locally, it was launched directly from the ArcBlock Launcher, so I don’t have a dev folder or backend code to modify.

Could you confirm whether there’s a way to enable CSRF / Passport for a hosted Pages Kit blocklet from the dashboard (for example with an env variable like ENABLE_PASSPORT=true)? Or is a proxy Node server the only option when the Pages Kit instance wasn’t created locally?

Twelve10 months ago

Just to add — if there was a simple toggle or env flag in the dashboard to enable Passport/CSRF for hosted Pages Kit instances, that would completely unlock Payment Kit.

Right now the login flow works and I can see my DID, but without that token there’s no way to call /api/payment-kit/payment-links directly.

Even a one-click “Enable Auth for this Blocklet” option would make a huge difference for creators building straight from the launcher. It’d basically turn Pages Kit + Payment Kit into a full no-backend storefront setup.

Xiao Fang10 months ago

I want to know which step you are stuck on right now, or please further explain your intention.

In this attempt at https://community.arcblock.io/discussions/0f440b8b-9a9d-4219-8023-cd9d684f891b#84000e82-e10e-499e-8156-c68b7e547862, we know that we can read the CSRF token and user DID information through cookies to create a payment session. Similarly, the creation of payment links can also be done, but the creation of payment links requires logging in with an account that has administrator privileges to call the creation function. What we do through the Node SDK is actually create it through programmatic calls (which have administrator privileges by default).

Twelve10 months ago

Thanks for following up 🙏

Where I’m stuck right now is that I can log in and read my DID from useSessionContext(), but when I try to create a payment link directly from a Pages Kit component, I get the CSRF mismatch error.

Since this Pages Kit was launched directly from the ArcBlock dashboard (no local folder or Node backend), I don’t have a way to call the Payment Kit SDK with admin privileges.

My intention is to make it possible for creators like me — who build directly through the dashboard — to trigger certain Payment Kit functions (like creating new payment links) from the front-end without needing a separate proxy or backend.

We can already handle checkouts fine — for example, users can fill carts using existing price IDs — but the missing piece is being able to programmatically generate new payment links from the hosted Pages Kit itself.

I’m just trying to understand the right path here: is it possible to do this from a hosted Pages Kit, or would I need to set up some kind of small API blocklet to handle the link creation part on the backend?

Xiao Fang10 months ago

We recommend that administrators' operations be generated in the background or through SDK calls.

If you want to generate a payment link through the pages kit component, there is a prerequisite:

  1. The user needs to log in first.
  2. The logged-in user needs to have the permission to generate payment links (admin\owner account).

If the above conditions are met, it should be okay for us to create calls in custom components. Below is my attempted call.

javascriptCopy
import React, { useState } from '@blocklet/pages-kit/builtin/react';
import { Box, Button, CircularProgress, Alert, Typography, Container } from '@blocklet/pages-kit/builtin/mui/material';

// 1. Utility function: Get specific cookie value by key
function getCookie(key) {
  if (typeof document === 'undefined') return null; // Handle server-side rendering
  
  const cookieArr = document.cookie.split("; ");
  for (let i = 0; i < cookieArr.length; i++) {
    const [cookieKey, cookieValue] = cookieArr[i].split("=");
    if (cookieKey === key) {
      return decodeURIComponent(cookieValue);
    }
  }
  return null;
}

const createLink = async () => {
  // Check for required cookies
  const userDid = getCookie('connected_did');
  const csrfToken = getCookie('x-csrf-token');
  
  if (!userDid || !csrfToken) {
    throw new Error('Missing required authentication information. Please log in again.');
  }

  try {
    const response = await fetch('/payment-kit/api/payment-links?livemode=false', { // payment kit prefix, if production mode, you can remove livemode query
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-user-did': userDid,
        'x-csrf-token': csrfToken
      },
      credentials: 'include',
      body: JSON.stringify({
        create_mine: true,
        line_items: [
          {
            price_id: 'price_lQBVWaMccolkStQv0yHlM9mQ', // Replace with actual price ID
            quantity: 1,
          }
        ],
        mode: 'payment'
      })
    });

    const data = await response.json();

    console.log('data---', data)

    if (!response.ok) {
      throw new Error(data.error || 'Failed to create payment session');
    }

    return data;
  } catch (error) {
    console.error('Error creating checkout session:', error);
    throw error;
  }
};

export default function PaymentCheckout() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleCheckout = async () => {
    setLoading(true);
    setError(null);
    
    try {
      const linkData = await createLink();
      
      // Redirect to payment page
      if (linkData.id) {
        window.location.href = `${window.origin}/payment-kit/checkout/pay/${linkData.id}`;
      } else {
        throw new Error('Payment URL not received');
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  // Check if user is logged in (based on cookie)
  const isUserLoggedIn = !!getCookie('connected_did');

  return (
    <Container maxWidth="sm" sx={{ mt: 8, mb: 8 }}>
      <Box 
        sx={{ 
          display: 'flex', 
          flexDirection: 'column', 
          alignItems: 'center', 
          p: 4, 
          boxShadow: 3, 
          borderRadius: 2,
          backgroundColor: 'background.paper'
        }}
      >
        <Typography variant="h4" component="h1" gutterBottom>
          Purchase Service
        </Typography>
        
        <Typography variant="body1" color="text.secondary" sx={{ mb: 4, textAlign: 'center' }}>
          Click the button below to make a payment. You will receive service access upon completion.
        </Typography>
        
        {error && (
          <Alert severity="error" sx={{ mb: 3, width: '100%' }}>
            {error}
          </Alert>
        )}
        
        {!isUserLoggedIn && (
          <Alert severity="warning" sx={{ mb: 3, width: '100%' }}>
            Please log in before proceeding with payment
          </Alert>
        )}
        
        <Button
          variant="contained"
          color="primary"
          size="large"
          onClick={handleCheckout}
          disabled={loading || !isUserLoggedIn}
          startIcon={loading && <CircularProgress size={20} color="inherit" />}
        >
          {loading ? 'Processing...' : 'Pay Now'}
        </Button>
      </Box>
    </Container>
  );
}

If you encounter any issues during your attempt, you can check our versions:

• server version

• Pages Kit version

• Payment Kit version

Reply