✏️ 正在编辑: AxeptaApi.php
路径:
/home/bpioifn/www/pigmentse/modules/axepta/classes/AxeptaApi.php
提示:
您可以编辑任何文件(包括二进制文件),但请注意不当修改可能导致文件损坏。
<?php /** * 1961-2020 BNP Paribas * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 3.0) that is available * through the world-wide-web at this URL: http://www.opensource.org/licenses/OSL-3.0 * If you are unable to obtain it through the world-wide-web, please send an email * to modules@quadra-informatique.fr so we can send you a copy immediately. * * @author Quadra Informatique <modules@quadra-informatique.fr> * @copyright 1961-2020 BNP Paribas * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ require_once _PS_MODULE_DIR_.'axepta/classes/AxeptaOrderReference.php'; require_once _PS_MODULE_DIR_.'axepta/classes/AxeptaBlowfish.php'; require_once _PS_MODULE_DIR_.'axepta/classes/AxeptaCustomerRecurringPaymentCard.php'; require_once _PS_MODULE_DIR_.'axepta/classes/AxeptaLogger.php'; require_once _PS_MODULE_DIR_.'axepta/classes/AxeptaIsoCountry.php'; require_once _PS_MODULE_DIR_.'axepta/axepta.php'; require_once(_PS_CONFIG_DIR_.'/config.inc.php'); class AxeptaApi { const PAYMENT = 'payment'; const REFUND = 'refund'; const CANCEL = 'cancel'; const ANTICIPATE_REFUND = 'ANTICIPATE_REFUND'; const CARDS_WITHOUT_TRI_TO_DISABLE = ''; const CARDS_WITH_N_TIMES = 'CB,VISA,MASTERCARD,AMEX'; const INITIAL_PAYMENT = 'I'; const INITIAL_RECURRING_PAYMENT = 'R'; const URL_INQUIRE_WITH_PAYID = 'https://paymentpage.axepta.bnpparibas/inquire.aspx'; const ONECLICK = 'oneclick'; const RECCURING = 'recurring'; const MAX_TRANSID_SIZE = 13; const MIN_CETELEM_AMOUNT = 90; const MAX_CETELEM_AMOUNT = 3000; const MIN_CETELEM_PRESTO_AMOUNT = 150; const MAX_CETELEM_PRESTO_AMOUNT = 16000; const MAX_REFNR_LENGTH = 12; public static $IGNORE_IFRAME = [ 'FC3', 'FC4' ]; public static function getPaymentMethods($iso_country, $id_currency, $abo = false) { if (Tools::strlen($iso_country) >= 3) { $iso_country = explode(',', (string)$iso_country); } else { $iso_country = [(string)$iso_country]; } $iso_country[] = 'ALL'; $currency = new Currency((int)$id_currency); $operation = self::PAYMENT; if ($abo) { $operation = self::RECCURING; } $methods = Db::getInstance()->executeS(' SELECT * FROM '._DB_PREFIX_.'axepta_xml_method xm LEFT JOIN '._DB_PREFIX_.'axepta_xml_parameter_set xps ON xps.method_id = xm.id LEFT JOIN '._DB_PREFIX_.'axepta_xml_allow_countries xac ON xac.method_id = xm.id LEFT JOIN '._DB_PREFIX_.'axepta_xml_method_lang xmla ON xmla.method_id = xm.id WHERE xps.operation = "'.pSQL($operation).'" AND xac.currency IN ("'.pSQL($currency->iso_code).'", "ALL") AND xac.country IN ("'.(string)implode($iso_country, '","').'") GROUP BY xm.id '); return $methods; } public static function getPaymentMethodsWithoutMethods($id_country, $id_currency, $abo = false) { if (Tools::strlen($id_country) >= 3) { $countries = str_replace(',', '", "', $id_country); } else { $countries = $id_country; } $currency = new Currency((int)$id_currency); $operation = self::PAYMENT; if ($abo) { $operation = self::RECCURING; } $methods = Db::getInstance()->executeS(' SELECT * FROM '._DB_PREFIX_.'axepta_xml_method xm LEFT JOIN '._DB_PREFIX_.'axepta_xml_parameter_set xps ON xps.method_id = xm.id LEFT JOIN '._DB_PREFIX_.'axepta_xml_allow_countries xac ON xac.method_id = xm.id LEFT JOIN '._DB_PREFIX_.'axepta_xml_method_lang xmla ON xmla.method_id = xm.id WHERE xps.operation = "'.pSQL($operation).'" GROUP BY xm.id '); return $methods; } /** * Decrypt Activation key */ public static function decryptActivationKey($key) { $datas = (explode("\n", $key)); $data = trim($datas[0]); $public_key_res = openssl_pkey_get_public(Tools::file_get_contents(_PS_MODULE_DIR_.'axepta/tools/rsa.pub')); $signature = trim(Tools::substr($key, strpos($key, "\n") + 1)); $signature_decode = base64_decode($signature); if (function_exists('openssl_verify')) { $result = openssl_verify($data, $signature_decode, $public_key_res); if ($result == 1) { return true; } elseif ($result == 0) { return false; } } return false; } /** * Decrypt Activation key */ public static function ctDecrypt($cipher, $len, $password) { $blowfish = new AxeptaBlowfish(); if (mb_strlen($password) <= 0) { $password = ' '; } # converts hex to bin $cipher = pack('H'.strlen($cipher), $cipher); if ($len > strlen($cipher)) { echo 'Length mismatch. The parameter len is too large.'; return false; } $blowfish->bfSetKey($password); return mb_substr($blowfish->decrypt($cipher), 0, $len); } public static function isFeatureActivated($feature_list, $activation_key = '') { if (!is_array($feature_list)) { $feature_list = array($feature_list); } // Get only trigramme $keys = explode(';', $activation_key); array_pop($keys); $found = true; foreach ($feature_list as $feature) { if (!in_array($feature, $keys) && $feature != "ABO" && $feature != "ONE" && $feature != "3DS") { $found = false; } } return $found; } /** * Create MAC * @param type $TransID * @param type $Amount * @return type */ public static function creatingMacValue($merchant_id, $TransID, $Amount = '', $PayId = '') { $context = Context::getContext(); $merchant = new AxeptaConfigurationAccount($merchant_id); return self::ctHMAC($merchant->mid, $Amount, $context->currency->iso_code, $merchant->hmac_key, $PayId, $TransID); } /** * return hash hmac * * @param type $PayId * @param type $TransID * @param type $MerchantID * @param type $Amount * @param type $Currency * @param type $HmacPassword * @return type */ public static function ctHMAC($MerchantID, $Amount, $Currency, $HmacPassword, $PayId = "", $TransID = "") { return hash_hmac("sha256", "$PayId*$TransID*$MerchantID*$Amount*$Currency", $HmacPassword); } /** * format params * @param type $params */ public static function formatParams($params, $trigram, $id_merchant_account, $url_bnp) { // delete empty parameters $context = Context::getContext(); foreach ($params as $key => $value) { if (is_null($value) || empty($value)) { unset($params[$key]); } } $pay_id = isset($params['PayID']) ? $params['PayID'] : ''; $amount = isset($params['Amount']) ? $params['Amount'] : ''; $trans_id = isset($params['TransID']) ? $params['TransID'] : ''; $merchant = new AxeptaConfigurationAccount($id_merchant_account); $MAC = "MAC=".self::creatingMacValue($id_merchant_account, $trans_id, $amount, $pay_id); $data = array(); foreach ($params as $key => $value) { $data[] = "$key=$value"; } $data[] = $MAC; $plaintext = join("&", $data); $Len = mb_strlen($plaintext); /* if trans_id existe pour id_cart */ $ref = AxeptaOrderReference::getReferenceByCartId($context->cart->id); $res = AxeptaTransaction::getTransactionByReference($ref); if ($res) { $transaction = new AxeptaTransaction($res['id_axepta_transaction']); } else { $transaction = null; } if (!is_null($transaction)) { $merchant = new AxeptaConfigurationAccount($transaction->id_axepta_configuration_account); $merchant_name = $merchant->mid; $password = $merchant->password; } else { $merchant = new AxeptaConfigurationAccount($id_merchant_account); $merchant_name = $merchant->mid; $password = $merchant->password; } $dataEncrypted = self::ctEncrypt($plaintext, $Len, $password); if (!$dataEncrypted) { echo 'They are a problem with the payment process. Please contact Axepta Online BNP Paribas support.'; exit; } $link = new Link(); if ($merchant->mode_view == 2) { $url_back = $link->getModuleLink('axepta', 'returniframe', array(), true); } else { $url_back = $link->getPageLink('cart?action=show', true); } return [ 'Data' => $dataEncrypted, 'Len' => $Len, 'mid' => $merchant_name, 'url' => $url_bnp, 'url_back' => $url_back, ]; } /** * Encrypt the passed text (any encoding) with Blowfish. * * @param string $plaintext * @param integer $len * @param string $password * @return bool|string */ public static function ctEncrypt($plaintext, $len, $password) { $blowfish = new AxeptaBlowfish(); if (mb_strlen($password) <= 0) { $password = ' '; } if (mb_strlen($plaintext) != $len) { echo 'Length mismatch. The parameter len differs from actual length.'; return false; } $plaintext = $blowfish->expand($plaintext); $blowfish->bfSetKey($password); return bin2hex($blowfish->encrypt($plaintext)); } public static function getAllMethodsInBdd() { return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'axepta_xml_method'); } /** * Get parameters in bdd * @global type $wpdb * @param type $operation * @return type */ public static function getParamsInBdd($operation, $trigram, $ccBrand = null) { if (!is_null($ccBrand)) { $methods = self::getAllMethodsInBdd(); foreach ($methods as $method) { $cc_brand_explode = explode('/', $method->code); foreach ($cc_brand_explode as $key => $value) { if ($value == $ccBrand) { $trigram = $method->trigram; } } } } return Db::getInstance()->executeS('SELECT axp.id, axp.name, axp.format,axp.required FROM '._DB_PREFIX_.'axepta_xml_parameter axp ' .'LEFT JOIN '._DB_PREFIX_.'axepta_xml_parameter_set axps ON axps.parameter_set_id = axp.parameter_set_id ' .'LEFT JOIN '._DB_PREFIX_.'axepta_xml_method axm ON axm.id = axps.method_id ' .'WHERE axps.operation = "'.pSQL($operation).'" AND axm.trigram = "'.pSQL($trigram).'" '); } /** * Get the payment params * */ public static function getUrlByTrigramAndOperation($trigram, $operation) { if ($trigram && $operation) { return Db::getInstance()->getValue('SELECT url FROM '._DB_PREFIX_.'axepta_xml_parameter_set a ' .'LEFT JOIN '._DB_PREFIX_.'axepta_xml_method axm ON a.method_id = axm.id ' .' WHERE axm.trigram = "'.pSQL($trigram).'" AND operation = "'.pSQL($operation).'" '); } return false; } /** * Get the payment params * */ public static function getIdAccountAndIdCurrency($id_country, $id_currency) { $iso_code = Country::getIsoById($id_country); if (Shop::isFeatureActive()) { $id_shop = Context::getContext()->shop->id; return Db::getInstance()->getValue('SELECT a.id_axepta_configuration_account FROM '._DB_PREFIX_.'axepta_configuration_account a LEFT JOIN '._DB_PREFIX_.'axepta_configuration_account_shop as ash ON a.id_axepta_configuration_account = ash.id_axepta_configuration_account' .' WHERE a.id_country LIKE "%'.pSQL($iso_code).'%" AND a.id_currency = "'.pSQL($id_currency).'" AND a.active = 1 AND ash.id_shop ='.(int)$id_shop); } else { return Db::getInstance()->getValue('SELECT id_axepta_configuration_account FROM '._DB_PREFIX_.'axepta_configuration_account a ' .' WHERE a.id_country LIKE "%'.pSQL($iso_code).'%" AND a.id_currency = "'.pSQL($id_currency).'" AND a.active = 1'); } } /** * Get the payment params * */ public function getLastCountryOrderForCustomer($id_customer) { if (empty($id_customer)) { return null; } return Db::getInstance()->getValue('SELECT a.`id_country`' . ' FROM `' . _DB_PREFIX_ . 'orders` o ' . ' LEFT JOIN `' . _DB_PREFIX_ . 'address` a ON a.`id_address` = o.`id_address_delivery`' . ' WHERE o.`id_customer` = "' . pSQL((int)$id_customer) . '"' . ' ORDER BY o.`id_order` DESC '); } /** * Get the payment params * */ public static function getIdAccountByIdCountryAndIdCurrencyVerifyAllExist($id_country, $id_currency) { if (Shop::isFeatureActive()) { $id_shop = Context::getContext()->shop->id; return Db::getInstance()->getValue('SELECT a.id_axepta_configuration_account FROM '._DB_PREFIX_.'axepta_configuration_account a LEFT JOIN '._DB_PREFIX_.'axepta_configuration_account_shop as ash ON a.id_axepta_configuration_account = ash.id_axepta_configuration_account' .' WHERE a.id_country = "ALL" AND a.id_currency = "'.(int)$id_currency.'" AND a.active = 1 AND ash.id_shop ='.(int)$id_shop); } else { return Db::getInstance()->getValue('SELECT id_axepta_configuration_account FROM '._DB_PREFIX_.'axepta_configuration_account a ' .' WHERE a.id_country = "ALL" AND a.id_currency = "'.(int)$id_currency.'" AND a.active = 1'); } } public static function getParams($trigram, $operation, $id_account, $id_saved_card = null, $id_recurring = null, $schedule = null, $transaction_id = null, $amount = null) { $context = Context::getContext(); $cart = new Cart($context->cart->id); if (!$amount) { $amount = $context->cart->getOrderTotal() * 100; $amount = preg_replace('~\.0+$~', '', $amount); } // init merchant if (!is_null($transaction_id)) { $transaction = new AxeptaTransaction($transaction_id); $merchantId = $transaction->merchant_id; $merchant = new AxeptaConfigurationAccount($transaction->id_axepta_configuration_account); } else { $transaction = new AxeptaTransaction(); if (!(int)$id_account) { $account_id = self::getIdAccountAndIdCurrency($context->country->id, $context->currency->id); if (!$account_id) { $account_id = self::getIdAccountByIdCountryAndIdCurrencyVerifyAllExist($context->country->id, $context->currency->id); } } else { $account_id = (int)$id_account; } $merchant = new AxeptaConfigurationAccount((int)$account_id); $merchantId = $merchant->mid; } // init 3ds if ($merchant) { if (!((bool) $merchant->secure_exemption && $amount < $merchant->secure_exemption_amount * 100)) { $amount3d = $amount; $amount = $amount; } else { $amount3d = 0; } } $qty = 1; if (isset($schedule)) { $recurring_payment = new AxeptaCustomerPaymentRecurring($schedule['id_axepta_customer_payment_recurring']); // $amount = $recurring_payment->amount_tax_exclude * 100; if ((int)$recurring_payment->getLateRecurringOccurence()) { $qty = (int)$recurring_payment->getLateRecurringOccurence(); } $amount = $qty * $amount; } $reference = Order::generateReference(); if (!empty($reference)) { $reference = AxeptaOrderReference::addCartReference((int)$cart->id, $reference); } if (is_null($merchantId)) { exit; } $params = self::getParamsInBdd($operation, $trigram); $arrayParams = []; // One Click // Initial Payment if (\Tools::getIsset('checkbox_state') && \Tools::getValue('checkbox_state') == "true" && empty($id_saved_card)) { $params[] = ['name' => 'credentialOnFile']; $params[] = ['name' => 'threeDSPolicy']; $credentialOnFileType = ['unscheduled' => 'CIT']; $credentialOnFileInitPayment = true; $credentialOnFileUseCase = "cof"; } // One click if ($operation == 'oneclick') { $credentialOnFileType = ['unscheduled' => 'CIT']; $credentialOnFileInitPayment = false; $credentialOnFileUseCase = "cof"; } if ($merchant->capture_method == 2 && Tools::getValue('method_code') != 'PAL') { $capture = (int)$merchant->capture_hours; } else { $capture = 'AUTO'; } $card_recurring = new AxeptaCustomerRecurringPaymentCard($id_recurring); // I = Initial payment for the new subscription if ($operation == 'recurring' && $card_recurring) { $credentialOnFileType = ['unscheduled' => 'MIT']; $credentialOnFileInitPayment = false; $credentialOnFileUseCase = "ucof"; $card = $card_recurring; if (Tools::getValue('method_code') == 'PAL') { $BillingAgreementID = $card_recurring->bid; } } elseif ($operation == 'recurring' && !$card_recurring && Tools::getValue('method_code') == 'PAL') { $RTF = self::INITIAL_PAYMENT; } else { $RTF = null; } if (Tools::getValue('is_recurring')) { $params[] = ['name' => 'credentialOnFile']; $params[] = ['name' => 'threeDSPolicy']; $credentialOnFileType = ['unscheduled' => 'CIT']; $credentialOnFileInitPayment = true; $credentialOnFileUseCase = "ucof"; } // paypal specifications if (Tools::getValue('method_code') == 'PAL' && ($context->currency->iso_code == 'HUF' || $context->currency->iso_code == 'TWD')) { $amount = $amount / 100; } $address_delivery = new Address($context->cart->id_address_delivery); $address_invoice = new Address($context->cart->id_address_invoice); // conrrespondant à facturation. $country = new Country($address_invoice->id_country); $state = new State($address_delivery->id_state); $url_bnp = self::getUrlByTrigramAndOperation($trigram, $operation); $link = new Link(); $url_back = $link->getModuleLink('axepta', 'confirmation', array(), true); $countryIso3 = new AxeptaIsoCountry($address_invoice->id_country); $countryDeliveryIso3 = $address_invoice->id_country == $address_delivery->id_country ? $countryIso3 : new AxeptaIsoCountry($address_delivery->id_country); if ($trigram == 'FC3') { $payType = 1; } elseif ($trigram == 'FC4') { $payType = 2; } $gender = 'Mr'; if ($context->customer->id_gender != 1) { $gender = 'Mme'; } // Anonymous functions $setToCustomer = function ($address, $customer) { return [ 'consumer' => [ 'firstName' => $address->firstname, 'lastName' => $address->lastname, 'birthDate' => $customer->birthday ], 'email' => $customer->email ]; }; $setAddress = function ($address, $countryIso) { return [ 'city' => $address->city, 'country' => [ 'countryA3' => strtolower($countryIso->iso_code_3) ], 'addressLine1' => [ 'street' => substr($address->address1, 0, 32) ], 'postalCode' => $address->postcode ]; }; $setThreeDSPolicy = function ($currency, $is_exemption_active, $amount, $frictionless_value, $secure_exemption_amount, $register_card, $is_recurring) { $amount /= 100; if ($register_card || $is_recurring) { return ['challengePreference' => 'mandateChallenge']; } if (!$is_exemption_active || $amount > $secure_exemption_amount) { return ['challengePreference' => 'noPreference']; } if ($currency == 'EUR' && $amount <= $frictionless_value) { return ['threeDSExemption' => ['exemptionReason' => 'lowValue']]; } return ['challengePreference' => 'noChallenge']; }; foreach ($params as $param) { $value = null; switch ($param['name']) { case 'threeDSPolicy': $value = self::encodeParamJson($setThreeDSPolicy( $context->currency->iso_code, $merchant->secure_exemption, $amount, $merchant::FRICTION_LESS_VALUE, $merchant->secure_exemption_amount, filter_var(Tools::getValue('checkbox_state'), FILTER_VALIDATE_BOOLEAN), filter_var(Tools::getValue('is_recurring'), FILTER_VALIDATE_BOOLEAN) )); break; case 'billingAddress': $value = self::encodeParamJson($setAddress($address_invoice, $countryIso3)); break; case 'shippingAddress': $value = self::encodeParamJson($setAddress($address_delivery, $countryDeliveryIso3)); break; case 'billToCustomer': $value = self::encodeParamJson($setToCustomer($address_invoice, $context->customer)); break; case 'shipToCustomer': $value = self::encodeParamJson($setToCustomer($address_delivery, $context->customer)); break; case 'RefNr': $value = str_pad($reference, self::MAX_REFNR_LENGTH, '0', STR_PAD_LEFT); break; case 'MerchantID': $value = $merchantId; break; case 'MsgVer': $value = (!empty(Configuration::getGlobalValue('AXEPTA_MSG_VER'))) ? Configuration::getGlobalValue('AXEPTA_MSG_VER') :'2.0'; break; case 'credentialOnFile': if (is_array($credentialOnFileType)) { $value = [ 'type' => $credentialOnFileType, 'initialPayment' => $credentialOnFileInitPayment, 'useCase' => $credentialOnFileUseCase, ]; $value = self::encodeParamJson($value); } break; case 'card': if (isset($card) && is_object($card)) { $value = [ 'expiryDate' => $card->ccexpiry, 'cardholderName' => $card->holder_name ?? $context->customer->firstname . ' ' . $context->customer->lastname, 'number' => $card->pcnr, 'brand' => $card->ccbrand, ]; $value = self::encodeParamJson($value); } break; case 'browserInfo': $http_accept_language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 8); $explode = explode(',', $http_accept_language); if (strlen($explode[0]) > strlen($explode[1])) { $lang = $explode[0]; } else { $lang = $explode[1]; } $value = [ 'acceptHeaders' => $_SERVER['HTTP_ACCEPT'], 'ipAddress' => $_SERVER['REMOTE_ADDR'], 'javaScriptEnabled' => true, 'language' => $lang, 'userAgent' => $_SERVER['HTTP_USER_AGENT'], 'colorDepth' => 24, 'screenHeight' => 723, 'screenWidth' => 1536, 'timeZoneOffset' => "300", ]; $value = self::encodeParamJson($value); break; case 'TransID': if ($transaction->id) { $value = $transaction->id; } else { $value = $reference; } break; case 'Amount': $value = (int)$amount; break; case 'Amount3D': $value = (int)$amount3d; break; case 'Currency': $value = $context->currency->iso_code; break; case 'URLSuccess': $value = $url_back ?? null; break; case 'URLFailure': $value = $url_back ?? null; break; case 'Response': $value = 'encrypt'; break; case 'URLNotify': $value = $url_back ?? null; break; case 'UserData': $value = 'amount_'.(int)$amount; break; case 'Capture': $value = $capture; break; case 'OrderDesc': if ($merchantId == 'BNP_DEMO_AXEPTA') { $value = 'Test:0000'; } else { $value = $context->shop->name . ' Cart N°' . $context->cart->id; } break; case 'ReqID': $value = '20'.Tools::strlen($context->cart->id).'-'.Tools::strtoupper(uniqid($context->cart->id)); break; case 'Custom': $value = 'id_merchant=' . (int) $merchant->id_axepta_configuration_account . '|mid=' . $merchant->mid . '|operation=' . $operation . '|save_payment=' . Tools::getValue('checkbox_state') . '|is_recurring=' . Tools::getValue('is_recurring') . '|trigram=' . $trigram; break; case 'RTF': $value = $RTF; break; case 'ChDesc': $value = null; break; case 'Template': $value = null; break; case 'Language': $value = Tools::substr($context->language->iso_code, 0, 2); break; case 'PayID': $value = $transaction->pay_id; break; case 'Textfeld1': $value = null; break; case 'Textfeld2': $value = null; break; case 'CCNr': $value = $CCNr; break; case 'CCExpiry': $value = $CCExpiry; break; case 'CCBrand': $value = $CCBrand; break; case 'AddrCountryCode': $value = $country->iso_code; break; case 'AccOwner': $value = $address_invoice->lastname; break; case 'FirstName': $value = $context->customer->firstname; break; case 'LastName': $value = $context->customer->lastname; break; case 'AddrStreet': $value = $address_delivery->address1; break; case 'AddrStreet2': $value = $address_delivery->address2; break; case 'AddrCity': $value = $address_delivery->city; break; case 'AddrState': if ($state->name) { $value = $state->name; } else { $value = $context->country->iso_code; } break; case 'AddrZip': case 'bdZip': case 'AddrZIP': $value = $address_delivery->postcode; break; case 'UI': $value = 'hermes'; break; case 'BuyerEMail': $value = $context->customer->email; break; case 'Email': $value = $context->customer->email; break; case 'Phone': $value = self::checkRegexpData($address_delivery->phone); break; case 'BillingAgreementID': $value = $BillingAgreementID; break; case 'CustomerID': $value = (int)$context->customer->id; break; case 'SocialSecurityNumber': $value = Tools::getValue('security_social_number') ?? null; break; case 'PayType': $value = $payType; break; case 'Salutation': $value = $gender; break; case 'bdFirstName': $value = $context->customer->firstname; break; case 'bdLastName': $value = $context->customer->lastname; break; case 'bdStreet': $value = $address_delivery->address1; break; case 'bdZip': $value = $address_delivery->postcode; break; case 'bdCity': $value = $address_delivery->city; break; case 'bdCountryCode': $value = $context->country->iso_code; break; case 'UseBillingData': $value = 'yes'; break; } $arrayParams[$param['name']] = $value; } $axeptaModule = \Module::getInstanceByName('axepta'); $arrayParams['EtiId'] = 'PRSHP_' . _PS_VERSION_ . '_WE_' . $axeptaModule->version; // Cetelem Presto specifications if ($trigram == 'PRE') { $account_configuration = new AxeptaConfigurationAccount($id_account); $arrayParams['GoodsCategory'] = $account_configuration->presto_product_category; $arrayParams['AddrStreet'] = substr($arrayParams['AddrStreet'], 0, 32); } elseif ($trigram == 'FC3' || $trigram == 'FC4') { $arrayParams['bdZip'] = $address_delivery->postcode; } if (!self::verifyParam($params, $arrayParams)) { exit; } if ($merchant->logs) { $message = ''; if (is_array($arrayParams)) { foreach ($arrayParams as $key => $row_params) { if (is_array($row_params)) { foreach ($row_params as $key_row => $row_param) { $message .= ' | '.$key_row.' => '.$row_param; } } else { $message .= ' | '.$key.' => '.$row_params; } } } AxeptaLogger::log($message, AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); } $params_returned = self::formatParams($arrayParams, $trigram, $id_account, $url_bnp); $currency = new Currency(Context::getContext()->cart->id_currency); if (Validate::isLoadedObject($currency)) { $customField1 = number_format($amount / 100, 2)." ".$currency->iso_code; } else { $customField1 = number_format($amount / 100, 2); } # Add amount and order reference on CustomField to display them on payment page $language = mb_substr($context->language->iso_code, 0, 2); // CustomField4 $cartProducts = $cart->getProducts(); $tempCustomField4 = array(); $cartQuantity = 0; foreach ($cartProducts as $cartProduct) { $cartQuantity += $cartProduct['cart_quantity']; $tempCustomField4[] = $cartProduct['cart_quantity'] . ' x ' . $cartProduct['name']; } $customField4 = implode('|', $tempCustomField4); // CustomField6 $customField6 = sprintf( '%s|%s|%s', $address_delivery->lastname . ' ' . $address_delivery->firstname, $address_delivery->address1, $address_delivery->postcode . ' ' . $address_delivery->city ); $params_returned['CustomField1'] = $customField1; $params_returned['CustomField2'] = $arrayParams['TransID']; $params_returned['CustomField3'] = $context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO')); $params_returned['CustomField4'] = $axeptaModule->l('Total number of items : ') . $cartQuantity . '||' . $customField4; // Order Detail $params_returned['CustomField6'] = $customField6; // Delivery Address $params_returned['Language'] = $language; return $params_returned; } /** * Encode param in json format * @param array $param * @return string */ public static function encodeParamJson($param) { if (is_array($param)) { return base64_encode(json_encode($param)); } return false; } /** * Decode param in json format * @param string $param * @return array */ public static function decodeParamJson($param) { if ($param) { return json_decode(base64_decode($param), true); } return false; } public static function verifyParam($paramsInBdd, $params) { $required = 'M'; foreach ($params as $paramName => $data) { for ($i = 0; $i < sizeof($paramsInBdd); $i++) { if ($paramsInBdd[$i]['name'] === $paramName) { $isRequired = $paramsInBdd[$i]['required']; $format = $paramsInBdd[$i]['format']; break; } } if ($isRequired !== $required) { return true; } if ($format == 'JSON') { continue; } // Lenght is fixed or is max ? if (strpos($format, '.')) { $lenghtFixed = false; } else { $lenghtFixed = true; } // verify lenght of string $lenght = preg_replace('/[^0-9]/', '', $format); if ($lenghtFixed) { if (Tools::strlen($data) != $lenght) { echo 'Lenght of '.$paramName.' is not equal to '.$lenght; return false; } } else { if (Tools::strlen($data) > $lenght) { echo 'Lenght of '.$paramName.' is greater than '.$lenght; return false; } } //verify data $alphaNumFormat = preg_replace('/[^a-zA-Z]/', '', $format); switch (Tools::strtolower($alphaNumFormat)) { // alphanumeric with special characters case 'ans': break; // alphabetical only case 'a': if (!preg_match("/[a-z\s]/i", $data)) { echo $paramName.' is not only alphabetical string'; return false; } break; // alphabetical with special characters case 'as': if (preg_match('~[0-9]~', $data)) { echo $paramName.' contains digit number'; return false; } break; // numeric only case 'n': if (!is_numeric($data)) { echo $paramName.' is not only numeric'; return false; } break; // alphanumeric case 'an': if (preg_match('/[^a-z_\-0-9]/i', $data)) { echo $paramName.' is not only alphanumeric'; return false; } break; case 'ns': if (preg_match('~[a-zA-Z]~', $data)) { echo $paramName.' contains alphabetical letter'; return false; } break; case 'bool': if (!is_bool($data)) { echo $paramName.' is not a boolean'; return false; } break; } } return true; } /** * * Get an order by its cart id * @param integer $id_cart * @param integer $id_shop * @return integer */ public static function getOrderByCartId($id_cart, $id_shop) { $sql = 'SELECT `id_order` FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$id_cart.' AND `id_shop` = '.(int)$id_shop; $result = Db::getInstance()->getRow($sql); return isset($result['id_order']) ? $result['id_order'] : false; } public static function ctSplit($value) { $array = array(); for ($i = 0; $i < sizeof($value); $i++) { $explode = explode('=', $value[$i]); $array[$explode[0]] = $explode[1]; } return $array; } /* fonction abonnement */ public function sendRecurringSchedules() { global $kernel; if (!$kernel) { require_once _PS_ROOT_DIR_.'/app/AppKernel.php'; $kernel = new \AppKernel('prod', false); $kernel->boot(); } $module = Module::getInstanceByName('axepta'); $schedules = AxeptaPaymentRecurring::getShedulesToCapture(); if (!empty($schedules)) { $this->context = Context::getContext(); foreach ($schedules as $schedule) { $this->context->schedule = $schedule; $this->context->customer = new Customer((int)$this->context->schedule['id_customer']); $order = new Order($schedule['id_order']); $currency = new Currency($order->id_currency); $this->context->order = $order; $this->context->currency = $currency; $transaction = new AxeptaTransaction($schedule['id_axepta_transaction']); $merchant = new AxeptaConfigurationAccount($transaction->id_axepta_configuration_account); if (!$merchant) { $rawData = json_decode($schedule['raw_data']); $id_merchant = AxeptaConfigurationAccount::getIdByMid($rawData['mid']); $merchant = new AxeptaConfigurationAccount($id_merchant); } if (!$merchant) { AxeptaLogger::log('Merchant not found', AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); $schedule_update = new AxeptaCustomerPaymentRecurring($schedule['id_axepta_customer_payment_recurring']); $schedule_update->status = AxeptaCustomerPaymentRecurring::STATUS_PAUSE; $schedule_update->save(); exit; } //if (AxeptaApi::isFeatureActivated('ABO', $merchant->activation_key)) { $this->createCart(); $id_recurring_payment_card = AxeptaCustomerRecurringPaymentCard::getIdByIdCustomerAndIdAxeptaCustomerPaymentRecurring((int) $order->id_customer, (int) $schedule['id_axepta_customer_payment_recurring']); $recurring_payment_card = new AxeptaCustomerRecurringPaymentCard($id_recurring_payment_card); $operation = AxeptaTransaction::RECURRING; $trigram = AxeptaCustomerRecurringPaymentCard::getTrigramByCcbrand($recurring_payment_card->ccbrand); $url = AxeptaApi::getUrlByTrigramAndOperation($trigram, $operation); //$merchant = new AxeptaConfigurationAccount($transaction->id_axepta_configuration_account); $id_account = $merchant->id_axepta_configuration_account; $params = self::getParams($trigram, $operation, $id_account, null, $id_recurring_payment_card, $schedule); /* log axepta pour test cron */ if ($merchant->logs) { $message = 'PASSAGE DANS send_recurring_schedules fonction =>'; $message .= 'Les paramètres envoyés seront les suivants =>'; $message .= ' Params: '; AxeptaLogger::log($message, AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); } $response = AxeptaApi::checkAxeptaResponseWithCurl($url, $params); /* mise à jour montant en fonction des paiements manqués */ if ($response === false) { continue; } /* data and decrypt */ $a = explode('&', $response); $data = AxeptaApi::ctSplit($a); $plaintext = AxeptaApi::ctDecrypt($data['Data'], $data['Len'], $merchant->password); $b = explode('&', $plaintext); $save_data = AxeptaApi::ctSplit($b); $schedule_update = new AxeptaCustomerPaymentRecurring($schedule['id_axepta_customer_payment_recurring']); $schedule_update->current_occurence = (int)$schedule_update->current_occurence + 1; $schedule_update->last_schedule = date('Y-m-d H:i:s'); $interval = $schedule_update->number_occurences; $time = strtotime(date($schedule_update->last_schedule)); $schedule_update->next_schedule = ($schedule_update->periodicity == 'D') ? date("Y-m-d H:i:s", strtotime("+$interval day", $time)) : date("Y-m-d H:i:s", strtotime("+$interval month", $time)); if ($save_data['Code'] != '00000000') { $schedule_update->status = 1; } $status = (int) _PS_OS_PAYMENT_; if ($save_data['Status'] == 'FAILED') { $status = (int) _PS_OS_ERROR_; } if (empty($schedule_update->scheme_reference_id)) { $schedule_update->scheme_reference_id = isset($save_data['schemeReferenceID']) ? $save_data['schemeReferenceID'] : ''; } $schedule_update->save(); //$amount = $amount / 100; $customer = new Customer($order->id_customer); if (!$this->context->cart->OrderExists()) { $module->validateOrder( (int) $this->context->cart->id, $status, (float) $this->context->cart->getOrderTotal(), (string) $module->displayName, null, null, (int) $this->context->cart->id_currency, false, $customer->secure_key ); $id_order = AxeptaApi::getOrderByCartId( (int) $this->context->cart->id, (int) $this->context->cart->id_shop ); $this->context->order = new Order((int) $id_order); } /* creation of new transaction */ $new_transaction = new AxeptaTransaction(); $new_transaction->id_axepta_configuration_account = $transaction->id_axepta_configuration_account; $new_transaction->merchant_id = $transaction->merchant_id; $new_transaction->transaction_reference = $transaction->transaction_reference; $new_transaction->transaction_date = date('Y-m-d H:i:s'); $new_transaction->id_order = $id_order; $new_transaction->pay_id = isset($save_data['PayID']) ? $save_data['PayID'] : ''; $new_transaction->xid = isset($save_data['XID']) ? $save_data['XID'] : ''; $new_transaction->response_code = isset($save_data['Code']) ? $save_data['Code'] : ''; $new_transaction->pcnr = isset($save_data['PCNr']); $new_transaction->transaction_type = AxeptaTransaction::RECURRING; $new_transaction->ccexpiry = isset($save_data['CCExpiry']) ? $data['CCExpiry'] : ''; $new_transaction->amount = $this->context->cart->getOrderTotal(); $new_transaction->payment_bean_brand = 'N/A'; $new_transaction->pcnr = isset($save_data['PCNr']) ? $save_data['PCNr'] : ''; $new_transaction->bid = isset($save_data['billingagreementid']) ? $save_data['billingagreementid'] : ''; $new_transaction->ccexpiry = isset($save_data['CCExpiry']) ? $save_data['CCExpiry'] : ''; $new_transaction->response_code = isset($save_data['Code']) ? $save_data['Code'] : ''; $new_transaction->status =isset($data['Status']) ? $data['Status'] : ''; $new_transaction->description = isset($save_data['Description']) ? $save_data['Description'] : ''; $new_transaction->scheme_reference_id = isset($save_data['schemeReferenceID']) ? $save_data['schemeReferenceID'] : ''; $message = ""; foreach ($save_data as $key => $value) { $message .= $key . ': ' . $value . "<br>"; } if ($merchant->logs) { $message_reponse = 'PASSAGE DANS send_recurring_schedules fonction =>'; $message_reponse .= 'Les paramètres recus seront les suivants =>'; $message_reponse .= ' Params: '; $message_reponse .= $message; AxeptaLogger::log($message_reponse, AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); } $new_transaction->raw_data = json_encode($save_data); $new_transaction->save(); /*} else { return false; }*/ } } } /** * Create the Cart */ public function createCart() { // Init Cart $this->context->cart = new Cart(); // Mandatory if (is_null($this->context->cart->id_lang)) { $this->context->cart->id_lang = $this->context->customer->id_lang; } if (is_null($this->context->cart->id_currency)) { $this->context->cart->id_currency = $this->context->currency->id; } if (is_null($this->context->cart->id_customer)) { $this->context->cart->id_customer = $this->context->customer->id; } if (is_null($this->context->cart->id)) { $this->context->cart->add(); $this->context->cookie->__set('id_cart', $this->context->cart->id); } // Optional $this->context->cart->id_address_delivery = (int)$this->context->order->id_address_delivery; $this->context->cart->id_address_invoice = (int)$this->context->order->id_address_invoice; $this->context->cart->id_carrier = (int)$this->context->order->id_carrier; $this->context->cart->id_shop = (int)$this->context->order->id_shop; $this->context->cart->id_shop_group = (int)$this->context->order->id_shop_group; // Add the product $this->context->cart->updateQty( (int)1, (int)$this->context->schedule['id_product'], null, null, 'up', null, new Shop((int)$this->context->cart->id_shop), false ); $qty = 1; $recurring_payment = new AxeptaCustomerPaymentRecurring($this->context->schedule['id_axepta_customer_payment_recurring']); if ((int)$recurring_payment->getLateRecurringOccurence()) { $qty = (int)$recurring_payment->getLateRecurringOccurence(); } $specific_price = new SpecificPrice(); $specific_price->id_cart = (int)$this->context->cart->id; $specific_price->id_shop = 0; $specific_price->id_shop_group = 0; $specific_price->id_currency = 0; $specific_price->id_country = 0; $specific_price->id_group = 0; $specific_price->id_customer = (int)$this->context->customer->id; $specific_price->id_product = (int)$this->context->schedule['id_product']; $specific_price->id_product_attribute = 0; $specific_price->price = (float)$recurring_payment->amount_tax_exclude * $qty; $specific_price->from_quantity = 1; $specific_price->reduction = 0; $specific_price->reduction_type = 'amount'; $specific_price->from = '0000-00-00 00:00:00'; $specific_price->to = '0000-00-00 00:00:00'; $specific_price->save(); $recurring_payment->current_specific_price = $specific_price->id; $recurring_payment->save(); $this->context->cart->price = $specific_price->price; $this->context->cart->save(); } /** * check transaction status * @param type $trans_id */ public static function checkTransactionStatus($trans_id) { $trans = new AxeptaTransaction($trans_id); $merchant = new AxeptaConfigurationAccount($trans->id_axepta_configuration_account); if (is_null($trans)) { return null; } $array = [ 'MerchantID' => $trans->merchant_id, 'TransID' => $trans->id_axepta_transaction, 'PayID' => $trans->pay_id ]; $data = AxeptaApi::formatParams($array, null, $merchant->id_axepta_configuration_account, null); $data['MerchantID'] = $trans->merchant_id; $content = self::checkAxeptaResponseWithCurl(self::URL_INQUIRE_WITH_PAYID, $data); $a = explode('&', $content); $content = AxeptaApi::ctSplit($a); $plaintext = AxeptaApi::ctDecrypt($content['Data'], $content['Len'], $merchant->password); $a = explode('&', $plaintext); return AxeptaApi::ctSplit($a); } /** * check computop with curl * @param type $urlcheckAxeptaResponseWithCurl * @param type $postFields * @return mix */ public static function checkAxeptaResponseWithCurl($url, $postFields) { $postFields['MerchantID'] = $postFields['mid']; unset($postFields['mid']); unset($postFields['url']); unset($postFields['url_back']); $options = array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false, CURLOPT_FAILONERROR => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postFields, CURLOPT_VERBOSE => true, ); $CURL = curl_init(); curl_setopt_array($CURL, $options); $content = curl_exec($CURL); if (curl_errno($CURL)) { return false; } curl_close($CURL); return $content; } /** * process refund * @param type $order_id * @param type $amount * @param type $reason * @return boolean */ public static function processRefund($order_id, $amount = null, $slip_id = null) { AxeptaLogger::log("Début processRefund", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); $order = new Order($order_id); if (!Validate::isLoadedObject($order)) { AxeptaLogger::log("L'objet Order ne peut pas être instancier (id : ".$order_id.")", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); return false; } $operation = AxeptaTransaction::REFUND; $transaction_infos = AxeptaTransaction::getTransactionSuccessByIdOrder($order->id); if (empty($transaction_infos)) { AxeptaLogger::log("Impossible de charger les infos de la transaction success", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); return false; } $transaction = new AxeptaTransaction($transaction_infos['id_axepta_transaction']); if (!Validate::isLoadedObject($transaction)) { AxeptaLogger::log("L'objet AxeptaTransaction ne peut pas être instancier (id : ".$transaction_infos['id_axepta_transaction'].")", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); return false; } $transaction_status = self::checkTransactionStatus($transaction->id_axepta_transaction); if ((int)$transaction_status['AmountCap'] == 0) { if ((int)$transaction_status['AmountAuth'] == $amount) { $operation = 'cancellation'; } } $date_transaction = new DateTime($transaction->transaction_date); $date_now = new DateTime('now'); $diff = $date_transaction->diff($date_now); $nb_months = $diff->m; if ($nb_months > 11) { AxeptaLogger::log("La transaction success date de plus de 11 mois.", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); return false; } if ($transaction->transaction_type == 'oneclick') { $infos = AxeptaCustomerOneClickPaymentCard::verifyIfCardExist($order->id_customer, $transaction->pcnr); $oneclick_card = new AxeptaCustomerOneClickPaymentCard($infos['id']); $trigram = AxeptaCustomerOneClickPaymentCard::getTrigramByCcbrand($oneclick_card->ccbrand); $id_saved_card = $oneclick_card->id; } else { $trigram = $transaction->trigram; } $merchant = new AxeptaConfigurationAccount($transaction->id_axepta_configuration_account); $url = self::getUrlByTrigramAndOperation($trigram, $operation); $amount = (int)$amount; if ($transaction->transaction_type == 'oneclick') { $params = self::getParams($trigram, $operation, $merchant->id_axepta_configuration_account, $id_saved_card, null, null, $transaction->id); } else { $params = self::getParams($trigram, $operation, $merchant->id_axepta_configuration_account, null, null, null, $transaction->id, (int)$amount); } AxeptaLogger::log("Paramètres envoyés : ".print_r($params, true), AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); $response = self::checkAxeptaResponseWithCurl($url, $params); AxeptaLogger::log("Réponse : ".print_r($response, true), AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); if ($response === false) { AxeptaLogger::log("La réponse est FALSE", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); return false; } $a = explode('&', $response); $data = AxeptaApi::ctSplit($a); $plaintext = AxeptaApi::ctDecrypt($data['Data'], $data['Len'], $merchant->password); $b = explode('&', $plaintext); $save_data = AxeptaApi::ctSplit($b); AxeptaLogger::log("Réponse décryptée: ".print_r($save_data, true), AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); if ($save_data['Code'] != '00000000') { AxeptaLogger::log("Le code réponse est différent de 00000000", AxeptaLogger::LOG_DEBUG, AxeptaLogger::FILE_DEBUG); return false; } $diff_amount = $transaction_status['AmountAuth'] - $transaction_status['AmountCred']; $new_transaction = new AxeptaTransaction(); $new_transaction->id_axepta_configuration_account = $transaction->id_axepta_configuration_account; $new_transaction->merchant_id = $transaction->merchant_id; $new_transaction->transaction_reference = $transaction->transaction_reference; $new_transaction->transaction_date = date('Y-m-d H:i:s'); $new_transaction->id_order = $transaction->id_order; $new_transaction->id_order_slip = $slip_id; $new_transaction->pay_id = $save_data['PayID']; $new_transaction->xid = $save_data['XID']; $new_transaction->response_code = $save_data['Code']; $new_transaction->transaction_type = $operation; $new_transaction->amount = $amount / 100; $new_transaction->payment_bean_brand = 'N/A'; $new_transaction->trigram = $trigram; $new_transaction->pcnr = (isset($save_data['PCNr'])) ? $save_data['PCNr'] : null; $new_transaction->ccexpiry = (isset($save_data['CCExpiry'])) ? $save_data['CCExpiry'] : null; $new_transaction->response_code = $save_data['Code']; $new_transaction->status = $save_data['Description']; $message = ""; foreach ($save_data as $key => $value) { $message .= $key.': '.$value."<br>"; } $new_transaction->raw_data = $message; return $new_transaction->save(); /* sauvegarder la transaction ici */ } public static function getTrigramByCcbrand($ccbrand) { $methods = [ 'VISA' => 'VIM', 'VISA Electron' => 'VIM', 'MasterCard' => 'VIM', 'Maestro' => 'VIM', 'Cartes Bancaires' => 'CVM' ]; foreach ($methods as $key => $value) { $trigram = false; if ($key === $ccbrand) { $trigram = $value; } else { $trigram = Db::getInstance()->getValue('SELECT trigram FROM `'._DB_PREFIX_.'axepta_xml_method`' .' WHERE code LIKE "%'.pSQL($ccbrand).'%"'); } if (!$trigram === false) { break; } } return $trigram; } public static function generateString($strength) { $permittedChars = 'BCDEFGHIJKLMNOPQRSTUVWXYZ'; $inputLength = Tools::strlen($permittedChars); $randomString = ''; for ($i = 0; $i < $strength; $i++) { $randomCharacter = $permittedChars[mt_rand(0, $inputLength - 1)]; $randomString .= $randomCharacter; } return $randomString; } public static function generateUniqTransId($order_id) { $transIdFirst = Tools::strlen($order_id).'A'.$order_id; $diff = self::MAX_TRANSID_SIZE - (Tools::strlen($transIdFirst)); return $transIdFirst.self::generateString($diff); } public static function getOrderIdFromTransId($trans_id) { $orderIdLenPos = strpos($trans_id, 'A', 0); $orderIdLen = (int)Tools::substr($trans_id, 0, $orderIdLenPos); return Tools::substr($trans_id, $orderIdLenPos + 1, $orderIdLen); } public static function isMethodAllowedInCountry($id_method = 0, $currency = '', $country = '') { if ((int)$id_method && $country && $currency) { $sql = 'SELECT id FROM `'._DB_PREFIX_.'axepta_xml_allow_countries` WHERE method_id = '.(int)$id_method.' AND currency = "'.pSQL($currency).'" AND country = "'.pSQL($country).'"'; return Db::getInstance()->getValue($sql); } return false; } public static function checkRegexpData($phone) { if (preg_match("#(^\+[0-9]{2}|^\+[0-9]{2}\(0\)|^\(\+[0-9]{2}\)\(0\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\-\s]{10}$)#", $phone)) { if (stripos($phone, '+33') !== false) { $phone = str_replace("+33", "0", $phone); } } else { $phone = '0606060606'; } return $phone; } /** * return hash hmac for api response * * @param type $PayId * @param type $TransID * @param type $MerchantID * @param type $Status * @param type $Code * @param type $HmacPassword * @return string */ public static function ctHMACResponse($PayId, $TransID, $MerchantID, $Status, $Code, $HmacPassword) { return hash_hmac('sha256', "$PayId*$TransID*$MerchantID*$Status*$Code", $HmacPassword); } public static function apiResponseVerifyHmac($data, $merchant) { $trans_id = $data['TransID'] ?? ''; $pay_id = $data['PayID'] ?? ''; $merchant_name = $merchant->mid ?? ''; $hmac_key = $merchant->hmac_key ?? ''; $status = $data['Status'] ?? ''; $code = $data['Code'] ?? ''; $verifyHmac = self::ctHMACResponse($pay_id, $trans_id, $merchant_name, $status, $code, $hmac_key); if (strtolower($data['MAC']) !== strtolower($verifyHmac)) { return false; } return true; } }
💾 保存文件
← 返回文件管理器