# Performing 3D Secure

This section describes how to perform 3D Secure if you are using the <intergiro-card-input> tag. The tag does most of the heavy lifting of the 3D Secure process, but it does require some integration.

Any of the APIs that you might use to create an order will return a Verification required error if the cardholder is required to perform SCA.

Example of Verification required error:

{
  "status": 400,
  "type": "malformed content",
  "error": "verification required",
  "content": {
    "property": "card",
    "type": "Card.Creatable | Card.Token",
    "description": "verification required",
    "details": {
      "visible": false,
      "method": "POST",
      "url": "https://acs.sandbox.3dsecure.io/3dsmethod",
      "data": {
        "type": "method",
        "threeDSServerTransID": "d461f105-1792-407f-95ff-9a496fd918a9"
      }
    }
  }
}

The received Verification required error needs to be submitted together with the card token back to the <intergiro-card-input> component which will initialize the 3D Secure cycle. This can result in rendering an invisible iframe for frictionless flow or a visible iframe that requires user interaction.

After the user interaction is completed, the <intergiro-card-input> component will again produce a new card token which should be submitted to the same API again (e.g. create order API).

Note that it is possible for the Verification required error to be received more then once, in which case the described cycle needs to be repeated until the API either returns a new created order or some other error.

# Snippet - 3D Secure when creating an order

<!DOCTYPE html>
<html>

<head>
	<script type="module" src="https://merchant.intergiro.com/ui/"></script>
	<link href="https://theme.payfunc.com/intergiro/variables.css" rel="stylesheet">

	<script defer>
		const order = {
			number: "Card-Input-Example" + (Math.random() * 10000).toString(),
			payment: { type: "card" },
			items: 150,
			currency: "EUR",
		}
		async function create(order, card, error) {
			const element = document.querySelector("intergiro-card-input")
			card = await element.submit(card, error)
			let result
			if (typeof card == "string") {
				order.payment.card = card
				order.id = error?.id // Add the id returned from the previous request.
				const response = await fetch("https://merchant.intergiro.com/v1/order", {
					headers: {
						"Accept": "application/json",
						"Content-Type": "application/json",
						Authorization:
							"Bearer <customer.api.key> | Bearer <private.api.key>",
					},
					method: "POST",
					body: JSON.stringify(order),
				})
				result = response.headers.get("content-type").startsWith("application/json")
					? await response.json()
					: await response.text()
				if (response.ok == true) {
					alert(JSON.stringify(result));
				} else {
					result = create(order, card, result)
				}
			} else {
				alert(JSON.stringify(card))
				result = card
			}
			return result
		}
	</script>
</head>
<body style="width: 100%; max-width: 20em; margin-left: auto; margin-right: auto;">
	<main>
		<intergiro-card-input class="input"
			api-key="<public.api.key>">
		</intergiro-card-input>
		<button type="submit" onclick="create(order)">Submit</button>
	</main>
</body>
</html>

# Snippet - 3D Secure when creating a customer

<!DOCTYPE html>
<html>

<head>
	<script type="module" src="https://merchant.intergiro.com/ui/"></script>
  	<link href="https://merchant.intergiro.com/theme/intergiro/index.css" rel="stylesheet">
	<script defer>
		async function create(customer, card, error) {
			const element = document.querySelector("intergiro-card-input")
			card = await element.submit(card, error)
			let result
			if (typeof card == "string") {
				customer = customer ?? { method: [{ type: "token" }] }
				customer.method[0].card = card
				customer.id = error?.id // Add the id returned from the previous request.
				const response = await fetch("https://merchant.intergiro.com/v1/customer", {
					headers: {
						"Accept": "application/json",
						"Content-Type": "application/json",
						Authorization:
							"Bearer <private.api.key>",
					},
					method: "POST",
					body: JSON.stringify(customer),
				})
				result = response.headers.get("content-type").startsWith("application/json")
					? await response.json()
					: await response.text()
				if (response.ok == true) {
					alert(Json.stringify(result))
				} else {
					result = create(customer, card, result)
				}
			} else {
				alert(JSON.stringify(card))
				result = card
			}
			return result
		}
	</script>
</head>

<body style="width: 100%; max-width: 20em; margin-left: auto; margin-right: auto;">
	<main>
		<intergiro-card-input class="input" api-key="<public.api.key>">
		</intergiro-card-input>
		<button type="submit" onclick="create()">Submit</button>
	</main>
</body>

</html>


# Snippet - 3D Secure when creating an order with a saved card

To perform 3DS with a saved card, the <intergiro-payment-update> element should be used. A customer payment method needs to be assigned to the method property of the element.

The submit function on the <intergiro-payment-update> element has 2 optional input fields, payment and error. Both input fields should be undefined in the first call. The function will return the card payment to be used in the /order endpoint as indicated in the example below. If the order endpoint returnes a verification required error, the submit function should be called again with the card payment returned from the previous call and the error.

If csc needs to be collected, set property layout to "csc". If no layout is specified or if layout is set to "none", the component will be invisible.

<!DOCTYPE html>
<html>

<head>
	<script type="module" src="https://merchant.intergiro.com/ui/"></script>
	<link href="https://theme.payfunc.com/intergiro/index.css" rel="stylesheet">

	<script defer>
		async function create(payment, error) {
			let result
			const element = document.querySelector("intergiro-payment-update")
			payment = await element.submit(payment, error)
			if (payment.card) {
				const order = {
					id: error?.id, // Add the id returned from the previous request.
					items: 150,
					currency: "EUR",
					customer: "<customer-id>",
					payment: payment,
				}
				const response = await fetch("https://merchant.intergiro.com/v1/order", {
					headers: {
						"Accept": "application/json",
						"Content-Type": "application/json",
						Authorization:
							"Bearer <customer.api.key> | Bearer <private.api.key>",
					},
					method: "POST",
					body: JSON.stringify(order),
				})
				result = await response.json()
				if (response.ok == true) {
					alert(JSON.stringify(result));
				} else {
					result = create(payment, result)
				}
			} 
			return result
		}
	</script>
</head>
<body>
	<intergiro-payment-update 
		layout="csc" 
		method='<customer-payment-method>' 
		api-key="<public-api-key>">
	</intergiro-payment-update>
	<button type="submit" onclick="create()">Submit</button>
</body>
</html>