Accepting Payments
Yleiskatsaus
Fenerum integroituu johtaviin maksupalveluntarjoajiin auttaakseen sinua keräämään ja hallitsemaan asiakkaidesi maksutapoja. Kun maksukortti on rekisteröity Fenerumiin, voit veloittaa sen automaattisesti laskuista ja tilauksista.
Tuetut palveluntarjoajat:
Edellytykset
Ennen kuin alat vastaanottaa maksuja, määritä maksupalveluntarjoaja Fenerumissa:
- Siirry Fenerumissa kohtaan Settings → Integrations
- Lisää maksupalveluntarjoajasi API‑tunnistetiedot
- Ota maksuyhdyskäytävä käyttöön organisaatiollesi
Stripe Integration
Näin se toimii
Stripen integrointi Fenerumiin koostuu kahdesta vaiheesta:
- Frontend: Kerää korttitiedot Stripe Elementsin avulla (PCI‑yhteensopiva, korttidata menee suoraan Stripelle)
- Backend: Rekisteröi Stripen payment method ID Fenerumiin (palvelimellasi, turvallinen token‑käsittely)
Tietoturvahuomio: Älä koskaan paljasta Fenerumin API‑tokenia frontend‑koodissa. Kutsu Fenerumin APIa aina backendistä, jossa token on turvallisesti tallennettu ympäristömuuttujiin.
Frontend: kerää maksutapa
Käytä Stripe Elementsia korttitietojen turvalliseen keräämiseen. Korttidata lähetetään suoraan Stripelle — palvelimesi ei näe sitä.
<!DOCTYPE html>
<html>
<head>
<title>Add Payment Method</title>
<script src="https://js.stripe.com/v3/"></script>
<style>
#payment-form { max-width: 500px; margin: 50px auto; padding: 20px; }
#card-element { border: 1px solid #ccc; padding: 10px; border-radius: 4px; }
button { margin-top: 20px; padding: 10px 20px; background: #5469d4; color: white; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background: #4158c4; }
.success { color: green; margin-top: 20px; }
.error { color: red; margin-top: 20px; }
</style>
</head>
<body>
<form id="payment-form">
<h2>Add Payment Method</h2>
<div id="card-element"></div>
<button type="submit">Save Card</button>
<div id="message"></div>
</form>
<script>
// Initialize Stripe with your publishable key (safe for frontend)
const stripe = Stripe('pk_test_YOUR_PUBLISHABLE_KEY')
const elements = stripe.elements()
const cardElement = elements.create('card')
cardElement.mount('#card-element')
const form = document.getElementById('payment-form')
const messageDiv = document.getElementById('message')
form.addEventListener('submit', async (event) => {
event.preventDefault()
messageDiv.textContent = ''
// Step 1: Create payment method with Stripe (card data stays secure)
const {error, paymentMethod} = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
})
if (error) {
messageDiv.textContent = error.message
messageDiv.className = 'error'
return
}
// Step 2: Send ONLY the payment method ID to YOUR backend
<!-- focus-start -->
try {
const response = await fetch('/api/register-payment-card', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
paymentMethodId: paymentMethod.id,
accountId: 'ACCOUNT_UUID_HERE'
})
})
const data = await response.json()
<!-- focus-end -->
if (response.ok) {
messageDiv.textContent = `Card saved: ${data.brand} ending in ${data.card_number.slice(-4)}`
messageDiv.className = 'success'
form.reset()
} else {
messageDiv.textContent = data.error || 'Failed to save card'
messageDiv.className = 'error'
}
} catch (err) {
messageDiv.textContent = 'Network error: ' + err.message
messageDiv.className = 'error'
}
})
</script>
</body>
</html>Keskeiset huomiot:
- Stripen publishable key (
pk_test_...) on turvallista käyttää frontend‑koodissa - Korttidata lähetetään suoraan Stripelle, eikä se kulje palvelimesi kautta
- Vain payment method ID lähetetään backendiin
- Ei Fenerumin API‑tokenia frontendiin!
Backend: rekisteröi Fenerumiin
Backend vastaanottaa Stripen payment method ID:n ja rekisteröi sen Fenerumiin käyttäen ympäristömuuttujiin tallennettua API‑tokenia.
// Example backend endpoint (works with Express, Fastify, Next.js, etc.)
// Endpoint: POST /api/register-payment-card
// Body: { paymentMethodId: string, accountId: string }
async function registerPaymentCard(req, res) {
const { paymentMethodId, accountId } = req.body
// Validate inputs
if (!paymentMethodId || !accountId) {
return res.status(400).json({ error: 'Missing required fields' })
}
<!-- focus-start -->
try {
// Call Fenerum API with token from environment variables
const response = await fetch('https://app.fenerum.com/api/v1/paymentcards/', {
method: 'POST',
headers: {
'Authorization': `Token ${process.env.FENERUM_API_TOKEN}`,
'X-Client-System': 'YourApp',
'Content-Type': 'application/json',
},
body: JSON.stringify({
account: accountId,
token: paymentMethodId,
gateway: 'stripe_new'
})
})
const data = await response.json()
<!-- focus-end -->
if (!response.ok) {
console.error('Fenerum API error:', data)
return res.status(response.status).json({
error: 'Failed to register card with Fenerum'
})
}
// Return success with card details
return res.status(200).json({
uuid: data.uuid,
brand: data.brand,
card_number: data.card_number,
month: data.month,
year: data.year
})
} catch (error) {
console.error('Error registering payment card:', error)
return res.status(500).json({ error: 'Internal server error' })
}
}Ympäristömuuttujien määrittäminen:
# .env file (NEVER commit this to version control!)
FENERUM_API_TOKEN=your_actual_token_hereEsimerkkivastaus:
{
"uuid": "09655a26-12e0-4a82-8524-7851998886fc",
"brand": "Visa",
"card_number": "XXXXXXXXXXXX4242",
"month": 12,
"year": 2025
}Customer Self-Service
Suositus: käytä Fenerum Self-Service -palvelua
Paras tapa antaa asiakkaiden hallita maksutapojaan on Fenerum Self-Service — täysin hostattu portaali, jossa asiakkaat voivat lisätä maksukortteja, hallita tilauksia ja tarkastella laskuja ilman koodausta.
Hyödyt:
- Asiakkaat voivat lisätä ja hallita maksukortteja itse Stripen tai Quickpayn kautta
- Automaattinen integraatio brändisi kanssa
- Ei koodia — ota vain käyttöön organisaatiosi asetuksissa
- Turvallinen autentikointi sähköpostilinkin kautta
API‑integraatio:
Luo asiakkaille suora käyttölinkki Self‑Serviceen:
# Generate Self-Service access link
curl -X POST https://app.fenerum.com/api/self-service/initiate-organization/ \
-H "Authorization: Token YOUR_FENERUM_TOKEN" \
-H "X-Client-System: YourApp" \
-H "Content-Type: application/json" \
-d '{
"email": "customer@example.com"
}'Vastaus:
{
"url": "https://your-company.hostedsignup.com/access/abc123..."
}Lähetä tämä linkki asiakkaallesi — hän pääsee välittömästi omaan portaaliinsa lisäämään maksukortteja ja hallitsemaan tilauksiaan.
Kun asiakkaat lisäävät maksukortin Self‑Servicen kautta, Fenerum:
- Tallentaa kortin asiakkaan tilille
- Asettaa “Payment card” oletusperintätavaksi
- Päivittää kaikki aktiiviset tilaukset käyttämään uutta maksutapaa
Lue lisää: Self‑Service Documentation
Quickpay Integration
Näin se toimii
Fenerum käyttää QuickPay subscriptions -toiminnallisuutta maksukorttien tallentamiseen. Integraatiopolku on seuraava:
- Backend: Luo QuickPay‑maksulinkki QuickPayn APIlla
- Frontend: Näytä asiakkaalle QuickPayn maksulomake (korttidata menee suoraan QuickPaylle)
- Callback: QuickPay lähettää callbackin, kun subscription ID on muodostettu
- Backend: Rekisteröi subscription ID Fenerumiin
Tietoturvahuomio: Kaikki API‑kutsut (sekä QuickPay että Fenerum) on tehtävä backendissä, jossa tokenit säilytetään turvallisesti.
Vaihe 1: Luo QuickPay-maksulinkki
Backendi luo QuickPay‑maksulinkin käyttäen QuickPayn payment link APIa.
// Backend endpoint to create QuickPay payment link
// Endpoint: POST /api/create-quickpay-link
// Body: { accountId: string, customerEmail: string }
async function createQuickpayLink(req, res) {
const { accountId, customerEmail } = req.body
<!-- focus-start -->
try {
// Create QuickPay payment (subscription)
const paymentResponse = await fetch('https://api.quickpay.net/payments', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(':' + process.env.QUICKPAY_API_KEY).toString('base64')}`,
'Accept-Version': 'v10',
'Content-Type': 'application/json'
},
body: JSON.stringify({
currency: 'DKK',
order_id: `sub_${accountId}_${Date.now()}`,
variables: {
fenerum_account_id: accountId,
customer_email: customerEmail
}
})
})
const payment = await paymentResponse.json()
// Create payment link for the subscription
const linkResponse = await fetch(`https://api.quickpay.net/payments/${payment.id}/link`, {
method: 'PUT',
headers: {
'Authorization': `Basic ${Buffer.from(':' + process.env.QUICKPAY_API_KEY).toString('base64')}`,
'Accept-Version': 'v10',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 0, // 0 for card authorization only
auto_capture: false,
callback_url: `${process.env.YOUR_DOMAIN}/api/quickpay-callback`
})
})
const link = await linkResponse.json()
<!-- focus-end -->
return res.json({ url: link.url })
} catch (error) {
console.error('Error creating QuickPay link:', error)
return res.status(500).json({ error: 'Internal server error' })
}
}Ympäristöasetukset:
QUICKPAY_API_KEY=your_quickpay_api_key_here
YOUR_DOMAIN=https://yourdomain.com
FENERUM_API_TOKEN=your_fenerum_token_hereVaihe 2: Uudelleenohjausreitti
Luo backend‑reitti, joka generoi QuickPay‑linkin ja uudelleenohjaa asiakkaan suoraan QuickPayn hostatulle sivulle.
// Backend redirect route
// When customer visits: GET /add-payment-card
// They are redirected to QuickPay's hosted payment page
async function redirectToQuickpay(req, res) {
// Get logged-in user's information from session/auth
const accountId = req.user.fenerumAccountId
const email = req.user.email
<!-- focus-start -->
try {
// Create QuickPay payment (subscription)
const paymentResponse = await fetch('https://api.quickpay.net/payments', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(':' + process.env.QUICKPAY_API_KEY).toString('base64')}`,
'Accept-Version': 'v10',
'Content-Type': 'application/json'
},
body: JSON.stringify({
currency: 'DKK',
order_id: `sub_${accountId}_${Date.now()}`,
variables: {
fenerum_account_id: accountId,
customer_email: email
}
})
})
const payment = await paymentResponse.json()
// Create payment link
const linkResponse = await fetch(`https://api.quickpay.net/payments/${payment.id}/link`, {
method: 'PUT',
headers: {
'Authorization': `Basic ${Buffer.from(':' + process.env.QUICKPAY_API_KEY).toString('base64')}`,
'Accept-Version': 'v10',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 0,
auto_capture: false,
callback_url: `${process.env.YOUR_DOMAIN}/api/quickpay-callback`
})
})
const link = await linkResponse.json()
// Redirect customer to QuickPay
return res.redirect(link.url)
<!-- focus-end -->
} catch (error) {
console.error('Error creating QuickPay link:', error)
return res.status(500).send('Failed to create payment link')
}
}Käyttö:
Anna asiakkaille linkki backend‑reitille:
<a href="/add-payment-card">Add Payment Method</a>Reitti käyttää sisäänkirjautuneen käyttäjän sessiosta/authista saatavia tietoja tilin ID:stä ja sähköpostista — URLissa ei ole arkaluonteista dataa.
Vaihe 3: Käsittele QuickPay-callback
Kun asiakas on täyttänyt maksulomakkeen, QuickPay lähettää palvelimellesi callbackin, joka sisältää subscription ID:n.
// QuickPay callback handler
// Endpoint: POST /api/quickpay-callback
// Receives QuickPay callback when card is added
async function handleQuickpayCallback(req, res) {
const { id: subscriptionId, variables } = req.body
const accountId = variables?.fenerum_account_id
if (!subscriptionId || !accountId) {
return res.status(400).json({ error: 'Missing required data' })
}
<!-- focus-start -->
try {
// Register the QuickPay subscription with Fenerum
const response = await fetch('https://app.fenerum.com/api/v1/paymentcards/', {
method: 'POST',
headers: {
'Authorization': `Token ${process.env.FENERUM_API_TOKEN}`,
'X-Client-System': 'YourApp',
'Content-Type': 'application/json'
},
body: JSON.stringify({
account: accountId,
token: subscriptionId.toString(), // QuickPay subscription ID
gateway: 'quickpay'
})
})
const data = await response.json()
<!-- focus-end -->
if (response.ok) {
console.log('Payment card registered with Fenerum:', data)
return res.status(200).json({ success: true })
} else {
console.error('Failed to register card with Fenerum:', data)
return res.status(500).json({ error: 'Failed to register card' })
}
} catch (error) {
console.error('Error in QuickPay callback:', error)
return res.status(500).json({ error: 'Internal server error' })
}
}Fenerumin vastaus:
{
"uuid": "09655a26-12e0-4a82-8524-7851998886fc",
"brand": "Visa",
"card_number": "XXXXXXXXXXXX4242",
"month": 12,
"year": 2025,
"payment_gateway": "quickpay",
"account": "50e9aa0b-8d35-4da7-9a9b-8a35b11579b2"
}Keskeiset huomiot:
- QuickPayn subscription ID on tallennettava Fenerumiin merkkijonona
gateway‑arvon on oltavaquickpay- Korttidata ei koskaan kulje palvelimesi kautta — se menee suoraan QuickPaylle
- Katso QuickPay integration guide asennusohjeita varten
Customer Self-Service
Suositus: käytä Fenerum Self-Service -palvelua
Paras tapa on käyttää Fenerum Self-Service ‑portaalia, jossa asiakkaat voivat lisätä QuickPay‑maksukortit itse hostatussa käyttöliittymässä.
Self‑Service‑portaali tukee sekä Stripe‑ että Quickpay‑maksutapoja ja tarjoaa yhtenäisen käyttökokemuksen asiakkaillesi. Katso API‑integraation tiedot yllä olevasta [Customer Self-Service]#customer-self-service ‑osiosta Stripen kohdalta.
Maksukorttien hallinta
Listaa tilin kortit
curl https://app.fenerum.com/api/v1/paymentcards/?account=CUST001 \
-H "Authorization: Token YOUR_FENERUM_TOKEN" \
-H "X-Client-System: YourApp"Vastaus:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"uuid": "09655a26-12e0-4a82-8524-7851998886fc",
"active": true,
"brand": "Visa",
"card_number": "XXXXXXXXXXXX4242",
"month": 12,
"year": 2025,
"payment_gateway": "stripe_new",
"account": "50e9aa0b-8d35-4da7-9a9b-8a35b11579b2"
}
]
}Hae kortin tiedot
curl https://app.fenerum.com/api/v1/paymentcards/{card_uuid}/ \
-H "Authorization: Token YOUR_FENERUM_TOKEN" \
-H "X-Client-System: YourApp"Poista kortti käytöstä
curl -X POST https://app.fenerum.com/api/v1/paymentcards/{card_uuid}/disable/ \
-H "Authorization: Token YOUR_FENERUM_TOKEN" \
-H "X-Client-System: YourApp"Huomio: Kortin poistaminen käytöstä Fenerumissa ei poista sitä maksupalveluntarjoajalta. Se ainoastaan estää Fenerumia veloittamasta korttia.
Maksuyhdyskäytävän viitetiedot
Kun luot maksukortteja, käytä seuraavia gateway‑tunnisteita:
| Palveluntarjoaja | Gateway‑arvo | Token-tyyppi |
|---|---|---|
| Stripe | stripe_new | Payment Method ID (pm_...) |
| Quickpay | quickpay | Subscription ID (integer) |
Vianmääritys
Kortin rekisteröinti epäonnistuu:
- Varmista, että maksupalveluntarjoajan tunnukset on määritetty oikein Fenerumin asetuksissa
- Tarkista, että tilin UUID on olemassa Fenerumissa
- Varmista, että tokenin muoto vastaa gateway‑tyyppiä (pm_... Stripelle, integer Quickpaylle)
- Vahvista, että käytät oikeaa gateway‑arvoa (
stripe_newtaiquickpay)