For Zoho Services only:


I'm actually part of something bigger at Ascent Business Solutions recognized as the top Zoho Premium Solutions Partner in the United Kingdom.

Ascent Business Solutions offer support for smaller technical fixes and projects for larger developments, such as migrating to a ZohoCRM.  A team rather than a one-man-band is always available to ensure seamless progress and address any concerns. You'll find our competitive support rates with flexible, no-expiration bundles at http://ascentbusiness.co.uk/zoho-support-2.  For larger projects, check our bespoke pricing structure and receive dedicated support from our hands-on project consultants and developers at http://ascentbusiness.co.uk/crm-solutions/zoho-crm-packages-prices.

The team I manage specializes in coding API integrations between Zoho and third-party finance/commerce suites such as Xero, Shopify, WooCommerce, and eBay; to name but a few.  Our passion lies in creating innovative solutions where others have fallen short as well as working with new businesses, new sectors, and new ideas.  Our success is measured by the growth and ROI we deliver for clients, such as transforming a garden shed hobby into a 250k monthly turnover operation or generating a +60% return in just three days after launch through online payments and a streamlined e-commerce solution, replacing a paper-based system.

If you're looking for a partner who can help you drive growth and success, we'd love to work with you.  You can reach out to us on 0121 392 8140 (UK) or info@ascentbusiness.co.uk.  You can also visit our website at http://ascentbusiness.co.uk.

ZohoBooks: Stripe Terminal Integration

What?
A quick article on some code added to a button in ZohoBooks off the invoice module to initiate your Stripe terminal to take a payment.

Why?
Just to make it easy on the staff at a counter or on the phone. They bring up the invoie in ZohoBooks, click on the button, and the Stripe terminal will ask for the amount on the invoice.

Well almost. We've gone the extra step in that we added a custom field that can override the full balance, to allow partial payments such as a deposit or instalment.

How?
I won't go in to how to create a button in ZohoBooks but you simply add it to the invoice and then when it prompts for some code, you give it the snippet below.

The Magic
You would create a button for each terminal
copyraw
/* *******************************************************************************
Function:       Map Take_Payment( Map invoice, Map organization, Map user)
Label:          Take Payment
Trigger:        On button click
Purpose:		Preps stripe terminal to take payment for balance of invoice.
Inputs:         invoice
Outputs:        -

Date Created:   2023-02-24 
                - Initial release
				- Reads Books Invoice and sends the amount to the reader for a payment atempt
Date Modified:	2023-02-24 (Joel Lipman)
                - If custom field "Amount To Be Taken" is not greater than zero, then defaults to balance due of invoice.

More Information:
		TEST PAYMENT SCENARIOS WITH PHYSICAL TEST CARD 
		// Send in as payment endings: eg. $100.00 == payment approved
		00 Payment Approved
		01 Payment Declined // call issuer code
		05 Payment Declined Generic
		55 Payment Declined Incorrect Pin
		65 Payment Declined withdrawal_count_limit_exceeded
		75 Pin try exceeded

******************************************************************************* */
v_BooksOrgID = organization.get("organization_id");
//
// some Stripe variables (add your own here)
v_StripeTerminalID = "tmr_ABCDEFGabcdefg";
v_StripeCustomerKey = "sk_live_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
V_StripeLocationsEndpoint = " https://api.stripe.com/v1/terminal/locations";
//
// set Stripe header
m_Headers = Map();
m_Headers.put("Authorization","Bearer " + v_StripeCustomerKey);
//
// default to balance due on this Invoice
v_AmountToPay = ifnull(invoice.get("balance"),0);
//
// Get custom Amount to Pay from Invoice
l_CustomFields = invoice.get("custom_fields");
if(l_CustomFields.size() > 0)
{
	for each  m_CustomField in l_CustomFields
	{
		if(m_CustomField.get("label") == "Amount To Be Taken")
		{
			if(m_CustomField.get("value") > 0)
			{
				v_AmountToPay = m_CustomField.get("value");
			}
		}
	}
}
//
// format to Stripe amount
v_AmountToPay = v_AmountToPay.truncate(2);
v_StripeAmount = v_AmountToPay * 100;
v_StripeAmount = v_StripeAmount.floor();
v_StripeAmount = v_StripeAmount.toNumber();
info v_StripeAmount;
//
// Create payment intent in Stripe
v_PaymentIntentEndpoint = "https://api.stripe.com/v1/payment_intents";
m_Params = Map();
m_Params.put("amount",v_StripeAmount);
m_Params.put("currency","gbp");
//m_Params.put("automatic_payment_methods[enabled]", false);
m_Params.put("payment_method_types[]","card_present");
m_Params.put("capture_method","manual");
v_DescriptionString = "IN: " + invoice.get("invoice_number") + " ID: " + invoice.get("invoice_id");
m_Params.put("description",v_DescriptionString);
// Later Add Code to  "customer_id": "123456700000001234567", get customer id then Email
v_BooksCustomerID = invoice.get("customer_id");
r_CustomerDetails = zoho.books.getRecordsByID("contacts",v_BooksOrgID,v_BooksCustomerID,"zbooks");
v_CustomerCheckCode = r_CustomerDetails.get("code");
if(v_CustomerCheckCode == 0)
{
	m_ContactDetails = r_CustomerDetails.get("contact");
	if(m_ContactDetails != null)
	{
		m_Params.put("receipt_email",m_ContactDetails.get("email"));
	}
}
r_CreatePaymentIntent = invokeurl
[
	url :v_PaymentIntentEndpoint
	type :POST
	parameters:m_Params
	headers:m_Headers
];
info "Payment Intent Create";
info r_CreatePaymentIntent;
//
v_CheckObject = ifnull(r_CreatePaymentIntent.get("object"),"-");
v_CheckAmount = ifnull(r_CreatePaymentIntent.get("amount"),"-");
//
// Process Payment Intent
if(v_CheckObject == "payment_intent")
{
	v_PaymentIntentID = r_CreatePaymentIntent.get("id");
	info "Payment Intent Created Successfuly!!! ID: ";
	info v_PaymentIntentID;
	//
	// Hand Off Payment Intent to Reader
	v_ReaderHandOffEndpoint = "https://api.stripe.com/v1/terminal/readers/" + v_StripeTerminalID + "/process_payment_intent";
	m_PaymentHandOffParams = Map();
	m_PaymentHandOffParams.put("payment_intent",v_PaymentIntentID);
	r_ReaderPaymentHandOff = invokeurl
	[
		url :v_ReaderHandOffEndpoint
		type :POST
		parameters:m_PaymentHandOffParams
		headers:m_Headers
	];
	info r_ReaderPaymentHandOff;
}
return r_ReaderPaymentHandOff;
  1.  /* ******************************************************************************* 
  2.  Function:       Map Take_Payment( Map invoice, Map organization, Map user) 
  3.  Label:          Take Payment 
  4.  Trigger:        On button click 
  5.  Purpose:        Preps stripe terminal to take payment for balance of invoice. 
  6.  Inputs:         invoice 
  7.  Outputs:        - 
  8.   
  9.  Date Created:   2023-02-24 
  10.                  - Initial release 
  11.                  - Reads Books Invoice and sends the amount to the reader for a payment atempt 
  12.  Date Modified:    2023-02-24 (Joel Lipman) 
  13.                  - If custom field "Amount To Be Taken" is not greater than zero, then defaults to balance due of invoice. 
  14.   
  15.  More Information: 
  16.          TEST PAYMENT SCENARIOS WITH PHYSICAL TEST CARD 
  17.          // Send in as payment endings: eg. $100.00 == payment approved 
  18.          00 Payment Approved 
  19.          01 Payment Declined // call issuer code 
  20.          05 Payment Declined Generic 
  21.          55 Payment Declined Incorrect Pin 
  22.          65 Payment Declined withdrawal_count_limit_exceeded 
  23.          75 Pin try exceeded 
  24.   
  25.  ******************************************************************************* */ 
  26.  v_BooksOrgID = organization.get("organization_id")
  27.  // 
  28.  // some Stripe variables (add your own here) 
  29.  v_StripeTerminalID = "tmr_ABCDEFGabcdefg"
  30.  v_StripeCustomerKey = "sk_live_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  31.  V_StripeLocationsEndpoint = " https://api.stripe.com/v1/terminal/locations"
  32.  // 
  33.  // set Stripe header 
  34.  m_Headers = Map()
  35.  m_Headers.put("Authorization","Bearer " + v_StripeCustomerKey)
  36.  // 
  37.  // default to balance due on this Invoice 
  38.  v_AmountToPay = ifnull(invoice.get("balance"),0)
  39.  // 
  40.  // Get custom Amount to Pay from Invoice 
  41.  l_CustomFields = invoice.get("custom_fields")
  42.  if(l_CustomFields.size() > 0) 
  43.  { 
  44.      for each  m_CustomField in l_CustomFields 
  45.      { 
  46.          if(m_CustomField.get("label") == "Amount To Be Taken") 
  47.          { 
  48.              if(m_CustomField.get("value") > 0) 
  49.              { 
  50.                  v_AmountToPay = m_CustomField.get("value")
  51.              } 
  52.          } 
  53.      } 
  54.  } 
  55.  // 
  56.  // format to Stripe amount 
  57.  v_AmountToPay = v_AmountToPay.truncate(2)
  58.  v_StripeAmount = v_AmountToPay * 100
  59.  v_StripeAmount = v_StripeAmount.floor()
  60.  v_StripeAmount = v_StripeAmount.toNumber()
  61.  info v_StripeAmount; 
  62.  // 
  63.  // Create payment intent in Stripe 
  64.  v_PaymentIntentEndpoint = "https://api.stripe.com/v1/payment_intents"
  65.  m_Params = Map()
  66.  m_Params.put("amount",v_StripeAmount)
  67.  m_Params.put("currency","gbp")
  68.  //m_Params.put("automatic_payment_methods[enabled]", false)
  69.  m_Params.put("payment_method_types[]","card_present")
  70.  m_Params.put("capture_method","manual")
  71.  v_DescriptionString = "IN: " + invoice.get("invoice_number") + " ID: " + invoice.get("invoice_id")
  72.  m_Params.put("description",v_DescriptionString)
  73.  // Later Add Code to  "customer_id": "123456700000001234567", get customer id then Email 
  74.  v_BooksCustomerID = invoice.get("customer_id")
  75.  r_CustomerDetails = zoho.books.getRecordsByID("contacts",v_BooksOrgID,v_BooksCustomerID,"zbooks")
  76.  v_CustomerCheckCode = r_CustomerDetails.get("code")
  77.  if(v_CustomerCheckCode == 0) 
  78.  { 
  79.      m_ContactDetails = r_CustomerDetails.get("contact")
  80.      if(m_ContactDetails != null) 
  81.      { 
  82.          m_Params.put("receipt_email",m_ContactDetails.get("email"))
  83.      } 
  84.  } 
  85.  r_CreatePaymentIntent = invokeUrl 
  86.  [ 
  87.      url :v_PaymentIntentEndpoint 
  88.      type :POST 
  89.      parameters:m_Params 
  90.      headers:m_Headers 
  91.  ]
  92.  info "Payment Intent Create"
  93.  info r_CreatePaymentIntent; 
  94.  // 
  95.  v_CheckObject = ifnull(r_CreatePaymentIntent.get("object"),"-")
  96.  v_CheckAmount = ifnull(r_CreatePaymentIntent.get("amount"),"-")
  97.  // 
  98.  // Process Payment Intent 
  99.  if(v_CheckObject == "payment_intent") 
  100.  { 
  101.      v_PaymentIntentID = r_CreatePaymentIntent.get("id")
  102.      info "Payment Intent Created Successfuly!!! ID: "
  103.      info v_PaymentIntentID; 
  104.      // 
  105.      // Hand Off Payment Intent to Reader 
  106.      v_ReaderHandOffEndpoint = "https://api.stripe.com/v1/terminal/readers/" + v_StripeTerminalID + "/process_payment_intent"
  107.      m_PaymentHandOffParams = Map()
  108.      m_PaymentHandOffParams.put("payment_intent",v_PaymentIntentID)
  109.      r_ReaderPaymentHandOff = invokeUrl 
  110.      [ 
  111.          url :v_ReaderHandOffEndpoint 
  112.          type :POST 
  113.          parameters:m_PaymentHandOffParams 
  114.          headers:m_Headers 
  115.      ]
  116.      info r_ReaderPaymentHandOff; 
  117.  } 
  118.  return r_ReaderPaymentHandOff; 

The incoming webhook
You now need to receive the Stripe webhook when it comes back into ZohoBooks to record it against the invoice. Note how we added the invoice reference and Zoho ID in the description of the payment capture in our previous bit of code:
copyraw
/* *******************************************************************************
Function:       Map stripe_terminal_payment( Map invoice, Map organization, Map user)
Label:          stripe_terminal_payment
Trigger:        Incoming Webhook
Purpose:		Listens for stripe terminal payments.
OAuth URL:		https://www.zohoapis.com/books/v3/settings/incomingwebhooks/iw_stripe_terminal_payment/execute?auth_type=oauth
Inputs:         invoice
Outputs:        -

Date Created:   2023-03-23 
                - Initial release
				- been successfully proccessed by the physical reader
Date Modified:	2024-05-21 (Joel Lipman)
                - Revamp of code as per best practices
                - Correct error: Check and update the code in line 74 as there is a Exception : Value is empty and 'get' function cannot be applied

More Information:
		Navigate to payments, then find pending webhook response event, terminal.reader.action_succeeded, then view event details

******************************************************************************* */
//
// initialize
m_Blank = Map();
m_Response = Map();
v_BooksOrgID = organization.get("organization_id");
//
// Stripe API Key (add your own here)
v_StripeCustomerKey = "sk_live_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//
// set Stripe header
m_Headers = Map();
m_Headers.put("Authorization","Bearer " + v_StripeCustomerKey);
//
// capture response webhook
m_Webhook = Map();
m_Webhook.put("data",body.get("data"));
m_Webhook.put("type",body.get("type"));
//
// Check Type 
m_Data = ifnull(m_Webhook.get("data"),m_Blank);
v_Type = ifnull(m_Webhook.get("type"),"-");
if(v_Type == "terminal.reader.action_succeeded")
{
	// Get Payment Intent that needs to be Captured
	m_Object = m_Data.get("object");
	m_Action = m_Object.get("action");
	m_ProcessPaymentIntent = m_Action.get("process_payment_intent");
	v_PaymentIntentID = m_ProcessPaymentIntent.get("payment_intent");
	//
	// Retrieve details on the Payment Intent
	v_PaymentIntentEndpoint = "https://api.stripe.com/v1/payment_intents/" + v_PaymentIntentID;
	r_PaymentIntentDetails = invokeurl
	[
		url :v_PaymentIntentEndpoint
		type :GET
		headers:m_Headers
	];
	//
	// get amount (used to capture payment intent)
	v_Amount = ifnull(r_PaymentIntentDetails.get("amount"),0);
	v_AmountReceived = ifnull(r_PaymentIntentDetails.get("amount_received"),0);
	v_AmountCapturable = ifnull(r_PaymentIntentDetails.get("amount_capturable"),0);
	v_CaptureIntentEndpoint = "https://api.stripe.com/v1/payment_intents/" + v_PaymentIntentID + "/capture";
	m_CaptureParams = Map();
	m_CaptureParams.put("amount_to_capture",v_AmountCapturable);
	r_CapturePayment = invokeurl
	[
		url :v_CaptureIntentEndpoint
		type :POST
		parameters:m_CaptureParams
		headers:m_Headers
	];
	//
	// get card details (we need to store last 4 digits)
	v_StripeReference = "";
	v_Last4Digits = "";
	v_ZB_InvoiceID = 0;
	m_Charges = ifnull(r_PaymentIntentDetails.get("charges"),m_Blank);
	l_Data = ifnull(m_Charges.get("data"),{});
	for each  m_Data in l_Data
	{
		if(m_Data.get("id") != null)
		{
			v_StripeReference = m_Data.get("id");
		}
		if(m_Data.get("payment_method_details") != null)
		{
			m_CardPresent = ifnull(m_Data.get("payment_method_details").get("card_present"),m_Blank);
			v_Last4Digits = ifnull(m_CardPresent.get("last4"),"");
		}
		if(m_Data.get("description") != null)
		{
			v_ChargeDescription = ifnull(m_Data.get("description"),"");
			v_ZB_InvoiceID = v_ChargeDescription.getSuffix("ID: ");
			v_ZB_InvoiceID = if(isNumber(v_ZB_InvoiceID),v_ZB_InvoiceID,0).toLong();
		}
	}
	//
	// create payment record
	if(v_ZB_InvoiceID != 0)
	{
		//
		// get ZohoBooks nominal account for Stripe
		v_NominalAccountID = "";
		r_ChartOfAccounts = invokeurl
		[
			url :"https://www.zohoapis.com/books/v3/chartofaccounts?organization_id=" + v_BooksOrgID
			type :GET
			connection:"zbooks"
		];
		if(r_ChartOfAccounts.get("chartofaccounts") != null)
		{
			for each  m_NomAccount in r_ChartOfAccounts.get("chartofaccounts")
			{
				if(m_NomAccount.get("account_name").equalsIgnoreCase("Stripe Clearing"))
				{
					v_NominalAccountID = m_NomAccount.get("account_id");
				}
			}
		}
		//
		// retrieve invoice details from ZohoBooks
		r_InvoiceDetails = zoho.books.getRecordsByID("invoices",v_BooksOrgID,v_ZB_InvoiceID,"zbooks");
		m_Invoice = ifnull(r_InvoiceDetails.get("invoice"),m_Blank);
		if(m_Invoice.get("customer_id") != null)
		{
			m_CreatePayment = Map();
			m_CreatePayment.put("customer_id",m_Invoice.get("customer_id"));
			m_CreatePayment.put("payment_mode","In Person - Card");
			m_CreatePayment.put("amount",v_AmountReceived / 100);
			m_CreatePayment.put("date",zoho.currentdate.toString("yyyy-MM-dd"));
			//
			l_Invoices = List();
			m_ThisInvoice = Map();
			m_ThisInvoice.put("invoice_id",v_ZB_InvoiceID.toString());
			m_ThisInvoice.put("amount_applied",v_AmountReceived / 100);
			l_Invoices.add(m_ThisInvoice);
			m_CreatePayment.put("invoices",l_Invoices);
			m_CreatePayment.put("invoice_id",v_ZB_InvoiceID.toString());
			m_CreatePayment.put("amount_applied",v_AmountReceived / 100);
			//
			v_PaymentRef = if(v_StripeReference=="", m_Invoice.get("invoice_number"), v_StripeReference);
			m_CreatePayment.put("reference_number",v_PaymentRef);
			m_CreatePayment.put("account_id",v_NominalAccountID);
			//info m_CreatePayment;
			//
			r_CreatePayment = zoho.books.createRecord("customerpayments",v_BooksOrgID,m_CreatePayment,"zbooks");
			//info r_CreatePayment;
			if(r_CreatePayment.get("message") != null)
			{
				if(r_CreatePayment.get("message").contains("payment has been created"))
				{
					//
					// update the invoice (request by client to store last 4 digits on invoice)
					l_CustomFields = List();
					m_CustomField = Map();
					m_CustomField.put("api_name","cf_last_4_digits");
					m_CustomField.put("value",v_Last4Digits);
					l_CustomFields.add(m_CustomField);
					m_UpdateInvoice = Map();
					m_UpdateInvoice.put("custom_fields",l_CustomFields);
					r_UpdateInvoice = zoho.books.updateRecord("Invoices",v_BooksOrgID,v_ZB_InvoiceID,m_UpdateInvoice,"zbooks");
				}
			}
		}
	}
}
m_Response.put("message",r_CreatePayment.get("message"));
m_Response.put("code",0);
return m_Response;
  1.  /* ******************************************************************************* 
  2.  Function:       Map stripe_terminal_payment( Map invoice, Map organization, Map user) 
  3.  Label:          stripe_terminal_payment 
  4.  Trigger:        Incoming Webhook 
  5.  Purpose:        Listens for stripe terminal payments. 
  6.  OAuth url:        https://www.zohoapis.com/books/v3/settings/incomingwebhooks/iw_stripe_terminal_payment/execute?auth_type=oauth 
  7.  Inputs:         invoice 
  8.  Outputs:        - 
  9.   
  10.  Date Created:   2023-03-23 
  11.                  - Initial release 
  12.                  - been successfully proccessed by the physical reader 
  13.  Date Modified:    2024-05-21 (Joel Lipman) 
  14.                  - Revamp of code as per best practices 
  15.                  - Correct error: Check and update the code in line 74 as there is a Exception : Value is empty and 'get' function cannot be applied 
  16.   
  17.  More Information: 
  18.          Navigate to payments, then find pending webhook response event, terminal.reader.action_succeeded, then view event details 
  19.   
  20.  ******************************************************************************* */ 
  21.  // 
  22.  // initialize 
  23.  m_Blank = Map()
  24.  m_Response = Map()
  25.  v_BooksOrgID = organization.get("organization_id")
  26.  // 
  27.  // Stripe API Key (add your own here) 
  28.  v_StripeCustomerKey = "sk_live_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  29.  // 
  30.  // set Stripe header 
  31.  m_Headers = Map()
  32.  m_Headers.put("Authorization","Bearer " + v_StripeCustomerKey)
  33.  // 
  34.  // capture response webhook 
  35.  m_Webhook = Map()
  36.  m_Webhook.put("data",body.get("data"))
  37.  m_Webhook.put("type",body.get("type"))
  38.  // 
  39.  // Check Type 
  40.  m_Data = ifnull(m_Webhook.get("data"),m_Blank)
  41.  v_Type = ifnull(m_Webhook.get("type"),"-")
  42.  if(v_Type == "terminal.reader.action_succeeded") 
  43.  { 
  44.      // Get Payment Intent that needs to be Captured 
  45.      m_Object = m_Data.get("object")
  46.      m_Action = m_Object.get("action")
  47.      m_ProcessPaymentIntent = m_Action.get("process_payment_intent")
  48.      v_PaymentIntentID = m_ProcessPaymentIntent.get("payment_intent")
  49.      // 
  50.      // Retrieve details on the Payment Intent 
  51.      v_PaymentIntentEndpoint = "https://api.stripe.com/v1/payment_intents/" + v_PaymentIntentID; 
  52.      r_PaymentIntentDetails = invokeUrl 
  53.      [ 
  54.          url :v_PaymentIntentEndpoint 
  55.          type :GET 
  56.          headers:m_Headers 
  57.      ]
  58.      // 
  59.      // get amount (used to capture payment intent) 
  60.      v_Amount = ifnull(r_PaymentIntentDetails.get("amount"),0)
  61.      v_AmountReceived = ifnull(r_PaymentIntentDetails.get("amount_received"),0)
  62.      v_AmountCapturable = ifnull(r_PaymentIntentDetails.get("amount_capturable"),0)
  63.      v_CaptureIntentEndpoint = "https://api.stripe.com/v1/payment_intents/" + v_PaymentIntentID + "/capture"
  64.      m_CaptureParams = Map()
  65.      m_CaptureParams.put("amount_to_capture",v_AmountCapturable)
  66.      r_CapturePayment = invokeUrl 
  67.      [ 
  68.          url :v_CaptureIntentEndpoint 
  69.          type :POST 
  70.          parameters:m_CaptureParams 
  71.          headers:m_Headers 
  72.      ]
  73.      // 
  74.      // get card details (we need to store last 4 digits) 
  75.      v_StripeReference = ""
  76.      v_Last4Digits = ""
  77.      v_ZB_InvoiceID = 0
  78.      m_Charges = ifnull(r_PaymentIntentDetails.get("charges"),m_Blank)
  79.      l_Data = ifnull(m_Charges.get("data"),{})
  80.      for each  m_Data in l_Data 
  81.      { 
  82.          if(m_Data.get("id") != null) 
  83.          { 
  84.              v_StripeReference = m_Data.get("id")
  85.          } 
  86.          if(m_Data.get("payment_method_details") != null) 
  87.          { 
  88.              m_CardPresent = ifnull(m_Data.get("payment_method_details").get("card_present"),m_Blank)
  89.              v_Last4Digits = ifnull(m_CardPresent.get("last4"),"")
  90.          } 
  91.          if(m_Data.get("description") != null) 
  92.          { 
  93.              v_ChargeDescription = ifnull(m_Data.get("description"),"")
  94.              v_ZB_InvoiceID = v_ChargeDescription.getSuffix("ID: ")
  95.              v_ZB_InvoiceID = if(isNumber(v_ZB_InvoiceID),v_ZB_InvoiceID,0).toLong()
  96.          } 
  97.      } 
  98.      // 
  99.      // create payment record 
  100.      if(v_ZB_InvoiceID != 0) 
  101.      { 
  102.          // 
  103.          // get ZohoBooks nominal account for Stripe 
  104.          v_NominalAccountID = ""
  105.          r_ChartOfAccounts = invokeUrl 
  106.          [ 
  107.              url :"https://www.zohoapis.com/books/v3/chartofaccounts?organization_id=" + v_BooksOrgID 
  108.              type :GET 
  109.              connection:"zbooks" 
  110.          ]
  111.          if(r_ChartOfAccounts.get("chartofaccounts") != null) 
  112.          { 
  113.              for each  m_NomAccount in r_ChartOfAccounts.get("chartofaccounts") 
  114.              { 
  115.                  if(m_NomAccount.get("account_name").equalsIgnoreCase("Stripe clearing")) 
  116.                  { 
  117.                      v_NominalAccountID = m_NomAccount.get("account_id")
  118.                  } 
  119.              } 
  120.          } 
  121.          // 
  122.          // retrieve invoice details from ZohoBooks 
  123.          r_InvoiceDetails = zoho.books.getRecordsByID("invoices",v_BooksOrgID,v_ZB_InvoiceID,"zbooks")
  124.          m_Invoice = ifnull(r_InvoiceDetails.get("invoice"),m_Blank)
  125.          if(m_Invoice.get("customer_id") != null) 
  126.          { 
  127.              m_CreatePayment = Map()
  128.              m_CreatePayment.put("customer_id",m_Invoice.get("customer_id"))
  129.              m_CreatePayment.put("payment_mode","In Person - Card")
  130.              m_CreatePayment.put("amount",v_AmountReceived / 100)
  131.              m_CreatePayment.put("date",zoho.currentdate.toString("yyyy-MM-dd"))
  132.              // 
  133.              l_Invoices = List()
  134.              m_ThisInvoice = Map()
  135.              m_ThisInvoice.put("invoice_id",v_ZB_InvoiceID.toString())
  136.              m_ThisInvoice.put("amount_applied",v_AmountReceived / 100)
  137.              l_Invoices.add(m_ThisInvoice)
  138.              m_CreatePayment.put("invoices",l_Invoices)
  139.              m_CreatePayment.put("invoice_id",v_ZB_InvoiceID.toString())
  140.              m_CreatePayment.put("amount_applied",v_AmountReceived / 100)
  141.              // 
  142.              v_PaymentRef = if(v_StripeReference=="", m_Invoice.get("invoice_number"), v_StripeReference)
  143.              m_CreatePayment.put("reference_number",v_PaymentRef)
  144.              m_CreatePayment.put("account_id",v_NominalAccountID)
  145.              //info m_CreatePayment; 
  146.              // 
  147.              r_CreatePayment = zoho.books.createRecord("customerpayments",v_BooksOrgID,m_CreatePayment,"zbooks")
  148.              //info r_CreatePayment; 
  149.              if(r_CreatePayment.get("message") != null) 
  150.              { 
  151.                  if(r_CreatePayment.get("message").contains("payment has been created")) 
  152.                  { 
  153.                      // 
  154.                      // update the invoice (request by client to store last 4 digits on invoice) 
  155.                      l_CustomFields = List()
  156.                      m_CustomField = Map()
  157.                      m_CustomField.put("api_name","cf_last_4_digits")
  158.                      m_CustomField.put("value",v_Last4Digits)
  159.                      l_CustomFields.add(m_CustomField)
  160.                      m_UpdateInvoice = Map()
  161.                      m_UpdateInvoice.put("custom_fields",l_CustomFields)
  162.                      r_UpdateInvoice = zoho.books.updateRecord("Invoices",v_BooksOrgID,v_ZB_InvoiceID,m_UpdateInvoice,"zbooks")
  163.                  } 
  164.              } 
  165.          } 
  166.      } 
  167.  } 
  168.  m_Response.put("message",r_CreatePayment.get("message"))
  169.  m_Response.put("code",0)
  170.  return m_Response; 

Source(s):
Category: Zoho :: Article: 841

Credit where Credit is Due:


Feel free to copy, redistribute and share this information. All that we ask is that you attribute credit and possibly even a link back to this website as it really helps in our search engine rankings.

Disclaimer: Please note that the information provided on this website is intended for informational purposes only and does not represent a warranty. The opinions expressed are those of the author only. We recommend testing any solutions in a development environment before implementing them in production. The articles are based on our good faith efforts and were current at the time of writing, reflecting our practical experience in a commercial setting.

Thank you for visiting and, as always, we hope this website was of some use to you!

Kind Regards,

Joel Lipman
www.joellipman.com

Related Articles

Joes Revolver Map

Accreditation

Badge - Certified Zoho Creator Associate
Badge - Certified Zoho Creator Associate

Donate & Support

If you like my content, and would like to support this sharing site, feel free to donate using a method below:

Paypal:
Donate to Joel Lipman via PayPal

Bitcoin:
Donate to Joel Lipman with Bitcoin bc1qf6elrdxc968h0k673l2djc9wrpazhqtxw8qqp4

Ethereum:
Donate to Joel Lipman with Ethereum 0xb038962F3809b425D661EF5D22294Cf45E02FebF
© 2024 Joel Lipman .com. All Rights Reserved.