Hello Admins
Now upgraded to version 4.12 and I've been trying a lot to make my banking API integration work, but I'm struggling. Below is what I've been able to do. I need help... I'd be happy to give global admin access if needed.
Thanks very much in advance for your time and attention
Art
1. Created system record type to store the client id and secret
Name: Plaid Authentication
Internal name: plaidAuth
Display style: Single form
Record type fields
Client ID
Internal name: clientId
Data type: Single line text
Required: yes
Client Secret
Internal name: clientSecret
Data type: Single line text
Required: yes
Access Token
Internal name: accessToken
Data type: Single line text
Required:
Plaid Public Key
Internal name: publicKey
Data type: Single line text
Required:
Plaid Env
Internal name: plaidEnv
Data type: Single selection
Required:
Possible Values:
Sandbox
Internal name: sandbox
Development
Internal name: development
Production
Internal name: production
Plaid Country Codes
Internal name: countryCodes
Data type: Multiple selection
Required:
Possible Values:
US
Internal name: us
CA
Internal name: ca
FR
Internal name: fr
ES
Internal name: es
GB
Internal name: gb
Plaid Products
Internal name: plaidProducts
Data type: Multiple selection
Required:
Possible Values:
Auth
Internal name: auth
Transactions
Internal name: transactions
Identity
Internal name: identity
Income
Internal name: income
Assets
Internal name: assets
Node
Internal name: node
Data type: Single line text
Required:
2. Created user record type to store each financial institution account link information
Name: Institution Link
Internal name: institutionLink
Display style: List
Show in Menu: yes
Record type fields
Institution Name
Internal name: institutionName
Data type: Single line text
Required:
Institution Id
Internal name: institutionId
Data type: Single line text
Required:
Item ID
Internal name: itemId
Data type: Single line text
Required:
Account Name
Internal name: accountName
Data type: Single line text
Required:
Account Type
Internal name: accountType
Data type: Single selection
Required:
Possible Values:
Checking
Internal name: checking
Savings
Internal name: savings
Account Number
Internal name: accountNumber
Data type: Single line text
Required:
Routing Number (US only)
Internal name: routingNumber
Data type: Single line text
Required:
Institution Number (CA only)
Internal name: institutionNumber
Data type: Single line text
Required:
BIC
Internal name:
Data type: bic
Required:
IBAN
Internal name: iban
Data type: Single line text
Required:
Bank Sort Code
Internal name: bankSortCode
Data type: Single line text
Required:
3. Began with the the library script
Name: Plaid
Type: Library
Included libraries: none
Parameters:
Code: Select all
# Settings for the access token record type
auth.recordType = plaidAuth
auth.clientId = clientId
auth.clientSecret = clientSecret
auth.token = accessToken
auth.publicKey = publicKey
# Settings for Plaid
plaidEnv = plaidEnv
countryCodes = countryCodes
products = plaidProducts
node = index.js
# Settings for the Plaid Link record type
link.recordType = plaidLink
link.institutionId = institutionId
link.institutionName = institutionName
link.accountType = accountName
link.accountName = accountType
link.accountNumber = accountNumber
link.accountRouting = routingNumber
link.accountInstitutionNum = institutionNumber
link.accountBIC = bic
link.accountIBAN = iban
link.accountSortCode = sort_code
# Messages
error.invalidRequest = Invalid request
error.itemLoginRequired = Login required
error.itemNotSupported = Item not supported
error.mfaNotSupported = Multi-function authentication method used is not supported
error.noAccounts = There are no accounts associated with you at this institution
error.productNotReady = We are still pulling your account information from this financial institution. Please try again after a few seconds
Script code: This is where I'm struggling most and hoping I can get some help to move this forward
Code: Select all
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import groovyx.net.http.HTTPBuilder
import java.util.concurrent.CountDownLatch
import org.apache.commons.codec.binary.Base64
import org.cyclos.entities.banking.PaymentTransferType
import org.cyclos.entities.banking.SystemAccountType
import org.cyclos.entities.users.RecordCustomField
import org.cyclos.entities.users.SystemRecord
import org.cyclos.entities.users.SystemRecordType
import org.cyclos.entities.users.User
import org.cyclos.entities.users.UserRecord
import org.cyclos.entities.users.UserRecordType
import org.cyclos.impl.banking.PaymentServiceLocal
import org.cyclos.impl.system.ScriptHelper
import org.cyclos.impl.users.RecordServiceLocal
import org.cyclos.impl.utils.persistence.EntityManagerHandler
import org.cyclos.model.EntityNotFoundException
import org.cyclos.model.banking.accounts.SystemAccountOwner
import org.cyclos.model.banking.transactions.PaymentVO
import org.cyclos.model.banking.transactions.PerformPaymentDTO
import org.cyclos.model.banking.transfertypes.TransferTypeVO
import org.cyclos.model.users.records.RecordDataParams
import org.cyclos.model.users.records.UserRecordDTO
import org.cyclos.model.users.recordtypes.RecordTypeVO
import org.cyclos.model.users.users.UserLocatorVO
import org.cyclos.utils.ParameterStorage
/**
* Class used to store / retrieve the authentication information for Plaid
* A system record type is used, with the following fields: client id (string),
* client secret (string), and access token (string)
*/
class PlaidAuth {
String recordTypeName
String clientIdName
String clientSecretName
String accessTokenName
SystemRecordType recordType
SystemRecord record
Map<String, Object> wrapped
public PlaidAuth(Object binding) {
def params = binding.scriptParameters
recordTypeName = params.'auth.recordType' ?: 'plaidAuth'
clientIdName = params.'auth.clientId' ?: 'clientId'
clientSecretName = params.'auth.clientSecret' ?: 'clientSecret'
accessTokenName = params.'auth.accessToken' ?: 'accessToken'
// Read the record type and the parameters for field internal names
recordType = binding.entityManagerHandler
.find(SystemRecordType, recordTypeName)
// Should return the existing instance, of a single form type.
// Otherwise it would be an error
record = binding.recordService.newEntity(
new RecordDataParams(recordType: new RecordTypeVO(id: recordType.id)))
if (!record.persistent) throw new IllegalStateException(
"No instance of system record ${recordType.name} was found")
wrapped = binding.scriptHelper.wrap(record, recordType.fields)
}
public String getClientId() {
wrapped[clientIdName]
}
public String getClientSecret() {
wrapped[clientSecretName]
}
public String getAccessToken() {
wrapped[accessTokenName]
}
public void setClientId(String clientId) {
wrapped[clientIdName] = clientId
}
public void setClientSecret(String clientSecret) {
wrapped[clientSecretName] = clientSecret
}
public void setAccessToken(String accessToken) {
wrapped[tokenName] = accessToken
}
}
// Instantiate the objects
PlaidAuth auth = new PlaidAuth(binding)
PlaidRecord record = new PlaidRecord(binding)
PlaidService plaid = new PlaidService(binding, auth, record)
/**
* Class used to store / retrieve Plaid items as user records in Cyclos
*/
class PlaidRecord {
String recordTypeName
String itemIdName
String accoutName
String accoutTypeName
String accoutNumberName
String routingNumberName
String institutionNumberName
String bicName
String ibanName
String sortCodeName
UserRecordType recordType
Map<String, RecordCustomField> fields
private EntityManagerHandler entityManagerHandler
private RecordServiceLocal recordService
private ScriptHelper scriptHelper
public PlaidRecord(Object binding) {
def params = binding.scriptParameters
recordTypeName = params.'link.recordType' ?: 'plaidLink'
institutionNameName = params.'link.institutionName' ?: 'institutionName'
institutionIdName = params.'link.institutionId' ?: 'institutionId'
itemIdName = params.'link.itemId' ?: 'itemId'
entityManagerHandler = binding.entityManagerHandler
recordService = binding.recordService
scriptHelper = binding.scriptHelper
recordType = binding.entityManagerHandler.find(UserRecordType, recordTypeName)
fields = [:]
recordType.fields.each {f -> fields[f.internalName] = f}
}
/**
* Creates a Plaid Link record, for the given user and JSON,
* as returned from Plaid's create link REST method???
*/