payment-kit 1.29.7 → 1.29.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/src/host-glue.ts +79 -0
- package/api/src/host-node/serve-static-arc.ts +1 -0
- package/api/src/integrations/app-store/native-asn1.ts +1 -0
- package/api/src/integrations/app-store/signed-data-verifier.ts +6 -1
- package/api/src/integrations/stripe/setup.ts +3 -3
- package/api/src/libs/arcblock-transfer.ts +27 -0
- package/api/src/libs/context.ts +10 -2
- package/api/src/libs/did-connect/tenant-identity.ts +19 -1
- package/api/src/libs/env.ts +65 -22
- package/api/src/libs/notification/index.ts +4 -3
- package/api/src/libs/util.ts +31 -2
- package/api/src/middlewares/hono/csrf.ts +6 -0
- package/api/src/middlewares/hono/session.ts +22 -0
- package/api/src/routes/connect/pay.ts +21 -9
- package/api/src/routes/hono/credit-grants.ts +1 -1
- package/api/src/routes/hono/entitlements.ts +8 -1
- package/api/src/routes/hono/payment-methods.ts +6 -2
- package/api/src/service.ts +42 -4
- package/api/src/store/models/payment-currency.ts +7 -1
- package/api/src/store/models/payment-method.ts +30 -6
- package/api/tests/libs/arcblock-transfer.spec.ts +58 -0
- package/api/tests/libs/notification-guard.spec.ts +25 -8
- package/api/tests/libs/util.spec.ts +51 -0
- package/blocklet.yml +1 -1
- package/cloudflare/cf-adapter.ts +46 -50
- package/cloudflare/did-connect-runtime.ts +43 -5
- package/cloudflare/esbuild-cf-config.cjs +12 -7
- package/cloudflare/tests/cf-adapter.spec.ts +12 -2
- package/cloudflare/worker.ts +41 -1
- package/package.json +9 -9
- package/src/components/layout/user.tsx +7 -1
- package/vite.arc.config.ts +19 -0
package/cloudflare/worker.ts
CHANGED
|
@@ -10,6 +10,11 @@ import { Client as PgClient } from 'pg';
|
|
|
10
10
|
import postgres from 'postgres';
|
|
11
11
|
import { Hono } from 'hono';
|
|
12
12
|
import { cors } from 'hono/cors';
|
|
13
|
+
import { getCookie } from 'hono/cookie';
|
|
14
|
+
// Worker-safe CSRF crypto (the SAME module the csrf middleware verifies with —
|
|
15
|
+
// util/csrf passes through to the real package in the CF bundle, see build.ts).
|
|
16
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
17
|
+
import { sign as signCsrf, getCsrfSecret } from '@blocklet/sdk/lib/util/csrf';
|
|
13
18
|
import { setDB } from './shims/sequelize-d1/model';
|
|
14
19
|
import { initialize } from '../api/src/store/models';
|
|
15
20
|
import { Sequelize } from './shims/sequelize-d1/sequelize-class';
|
|
@@ -386,6 +391,20 @@ function buildApp(env: Env): Hono<HonoEnv> {
|
|
|
386
391
|
// Flag: HTTP request context. createEvent uses waitUntil (non-blocking).
|
|
387
392
|
// In queue consumer/cron, this flag is absent — createEvent uses __cfPendingJobs__ (blocking).
|
|
388
393
|
(globalThis as any).__cfHttpContext__ = true;
|
|
394
|
+
// The @blocklet/sdk CSRF util reads its signing secret DIRECTLY from
|
|
395
|
+
// process.env (`BLOCKLET_APP_ASK || BLOCKLET_APP_SK`), not the config slot. The
|
|
396
|
+
// Phase-12a removal of the per-request process.env mirror left it undefined, so
|
|
397
|
+
// every CSRF-signed response hit `createHmac(<undefined key>)` → 500 (e.g.
|
|
398
|
+
// GET /api/settings). Restore just that one var from the APP_SK binding (the
|
|
399
|
+
// standalone worker's app secret key). Idempotent within the isolate.
|
|
400
|
+
if (c.env.APP_SK && !process.env.BLOCKLET_APP_SK) {
|
|
401
|
+
process.env.BLOCKLET_APP_SK = c.env.APP_SK;
|
|
402
|
+
}
|
|
403
|
+
// Test/staging escape hatch: forward PAYMENT_DISABLE_CSRF to the config boundary
|
|
404
|
+
// so the csrf middleware (readConfig) can honor it. Default-absent → CSRF stays on.
|
|
405
|
+
if ((c.env as any).PAYMENT_DISABLE_CSRF && !process.env.PAYMENT_DISABLE_CSRF) {
|
|
406
|
+
process.env.PAYMENT_DISABLE_CSRF = (c.env as any).PAYMENT_DISABLE_CSRF;
|
|
407
|
+
}
|
|
389
408
|
setDB(withD1Retry(c.env.DB.withSession('first-primary')));
|
|
390
409
|
ensureModelsInit();
|
|
391
410
|
|
|
@@ -496,6 +515,28 @@ function buildApp(env: Env): Hono<HonoEnv> {
|
|
|
496
515
|
// Health check
|
|
497
516
|
app.get('/health', (c) => c.json({ status: 'ok' }));
|
|
498
517
|
|
|
518
|
+
// did/csrfToken — the @blocklet/js-sdk axios adapter fetches its CSRF header from
|
|
519
|
+
// THIS endpoint (getCSRFTokenByLoginToken), not from the cookie. The shared
|
|
520
|
+
// blocklet-service (AUTH_SERVICE) only implements it on newer versions, so the
|
|
521
|
+
// catch-all proxy below 404s on older AUTH_SERVICE — leaving the SDK with no CSRF
|
|
522
|
+
// header and every mutating request 403'ing ("csrf token mismatch"). Sign it
|
|
523
|
+
// LOCALLY with the SAME secret + algorithm the payment csrf middleware verifies
|
|
524
|
+
// with (util/csrf sign over login_token), so token == cookie == what verify()
|
|
525
|
+
// expects. Must be registered BEFORE the /.well-known/service/* catch-all. This
|
|
526
|
+
// also makes the embedded arc-node CF runtime self-sufficient (no AUTH_SERVICE
|
|
527
|
+
// csrfToken endpoint required).
|
|
528
|
+
app.get('/.well-known/service/api/did/csrfToken', (c) => {
|
|
529
|
+
const loginToken = getCookie(c, 'login_token');
|
|
530
|
+
if (!loginToken) return c.json({ loginToken: null, csrfToken: null });
|
|
531
|
+
// Same secret resolution as the csrf middleware's csrfSecret() (PAYMENT_CSRF_SECRET
|
|
532
|
+
// override else the app secret key). Read APP_SK from the binding directly so we
|
|
533
|
+
// do not depend on the process.env.BLOCKLET_APP_SK mirror timing; getCsrfSecret()
|
|
534
|
+
// is the final fallback.
|
|
535
|
+
const secret = (c.env as any).PAYMENT_CSRF_SECRET || c.env.APP_SK || getCsrfSecret();
|
|
536
|
+
if (!secret) return c.json({ loginToken, csrfToken: null });
|
|
537
|
+
return c.json({ loginToken, csrfToken: signCsrf(secret, loginToken) });
|
|
538
|
+
});
|
|
539
|
+
|
|
499
540
|
// user-session under /.well-known/service — proxy to blocklet-service session API
|
|
500
541
|
// Returns full session data including connectedAccounts (needed by @arcblock/ux SessionUser)
|
|
501
542
|
app.get('/.well-known/service/api/user-session', async (c) => {
|
|
@@ -691,7 +732,6 @@ function buildApp(env: Env): Hono<HonoEnv> {
|
|
|
691
732
|
startsWithZ: sk.startsWith('z'),
|
|
692
733
|
});
|
|
693
734
|
});
|
|
694
|
-
|
|
695
735
|
// === DID Auth Login routes ===
|
|
696
736
|
// Only proxy login-related /api/did/* paths to blocklet-service.
|
|
697
737
|
// Other /api/did/* paths (subscription, pay, collect, etc.) are Payment Kit's own
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.9",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"prelint": "npm run types",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@abtnode/cron": "^1.17.13-beta-20260613-094425-b81920c8",
|
|
50
50
|
"@arcblock/did": "^1.30.24",
|
|
51
|
-
"@arcblock/did-connect-js": "^4.
|
|
51
|
+
"@arcblock/did-connect-js": "^4.1.2",
|
|
52
52
|
"@arcblock/did-connect-react": "^3.5.4",
|
|
53
53
|
"@arcblock/did-connect-storage-nedb": "^1.8.0",
|
|
54
54
|
"@arcblock/did-util": "^1.30.24",
|
|
@@ -60,13 +60,13 @@
|
|
|
60
60
|
"@blocklet/error": "^0.3.5",
|
|
61
61
|
"@blocklet/js-sdk": "^1.17.13-beta-20260613-094425-b81920c8",
|
|
62
62
|
"@blocklet/logger": "^1.17.13-beta-20260613-094425-b81920c8",
|
|
63
|
-
"@blocklet/payment-broker-client": "1.29.
|
|
64
|
-
"@blocklet/payment-react": "1.29.
|
|
65
|
-
"@blocklet/payment-vendor": "1.29.
|
|
63
|
+
"@blocklet/payment-broker-client": "1.29.9",
|
|
64
|
+
"@blocklet/payment-react": "1.29.9",
|
|
65
|
+
"@blocklet/payment-vendor": "1.29.9",
|
|
66
66
|
"@blocklet/sdk": "^1.17.13-beta-20260613-094425-b81920c8",
|
|
67
67
|
"@blocklet/ui-react": "^3.5.4",
|
|
68
|
-
"@blocklet/uploader": "^0.
|
|
69
|
-
"@blocklet/xss": "^0.
|
|
68
|
+
"@blocklet/uploader": "^0.15.4",
|
|
69
|
+
"@blocklet/xss": "^0.15.4",
|
|
70
70
|
"@hono/node-server": "2.0.4",
|
|
71
71
|
"@mui/icons-material": "^7.1.2",
|
|
72
72
|
"@mui/lab": "7.0.0-beta.14",
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"devDependencies": {
|
|
134
134
|
"@abtnode/types": "^1.17.13-beta-20260613-094425-b81920c8",
|
|
135
135
|
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
136
|
-
"@blocklet/payment-types": "1.29.
|
|
136
|
+
"@blocklet/payment-types": "1.29.9",
|
|
137
137
|
"@types/connect": "^3.4.38",
|
|
138
138
|
"@types/debug": "^4.1.12",
|
|
139
139
|
"@types/dotenv-flow": "^3.3.3",
|
|
@@ -180,5 +180,5 @@
|
|
|
180
180
|
"parser": "typescript"
|
|
181
181
|
}
|
|
182
182
|
},
|
|
183
|
-
"gitHead": "
|
|
183
|
+
"gitHead": "249bd9bf3c6cc54f77c260edb4b4d3c0be60f126"
|
|
184
184
|
}
|
|
@@ -34,7 +34,13 @@ export default function UserLayout(props: any) {
|
|
|
34
34
|
return (
|
|
35
35
|
<PaymentProvider session={session} connect={connectApi}>
|
|
36
36
|
<UserCenter
|
|
37
|
-
|
|
37
|
+
// Must match the userCenter nav link declared in blocklet.yml (`link: /customer`).
|
|
38
|
+
// UserCenter resolves both this prop and the nav link via `new URL(x, origin).pathname`,
|
|
39
|
+
// which strips any mount prefix — so the nav tab always resolves to the bare `/customer`.
|
|
40
|
+
// Prefixing here (e.g. `${prefix}customer`) makes the active tab fail to match, which
|
|
41
|
+
// triggers UserCenter's auto-redirect to the bare nav link and 404s the embedded mount
|
|
42
|
+
// (#1394). The bare path also works in the non-embedded form, where prefix is `/`.
|
|
43
|
+
currentTab="/customer"
|
|
38
44
|
hideFooter
|
|
39
45
|
embed={embed === '1'}
|
|
40
46
|
notLoginContent="undefined">
|
package/vite.arc.config.ts
CHANGED
|
@@ -29,6 +29,25 @@ export default defineConfig({
|
|
|
29
29
|
root: coreDir,
|
|
30
30
|
base: `${UI_PREFIX}/`,
|
|
31
31
|
plugins: [
|
|
32
|
+
// Inject the Buffer polyfill at the top of the entry — the did-connect
|
|
33
|
+
// SessionProvider.refresh path serializes request bodies with Buffer, which is
|
|
34
|
+
// undefined in the browser, so without this the arc-embedded payment SPA throws
|
|
35
|
+
// "ReferenceError: Buffer is not defined" on session refresh and never renders.
|
|
36
|
+
// The standalone cloudflare/vite.config.ts already does this (cf-buffer-polyfill);
|
|
37
|
+
// the arc build was missing it. Reuses the same shim.
|
|
38
|
+
{
|
|
39
|
+
name: 'arc-buffer-polyfill',
|
|
40
|
+
enforce: 'pre' as const,
|
|
41
|
+
transform(code: string, id: string) {
|
|
42
|
+
if (id.endsWith('/src/index.tsx')) {
|
|
43
|
+
const shim = path
|
|
44
|
+
.resolve(coreDir, 'cloudflare/frontend-shims/buffer-polyfill.ts')
|
|
45
|
+
.replace(/\\/g, '/');
|
|
46
|
+
return `import '${shim}';\n` + code;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
},
|
|
50
|
+
},
|
|
32
51
|
tsconfigPaths({ root: coreDir }),
|
|
33
52
|
react(),
|
|
34
53
|
// Build-time window.blocklet bootstrap (P2 helper, single source). The
|