feb5f1f03b
- New BirNur.svelte: waqf configuration based on companions' model - Reframed Support.svelte with dual-track: bank trustee giving + app support - Updated App.svelte to add Waqf tab (tab 14) between WorshipTracker and Support - Model inspired by Uthman's Well of Rumah and Abdur Rahman bin Auf's productive endowment
233 lines
7.6 KiB
JSON
233 lines
7.6 KiB
JSON
{
|
|
"name": "Polar.sh → Twenty CRM Sync",
|
|
"nodes": [
|
|
{
|
|
"id": "webhook-trigger",
|
|
"name": "Polar Webhook",
|
|
"type": "n8n-nodes-base.webhook",
|
|
"typeVersion": 2,
|
|
"position": [250, 300],
|
|
"webhookId": "polar-twenty-sync",
|
|
"authentication": "none",
|
|
"properties": {
|
|
"httpMethod": "POST",
|
|
"path": "polar-webhook",
|
|
"responseMode": "onReceived",
|
|
"responseData": "",
|
|
"options": {}
|
|
},
|
|
"notes": "SET ME: Configure this webhook URL in Polar.sh dashboard under Webhooks → Add endpoint. Polar sends checkout.created, checkout.updated, checkout.succeeded events."
|
|
},
|
|
{
|
|
"id": "code-parse",
|
|
"name": "Parse Polar Payload",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [450, 300],
|
|
"properties": {
|
|
"language": "javaScript",
|
|
"code": "// Parse Polar.sh webhook payload\n// Polar sends: type, data (containing checkout object)\n// Checkout object has: customer (email, name, billingAddress), product (name, metadata), amount, currency\n\nconst payload = $input.first().json;\nconst eventType = payload.type || '';\nconst checkout = payload.data || {};\n\n// Extract fields from Polar payload\nconst email = checkout.customer?.email || checkout.customerEmail || '';\nconst name = checkout.customer?.name || checkout.customerName || '';\nconst amount = checkout.amount || 0;\nconst currency = checkout.currency || 'usd';\nconst productName = checkout.product?.name || checkout.productName || '';\nconst metadata = checkout.product?.metadata || checkout.metadata || {};\nconst donationType = metadata.donationType || metadata.type || '';\nconst timestamp = checkout.createdAt || new Date().toISOString();\nconst polarCheckoutId = checkout.id || '';\n\n// Map donation type\nlet donationLabel = '';\nif (donationType === 'sadaqah' || productName.toLowerCase().includes('sadaqah')) {\n donationLabel = 'Sadaqah';\n} else if (donationType === 'zakat' || productName.toLowerCase().includes('zakat')) {\n donationLabel = 'Zakat';\n} else if (donationType === 'hibah' || productName.toLowerCase().includes('hibah')) {\n donationLabel = 'Hibah';\n} else {\n donationLabel = 'Donation';\n}\n\n// Format amount to display value (cents to main unit)\nconst amountDisplay = currency === 'myr' ?\n `RM${(amount / 100).toFixed(2)}` :\n `${(amount / 100).toFixed(2)} ${currency.toUpperCase()}`;\n\nreturn {\n email,\n name,\n amount,\n amountDisplay,\n currency,\n donationLabel,\n donationType,\n productName,\n polarCheckoutId,\n timestamp\n};"
|
|
},
|
|
"notes": "Extracts and normalises Polar.sh webhook fields. Metadata fields are set in Polar product configuration."
|
|
},
|
|
{
|
|
"id": "http-twenty",
|
|
"name": "Twenty CRM - Upsert Contact",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [650, 300],
|
|
"credentials": {
|
|
"httpRequest": {
|
|
"id": "SET_ME_TwentyCRMApiKeyId",
|
|
"name": "Twenty CRM API Key"
|
|
}
|
|
},
|
|
"properties": {
|
|
"method": "POST",
|
|
"url": "SET_ME_TwentyCRMAPIUrl/rest/contacts",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendBody": true,
|
|
"bodyParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "email",
|
|
"value": "={{ $json.email }}"
|
|
},
|
|
{
|
|
"name": "name",
|
|
"value": "={{ $json.name }}"
|
|
},
|
|
{
|
|
"name": "city",
|
|
"value": ""
|
|
},
|
|
{
|
|
"name": "phone",
|
|
"value": ""
|
|
},
|
|
{
|
|
"name": "position",
|
|
"value": "={{ $json.donationLabel }}"
|
|
},
|
|
{
|
|
"name": "linkedinLink",
|
|
"value": ""
|
|
},
|
|
{
|
|
"name": "xLink",
|
|
"value": ""
|
|
},
|
|
{
|
|
"name": "introduction",
|
|
"value": ""
|
|
}
|
|
]
|
|
},
|
|
"options": {
|
|
"timeout": 10000,
|
|
"allowUnauthorizedCerts": false,
|
|
"redirect": {},
|
|
"response": {
|
|
"response": {
|
|
"responseFormat": "json"
|
|
}
|
|
}
|
|
},
|
|
"headers": {
|
|
"parameters": [
|
|
{
|
|
"name": "Content-Type",
|
|
"value": "application/json"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"notes": "SET ME: Replace the URL placeholder with your Twenty CRM instance URL (e.g., https://your-workspace.twenty.com). Configure the header auth credential with your Twenty CRM API key."
|
|
},
|
|
{
|
|
"id": "set-activity",
|
|
"name": "Twenty CRM - Log Note Activity",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [650, 480],
|
|
"credentials": {
|
|
"httpRequest": {
|
|
"id": "SET_ME_TwentyCRMApiKeyId",
|
|
"name": "Twenty CRM API Key"
|
|
}
|
|
},
|
|
"properties": {
|
|
"method": "POST",
|
|
"url": "SET_ME_TwentyCRMAPIUrl/rest/activityTargets",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendBody": true,
|
|
"bodyParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "title",
|
|
"value": "={{ $json.donationLabel + ' Donation - ' + $json.amountDisplay }}"
|
|
},
|
|
{
|
|
"name": "body",
|
|
"value": "={{ 'Donation from ' + $json.name + ' (' + $json.email + ')\\n' + 'Type: ' + $json.donationLabel + '\\n' + 'Amount: ' + $json.amountDisplay + '\\n' + 'Checkout ID: ' + $json.polarCheckoutId + '\\n' + 'Date: ' + $json.timestamp }}"
|
|
},
|
|
{
|
|
"name": "type",
|
|
"value": "Note"
|
|
},
|
|
{
|
|
"name": "visibility",
|
|
"value": "workspace"
|
|
}
|
|
]
|
|
},
|
|
"options": {
|
|
"timeout": 10000,
|
|
"allowUnauthorizedCerts": false,
|
|
"redirect": {},
|
|
"response": {
|
|
"responseFormat": "json"
|
|
}
|
|
},
|
|
"headers": {
|
|
"parameters": [
|
|
{
|
|
"name": "Content-Type",
|
|
"value": "application/json"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"notes": "SET ME: Same credential and URL base as above. This node logs a note activity for the contact."
|
|
},
|
|
{
|
|
"id": "noop-complete",
|
|
"name": "Done",
|
|
"type": "n8n-nodes-base.noOp",
|
|
"typeVersion": 1,
|
|
"position": [850, 300],
|
|
"properties": {}
|
|
}
|
|
],
|
|
"connections": {
|
|
"Polar Webhook": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Parse Polar Payload",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Parse Polar Payload": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Twenty CRM - Upsert Contact",
|
|
"type": "main",
|
|
"index": 0
|
|
},
|
|
{
|
|
"node": "Twenty CRM - Log Note Activity",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Twenty CRM - Upsert Contact": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Done",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Twenty CRM - Log Note Activity": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Done",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"pinData": {},
|
|
"settings": {
|
|
"executionOrder": "v1"
|
|
},
|
|
"staticData": null,
|
|
"tags": [],
|
|
"versionId": "1.0.0"
|
|
}
|