123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083 |
- <?php
- class copayco_api
- {
-
- const SUBMIT_URL = 'https://www.copayco.com/pay.php';
-
- const SUBMIT_URL_TEST = 'https://www.test.copayco.com/pay.php';
-
- const NOTIFICATION_URL = 'https://www.copayco.com/notify_delivering.php';
-
- const NOTIFICATION_URL_TEST = 'https://www.test.copayco.com/notify_delivering.php';
-
- const TA_ID_KEY = 'ta_id';
-
- const REQUEST_TYPE_KEY = 'request_type';
-
- const SIGNATURE_KEY = 'signature';
-
- const PAYMENT_MODE_KEY = 'payment_mode';
-
- const STATUS_KEY = 'status';
-
- private static $aReqFields = array(
- 'shop_id' => TRUE,
- 'ta_id' => TRUE,
- 'amount' => TRUE,
- 'currency' => TRUE,
- 'description' => FALSE,
- 'custom' => FALSE,
- 'payment_mode' => FALSE,
- 'charset' => FALSE,
- 'lang' => FALSE,
- 'order_no' => FALSE,
- 'purpose' => FALSE,
- 'date_time' => FALSE,
- 'random' => FALSE,
- 'signature' => FALSE,
- );
-
- private static $aCheckFields = array(
- 'request_type' => TRUE,
- 'ta_id' => TRUE,
- 'amount' => TRUE,
- 'currency' => TRUE,
- 'custom' => FALSE,
- 'payment_mode' => FALSE,
- 'client_ip' => TRUE,
- 'date_time' => FALSE,
- 'random' => FALSE,
- 'signature' => TRUE,
- );
-
- private static $aPerformFields = array(
- 'request_type' => TRUE,
- 'status' => TRUE,
- 'ta_id' => TRUE,
- 'cpc_ta_id' => TRUE,
- 'amount' => TRUE,
- 'currency' => TRUE,
- 'custom' => FALSE,
- 'payment_mode' => FALSE,
- 'date_time' => FALSE,
- 'random' => FALSE,
- 'signature' => TRUE,
- );
-
- private static $aNotificationFields = array(
- 'shop_id' => TRUE,
- 'ta_id' => TRUE,
- 'amount' => TRUE,
- 'currency' => FALSE,
- 'state' => TRUE,
- 'date_time' => TRUE,
- 'random' => FALSE,
- 'signature' => TRUE,
- 'return_url' => FALSE,
- );
-
- private static $aCorrespondence = array(
- 'shop_id' => 'iShopId',
- 'ta_id' => 'sTaId',
- 'amount' => 'nAmount',
- 'currency' => 'sCurrency',
- 'description' => 'sDescription',
- 'custom' => 'mCustom',
- 'payment_mode' => 'aPaymentMode',
- 'cpc_ta_id' => 'iCPCTaId',
- 'charset' => 'sCharset',
- 'lang' => 'sLanguage',
- 'order_no' => 'sOrderNo',
- 'purpose' => 'sPurpose',
- 'date_time' => 'sDateTime',
- 'random' => 'iRand',
- 'state' => 'sState',
- 'return_url' => 'sReturnUrl',
- );
-
- private static $aAutoFill = array(
-
- 'iCPCTaId',
- 'sDateTime',
- 'iRand',
- );
-
- private static $aFieldNumber = array(
- 'shop_id' => 1,
- 'ta_id' => 2,
- 'amount' => 3,
- 'currency' => 4,
- 'description' => 5,
- 'custom' => 6,
- 'payment_mode' => 7,
- 'request_type' => 9,
- 'status' => 10,
- 'state' => 11,
- 'return_url' => 12,
- 'client_ip' => 20,
- 'cpc_ta_id' => 30,
- 'order_no' => 60,
- 'purpose' => 61,
- 'charset' => 70,
- 'lang' => 71,
- 'date_time' => 80,
- 'random' => 81,
- 'signature' => 99,
- );
-
- private static $aLegalCurrencies = array(
- 'UAH',
- 'RUB',
- 'USD',
- 'EUR',
- );
-
- private static $aLegalPaymentMode = array(
- 'paycard',
- 'account',
- 'ecurrency',
- 'copayco',
- 'terminal',
- 'sms',
- );
-
- private static $aLegalLanguages = array(
- 'ru',
- 'en',
- 'ua',
- );
-
- private static $aLegalCharsets = array(
- 'utf-8',
- 'windows-1251',
- 'koi8-r',
- 'koi8-u',
- );
-
- private $bTestMode = FALSE;
-
- private $sNotifyMode = 'curl';
-
- private $sErrMsg = NULL;
-
- private $sSignKey = NULL;
-
- private $iUseRand = 2;
-
- protected $iShopId = NULL;
-
- protected $sTaId = NULL;
-
- protected $iCPCTaId = NULL;
-
- protected $nAmount = NULL;
-
- protected $sCurrency = NULL;
-
- protected $sDescription = NULL;
-
- protected $mCustom = NULL;
-
- protected $aPaymentMode = array();
-
- protected $sCharset = NULL;
-
- protected $sLanguage = NULL;
-
- protected $sOrderNo = NULL;
-
- protected $sPurpose = NULL;
-
- protected $sDateTime = NULL;
-
- protected $iRand = NULL;
-
- protected $sState = NULL;
-
- protected $sReturnUrl = NULL;
-
- protected function __construct($sSignKey)
- {
- $aConf = $this->get_config($sSignKey);
-
- if (!empty($aConf['sign_key'])) {
- $this->sSignKey = $aConf['sign_key'];
- }
-
- if (!empty($aConf['shop_id'])) {
- $this->iShopId = $aConf['shop_id'];
- }
-
- if (!empty($aConf['notify_mode'])) {
- if (!in_array($aConf['notify_mode'], array('curl'))) {
- throw new copayco_exception('Incorrect notify mode: "' . $aConf['notify_mode'] . '".', 10001);
- }
- $this->sNotifyMode = $aConf['notify_mode'];
- }
-
- if (isset($aConf['charset'])) {
- $this->set_charset($aConf['charset']);
- }
-
- if (isset($aConf['use_rand'])) {
- $this->iUseRand = $aConf['use_rand'];
- }
-
- if (isset($aConf['test_mode'])) {
- $this->bTestMode = !empty($aConf['test_mode']);
- }
- }
-
- public static function instance($sSignKey = NULL)
- {
- return new copayco_api($sSignKey);
- }
-
-
- public function set_main_data($sTaId, $nAmount, $sCurrency = 'UAH', $iShopId = NULL)
- {
-
- if (empty($sTaId)) {
- throw new copayco_exception('Transaction ID can\'t be empty.', 10020);
- }
-
- if (empty($nAmount)) {
- throw new copayco_exception('Amount of payment can\'t be equal to 0.', 10030);
- }
- if (!is_numeric($nAmount)) {
- throw new copayco_exception('Amount must be numeric value.', 10031);
- }
- if ($nAmount < 0) {
- throw new copayco_exception('Amount must be greater than 0.', 10032);
- }
-
- if (!empty($iShopId)) {
- $this->iShopId = $iShopId;
- } elseif (empty($this->iShopId)) {
- throw new copayco_exception('Shop ID isn\'t set.', 10010);
- }
-
- if (empty($sCurrency) || !in_array($sCurrency, self::$aLegalCurrencies)) {
- throw new copayco_exception('Currency must be equal to "' . implode('", "', self::$aLegalCurrencies) . '".', 10040);
- }
- $this->sTaId = $sTaId;
- $this->nAmount = round($nAmount * 100);
- $this->sCurrency = $sCurrency;
- }
-
- public function set_description($sDescription)
- {
- if (!is_scalar($sDescription)) {
- throw new copayco_exception('Description must have a scalar value.', 10050);
- }
- $sDescription = (string)$sDescription;
- if (strlen($sDescription) > 255) {
- throw new copayco_exception('Description can\'t be more than 255 symbols.', 10051);
- }
- $this->sDescription = $sDescription;
- }
-
- public function set_custom_field($mCustom)
- {
- if (!is_scalar($mCustom)) {
- throw new copayco_exception('Custom field must have a scalar value.', 10060);
- }
- $mCustom = (string)$mCustom;
- if (strlen($mCustom) > 255) {
- throw new copayco_exception('Custom field can\'t be more than 255 symbols.', 10061);
- }
- $this->mCustom = $mCustom;
- }
-
- public function set_payment_mode($mPaymentMode)
- {
- if (empty($mPaymentMode)) {
- throw new copayco_exception('Payment Mode can\'t be empty.', 20070);
- }
- if (is_array($mPaymentMode)) {
- foreach ($mPaymentMode as $v) {
- $this->set_payment_mode($v);
- }
- } else {
- if (!is_scalar($mPaymentMode) || !in_array($mPaymentMode, self::$aLegalPaymentMode)) {
- throw new copayco_exception('Payment Mode must be equal to "' . implode('", "', self::$aLegalPaymentMode) . '".', 20071);
- }
- if (!in_array($mPaymentMode, $this->aPaymentMode)) {
- $this->aPaymentMode[] = $mPaymentMode;
- }
- }
- }
-
- public function clear_payment_mode()
- {
- $this->aPaymentMode = array();
- }
-
- public function set_charset($sCharset)
- {
- $sCharset = strtolower($sCharset);
- if (!in_array($sCharset, self::$aLegalCharsets)) {
- throw new copayco_exception('Incorrect Charset: "' . $sCharset . '".', 20700);
- }
- $this->sCharset = $sCharset;
- }
-
- public function set_language($sLanguage)
- {
- $sLanguage = strtolower($sLanguage);
- if (!in_array($sLanguage, self::$aLegalLanguages)) {
- throw new copayco_exception('Incorrect Language: "' . $sLanguage . '".', 20710);
- }
- $this->sLanguage = $sLanguage;
- }
-
- public function set_order_no($sOrderNo)
- {
- $this->sOrderNo = $sOrderNo;
- }
-
- public function set_purpose($sPurpose)
- {
- $this->sPurpose = $sPurpose;
- }
-
- public function get_form_fields($aAttr = array(), $sSeparator = '')
- {
- $mRet = is_null($sSeparator) ? array() : '';
- $this->set_date_and_rand();
- foreach ($this->prepare_send_data() as $k => $v) {
- $sTag = '<input type="' . (isset($aAttr[$k]['type']) ? $aAttr[$k]['type'] : 'hidden') . '" name="' . $k . '" value="' . htmlspecialchars($v) . '"';
- $sTag .= (isset($aAttr[$k]) ? $this->get_additional_attr($aAttr[$k]) : '') . ' />';
- if (is_null($sSeparator)) {
- $mRet[] = $sTag;
- } else {
- $mRet .= $sTag . $sSeparator;
- }
- }
- return $mRet;
- }
-
- public function get_request_uri($sSeparator = '&')
- {
- $sRet = '';
- $this->set_date_and_rand();
- foreach ($this->prepare_send_data() as $k => $v) {
- $sRet .= ($sRet ? $sSeparator : '') . $k . '=' . urlencode($v);
- }
- return $this->get_submit_url() . '?' . $sRet;
- }
-
- public function get_submit_url()
- {
- return $this->bTestMode ? self::SUBMIT_URL_TEST : self::SUBMIT_URL;
- }
-
- public function get_notification_url()
- {
- return $this->bTestMode ? self::NOTIFICATION_URL_TEST : self::NOTIFICATION_URL;
- }
-
-
- public function check_data()
- {
- if ($this->get_request_type() != 'check') {
- throw new copayco_exception('It isn\'t check request.', 30091);
- }
- $this->define_http_val();
- return $this->check_http_fields(self::$aCheckFields, TRUE);
- }
-
- public function set_error_message($sErrMsg)
- {
- if ($sErrMsg) {
- $this->sErrMsg = $sErrMsg;
- }
- }
-
- public function output_check_answer($sCharset = NULL)
- {
- $sMsg = $this->get_request_type() == 'check' ? ($this->sErrMsg ? $this->sErrMsg : 'ok') : 'It isn\'t check request.';
- $this->output_header($sMsg, $sCharset);
- echo $sMsg;
- }
-
-
- public function get_perform_status()
- {
- if ($this->get_request_type() != 'perform') {
- throw new copayco_exception('It isn\'t perform request.', 30092);
- }
- $this->define_http_val();
- if ($this->check_http_fields(self::$aPerformFields)) {
- return $this->get_http_val(self::STATUS_KEY);
- }
- throw new copayco_exception('Perform status isn\'t set.', 30093);
- }
-
- public function get_copayco_ta_id()
- {
- return $this->iCPCTaId;
- }
-
- public function is_reserved()
- {
- return $this->get_perform_status() == 'reserved';
- }
-
- public function is_finished()
- {
- return $this->get_perform_status() == 'finished';
- }
-
- public function is_canceled()
- {
- return $this->get_perform_status() == 'canceled';
- }
-
- public function output_perform_answer($sCharset = NULL)
- {
- $sMsg = $this->get_request_type() == 'perform' ? ($this->sErrMsg ? $this->sErrMsg : 'ok') : 'It isn\'t perform request.';
- $this->output_header($sMsg, $sCharset);
- echo $sMsg;
- }
-
-
- public function send_delivered_state()
- {
- $this->send_notification('delivered');
- }
-
- public function send_canceled_state()
- {
- $this->send_notification('canceled');
- }
-
-
- final public function get_request_type()
- {
- $sKey = self::REQUEST_TYPE_KEY;
- $sType = $this->get_http_val($sKey);
- if (!in_array($sType, array('check', 'perform'))) {
- throw new copayco_exception('Field "' . $sKey . '" contain incorrect data.', 30002 + self::$aFieldNumber[$sKey] * 10);
- }
- return $sType;
- }
-
- public function get_ta_id()
- {
- return $this->get_http_val(self::TA_ID_KEY);
- }
-
- public function get_request_data()
- {
- $aFields = $this->get_request_type() == 'check' ? self::$aCheckFields : self::$aPerformFields;
- $aRet = array();
- foreach ($aFields as $k => $v) {
- $mVal = $this->get_http_val($k);
- if (!is_null($mVal)) {
- $aRet[$k] = $mVal;
- }
- }
- return $aRet;
- }
-
- public function check_signature($sSignature)
- {
- return $this->sSignKey ? $this->get_signature() == $sSignature : TRUE;
- }
-
- final public function get_signature()
- {
- if ($this->sSignKey) {
- $sStr = $this->sTaId . $this->nAmount . $this->sCurrency;
- $sStr .= empty($this->mCustom) || !empty($this->sState) ? '' : $this->mCustom;
- $sStr .= empty($this->sState) ? '' : $this->sState;
- $sStr .= empty($this->sDateTime) ? '' : $this->sDateTime;
- $sStr .= empty($this->iRand) ? '' : $this->iRand;
- $sStr .= $this->sSignKey;
- return md5($sStr);
- } else {
- return NULL;
- }
- }
-
- final public function get_sign_key()
- {
- return $this->sSignKey;
- }
-
- public static function get_field_number($sKey = NULL)
- {
- return empty($sKey) ? self::$aFieldNumber : (isset(self::$aFieldNumber[$sKey]) ? self::$aFieldNumber[$sKey] : NULL);
- }
-
-
- protected function get_config($sSignKey)
- {
- $sConfPath = $this->get_config_path();
- $aRet = $sConfPath && file_exists($sConfPath) ? include($sConfPath) : array();
- if (!empty($sSignKey)) {
- $aRet['sign_key'] = $sSignKey;
- }
- return $aRet;
- }
-
- protected function get_config_path()
- {
- return dirname(__FILE__) . '/config.php';
- }
-
- protected function set_date_and_rand()
- {
- $this->sDateTime = date('Y-m-d H:i:s');
- if (!empty($this->iUseRand) && (empty($this->iRand) || $this->iUseRand > 1)) {
- $this->iRand = rand(1, 1024);
- }
- }
-
- protected function get_additional_attr($aAttr)
- {
- $sRet = '';
- if ($aAttr) {
- foreach ($aAttr as $k => $v) {
- if (!in_array($k, array('type', 'name', 'value'))) {
- $sRet .= ' ' . $k . '="' . $v . '"';
- }
- }
- }
- return $sRet;
- }
-
- protected function prepare_send_data()
- {
- $aRet = array();
- foreach (self::$aReqFields as $k => $v) {
- $mVal = $this->get_property_val($k, $v);
- if ($mVal) {
- if ($k == self::PAYMENT_MODE_KEY) {
- if (count($mVal) > 1) {
- $i = 0;
- foreach ($mVal as $v1) {
- $aRet[$k . '[' . $i++ . ']'] = $v1;
- }
- } else {
- $aRet[$k] = $mVal[0];
- }
- } else {
- $aRet[$k] = $mVal;
- }
- }
- }
- return $aRet;
- }
-
- protected function get_property_val($sField, $bRequired)
- {
- $nNum = self::$aFieldNumber[$sField] * 10;
- if ($sField == self::SIGNATURE_KEY) {
- $mPropVal = $this->get_signature();
- } else {
- $sProp = self::$aCorrespondence[$sField];
- $mPropVal = $this->$sProp;
- }
- if ($bRequired && !$mPropVal) {
- throw new copayco_exception('Required field "' . $sField . '" isn\'t set.', 20001 + $nNum);
- }
- return $mPropVal;
- }
-
- protected function check_http_fields($aCheckFields, $bSetErrMsg = FALSE)
- {
- foreach ($aCheckFields as $k => $v) {
- $nNum = self::$aFieldNumber[$k] * 10;
- $mVal = $this->get_http_val($k);
- if ($v && is_null($mVal)) {
- $this->fix_error_message('Undefined required field "' . $k . '".', 30001 + $nNum, $bSetErrMsg);
- }
- $sProp = isset(self::$aCorrespondence[$k]) ? self::$aCorrespondence[$k] : NULL;
- if ($v && $sProp && $mVal != $this->$sProp) {
- $this->fix_error_message('Field "' . $k . '" contain incorrect data.', 30002 + $nNum, $bSetErrMsg);
- }
- }
- if (!$this->check_signature($this->get_http_val(self::SIGNATURE_KEY))) {
- $this->fix_error_message('Request contain incorrect signature.', 30992, $bSetErrMsg);
- }
- return TRUE;
- }
-
- protected function fix_error_message($sErrMsg, $nCode, $bSetErrMsg)
- {
- if ($bSetErrMsg) {
- $this->set_error_message($sErrMsg);
- }
- throw new copayco_exception($sErrMsg, $nCode);
- }
-
- protected function define_http_val()
- {
- $aCor = array_flip(self::$aCorrespondence);
- foreach (self::$aAutoFill as $v) {
- if (empty($this->$v)) {
- $this->$v = $this->get_http_val($aCor[$v]);
- }
- }
- }
-
- protected function get_http_val($sKey)
- {
- return isset($_POST[$sKey]) ? $_POST[$sKey] : (isset($_GET[$sKey]) ? $_GET[$sKey] : NULL);
- }
-
- protected function send_notification($sState)
- {
- $this->sState = $sState;
- $oCurl = curl_init($this->get_notification_url());
- curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
- if ($this->bTestMode) {
- curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, 0);
- curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, 0);
- }
- $this->set_date_and_rand();
- $aData = array();
- foreach (self::$aNotificationFields as $k => $v) {
- $aData[$k] = $this->get_property_val($k, $v);
- }
- curl_setopt($oCurl, CURLOPT_POSTFIELDS, $aData);
- curl_exec($oCurl);
- $sErr = curl_error($oCurl);
- curl_close($oCurl);
- if ($sErr) {
- throw new copayco_exception('There is CURL error ocured:' . $sErr, 50001);
- }
- }
-
- protected function output_header($sMsg, $sCharset = NULL)
- {
- if (empty($sCharset)) {
- $sCharset = empty($this->sCharset) ? 'utf-8' : $this->sCharset;
- }
- header('Content-Type: text/plain; charset=' . $sCharset);
- header('Accept-Ranges: bytes');
- header('Content-Length: ' . strlen($sMsg));
- header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
- header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
- header(
- $_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0' ?
- 'Pragma: no-cache' :
- 'Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0'
- );
- }
- }
- class copayco_exception extends Exception
- {
-
- public function get_error_type_code()
- {
- return substr($this->getCode(), 0, 2);
- }
-
- public function get_field_code()
- {
- return substr($this->getCode(), 2, 2);
- }
-
- public function get_error_serial_number()
- {
- return substr($this->getCode(), -1);
- }
-
- public function get_field_name()
- {
- $aFields = array_flip(copayco_api::get_field_number());
- $nCode = (int)$this->get_field_code();
- return $nCode && isset($aFields[$nCode]) ? $aFields[$nCode] : NULL;
- }
- }
- ?>
|