跳转到内容

没有意大利税号的会员

查看 Markdown

加入协会并不需要意大利税号(codice fiscale)。需要的是当事人的身份已被识别;在 Vimine 上,有两种方式:

  • 通过税号,或者
  • 通过出生信息:dob + birthplace + birth_country(ISO 3166-1 alpha-2)。

两者不能都没有。本指南的其余部分逐个字段说明,对于为他人办理入会的集成——交换生、刚到意大利的志愿者、住在国外的会员——有哪些变化。

POST /v1/enroll 和 POST /v1/signup 接受相同的字段:

字段
codicefiscale 可选。提供时会进行校验,并与姓名、出生日期和出生地比对
dob 出生日期,YYYY-MM-DD
birthplace 在意大利出生的人填市镇(comune);在国外出生的人填城市,自由文本
birth_country 出生国,两个字母(IT、FR、SN…)
gender 仅用于统计:不再与税号比对
// 没有税号:出生日期、出生地和出生国
await vimineServer.enroll({
email: 'marie.dupont@example.org',
first_name: 'Marie',
last_name: 'Dupont',
dob: '1985-03-10',
birthplace: 'Lyon',
birth_country: 'FR',
accept_statuto: { version: statuto.version, sha256: statuto.sha256 }
});

在 /v1/enroll 上,没有税号时,每缺少一项出生信息,就返回 422 validation_failed,并在 errors[] 中有一条记录:

{ "code": "validation_failed", "errors": [{ "field": "birth_country", "code": "required" }] }

/v1/signup 只创建账户:在这里出生信息仍是可选的,等当事人申请会员资格时才需要。

在国外出生:发送 birth_country

章节“在国外出生:发送 birth_country”

在意大利出生的人,税号中包含出生市镇;在国外出生的人,税号中只包含国家。因此,对后者的比对看的是 birth_country,并把 birthplace(城市)当作自由文本。发送 birth_country,正是让持有有效税号、在国外出生的人通过校验的关键:如果不发送,“Lyon”会被当作意大利市镇去查找,税号就会显得不一致。(以前把国家的意大利语名称当作出生地发送的表单——birthplace: 'Francia'——仍然可以通过;但更推荐使用 birth_country。)

公开校验接口也是如此,现在它还会说明税号中包含什么:

const r = await publicApi().validateFiscalCode({
code: 'DPNMRA85C50Z110U', first_name: 'Marie', last_name: 'Dupont', date: '1985-03-10', place: 'Lyon', country: 'FR'
});
// { valid: true, error: null, mismatches: [], hints: [], birth_date: '1985-03-10', birth_country: 'FR' }

birth_date 和 birth_country 是从税号本身读取的:您可以用它们预填表单。如果您发送了 gender,这个端点仍会比对它;入会和个人资料则不会。

不一致的税号与确认

章节“不一致的税号与确认”

输错的税号(结构或校验码有误)返回 invalid_codicefiscale:必须更正,永远不能确认。格式正确但与所填信息不一致的税号,则返回 422,并带有一条信息更丰富的记录:

{
"code": "validation_failed",
"errors": [{
"field": "codicefiscale",
"code": "codicefiscale_mismatch",
"mismatches": ["place"],
"hints": [],
"confirmable": true
}]
}
  • mismatches——哪些地方不一致:lastName、firstName、date、place;
  • hints——当姓和名互换后税号能对上时,为 names_swapped:通常提示对方互换即可;
  • confirmable——当事人能否确认这就是其医保卡(tessera sanitaria)上的税号。这种情况确实会发生:已撤销的市镇、音译、以另一种顺序登记的姓名。

当 confirmable 为 true 时,请询问当事人,并带上 codicefiscale_confirmed: true 重复请求。当姓、名和出生日期全都不一致时,就再也没有什么能把这个税号和这个人联系起来:confirmable 为 false,唯一的办法是更正。

import { VimineError } from '@vimine/sdk/server';
try {
await vimineServer.enroll(input);
} catch (err) {
const entry = err instanceof VimineError && err.errors?.find((e) => e.code === 'codicefiscale_mismatch');
if (!entry) throw err;
if (entry.confirmable && (await askThePerson(entry.mismatches, entry.hints))) {
await vimineServer.enroll({ ...input, codicefiscale_confirmed: true });
}
}

不要自作主张发送 codicefiscale_confirmed:这是当事人的声明,并会作为声明被记录。

入会时没有税号的人,在取得税号后可以在自己的个人资料中补充:

const me = await vimine.me.update({ codicefiscale: 'DPNMRA85C50Z110U' });
me.codicefiscale_check; // 'matched'

PATCH /v1/me 接受 birth_country 和只写字段 codicefiscale_confirmed;codicefiscale 也可以重新设为 null。GET /v1/me 说明当事人是如何被识别的:

codicefiscale_check
matched 税号与当事人的出生信息一致
mismatch_confirmed 税号不一致,但已由当事人确认
absent 没有税号:通过出生日期、出生地和出生国识别
null 尚未识别:不能申请会员资格

matched 的意思是一致,而不是已经过税务登记机关核实:税号始终是当事人申报的信息。

账户可以存在但尚未识别身份——例如只为登录而注册的人。当这样的人申请会员资格时,API 会明确指出,并列出缺少什么:

  • POST /v1/me/membership → 422 identification_required,errors[] 为缺少的出生信息({ field: 'birthplace', code: 'required' }…)。请引导当事人通过 PATCH /v1/me(权限 profile:write)完善个人资料,然后重复请求。
  • POST /v1/enroll/confirm——已有账户的所有者收到的“确认您的申请”链接 → 409 identification_required,errors[] 相同。请在页面上询问出生信息,并带上 identification 再次提交令牌:
await publicApi().confirmEnrollment(token, { dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR' });
// POST /v1/enroll/confirm { token, identification: { dob, birthplace, birth_country, codicefiscale?, codicefiscale_confirmed? } }

出生信息放在请求体中传送,绝不放在链接中:链接里从来没有任何个人信息。identification 只补全个人资料中的空字段,不会覆盖已有内容;如果校验不通过,响应就是上文那样的 422 validation_failed。

入会审批不变:pending_reasons 对所有人都取决于协会的入会模式(参见入会审批与生效)。

入场时:身份核对

章节“入场时:身份核对”

与出生信息一致的税号可以据此核对;仅有出生信息,或由当事人确认的税号,则无法核对。对于这些会员,协会会在当事人第一次到场时查看一次证件。集成扫码器的开发者会在 POST /v1/checkins(权限 checkins:write)针对会员卡的响应中看到它:

const r = await vimineServer.checkins.create('vmt_…');
// { kind: 'card', verdict: 'valid', …, identity_check: 'pending' }
if (r.identity_check === 'pending') show('首次入场:请查验证件');
identity_check
pending 该会员没有可核实的税号,协会中也还没有人查看过其证件:请把它显示给入口值守人员
verified 协会中已有人查看过证件
flagged 有人查看过证件,但与信息不符:由协会秘书处接手处理
null 无需核对

这只是一条提示,不属于 verdict,也不限制任何操作:带有 identity_check: 'pending' 的 valid 会员卡照样可以入场。核对结果在协会的管理后台中记录,而不是通过 API。公开核验接口 GET /v1/verify/{card_token} 从不携带它:从外部核验会员卡的人只能看到状态和到期日。

有些协会会在会员登记册中保存会员的地址,有些则不会。这由协会决定,并且对所有会员都适用,或对所有会员都不适用;公开资料中会声明:

GET https://api.vimine.network/v1/aps/{slug}
→ { "aps": { …, "member_address": "optional" } }
member_address
none 不要询问:即使发送了 address 也不会保存
optional 询问,但不强制
required 没有 address 时,入会返回 422,并带有 { field: 'address', code: 'required' }
await vimineServer.enroll({
…,
address: { kind: 'residence', line: 'Via Roma 1', postal_code: '20121', city: 'Milano', province: 'MI', country: 'IT' }
});

address 中的 line 和 city 为必填;kind 为 residence(默认,户籍地)或 domicile(住所地,与户籍地不同时填写);省略 country 时为 IT;province 仅适用于意大利地址。/v1/signup 没有 address:地址属于会员资格,而不属于账户。

协会不能强制要求税号

章节“协会不能强制要求税号”

不存在“税号必填”这样的设置。协会不能要求每位申请人都提供税号:没有税号的人,在任何地方都通过出生信息来识别。如果您的表单把税号设为必填,那是您的表单的选择——它会把协会本可以接纳的人挡在门外。

变更内容(2026-09-19 版)

章节“变更内容(2026-09-19 版)”

全部为新增:始终发送税号的表单无需任何改动即可继续使用。现有集成可能会注意到:

  • POST /v1/enroll 中的 codicefiscale 不再是必填项;没有税号时,需要 dob、birthplace 和 birth_country(每缺少一项返回 422 required);
  • 新的可选字段 birth_country、codicefiscale_confirmed(enroll、signup、PATCH /v1/me)和 address(enroll);
  • gender 不再与税号比对:不会再因为性别单独返回 422;
  • 不一致的税号仍返回 codicefiscale_mismatch,现在在 mismatches 之外还带有 hints 和 confirmable;格式错误的税号仍是 invalid_codicefiscale;
  • GET/PATCH /v1/me 现在有声明的 schema(Me),包含 birth_country 和 codicefiscale_check;
  • 新错误 identification_required:在 POST /v1/me/membership 上为 422,在 POST /v1/enroll/confirm 上为 409(后者在请求体中接受 identification);
  • POST /v1/validate/fiscal-code 接受 country,并且还返回 hints、birth_date、birth_country;error 为 invalid、mismatch 或 null;
  • POST /v1/checkins 在针对会员卡的响应中增加了 identity_check;GET /v1/verify/{card_token} 保持不变;
  • 公开资料增加了 aps.member_address。