Skip to main content

idkollen_client/models/
bankid_no.rs

1use chrono::NaiveDate;
2use serde::{Deserialize, Serialize};
3
4use super::common::ApiErrorCode;
5use super::email::Email;
6use super::ssn::Nnin;
7use super::url::Url;
8
9/// Request body for starting a BankID NO authentication session.
10#[must_use]
11#[derive(Debug, Clone, Default, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub struct BankIdNoAuthRequest {
14    /// URL to redirect the user to after completing the flow.
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub redirect_url: Option<Url>,
17    /// Request the user's Norwegian personal number (fødselsnummer).
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub request_ssn: Option<bool>,
20    /// Request the user's phone number.
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub request_phone: Option<bool>,
23    /// Request the user's email address.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub request_email: Option<bool>,
26    /// Request the user's registered address.
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub request_address: Option<bool>,
29    /// Reference ID returned verbatim in the result and callback.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub ref_id: Option<String>,
32    /// (BETA) Deep-link URI to return the user to your app after authentication.
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub app_callback_uri: Option<Url>,
35}
36
37impl BankIdNoAuthRequest {
38    #[inline]
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    #[inline]
44    pub fn redirect_url(mut self, url: Url) -> Self {
45        self.redirect_url = Some(url);
46        self
47    }
48
49    #[inline]
50    pub fn request_ssn(mut self, v: bool) -> Self {
51        self.request_ssn = Some(v);
52        self
53    }
54
55    #[inline]
56    pub fn request_phone(mut self, v: bool) -> Self {
57        self.request_phone = Some(v);
58        self
59    }
60
61    #[inline]
62    pub fn request_email(mut self, v: bool) -> Self {
63        self.request_email = Some(v);
64        self
65    }
66
67    #[inline]
68    pub fn request_address(mut self, v: bool) -> Self {
69        self.request_address = Some(v);
70        self
71    }
72
73    #[inline]
74    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
75        self.ref_id = Some(ref_id.into());
76        self
77    }
78
79    #[inline]
80    pub fn app_callback_uri(mut self, uri: Url) -> Self {
81        self.app_callback_uri = Some(uri);
82        self
83    }
84}
85
86/// Request body for starting a BankID NO backchannel authentication session.
87#[must_use]
88#[derive(Debug, Clone, Serialize)]
89#[serde(rename_all = "camelCase")]
90pub struct BankIdNoBackchannelAuthRequest {
91    /// Norwegian personal number (fødselsnummer).
92    pub ssn: Nnin,
93    /// URL to receive the result callback on success or failure.
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub callback_url: Option<Url>,
96    /// Reference ID returned verbatim in the result and callback.
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub ref_id: Option<String>,
99}
100
101impl BankIdNoBackchannelAuthRequest {
102    #[inline]
103    pub fn new(ssn: Nnin) -> Self {
104        Self {
105            ssn,
106            callback_url: None,
107            ref_id: None,
108        }
109    }
110
111    #[inline]
112    pub fn callback_url(mut self, url: Url) -> Self {
113        self.callback_url = Some(url);
114        self
115    }
116
117    #[inline]
118    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
119        self.ref_id = Some(ref_id.into());
120        self
121    }
122}
123
124/// Request body for starting a BankID NO signing session.
125#[must_use]
126#[derive(Debug, Clone, Default, Serialize)]
127#[serde(rename_all = "camelCase")]
128pub struct BankIdNoSignRequest {
129    /// URL to redirect the user to after completing the flow.
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub redirect_url: Option<Url>,
132    /// Text to sign (max 118 chars). Mutually exclusive with `documents`.
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub text: Option<String>,
135    /// Document IDs to sign (from `/v3/document`). Mutually exclusive with `text`.
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub documents: Option<Vec<String>>,
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub request_ssn: Option<bool>,
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub request_phone: Option<bool>,
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub request_email: Option<bool>,
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub request_address: Option<bool>,
146    /// Reference ID returned verbatim in the result and callback.
147    #[serde(skip_serializing_if = "Option::is_none")]
148    pub ref_id: Option<String>,
149}
150
151impl BankIdNoSignRequest {
152    #[inline]
153    pub fn new() -> Self {
154        Self::default()
155    }
156
157    #[inline]
158    pub fn redirect_url(mut self, url: Url) -> Self {
159        self.redirect_url = Some(url);
160        self
161    }
162
163    #[inline]
164    pub fn text(mut self, v: impl Into<String>) -> Self {
165        self.text = Some(v.into());
166        self
167    }
168
169    #[inline]
170    pub fn documents(mut self, v: Vec<String>) -> Self {
171        self.documents = Some(v);
172        self
173    }
174
175    #[inline]
176    pub fn request_ssn(mut self, v: bool) -> Self {
177        self.request_ssn = Some(v);
178        self
179    }
180
181    #[inline]
182    pub fn request_phone(mut self, v: bool) -> Self {
183        self.request_phone = Some(v);
184        self
185    }
186
187    #[inline]
188    pub fn request_email(mut self, v: bool) -> Self {
189        self.request_email = Some(v);
190        self
191    }
192
193    #[inline]
194    pub fn request_address(mut self, v: bool) -> Self {
195        self.request_address = Some(v);
196        self
197    }
198
199    #[inline]
200    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
201        self.ref_id = Some(ref_id.into());
202        self
203    }
204}
205
206/// BankID NO session status.
207#[non_exhaustive]
208#[derive(Debug, Clone, Deserialize)]
209#[serde(tag = "status")]
210#[expect(clippy::large_enum_variant)]
211pub enum BankIdNoStatus {
212    #[serde(rename = "PENDING")]
213    Pending(BankIdNoPending),
214    #[serde(rename = "COMPLETED")]
215    Completed(BankIdNoCompleted),
216    #[serde(rename = "FAILED")]
217    Failed(BankIdNoFailed),
218}
219
220/// Returned while the user has not yet acted.
221#[derive(Debug, Clone, Deserialize)]
222#[serde(rename_all = "camelCase")]
223pub struct BankIdNoPending {
224    pub id: String,
225    pub ref_id: Option<String>,
226    /// Redirect URL for the browser-flow login page.
227    pub url: Option<String>,
228    /// Present in the backchannel flow — display this to the user.
229    pub binding_message: Option<String>,
230}
231
232/// Returned when the BankID NO session has completed successfully.
233#[derive(Debug, Clone, Deserialize)]
234#[serde(rename_all = "camelCase")]
235pub struct BankIdNoCompleted {
236    pub id: String,
237    pub ref_id: Option<String>,
238    /// Norwegian personal number. Present when `request_ssn` was `true`.
239    pub ssn: Option<Nnin>,
240    pub name: String,
241    pub given_name: String,
242    pub surname: String,
243    /// Present when `request_phone` was `true`.
244    pub phone: Option<String>,
245    /// Present when `request_email` was `true`.
246    pub email: Option<Email>,
247    /// Present when `request_address` was `true`.
248    pub address: Option<String>,
249    pub birth_date: Option<NaiveDate>,
250    /// BankID PID.
251    pub pid: Option<String>,
252    pub bank_id: Option<String>,
253    /// Present when the session was a signing session.
254    pub sign_result: Option<BankIdNoSignResult>,
255    /// Present when documents were signed.
256    pub signed_documents: Option<Vec<BankIdNoSignedDocument>>,
257}
258
259/// Returned when the BankID NO session has failed.
260#[derive(Debug, Clone, Deserialize)]
261#[serde(rename_all = "camelCase")]
262pub struct BankIdNoFailed {
263    pub id: String,
264    pub ref_id: Option<String>,
265    pub error: ApiErrorCode,
266}
267
268/// Signing result returned in a completed BankID NO sign session.
269#[derive(Debug, Clone, Deserialize)]
270#[serde(rename_all = "camelCase")]
271pub struct BankIdNoSignResult {
272    pub end_user: String,
273    pub merchant: String,
274    pub hash: String,
275}
276
277/// A signed document reference returned in a completed BankID NO sign session.
278#[derive(Debug, Clone, Deserialize)]
279#[serde(rename_all = "camelCase")]
280pub struct BankIdNoSignedDocument {
281    /// Document UUID matching the uploaded document.
282    pub id: String,
283    /// SHA hash of the signed PDF.
284    pub hash: String,
285}