How to implement Payment SDK
Algorithms
There are five algorithms you must create
initialize_payment
- Create an algorithm called initialize_payment with a parameter called params

- Write your code in the code block

There are three main components you need to make the algorithm work.
- Settings object
- Payment object
- Response method
Tenant.notify(message: "Initialize Example payment", type: :info)
Tenant.notify(message: "#{params}", type: :info)
# params will contain fields
# - payment = Payment object
# get settings from the Settings datatype
setting = get_setting("EXAMPLE_SETTINGS")
# get Payment object for transaction
payment = params["payment"]
# print to the notification log
Tenant.notify(message: "Payment #{payment.to_hash}", type: :info)
# Example of how to use a template as the response
{
"action" => "render",
"template" => "Example::Example Payment Page",
"data" => {
"referenceId" => payment["referenceId"],
"transId" => SecureRandom.uuid(),
"amount" => payment["transactionData"]["amount"]
}
}
# Example of how to send data to user page
#{
# "action" => "return",
# "data" => page
#}
# Example of how to redirect to another site
#{
# "action" => "redirect",
# "redirect_to" => "http://urltohostedpayments"
# }
a. Get Settings object - To retrieve the record from the Settings datatype, call the get_setting algorithm
and pass the name of the record
setting = get_setting("EXAMPLE_SETTINGS")
b. Get Payment object - retrieve the Payment object that is sent to the algorithm through
params
payment = params["payment"]
c. Response method - There are three options for a response method:
- Render a template
{
"action" => "render",
"template" => "Example::Example Payment Page",
"data" => {
"referenceId" => payment["referenceId"],
"transId" => SecureRandom.uuid(),
"amount" => payment["transactionData"]["amount"]
}
}
- Send data to user page
{
"action" => "return",
"data" => page
}
- Redirect to another site
{
"action" => "redirect",
"redirect_to" => "http://urltohostedpayments"
}
- Save the algorithm once completed.
process_payment
- Create an algorithm called process_payment with a parameter called params

- Write your code in the code block

Tenant.notify(message: "Process Example process_payment", type: :info)
Tenant.notify(message: "#{params}", type: :info)
begin
# lookup the Payment entry by referenceId
payment = get_payment(params["referenceId"])
if payment.nil?
Cenit.fail("No Payment entry found for referenceId #{params["referenceId"]}")
end
# Check if the current status is Pending Payment and apply payment if so
if payment["transactionStatus"].casecmp?("Pending Payment")
# update the transactionStatus to either Approved or Failed
status = ""
if params["status"].eql?("APR")
status = "Approved"
end
payment["transactionStatus"] = status
# update the transactionId with the response from the payment provider
payment["transactionId"] = params["transId"]
# save any parameters sent back from the payment provider for later use
payment["transactionData"] = params
# add the payment provider transaction id as the transactionData.referenceId
payment["transactionData"]["referenceId"] = params["transId"]
# set the transactionData.payee to the info returned from the payment provider
payment["transactionData"]["payee"] = "#{params["payeeFirstname"]} #{params["payeeLastname"]}"
# set the transactionData.payee to the info returned from the payment provider
payment["transactionData"]["payeeAddress"] = "#{params["payeeAddress"]}"
# optionally build a URL to the paymnet providers detail page
payment["transactionData"]["detailURL"] = "https://paymentprovider/detail"
# set the transactionData.type
payment["transactionData"]["type"] = "Credit Card"
# payment["transactionData"]["type"] = "Check"
# optionally set the convenience or service fee charged by the payment provder
#payment["transactionData"]["convFee"] = 0
# save the payment
payment = save_payment(payment)
# return a success message as required by the payment provider
#{
# "action"=> "return",
# "code"=> "200",
# "data"=> "Payment completed successfully"
#}
# redirect to transactionData.redirectURL which
# will exist on the Payment after calling save_payment with the
# transactionStatus of Approved or Failed
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
elsif payment["transactionStatus"].casecmp?("Approved") || payment["transactionStatus"].casecmp?("Failed")
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
else
{
"action"=> "return",
"code"=> "500",
"data"=> "Payment in invalid state of #{payment["transactionStatus"]} for further actions"
}
end
rescue StandardError => ex
code = ex.message =~ /^\[(\d+)\]/ ? $1.to_i : 500
message = ex.message.gsub(/^\[(\d+)\] - /, '')
{
"action"=> "return",
"code"=> code,
"data"=> message
}
end
a. Lookup Payment record
- Begin the algorithm by looking up the Payment record by the referenceId
payment = get_payment(params["referenceId"])
- Add an if statement to check if the response from get_payment is null and to end the execution if it is
if payment.nil?
Cenit.fail("No Payment entry found for referenceId #{params["referenceId"]}")
end
b. Check if current status is Pending
- Check if the current status is Pending Payment and apply payment if so
if payment["transactionStatus"].casecmp?("Pending Payment")
- Update the transactionStatus to either Approved or Failed
status = ""
if params["status"].eql?("APR")
status = "Approved"
end
payment["transactionStatus"] = status
- Update the transactionId with the response from the payment provider
payment["transactionId"] = params["transId"]
- Save any parameters sent back from the payment provider for later use
payment["transactionData"] = params
- Add the payment provider transaction id as the transactionData.referenceId
payment["transactionData"]["referenceId"] = params["transId"]
- Set the transactionData.payee to the info returned from the payment provider
payment["transactionData"]["payee"] = "#{params["payeeFirstname"]} #{params["payeeLastname"]}"
- Set the transactionData.payeeAddress to the info returned from the payment provider
payment["transactionData"]["payeeAddress"] = "#{params["payeeAddress"]}"
- Optionally build a URL to the payment providers detail page
payment["transactionData"]["detailURL"] = "https://paymentprovider/detail"
- Set the transactionData.type
payment["transactionData"]["type"] = "Credit Card"
OR
payment["transactionData"]["type"] = "Check"
- Optionally set the convenience or service fee charged by the payment provder
payment["transactionData"]["convFee"] = 0
- Save the payment
payment = save_payment(payment)
c. Redirect to transactionData.redirectURL which will exist on the Payment after calling save_payment with the transactionStatus of Approved or Failed
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
elsif payment["transactionStatus"].casecmp?("Approved") || payment["transactionStatus"].casecmp?("Failed")
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
else
{
"action"=> "return",
"code"=> "500",
"data"=> "Payment in invalid state of #{payment["transactionStatus"]} for further actions"
}
end
d. Ending code
rescue StandardError => ex
code = ex.message =~ /^\[(\d+)\]/ ? $1.to_i : 500
message = ex.message.gsub(/^\[(\d+)\] - /, '')
{
"action"=> "return",
"code"=> code,
"data"=> message
}
end
payment_confirmation
- Create an algorithm called payment_confirmation with a parameter called params

- Write your code in the code block

Tenant.notify(message: "Process Example payment_confirmation", type: :info)
Tenant.notify(message: "#{params}", type: :info)
begin
# lookup the Payment entry by referenceId
payment = get_payment(params["referenceId"])
if payment.nil?
Cenit.fail("No Payment entry found for referenceId #{params["referenceId"]}")
end
# Check if the Payment is Approved or Failed and redirect
if payment["transactionStatus"].casecmp?("Approved") || payment["transactionStatus"].casecmp?("Failed")
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
else
{
"action"=> "return",
"code"=> "500",
"data"=> "Payment in invalid state of #{payment["transactionStatus"]} for further actions"
}
end
rescue StandardError => ex
code = ex.message =~ /^\[(\d+)\]/ ? $1.to_i : 500
message = ex.message.gsub(/^\[(\d+)\] - /, '')
{
"action"=> "return",
"code"=> code,
"data"=> message
}
end
a. Similarly to the process_payment algorithm, begin payment_confirmation by looking up the Payment record by referenceId and check if it is null
payment = get_payment(params["referenceId"])
if payment.nil?
Cenit.fail("No Payment entry found for referenceId #{params["referenceId"]}")
end
b. Check if the Payment status is Approved or Failed and redirect
if payment["transactionStatus"].casecmp?("Approved") || payment["transactionStatus"].casecmp?("Failed")
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
else
{
"action"=> "return",
"code"=> "500",
"data"=> "Payment in invalid state of #{payment["transactionStatus"]} for further actions"
}
end
c. End code
rescue StandardError => ex
code = ex.message =~ /^\[(\d+)\]/ ? $1.to_i : 500
message = ex.message.gsub(/^\[(\d+)\] - /, '')
{
"action"=> "return",
"code"=> code,
"data"=> message
}
end
- Save algorithm once completed.
cancel_payment
- Create an algorithm called cancel_payment with a parameter called params

- Write your code in the code block

Tenant.notify(message: "Process Example cancel_payment", type: :info)
Tenant.notify(message: "#{params}", type: :info)
payment = get_payment(params["referenceId"])
if payment.nil?
Cenit.fail("No Payment entry found for referenceId #{params["referenceId"]}")
end
payment["transactionStatus"] = "Cancel"
payment["transactionId"] = params["SECURETOKENID"]
payment["transactionData"] = params
payment = save_payment(payment)
if payment["transactionData"]["redirectURL"]
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
else
{
"action"=> "return",
"code"=> "200",
"data"=> "Payment cancelled"
}
end
a. Lookup Payment record by reference Id and check if it is null or not
payment = get_payment(params["referenceId"])
if payment.nil?
Cenit.fail("No Payment entry found for referenceId #{params["referenceId"]}")
end
b. Set Payment record details and save Payment
payment["transactionStatus"] = "Cancel"
payment["transactionId"] = params["SECURETOKENID"]
payment["transactionData"] = params
payment = save_payment(payment)
c. Set redirect
if payment["transactionData"]["redirectURL"]
{
"action" => "redirect",
"redirect_to" => payment["transactionData"]["redirectURL"]
}
else
{
"action"=> "return",
"code"=> "200",
"data"=> "Payment cancelled"
}
end
- Save algorithm
Using the SDK
- Go to laserfiche.velosimo.com and login
- Open your forms Process Designer Diagram and show details
- Select start in the diagram and the On Event Completion tab

- Set redirect to website and the URL to the initialize_payment algorithm on the Velosimo site.
Example - https://dev.velosimo.io/app/payment_adapter/laserfiche/example/initialize_payment
payment_adapter = Velosimo tenant
example = Velosimo namespace
initialize_payment = Algorithm

- Submit a new form. Once submitted you will be redirected to an environment where you can test each algorithm created.

a. Click Simulate Approved Postback

Updated almost 3 years ago