{"id":1877,"date":"2019-02-07T12:07:12","date_gmt":"2019-02-07T17:07:12","guid":{"rendered":"https:\/\/xlinesoft.com\/blog\/?p=1877"},"modified":"2019-02-15T17:51:32","modified_gmt":"2019-02-15T22:51:32","slug":"using-invoice-template-as-a-checkout-solution","status":"publish","type":"post","link":"https:\/\/xlinesoft.com\/blog\/2019\/02\/07\/using-invoice-template-as-a-checkout-solution\/","title":{"rendered":"Using Invoice template as a checkout solution"},"content":{"rendered":"<p>If you purchased or upgraded PHPRunner, ASPRunner.NET or ASPRunnerPro recently you may have noticed that we are using a new checkout solution based on <a href=\"https:\/\/xlinesoft.com\/invoice\">Invoice template<\/a>. In this article we will show you steps required to add this kind of functionality to your project. <\/p>\n<p>To see how it works live proceed to <a href=\"https:\/\/xlinesoft.com\/phprunner\/register.htm\">PHPRunner purchase<\/a> page, select Edition, enter your email address, add more options on the next screen and click Continue.<\/p>\n<p><a href=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template-300x183.png\" alt=\"\" width=\"300\" height=\"183\" class=\"alignnone size-medium wp-image-1878\" srcset=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template-300x183.png 300w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template-768x468.png 768w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template-1024x624.png 1024w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template-150x91.png 150w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template-400x244.png 400w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/invoice_template.png 1328w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<!--more--><\/p>\n<p>Sample code is PHP only. We will add C# code soon too. <\/p>\n<h4>1. SMTP settings<\/h4>\n<p>Make sure you specified correct SMTP settings in PHPRunner\/ASPRunner.NET. We will need this to send email receipts.  <\/p>\n<h4>2. Change admin password<\/h4>\n<p>Build application, logon as admin\/admin and change admin password. <\/p>\n<h4>3. Change Paypal\/Stripe settings<\/h4>\n<p>Go to Settings in web application and provide Paypal and Stripe settings in order to use both payment methods. <\/p>\n<h4>4. Sending email receipts<\/h4>\n<p>Now there is something interesting. Proceed to Editor, create folder &#8217;email&#8217; under &#8216;Custom files&#8217;, create subfolder &#8216;english&#8217; there (of whatever language you use in your project). Create file named orderemail.txt there. <\/p>\n<p><a href=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template-300x241.png\" alt=\"\" width=\"300\" height=\"241\" class=\"alignnone size-medium wp-image-1879\" srcset=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template-300x241.png 300w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template-768x618.png 768w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template-150x121.png 150w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template-400x322.png 400w, https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2019\/02\/incoice_email_template.png 946w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Here is the sample email text you can use. Note the use of %field_name% placeholders.  <\/p>\n<pre name=\"code\" class=\"php:nocontrols\">\r\nXlinesoft order %invoice_number%: %item%\r\n\r\n           Date: %date%\r\n   Order Number: %invoice_number%\r\n Product Number: 32557-inv\r\n  Product Title: %item%\r\n       Quantity: %quantity%\r\n     Unit Price: %item% US$ %price%\r\n          Total: US$ %total%\r\n\r\n          First: %buyer_info%\r\n           Last: \r\n   Company Name: \r\n  Email Address: %buyer_email%\r\n      Address 1: \r\n      Address 2: \r\n           City: \r\n State\/Province: \r\nZip\/Postal Code: \r\n        Country: \r\n          Phone: \r\n<\/pre>\n<h4>5. Custom invoice number generation<\/h4>\n<p>Many applications require to generate a custom invoice\/transaction instead of plain numbers like 1,2,3 etc. You may notice that in our checkout solution Invoice numbers look like <strong>INV-X0000365<\/strong>. Here is how it works.<\/p>\n<p>There is an extra table named invnumber that holds the latest order number. We get that number, increment it by one, format it the way we need it and update invoice_number table. Pretty straightforward. <\/p>\n<p>This code can be found under Invoices->Add page->Process record values event.  <\/p>\n<p><b>PHP code<\/b><\/p>\n<pre name=\"code\" class=\"php:nocontrols\">\r\n$rs = CustomQuery(\"select invnumber from invoice_number\");\r\n$data = db_fetch_array($rs);\r\n$values['invoice_number'] = \"INV-X\".str_pad($data[\"invnumber\"]+1, 7, \"0\",STR_PAD_LEFT);\r\nCustomQuery(\"update invoice_number set invnumber=invnumber+1\");\r\n<\/pre>\n<p><b>C# code<\/b><\/p>\n<pre name=\"code\" class=\"csharp:nocontrols\">\r\ndynamic data = XVar.Array(), rs = null;\r\nstring numb;\r\nrs = XVar.Clone(CommonFunctions.db_query(\"select invnumber from invoice_number\", GlobalVars.conn));\r\ndata = XVar.Clone(CommonFunctions.db_fetch_array((XVar)(rs)));\r\nnumb = (data[\"invnumber\"] + 1).ToString();\r\nchar s = '0';\r\nvalues.InitAndSetArrayItem(MVCFunctions.Concat(\"INV-X\", numb.PadLeft(7,s)), \"invoice_number\");\r\nCommonFunctions.db_query(\"update invoice_number set invnumber=invnumber+1\", GlobalVars.conn);\r\n<\/pre>\n<h4>6. Sending payment receipt (afterpay.php\/afterpay.cs)<\/h4>\n<p>This is a part of the template and can be edited under Custom Files. Function named runAfterPay will be executed after a successful payment. <\/p>\n<p>Here we update invoice as paid, set invoice payment date and also send the email receipt. <\/p>\n<p><b>PHP code<\/b><\/p>\n<pre name=\"code\" class=\"php:nocontrols\">\r\n&lt;?php\r\nfunction runAfterPay($hash, $payid, $paytype){\r\n\t\/\/ $hash - record id for update status field\r\n\t\/\/ $payid - Payment id from paypal or stripe\r\n\tif($hash && $payid){\r\n\r\n\t\t\t\/\/ mark invoice as paid\r\n\t\t\t$sql = \"update invoices set status='paid', transaction_id = '\".$payid.\"', paydate='\".date(\"Y-m-d\").\"' where hash='\".$hash.\"'\";\r\n\t\t\tDB::Exec($sql);\r\n\r\n\t\t\t$email=\"support@xlinesoft.com\";\r\n\t\t\t\t\r\n\t\t\t\/\/ get invoice id based on hash\r\n\t\t\t$params = array();\r\n\t\t\t$rs = DB::Query(\"select * from invoices where hash='\".$hash.\"'\");\r\n\t\t\tif ($data = $rs->fetchAssoc()) {\r\n\r\n\t\t\t\t$rs2 = DB::Query(\"select * from invoicedetails where id_invoice=\".$data[\"id\"]);\r\n\t\t\t\twhile( $data2 = $rs2->fetchAssoc() ) \t{\r\n\t\t\t\t\t\t\/\/ send order email, one per item\r\n\t\t\t\t\t\t$data[\"price\"]=$data2[\"price\"];\r\n\t\t\t\t\t\t$data[\"quantity\"]=$data2[\"quantity\"];\r\n\t\t\t\t\t\t$data[\"item\"]=$data2[\"item\"];\r\n\t\t\t\t\t\t$data[\"total\"]=$data2[\"total\"];\r\n\t\t\t\t\t  RunnerPage::sendEmailByTemplate($email, \"orderemail\", $data);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\techo \"ok\";\r\n\t\t}\r\n}\r\n?>\r\n<\/pre>\n<p><b>C# code<\/b><\/p>\n<pre name=\"code\" class=\"csharp:nocontrols\">\r\nusing System;\r\nusing System.IO;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Web;\r\nusing System.Web.Mvc;\r\nusing System.Reflection;\r\nusing runnerDotNet;\r\nnamespace runnerDotNet\r\n{\r\n\tpublic partial class GlobalController : BaseController\r\n\t{\r\n\t\tpublic static XVar runAfterPay(dynamic hash, dynamic payid, dynamic paytype)\r\n\t\t{\r\n\t\t\tif((XVar)(hash)  && (XVar)(payid))\r\n\t\t\t{\r\n\t\t\t\tdynamic data = XVar.Array(), email = null, rs = null, sql = null, var_params = null;\r\n\t\t\t\tsql = XVar.Clone(MVCFunctions.Concat(\"update invoices set status='paid', paydate='\", MVCFunctions.date(new XVar(\"Y-m-d\")), \"', payid='\", payid, \"', paytype='\", paytype, \"' where hash='\", hash, \"'\"));\r\n\t\t\t\tDB.Exec((XVar)(sql));\r\n\t\t\t\temail = new XVar(\"support@xlinesoft.com\");\r\n\t\t\t\tvar_params = XVar.Clone(XVar.Array());\r\n\t\t\t\trs = XVar.Clone(DB.Query((XVar)(MVCFunctions.Concat(\"select * from invoices where hash='\", hash, \"'\"))));\r\n\t\t\t\tif(XVar.Pack(data = XVar.Clone(rs.fetchAssoc())))\r\n\t\t\t\t{\r\n\t\t\t\t\tdynamic data2 = XVar.Array(), rs2 = null;\r\n\t\t\t\t\trs2 = XVar.Clone(DB.Query((XVar)(MVCFunctions.Concat(\"select * from invoicedetails where id_invoice=\", data[\"id\"]))));\r\n\t\t\t\t\twhile(XVar.Pack(data2 = XVar.Clone(rs2.fetchAssoc())))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdata.InitAndSetArrayItem(data2[\"price\"], \"price\");\r\n\t\t\t\t\t\tdata.InitAndSetArrayItem(data2[\"quantity\"], \"quantity\");\r\n\t\t\t\t\t\tdata.InitAndSetArrayItem(data2[\"item\"], \"item\");\r\n\t\t\t\t\t\tdata.InitAndSetArrayItem(data2[\"total\"], \"total\");\r\n\t\t\t\t\t\tRunnerPage.sendEmailByTemplate((XVar)(email), new XVar(\"orderemail\"), (XVar)(data));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tMVCFunctions.Echo(\"ok\");\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>Note the use of <strong>RunnerPage::sendEmailByTemplate()<\/strong> function. This function accepts the following parameters:<\/p>\n<pre name=\"code\" class=\"php:nocontrols\">\r\n$email - email address to send email to.\r\n\"orderemail\" - name of email template. Remember orderemail.txt file created on step 4? \r\n$data - array with data to replace placeholders in email template with the actual values.\r\n<\/pre>\n<h4>7. API integration<\/h4>\n<p>Now we need to integrate it into our existing website. We provide REST API for this purpose. There are two files that come with Invoice template, apitest.php and apitest.cs that provide sample API usage code. <\/p>\n<p>You will need to change $url variable &#8211; URL of Invoice add page on your website. Also you need to specify &#8220;your Authenticate key&#8221;. This can be any unique text string that you can specify in Invoice project under Settings->API Authorization key.<\/p>\n<pre name=\"code\" class=\"php:nocontrols\">\r\n&lt;?php\r\n\r\n\/\/This API allows to create an invoice sending buyer and seller data and also a list of items, prices, taxes etc. \r\n\/\/If invoice is created successfully it returns URL of the View page of this invoice.\r\n\r\nrequire_once(\"include\/dbcommon.php\");\r\n$url = \"https:\/\/yourwebsite.com\/invoice\/invoices_add.php\";\r\n$res[\"company_name\"]=\"Company Name\";\r\n$res[\"seller_info\"]=\"Seller Info\";\r\n$res[\"buyer_info\"] = \"buyer name\";\r\n$res[\"buyer_address\"] = \"buyer address\";\r\n$res[\"buyer_email\"] = \"buyer@email.com\";\r\n$res[\"tax\"]=\"10\";\r\n$res[\"terms\"]=\"terms\";\r\n$res[\"invoice_name\"]=\"Invoice Name\";\r\n$res[\"details\"] = array();\r\nfor($i=1;$i<3;$i++){\r\n\t$details = array();\r\n\t$details[\"item\"] = \"item_\".$i;\r\n\t$details[\"price\"] = $i;\r\n\t$details[\"quantity\"] = $i;\r\n\t$res[\"details\"][] = $details;\r\n}\r\n$str = json_encode($res);\r\n$parameters[\"invoice\"] = $str;\r\n$headers[\"WWW-Authenticate\"] = \"your Authenticate key\";\r\n$res = runner_post_request($url, $parameters, $headers);\r\nif($res[\"error\"])\r\n\techo $res[\"error\"];\r\nelse {\r\n\tif(strpos($res[\"content\"],\"http\")>-1)\r\n\t\techo \"<a href='\".$res[\"content\"].\"'>Invoice view<\/a>\";\r\n\telse\r\n\t\techo $res[\"content\"];\r\n}\r\n?>\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>If you purchased or upgraded PHPRunner, ASPRunner.NET or ASPRunnerPro recently you may have noticed that we are using a new checkout solution based on Invoice template. In this article we will show you steps required to add this kind of functionality to your project. To see how it works live proceed to PHPRunner purchase page, select Edition, enter your email address, add more options on the next screen and click Continue.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,10,1,4,8],"tags":[],"class_list":["post-1877","post","type-post","status-publish","format-standard","hentry","category-asp-net","category-news","category-php-category","category-php-code-generator","category-tutorials"],"_links":{"self":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts\/1877","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/comments?post=1877"}],"version-history":[{"count":14,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts\/1877\/revisions"}],"predecessor-version":[{"id":1894,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts\/1877\/revisions\/1894"}],"wp:attachment":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/media?parent=1877"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/categories?post=1877"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/tags?post=1877"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}