Pre-approved Payments Billing Integration Guide

Learn how to accept Pre-Approved payments for your business. On Demand Billing is a payment agreement between Merchant and Customer for the direct debiting based on the previously arranged terms. With the Pre-approved Payments functionality, individual customers purchasing products or services on a regular basis can pay without entering payment information again and again by simply granting payment authorization to the Merchant.

Table of contents:

§1. General Information

OKPAY provides outstanding functionality for Pre-Approved Payments billing – i.e. direct debiting based on previously arranged terms (i.e. On-Demand Billing). If you provide regular services and e.g. pay-per-use, VoIP, hosting and domain account renewals, and other similar services that require auto recharge - then you will most definitely benefit from enabling OKPAY Pre-approved Payments functionality for your business!

OKPAY Billing Agreement is a pre-authorization for the Merchant to automatically charge Clients for regular purchases or frequently used services - making it easier for Clients to maintain an active account.

Since OKPAY Pre-approved Billing gives both further convenience and speed of a regular payment, while also letting you provide uninterrupted service, we encourage our Merchants to set it up additional payment functionality.

While frequently using certain services or products (e.g. hosting, VoIP, entertainment websites, etc.) Clients need to keep track on their balance and recharge it regularly. It takes some time to perform certain steps and complete a payment.

However, with a Pre-approved Billing Contract the whole process is significantly simplified. Clients are able to set the certain limits in advance, allowing Merchant to charge their OKPAY account automatically without further action or confirmation from the Сlient. Thus by utilizing Auto-Recharge feature the service is provided non-stop.

Here are some features of the On-Demand Billing:

  • Pre-Approved payment can be used by Merchants for selling digital content, various services or subscriptions.
  • Client can set up a validity period or make it everlasting.
  • Client can set up various charge limits for each individual cycle in any currency supported by OKPAY.
  • Merchants can request charge from the Сlient manually or via API.
  • Merchants can specify who pays the fee: they or the client.

Note: Pre-Approved Payments Billing is available to any verified OKPAY user who selected a Business account type. Read more in the General Reference Guide for Merchants. Some general principles described in the Payment Integration Guide are also suitable for Pre-Approved Payments.

A new Pre-Approved Payment is created by placing a special link on the merchant's website. The link is similar to a regular payment link but features a slightly different set of variables. By clicking on the created link, customers are forwarded from the merchant's website to a Pre-Approved Payments page, where they can select OKPAY wallet and set the future limits for the Merchant. Subsequent payments are charged directly from the client's e-wallet according to the limits.

Both Merchant and Client are notified by e-mail about payments and all events related to future changes. Additionally, OKPAY sends IPN messages with all necessary technical details to the merchant's website or back office application.

To manage Pre-Approved Payments, go to your Profile » Pre-approved Payments where you can easily find a list of all pre-approved payment contracts and their corresponding Clients.

Figure 1. Pre-approved Payments Billing.

Pre-approved Payments Billing

Almost any task that is done using the web interface can be also performed via OKPAY API.

We will explain these steps and features in more detail.

§2. Creating Pre-Approved Payments Contract

To ensure your customers are able to sign up for a Pre-Approved Payments Contract and receive the service non-stop, you have to create a special URL which then should be placed on your website. Feel free to use the Button Generator or manually create a URL containing variables described in the Payment Links Variable Reference article of the Comprehensive Manual.

Note: Please learn more about general payment links and buttons usage in Comprehensive Manual, section Payment Links.

Example 1. The simplest payment link contains only a few parameters:

https://checkout.okpay.eu?ok_receiver=OK702746927&ok_kind=preapproved&ok_p_title=My+First+Pre-Approved+Payment&ok_currency=EUR

We have a payment link (ok_kind=preapproved) "My First Pre-Approved Payment". The validity period is not limited and the receiver wallet is OK702746927.

Example 2. Let's have a look at a more complicated example. We created a pre-approved payment link called "My Second Pre-Approved Payment". It is valid until August 1st, 2015, with the following charge limits set: 10 EUR daily, 30 EUR weekly, 100 EUR monthly.

https://checkout.okpay.eu?ok_receiver=OK702746927&ok_kind=preapproved&ok_p_title=My+Second+Pre-Approved+Payment&ok_currency=EUR&ok_p_end_date=2015-08-01&ok_p_monthly_amount=100&ok_p_daily_amount=10&ok_p_weekly_amount=30

Figure 2. Pre-approved payments button graphics.

Pre-Approved Payments buttons

Figure 3. Checkout page interface for pre-approved payment.

Pre-Approved Payments Checkout

Pre-approved payments assumes a billing agreement, thus once you create it a customer has to accept the conditions or apply his own spending limits.

§3. Handling IPN Messages

Pre-Approved Payments event handling in IPN messages allows you to fully automate your work with clients. Get an instant IPN notification if you have a new client, if there is a problem with payment, if payment is successfully charged, if a payment contract is canceled, and so on.

Hereafter we will describe the specific features of IPN with regard to the receiving of payments. If you are looking for more information on IPN, such as examples of basic-code writing rules, testing, or IPN messages history, please refer to the IPN section of the Comprehensive Manual.

§3.1. IPN Handler Setup

In order to use the IPN, first of all, you need to inform OKPAY where the IPN handler script is located on your server:

  • In wallet settings (Profile » Wallets and Currencies » select wallet and click on Edit » Integration tab. Under "Payment Notification (IPN)" enter URL address of your IPN handler;
  • Dynamically in the payment link by specifying the IPN handler address in ok_ipn.

Read more on how to setup IPN handler, subsection of the Comprehensive Manual.

§ 3.2. Writing Handler Code

General code-writing rules for IPN handler can be found in the Implementing a Generic IPN Listener, subsection of the Comprehensive Manual.

To identify an incoming IPN as a pre-approved payment message you need to look up the ok_txn_kind variable which should be equal to ok_txn_kind=preapproved. Then you need to examine the ok_p_event variable in order to determine an event type. They are as follows:

  • Access_granted - new pre-approved payments contract is registered. The event does not require instant upcoming payment from the client upon approval.
  • Access_denied - pre-approved payments contract is finished or invalid. The client can revoke payment contract authorization at any time.
  • Payment - pre-approved payment event received. The pre-approved payment has been automatically processed according with the contract.

You should also check for the ok_p_status variable:

  1. Active - pre-approved payments contract is active.
  2. Failed - payment for the pre-approved payments contract is failed.
  3. Canceled - pre-approved payments contract canceled either by merchant or by customer.
  4. Expired - the pre-approved payments contract was completed by the expiration date.

Figure 4. A sequence of status transitions (ok_p_status).

Status Transitions

Figure 5. A sequence of events transitions (ok_p_event).

Event Transitions

When processing a pre-approved payment IPN , ok_p_status is an important variable to remember. This indicates if a payment contract is active. For example, if the client revokes his authorization, the status is changed to canceled.

In the Code Samples in Various Programming Languages section you can find a detailed example of how the IPN handler for pre-approved payments should look like. Feel free to use this example to create your own handler.

§ 3.3. Tips for Safe Handling of Pre-Approved Payments Messages

Firstly, to ensure the safe and proper operation of your pre-approved payments, verify that the received IPN is genuine, that it is sent by the OKPAY server and that it has not been handled before (check ok_ipn_id). Details of this can be found on the Implementing a Generic IPN Listener, subsection of the Comprehensive Manual.

Close attention should be paid to the event processing variable ok_p_event=payment. You should also check for the following:

  1. That the operation status is ok_txn_status=completed.
  2. That this operation has not been carried out earlier. You can do this by checking the variable ok_txn_id.
  3. That the recipient's wallet number ok_receiver_wallet or Account ID ok_receiver_id belongs to you.
  4. That the incoming amount is correct (ok_txn_net for the amount minus the OKPAY fee or ok_txn_gross for the total amount charged).
  5. That the payment currency, ok_txn_currency, is correct. Also make sure that the value of the transferred funds, ok_txn_fee, meets with the one you used in reference to a payment.

We recommend that you start writing code for your handler based on the sample in the Code Samples in Various Programming Languages section.

§ 3.4. Testing Pre-Approved Payments IPN

OKPAY contains an IPN simulator to test the message handling of your scripts. This functionality is described on the IPN Testing, subsection of Comprehensive Manual.

The IPN payments simulator can be used for the initial testing of your source code. For a more thorough and practical testing of your business logic please refer to the Final Testing of the Pre-Approved Payments.

§4. Managing Pre-Approved Payments via API

OKPAY system allows for a full automated process of pre-approved payments for your business. API functions and IPN are parts of a single integration system.

You can manage your customers not only via the OKPAY web interface (see Managing Pre-Approved Payments via Web Interface) but also inside the information system of your company. You can write a code that uses the appropriate API functions.

The pre-approved payment API contains the following functions:

For additional information, click on the function name.

Quite like using the OKPAY web interface, API functions allow you to have complete control over absolutely all of the contract properties.

A detailed example of API function calls in response to respective IPN messages can be found in Code Samples in Various Programming Languages.

§5. Managing Pre-Approved Payments via Web Interface

The OKPAY Pre-Approved Payments Billing (accessed from your Profile » Pre-approved Payments Billing) allows you to manage clients and via the web interface.

You can easily view a list of all clients and take the following actions with them:

  • Charge the client. Attempt to manually charge the client.
  • Completely cancel pre-approved payment contract. Cancel further payments from this client; if you need to suspend providing services and terminate your contract.
  • Find and view details of the required pre-approved payment. Lookup for a pre-approved payment for a particular client.

§5.1. Statistics, Search and Filtering Options

At the top of the page you can find useful statistical information about your clients, specifically, the number of active, failed, expired and canceled contracts.

Figure 6. Pre-approved payments search.

Search

The search and filtering options are located beneath the statistics. They include:

  • The contract status (active, expired, canceled, failed).
  • The ID of a specific pre-approved payments contract. Each contract has a unique identifier.
  • The contract title (each pre-approved payment contract may have a unique name).
  • The period of contract creation. You can select any date range.
  • The e-mail address, phone number or wallet ID of the client.

§5.2. Managing Individual Payment Contract

Use the search option to find a contract and click on the contract ID.

Figure 7. Link to the details of the contract is highlighted in red (column ID).

Pre-Approved Payment Details Link

Upon clicking on contract ID you will be forwarded to the pre-approved payment details page. It contains information on the client, parameters of the contract, history of the performed payments received from the client, etc.

Figure 8. Preapproved payment details page with merchant's options.

Pre-Approved Payment Details Page

You can perform following actions for the selected contract (see figure above):

  • Cancel the contract;
  • Charge the client by Manually reinitializing payment attempt.

§5.2.1. Cancelling a Payment Contract

Click on the Cancel Contract button and confirm that you would like to completely stop all future payments. Canceled contracts can no longer be reactivated. Clients would have to apply for the pre-approved payments contract with merchant again in order to restore their membership.

§5.2.2. Manual Payment Attempt Initialization

In some cases, the merchant can click on the Charge button to manually charge a client for the service.

Figure 9. Manual Payment Attempt Initialization.

Manual Payment Attempt Initialization

If a client has enough funds on the particular wallet, the payment will be processed automatically.

§6. Final Testing of the Pre-Approved Payments

As explained in Testing Pre-Approved Payment IPN, you can check the basic operation of your handler by using the IPN simulation service.

In addition, for a final and more complete testing of your code, as well as your business-logic operation, you may need an additional real-world testing with real clients.

We recommend that you create a test account, which can be used to perform pre-approved payments.

If you have any questions or problems feel free to contact OKPAY Support Service. Our technicians will be happy to help.

§7. Code Samples in Various Programming Languages

There are, for your reference, several examples of pre-approved payments with OKPAY provided in popular programming languages. These include:

  1. An IPN message handler example.
  2. An API class example for pre-approved payments.
Sample in PHP
 <?php
 /*
 	Pre-approved payments OKPAY API class
 */
 class OKPAY_Preapproved {
 	private $WalletID       = 'OK123456789';         // Wallet ID of service owner
 	private $APIPassword    = 'Your API Password';   // API password
 	private $SoapClient;                             // SOAP client for verification API
 	private $Key;                                    // Security key
 	public  $LogFilename    = 'PreapprovedTest.txt'; // Log file name
 	public  $Debug          = false;                 // Is debug mode on?
 
 	// Pre-defined variables
 	public function __construct() {
 		$this->Key = strtoupper(hash("sha256", $this->APIPassword.":".gmdate("Ymd:H")));
 		$this->SoapClient = new SoapClient("https://api.okpay.com/OkPayAPI?wsdl");
 	}
 
 	// IPN verification function
 	public function VerifyIPN() {
 		$Request = 'ok_verify=true';
 		foreach ($_POST as $Key => $Value) {
 			$value = urlencode(stripslashes($Value));
 			$Request .= "&$Key=$Value";
 		}
 
 		$header  = "POST /ipn-verify HTTP/1.0\r\n";
 		$header .= "Host: checkout.okpay.eu\r\n";
 		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
 		$header .= "Content-Length: " . strlen($Request) . "\r\n\r\n";
 		$fp = fsockopen ('checkout.okpay.eu', 80, $errno, $errstr, 30);
 
 		if (!$fp) {
 			$this->log('Cannot connect to OKPAY');
 			return false;
 		} else {
 			fputs ($fp, $header . $Request);
 			while (!feof($fp)) {
 				$res = fgets ($fp, 1024);
 				if (strcmp ($res, "VERIFIED") == 0 && $_POST["ok_txn_kind"] == "preapproved") {
 					// IPN verified
 					$this->log('IPN verified');
 					$this->log('Request - '.$Request);
 					return true;
 				} elseif (strcmp ($res, "INVALID") == 0) {
 					// IPN invalid
 					$this->log('IPN INVALID');
 					$this->log('Request - '.$Request);
 					return false;
 				} elseif (strcmp ($res, "TEST")== 0 && $_POST["ok_txn_kind"] == "preapproved") {
 					// Test IPN
 					$this->log('IPN TEST');
 					$this->log('Request - '.$Request);
 					return true;
 				}
 			}
 			fclose ($fp);
 		}
 	}
 
 	// Get contract information
 	public function PreapprovedPaymentGet($ContractID) {
 		try {
 			$obj = new stdClass();
 			$obj->WalletID = $this->WalletID;
 			$obj->SecurityToken = $this->Key;
 			$obj->ContractID = $ContractID;
 			$webService = $this->SoapClient->PreapprovedPayment_Get($obj);
 			return $webService->PreapprovedPayment_GetResult;
 		} catch (Exception $e) {
 			$this->log(__LINE__.": Caught exception: ".  $e->getMessage());
 			return false;
 		}
 	}
 
 	// Get list of contracts by filter
 	public function PreapprovedPaymentsFilter($ContractID = 0, $Title = '', $Invoice = '', $Client = '', $Statuses = array()) {
 		try {
 			$obj = new stdClass();
 			$obj->WalletID = $this->WalletID;
 			$obj->SecurityToken = $this->Key;
 			$obj->ContractID = $ContractID;
 			$obj->Title = $Title;
 			$obj->Invoice = $Invoice;
 			$obj->Client = $Client;
 			$obj->Statuses = $Statuses;
 			$webService = $this->SoapClient->PreapprovedPayments_Filter($obj);
 			return $webService->PreapprovedPayments_FilterResult;
 		} catch (Exception $e) {
 			$this->log(__LINE__.": Caught exception: ".  $e->getMessage());
 			return false;
 		}
 	}
 
 	// Perform pre-approved payment from customer's wallet
 	public function PreapprovedPaymentCharge($ContractID, $Amount = 0.00, $Comment = '') {
 		try {
 			$obj = new stdClass();
 			$obj->WalletID = $this->WalletID;
 			$obj->SecurityToken = $this->Key;
 			$obj->ContractID = $ContractID;
 			$obj->Amount = $Amount;
 			$obj->Comment = $Comment;
 			$webService = $this->SoapClient->PreapprovedPayment_Charge($obj);
 			return $webService->PreapprovedPayment_ChargeResult;
 		} catch (Exception $e) {
 			$this->log(__LINE__.": Caught exception: ".  $e->getMessage());
 			return false;
 		}
 	}
 
 	// Terminates pre-approved payments contract
 	public function PreapprovedPaymentCancel($ContractID, $Comment = '') {
 		try {
 			$obj = new stdClass();
 			$obj->WalletID = $this->WalletID;
 			$obj->SecurityToken = $this->Key;
 			$obj->ContractID = $ContractID;
 			$obj->Comment = $Comment;
 			$webService = $this->SoapClient->PreapprovedPayment_Cancel($obj);
 			return $webService->PreapprovedPayment_CancelResult;
 		} catch (Exception $e) {
 			$this->log(__LINE__.": Caught exception: ".  $e->getMessage());
 			return false;
 		}
 	}
 
 	// Get all operations performed according to specific pre-approved payments contract
 	public function PreapprovedPaymentGetOperations($ContractID) {
 		try {
 			$obj = new stdClass();
 			$obj->WalletID = $this->WalletID;
 			$obj->SecurityToken = $this->Key;
 			$obj->ContractID = $ContractID;
 			$webService = $this->SoapClient->PreapprovedPayment_Get_Operations($obj);
 			return $webService->PreapprovedPayment_Get_OperationsResult;
 		} catch (Exception $e) {
 			$this->log(__LINE__.": Caught exception: ".  $e->getMessage());
 			return false;
 		}
 	}
 
 	private function log($message) {
 		if($this->Debug == true) {
 			file_put_contents($this->LogFilename, date("d.m.Y H:i:s").': '.$message."\r\n", FILE_APPEND);
 		}
 	}
 }
 ?>
 
 <pre>
 <?php
 /*
 * Dummy function, you need to use your own
 */
 function GetPayment($SomeID){
 	// Simulates getting order data
 	$Payment = new stdClass();
 	$Payment->ID = 4567;
 	$Payment->Currency = 'USD';
 	$Payment->ClientPaysFee = true;
 	$Payment->PaymentsAmount = 123.45;
 	return $Payment;
 }
 
 /*
 * Sample for API functions
 */
 $API = new OKPAY_Preapproved();                  // Initialize
 $API->Debug = true;                              // Enable debug mode
 $API->LogFilename = './preapproved_debug.txt'; // Change debug filename
 
 // Some contract ID
 $ContractID = 12345;
 
 // Get contract info
 $PreapprovedPayment = $API->PreapprovedPaymentGet($ContractID);
 print_r($PreapprovedPayment);
 
 // Get contracts list                 title part       created from           created till        statuses (`ok_s_status`)
 $PreapprovedPayments = $API->PreapprovedPaymentsFilter($ContractID 'My test payment', 'Invoice#12345', 'Client#54321', array());
 print_r($PreapprovedPayments);
 
 // Perform pre-approved payment
 $TransactionInfo = $API->PreapprovedPaymentCharge($ContractID, 'Operation: automatic account top-up');
 print_r($TransactionInfo);
 
 // Get all operations performed according to specific pre-approved payments contract
 $OperationsList = $API->PreapprovedPaymentGetOperations($ContractID);
 print_r($OperationsList);
 
 // Terminate pre-approved payments contract
 $Status = $API->PreapprovedPaymentCancel($ContractID);
 print_r($Status);
 
 
 /*
 * Sample IPN handler
 */
 if($_SERVER['REQUEST_METHOD'] === 'POST') {           // POST method - possibly IPN request
 	if($API->VerifyIPN()) {                           // If IPN message is valid
 		if($_POST['ok_txn_kind'] == 'preapproved') {  // This is pre-approved payment IPN request
 			$ok_p_id = (integer)$_POST['ok_p_id'];    // Get pre-approved ID
 			switch($_POST['ok_p_event']) {
 				case 'access_granted':
 					/*
 						Access granted
 					*/
 					if($PreapprovedPayment = $API->PreapprovedPaymentGet($ok_p_id)) {
 						/*
 							Store information about pre-approved payment in DB
 						*/
 
 					}
 
 					break;
 				case 'payment':
 					/*
 						Successful pre-approved payment received
 					*/
 					$Payment = GetPayment($_POST['ok_invoice']); // Get order details (dummy function)
 					if(
 						$_POST['ok_txn_status']      == 'completed' &&              // Ensure that status of payment is `completed`
 						$_POST['ok_receiver_wallet'] == 'OK123456789' &&            // Check that wallet of receiver is yours
 						$_POST['ok_txn_net']         == $Payment->PaymentsAmount && // Check payment amount
 						$_POST['ok_txn_currency']    == $Payment->Currency &&       // Check payment currency
 						$_POST['ok_txn_fee']         == $Payment->ClientPaysFee
 					){
 						/*
 							Do something...
 						*/
 
 					}
 
 					break;
 				case 'access_denied':  // Pre-approved payments contract is finished
 					/*
 						In all of these cases you should stop client charges with ID = $_POST['ok_p_id']
 					*/
 					if($PreapprovedPayment = $API->PreapprovedPaymentCancel($ok_p_id)) {
 						/*
 							You can use $PreapprovedPayment->Client->Email or $PreapprovedPayment->Client->WalletID to identify your client
 						*/
 
 					}
 					break;
 
 				default:
 					break;
 			}
 		}
 	}
 }
 
 ?>
Sample in C#
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 
 
 namespace Developers.OKPAY.COM
 {
 	///Add Service Reference to your C# project (https://api.okpay.com/OkPayAPI)
 
 	/// <summary>
 	/// Pre-approved payments OKPAY API class
 	/// </summary>
 	public class OkpayPreapprovedPayments
 	{
 		/// <summary>
 		///  Wallet ID of service owner
 		/// </summary>
 		private string WalletID = "OK123456789";
 
 		/// <summary>
 		/// API password
 		/// </summary>
 		private string APIAccessPassword = "Your API Password";
 
 
 		/// <summary>
 		///  Get contract information
 		/// </summary>
 		public OKPAY_API.PreapprovedPayment PreapprovedPaymentGet(long contractId)
 		{
 			string securityToken = this.SecurityToken;
 			using (var proxy = new OKPAY_API.I_OkPayAPIClient())
 			{
 				try
 				{
 					var contractInfo = proxy.PreapprovedPayment_Get(WalletID, securityToken, contractId);
 					return contractInfo;
 				}
 				catch (Exception ex)
 				{
 					Console.WriteLine(ex.ToString());
 					throw ex;
 				}
 			}
 		}
 
 		/// <summary>
 		///  Get contracts list
 		/// </summary>
 		public IEnumerable<OKPAY_API.PreapprovedPayment> PreapprovedPaymentsFilter(string title, string invoice, string client, OKPAY_API.PreapprovedPaymentStatuses[] statuses)
 		{
 			string securityToken = this.SecurityToken;
 			using (var proxy = new OKPAY_API.I_OkPayAPIClient())
 			{
 				try
 				{
 					var contracts = proxy.PreapprovedPayments_Filter(WalletID, securityToken, title, invoice, client, statuses);
 					return contracts;
 				}
 				catch (Exception ex)
 				{
 					Console.WriteLine(ex.ToString());
 					throw ex;
 				}
 			}
 		}
 
 		/// <summary>
 		/// Perform pre-approved payment from customer's wallet
 		/// </summary>
 		public OKPAY_API.TransactionInfo PreapprovedPaymentCharge(int contractId, decimal amount, string comment)
 		{
 			string securityToken = this.SecurityToken;
 			using (var proxy = new OKPAY_API.I_OkPayAPIClient())
 			{
 				try
 				{
 					var transactionInfo = proxy.PreapprovedPayment_Charge(WalletID, securityToken, contractId, amount, comment);
 					return transactionInfo;
 				}
 				catch (Exception ex)
 				{
 					Console.WriteLine(ex.ToString());
 					throw ex;
 				}
 			}
 		}
 
 		/// <summary>
 		/// Terminates pre-approved payments contract
 		/// </summary>
 		public OKPAY_API.PreapprovedPayment PreapprovedPaymentCancel(int contractId, string comment)
 		{
 			string securityToken = this.SecurityToken;
 			using (var proxy = new OKPAY_API.I_OkPayAPIClient())
 			{
 				try
 				{
 					var rusult = proxy.PreapprovedPayment_Cancel(WalletID, securityToken, contractId, comment);
 					return rusult;
 				}
 				catch (Exception ex)
 				{
 					Console.WriteLine(ex.ToString());
 					throw ex;
 				}
 			}
 		}
 
 		/// <summary>
 		/// Get payments operations
 		/// </summary>
 		public IEnumerable<OKPAY_API.TransactionInfo> PreapprovedPaymentGetOperations(long contractId)
 		{
 			string securityToken = this.SecurityToken;
 			using (var proxy = new OKPAY_API.I_OkPayAPIClient())
 			{
 				try
 				{
 					var operations = proxy.PreapprovedPayment_Get_Operations(WalletID, securityToken, contractId);
 					return operations;
 				}
 				catch (Exception ex)
 				{
 					Console.WriteLine(ex.ToString());
 					throw ex;
 				}
 			}
 		}
 
 		/// <summary>
 		/// Verify IPN request
 		/// </summary>
 		public bool VerifyIPN(byte[] parameters)
 		{
 			var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("https://checkout.okpay.eu/ipn-verify");
 
 			//Set values for the request back
 			req.Method = "POST";
 			req.ContentType = "application/x-www-form-urlencoded";
 			string strRequest = Encoding.UTF8.GetString(parameters);
 			strRequest += "&ok_verify=true";
 			req.ContentLength = strRequest.Length;
 
 			//Send the request to OKPAY and get the response
 			using (var streamOut = new System.IO.StreamWriter(req.GetRequestStream()))
 			{
 				streamOut.Write(strRequest);
 				streamOut.Close();
 				using (var streamIn = new System.IO.StreamReader(req.GetResponse().GetResponseStream()))
 				{
 					string strResponse = streamIn.ReadToEnd();
 					streamIn.Close();
 
 					if (strResponse == "VERIFIED")
 					{
 						return true;
 					}
 					else if (strResponse == "INVALID")
 					{
 						return false;
 					}
 					else if (strResponse == "TEST")
 					{
 						return true;
 					}
 					else
 					{
 						return false;
 					}
 				}
 			}
 		}
 
 		private string SecurityToken
 		{
 			get
 			{
 				return HashStringSHA256(this.APIAccessPassword + DateTime.UtcNow.ToString(":yyyyMMdd:HH"));
 			}
 		}
 
 		private string HashStringSHA256(string Value)
 		{
 			using (System.Security.Cryptography.SHA256CryptoServiceProvider x = new System.Security.Cryptography.SHA256CryptoServiceProvider())
 			{
 				byte[] data = System.Text.Encoding.ASCII.GetBytes(Value);
 				data = x.ComputeHash(data);
 				return BitConverter.ToString(data).Replace("-", "");
 			}
 		}
 	}
 
 	public class DummyOrder
 	{
 		public long ID { get; set; }
 		public decimal Amount { get; set; }
 		public string Currency { get; set; }
 		public decimal ClientPaysFee { get; set; }
 	}
 
 	public class DummyClass
 	{
 		public static DummyOrder GetDummyOrder(long orderID)
 		{
 			DummyOrder order = new DummyOrder();
 			order.ID = 4567;
 			order.Currency = "USD";
 			order.ClientPaysFee = 1;
 			order.Amount = 123.45M;
 			return order;
 		}
 	}
 
 	/// <summary>
 	/// Sample IPN handler
 	/// </summary>
 	public class IPN_Handler
 	{
 		OkpayPreapprovedPayments api_preapproved = new OkpayPreapprovedPayments();
 
 		public void ProcessRequest(System.Web.HttpContext context)
 		{
 			Dictionary<string, string> parameters = new Dictionary<string, string>();
 			foreach (var item in context.Request.Form)
 			{
 				parameters[item.ToString()] = System.Web.HttpUtility.HtmlDecode(context.Request.Form[item.ToString()]);
 			}
 
 			byte[] param = context.Request.BinaryRead(context.Request.ContentLength);
 			var ipnTestResult = api_preapproved.VerifyIPN(param);
 			if (ipnTestResult)                                   // If IPN message is valid
 			{
 				if (parameters["ok_txn_kind"] == "preapproved")  //This is pre-approved payment IPN request
 				{
 					OKPAY_API.PreapprovedPayment contract;
 
 					long contractId = long.Parse(parameters["ok_p_id"]);  // Get contract ID
 					switch (parameters["ok_p_event"])
 					{
 						case "access_granted":
 							/*
 								New contract registered
 							*/
 							contract = api_preapproved.PreapprovedPaymentGet(contractId);
 
 							/*
 								Store information in DB
 							*/
 							break;
 
 						case "payment":
 							/*
 								Pre-approved payment received
 							*/
 							var orderId = long.Parse(parameters["ok_invoice"]);
 							var order = DummyClass.GetDummyOrder(orderId); // Get order details (dummy function)
 							if (
 								parameters["ok_txn_status"] == "completed" && // Ensure that status of payment is `completed`
 								parameters["ok_receiver_wallet"] == "OK123456789" && // Check that wallet of receiver is yours
 								decimal.Parse(parameters["ok_txn_net"]) == order.Amount &&  // Check payment amount
 								decimal.Parse(parameters["ok_txn_fee"]) == order.ClientPaysFee && // Check fees configuration
 								parameters["ok_txn_currency"] == order.Currency // Check payment currency
 							)
 							{
 								/*
 									Do something...
 								*/
 							}
 							break;
 
 						case "access_denied":
 							/*
 								Pre-approved payments contract is finished
 							*/
 							contract = api_preapproved.PreapprovedPaymentGet(contractId);
 							/*
 								You can use contract.Client.Email or contract.Client.WalletID to identify your client
 							*/
 
 							break;
 						default:
 							break;
 					}
 				}
 			}
 		}
 	}
 }
OKPAY RSS
OKPAY Forum
OKPAY on Facebook
OKPAY on Livejournal
OKPAY on Twitter
OKPAY on VK
OKPAY on Linkedin
OKPAY on Youtube