481 lines
17 KiB
PHP
481 lines
17 KiB
PHP
<?php
|
||
|
||
namespace App\ServicePay\Citpay;
|
||
|
||
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: Administrator
|
||
* Date: 2019/3/9
|
||
* Time: 12:17
|
||
*/
|
||
class CitPay
|
||
{
|
||
|
||
public $body_data;
|
||
public $config;
|
||
public $rsa;
|
||
public $result;
|
||
static public $instance;//声明一个静态变量(保存在类中唯一的一个实例)
|
||
public $error = [];
|
||
|
||
private function __construct($config)
|
||
{
|
||
|
||
$dir = __DIR__;
|
||
//声明私有构造方法为了防止外部代码使用new来创建对象。
|
||
$default = [
|
||
'mid' => 'e09d368d3381a46d8f57ef6dbbdb0b8a',
|
||
'pt_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhYT40X9ByJo3Tr62MWW0bq96K/SCnXwcMzLjDj29Xdt+98ShPpr3bKycQ0dmtaC2j1Uj6D+JOVyxxQlZqRYWKcFfp4HqUVnynmYT+SIAZt0eSKw9W2hFlh3nrP8x+F0+qm6r9a/csi3i+qsKacmNcNDcmqA+E5yNPJybl0TfZnX0ChwutkG8MZX8dIFJWP1TcX6sHTdUQ6YwzvnT0CjtRBXv06yiWoJpvEeJLRIP4+9+Nyr+3m4XyVtPLP5QkwU3nClaE7zmLp3Vrkp47cXOeGQwKNEoSbWIGsRExKu364pz7S5zKBnhiipsT/0Hje/rgbPFwAFAS54QdtLgs1qBfQIDAQAB',
|
||
'app_key' => 'e09d368d3381a46d8f57ef6dbbdb0b8a',
|
||
'serct_code' => '3gZf8tHOfGoaqHEK+nOaGw==',
|
||
'url' => 'https://www.citpay.com',
|
||
'notify_url' => '',
|
||
'debug' => 1,
|
||
'logDir' => to_linux_path(storage_path() . '/logs/'),
|
||
'pem' => 'MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDp+oWyQfLBXQ79 azJ/wgbNSgsJPm+OMo0Z3+NnjCtjSsBFJ2iS4iwWUwfl3t0eSLQG/9fNc/EfqE2C yK/JT+8L0dD5XVGf8VlB8YW+1sDVUlprfDuea5LL/sJ04wfvBEDEG8ablNbCmj8+ MHYfneuJIjDyINbujBeNznsNKQURNNCG6Hw7TjR6LUKOLoDD77G37E+MyWyiAl+I 3dHzrg2Z8K3NfwHL49mQqsbQFuBJeiG2PjSitcTqQbWkdzaPU/KhvKrTOKg3sLhK aMBg4tw5k2CbT5E1XwI4oFUbauT9+9LHlvXzR21ZOgsmXHdX57GPhPRTra95AKCR Xs4M1PRPAgMBAAECggEBALJTouRKiRdAsrUIp5NhsMdz4FdqQ6Gv+4S1896uoT7q 8QGD2JriUFGvdLyJECQNq1AOXE6VSDglkPXVuMyI5JswjcIQkq6BRtMQnivmB1BO lOWI6POD730UrOZjRl+v8SDGPqfDV6832m2uh8jvFl4NNhrEVqu3EBifP3+3PMpv 7kYRbptuPM4IMOhhn2XiWu4Cje9l+iDKxDoXRnNREqWLb5Rl5i4UWmrqUvmrLhrB acN4v6Yp2VY78+Y+9LqtbacHC0BY7+CMHde2ME9DCKSsJ5slCrzR2Q7qATVS2fYQ 1uNe9KaONYDYhNQrflKt3j22Qhk/xmEzKu5Ud6K1drECgYEA+Jhl9XeWY+NZPW6N 7bGxW9nYTPQcnOx6DhYYJoIEnZcLRmMZBXFeG2c5a5Lyk5CJpJrwQpxgTiWEIwnz K5lpHY0ns2oeaUCfem4iueU47Gylf75/kmN6MEAKFnLO8zAIt4+K9riu1SM6cjDC JtuV9FEToROXtSHqVgThGgQ/OSkCgYEA8PKq/eQRuwf1FppOnjyNs1WbMtSEhO2X wAft1/VsdTCTq9vXxJn68viKCPFuXuL1YCET9oz/JG0aTs+o9w+tB9k7uswwBZsv +xMRMxH62BPL+TtBwWud7b2hjjXyf3ipZ+GJ+EgWHcDq6JtlqmBIh5RuYmCdxx+4 uCD04q61WLcCgYEA7jDHcJz24hqSBQSKxPb/IyzlzUYQrGMAx8JvvWXSmlSBHx4Q eWCYdNVA9UvFVZKl76vtDUXcGMRliVUdQ+coCoKXSZciMGMU6y/f4hI5qn6nTHDw twjNqLGTeNLka6rYj1jgI2ntSpcIhyUkwiqf0Yplrm6ha5Jlf6oJLO5ozZECgYEA 2K7S+Vp2W4VvcnE4jHMWV5V/6blWp5hnpOk8ir8KV2VlF+Ov6f0zwfejYyGDyU8/ rcBxjIMGHIMFaqSzZeOyDuHcJkPkV9ZU0u01xYDA3jsHb05L9x7JuviTZim7t8kS R/p7Mk3Znc5VMvQ0/IB0GYFxt4T9vwoW+3ef4o+NRIcCgYBunDV6+ajNsaASi9Aj O8xRVNRUQrjN6oUofmAudsjHRR58vKLb1eY5/yhZaTgG9+JzeDaHkHPJcYHdAC4b GFnqv9qwBJjIKef60ntqjGyiF3BqvvME4bzT9UQpklk08XUpvS+C6hFl7N7wQD30 B5Q5wI8M0c5TJqI1eGIVQOp5lg=='
|
||
];
|
||
$this->config = $config + $default;
|
||
|
||
$this->rsa = new RsaEncrypt();
|
||
}
|
||
|
||
|
||
static public function make($config = [])
|
||
{
|
||
|
||
//声明一个getinstance()静态方法,用于检测是否有实例对象
|
||
if (!self::$instance) self::$instance = new self($config);
|
||
return self::$instance;
|
||
}
|
||
|
||
public function loadBodyData($data, $time = 1)
|
||
{
|
||
$data['merchant_id'] = $this->config['mid'];
|
||
if ($time) {
|
||
$data['timestamp'] = intval($this->getTime());
|
||
|
||
}
|
||
|
||
return $data;
|
||
|
||
}
|
||
|
||
public function getAec($data, $time = 1)
|
||
{
|
||
$data = $this->loadBodyData($data, $time);
|
||
|
||
|
||
$content = $this->arrayToUrl($data);
|
||
// echo $content . '<br/>';
|
||
//echo $this->config['serct_code'] . '<br/>';
|
||
//加密取得encodeContent
|
||
$encryptDate = Aes56::encrypt($content, $this->config['serct_code']);
|
||
// echo $encryptDate . '<br/>';
|
||
return $encryptDate;
|
||
}
|
||
|
||
public function getResult()
|
||
{
|
||
return ($this->result);
|
||
}
|
||
|
||
public function getError()
|
||
{
|
||
return ($this->error);
|
||
}
|
||
|
||
public function checkRegist($data)
|
||
{
|
||
$this->writeFileLog('order', '1.检测用户是否注册开始');
|
||
|
||
$encryptDate = $this->getAec($data);
|
||
|
||
$requestParams = array(
|
||
// 在citpay平台中获取
|
||
"client_key" => $this->config['app_key'],
|
||
"request_content" => $encryptDate,
|
||
"sign_type" => "RSA2"
|
||
);
|
||
//print_r($requestParams);
|
||
// print_r($requestParams);
|
||
|
||
$requestParams['sign'] = $this->sign($requestParams);
|
||
|
||
|
||
$requestUrl = $this->config['url'] . "/openapi/accountcheck";
|
||
$this->writeFileLog('order', '检查用户信息' . json_encode($requestParams));
|
||
//发起CURl请求
|
||
$response = $this->curl($requestUrl, $requestParams);
|
||
//var_dump($response);
|
||
$response = json_decode($response, true);
|
||
$this->result = $response;
|
||
$this->writeFileLog('order', '检测用户返回数据' . json_encode($response));
|
||
// exit();
|
||
//dd($response);
|
||
if ($response["code"] == 200 || $response["code"] == 300) {
|
||
|
||
//var_dump("request invoke success!");
|
||
//验签返回结果是否正确
|
||
$res = $this->checkSign($response);
|
||
|
||
if ($res == true) {
|
||
$this->writeFileLog('order', '验证签名通过,检测用户返回结果:' . $response["code"]);
|
||
// 处理返回结果
|
||
if ($response["code"] == 200) {
|
||
|
||
return 1;
|
||
}
|
||
if ($response["code"] == 300) {
|
||
return 2;
|
||
}
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
public function regist($data)
|
||
{
|
||
$encryptDate = $this->getAec($data);
|
||
|
||
$requestParams = array(
|
||
// 在citpay平台中获取
|
||
"client_key" => $this->config['app_key'],
|
||
"request_content" => $encryptDate,
|
||
"sign_type" => "RSA2"
|
||
);
|
||
//print_r($requestParams);
|
||
|
||
$requestParams['sign'] = $this->sign($requestParams);
|
||
|
||
$this->writeFileLog('order', '发起注册信息' . json_encode($requestParams));
|
||
$requestUrl = $this->config['url'] . "/openapi/accountRegister";
|
||
//发起CURl请求
|
||
$response = $this->curl($requestUrl, $requestParams);
|
||
$this->result = $response = json_decode($response, true);
|
||
$this->writeFileLog('order', '注册用户返回数据' . json_encode($response));
|
||
if ($response["code"] == 200) {
|
||
|
||
//验签返回结果是否正确
|
||
$res = $this->checkSign($response, "");
|
||
if ($res == true) {
|
||
// 处理返回结果
|
||
return 1;
|
||
}
|
||
return 2;
|
||
}
|
||
return 0;
|
||
|
||
}
|
||
|
||
//回调验证签名
|
||
public function very($request)
|
||
{
|
||
$data = [
|
||
'order_no' => $request->input('order_no'),
|
||
'pay_state' => $request->input('pay_state'),
|
||
'currency_type' => 'USDT',
|
||
'digita_amount' => $request->input('digita_amount'),
|
||
'legalA_amount' => $request->input('legalA_amount'),
|
||
'legalB_amount' => $request->input('legalB_amount')
|
||
];
|
||
$encryptDate = $this->getAec($data);
|
||
|
||
$requestParams = array(
|
||
// 在citpay平台中获取
|
||
"client_key" => $this->config['app_key'],
|
||
"request_content" => $encryptDate,
|
||
"sign_type" => "RSA2"
|
||
);
|
||
//print_r($requestParams);
|
||
|
||
$requestParams['sign'] = $this->sign($requestParams);
|
||
|
||
|
||
$requestUrl = $this->config['url'] . "/openapi/depositOrder-notify";
|
||
//发起CURl请求
|
||
$response = $this->curl($requestUrl, $requestParams);
|
||
$this->result = $response = json_decode($response, true);
|
||
if ($response["code"] == 200) {
|
||
|
||
//验签返回结果是否正确
|
||
$res = $this->checkSign($response, "");
|
||
if ($res == true) {
|
||
// 处理返回结果
|
||
return 1;
|
||
}
|
||
return 2;
|
||
}
|
||
return 0;
|
||
|
||
}
|
||
|
||
//取得费率
|
||
public function getRatio()
|
||
{
|
||
$data["legalExchangeType"] = 'USD2CNY';
|
||
$data["digitalExchangeType"] = 'USDT2CNY';
|
||
$encryptDate = $this->getAec($data);
|
||
|
||
$requestParams = array(
|
||
// 在citpay平台中获取
|
||
"client_key" => $this->config['app_key'],
|
||
"request_content" => $encryptDate,
|
||
"sign_type" => "RSA2"
|
||
);
|
||
//print_r($requestParams);
|
||
|
||
$requestParams['sign'] = $this->sign($requestParams);
|
||
|
||
|
||
$requestUrl = $this->config['url'] . "/openapi/realCurrencyRate";
|
||
$this->writeFileLog('order', '发起费率信息' . json_encode($requestParams));
|
||
//发起CURl请求
|
||
$response = $this->curl($requestUrl, $requestParams);
|
||
$this->result = $response = json_decode($response, true);
|
||
$this->writeFileLog('order', '发起费率信息返回' . json_encode($response));
|
||
if ($response["code"] == 200) {
|
||
|
||
//验签返回结果是否正确
|
||
$res = $this->checkSign($response, "");
|
||
if ($res == true) {
|
||
// 处理返回结果
|
||
return json_decode($response['response'], 1);
|
||
}
|
||
return false;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public function addError($data)
|
||
{
|
||
array_push($this->error, $data);
|
||
|
||
}
|
||
|
||
/**
|
||
* 写入日志
|
||
* @param $filename
|
||
* @param string $str
|
||
*/
|
||
public function writeFileLog($filename, $str = '')
|
||
{
|
||
if ($this->config['debug']) {
|
||
$filename = str_replace("\\", "/", $this->config['logDir']) . 'citpay_' . $filename;
|
||
if (!is_dir(dirname($filename))) {
|
||
mkdir(dirname($filename), 0755, 1);
|
||
}
|
||
file_put_contents('' . $filename . '.log', date('Y-m-d H:i:s') . ' > ' . $str . "\n", FILE_APPEND);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public function decrypt($content)
|
||
{
|
||
$encryptDate = Aes56::decrypt($content, $this->config['serct_code']);
|
||
return $encryptDate;
|
||
|
||
}
|
||
|
||
|
||
//发起订单
|
||
public function orderBuy($data)
|
||
{
|
||
$this->writeFileLog('order', '-------------' . $data['order_no'] . '--------------');
|
||
//检测用户是否注册了
|
||
$mdata = [
|
||
"mobile_num" => $data['customer_mobile'],
|
||
];
|
||
$has = $this->checkRegist($mdata);
|
||
$this->writeFileLog('order', '检测用户完毕');
|
||
if (!$has) {
|
||
$this->addError(['msg' => '检测用户失败']);
|
||
return false;
|
||
}
|
||
if ($has == 2) {
|
||
//已经不存在,发起注册
|
||
$rdata = [
|
||
"mobile_num" => $data['customer_mobile'],
|
||
"customer_name" => $data['customer_name'],
|
||
];
|
||
$this->writeFileLog('order', '发起注册');
|
||
$rg_r = $this->regist($rdata);
|
||
if ($rg_r != 1) {
|
||
$this->writeFileLog('order', '注册失败');
|
||
$this->addError(['msg' => '注册用户失败']);
|
||
return false;
|
||
}
|
||
$this->writeFileLog('order', $data['customer_mobile'] . '注册成功');
|
||
|
||
} else {
|
||
$this->writeFileLog('order', '用户已经注册');
|
||
}
|
||
$this->writeFileLog('order', '发起费率请求');
|
||
//先取得费率
|
||
$ratio = $this->getRatio();
|
||
|
||
if (empty($ratio)) {
|
||
$this->addError(['msg' => '取得费率失败']);
|
||
return false;
|
||
}
|
||
$this->writeFileLog('order', '发起订单支付请求');
|
||
$money = $data['legalB_amount'];
|
||
$data['currency_type'] = 'USDT';
|
||
$data['legalB_amount'] = $money;//付款RMB金额
|
||
$data['legalA_amount'] = round($money / $ratio['digitalExchangeRate'], 2);//美元
|
||
$data['digita_amount'] = round($money / $ratio['digitalExchangeRate'], 0) * pow(10, 8);//10的8次方
|
||
$this->writeFileLog('order', '费率:' . $ratio['digitalExchangeRate'] . ',支付金额RMB:' . $money . ';美元=' . $data['legalA_amount']);
|
||
$data['notify_url'] = $this->config['notify_url'];
|
||
$this->writeFileLog('order', '发起支付数据' . json_encode($data));
|
||
$encryptDate = $this->getAec($data);
|
||
$requestParams = array(
|
||
// 在citpay平台中获取
|
||
"client_key" => $this->config['app_key'],
|
||
"request_content" => $encryptDate,
|
||
"sign_type" => "RSA2"
|
||
);
|
||
//print_r($requestParams);
|
||
$requestParams['sign'] = $this->sign($requestParams);
|
||
$requestUrl = $this->config['url'] . "/openapi/depositOrder";
|
||
//发起CURl请求
|
||
$this->writeFileLog('order', '发起支付参数' . json_encode($requestParams));
|
||
$response = $this->curl($requestUrl, $requestParams);
|
||
$this->result = $response = json_decode($response, true);
|
||
$this->writeFileLog('order', '订单请求结果' . json_encode($response));
|
||
//dump($response);
|
||
|
||
if ($response["code"] == 200) {
|
||
|
||
//验签返回结果是否正确
|
||
$res = $this->checkSign($response, "");
|
||
if ($res == true) {
|
||
// 处理返回结果
|
||
$this->writeFileLog('order', '处理返回成功,本订单结束');
|
||
return json_decode($response['response'], 1);
|
||
}
|
||
return false;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//回调
|
||
public function notify($data)
|
||
{
|
||
$this->writeFileLog('notify', '回调数据:' . json_encode($data));
|
||
}
|
||
|
||
//验证签名
|
||
public function checkSign($response)
|
||
{
|
||
$this->rsa->citpayPublicKey = $this->config['pt_key'];
|
||
$this->rsa->rsaPrivateKey = $this->config['pem'];;
|
||
return $this->rsa->rsaCheckV1($response, "");
|
||
}
|
||
|
||
public function sign($requestParams)
|
||
{
|
||
|
||
// 必须赋值:citpay公钥 从平台获取
|
||
$this->rsa->citpayPublicKey = $this->config['pt_key'];
|
||
$this->rsa->rsaPrivateKey = $this->config['pem'];;
|
||
return $this->rsa->rsaSign($requestParams);
|
||
}
|
||
|
||
public function arrayToUrl($params)
|
||
{
|
||
ksort($params);
|
||
|
||
$string = '';
|
||
if (!empty($params)) {
|
||
$array = array();
|
||
foreach ($params as $key => $value) {
|
||
$array[] = $key . '=' . $value;
|
||
}
|
||
$string = implode("&", $array);
|
||
}
|
||
return $string;
|
||
|
||
}
|
||
|
||
public function checkEmpty($value)
|
||
{
|
||
if (!isset($value))
|
||
return true;
|
||
if ($value === null)
|
||
return true;
|
||
if (trim($value) === "")
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
//时间戳
|
||
public function getTime()
|
||
{
|
||
list($s1, $s2) = explode(' ', microtime());
|
||
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
|
||
}
|
||
|
||
public function curl($url, $postFields = null)
|
||
{
|
||
$postCharset = "UTF-8";
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, $url);
|
||
curl_setopt($ch, CURLOPT_FAILONERROR, false);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||
|
||
$postBodyString = "";
|
||
$encodeArray = Array();
|
||
$postMultipart = false;
|
||
|
||
if (is_array($postFields) && 0 < count($postFields)) {
|
||
|
||
foreach ($postFields as $k => $v) {
|
||
if ("@" != substr($v, 0, 1)) //判断是不是文件上传
|
||
{
|
||
|
||
$postBodyString .= "$k=" . urlencode($v) . "&";
|
||
$encodeArray[$k] = $v;
|
||
} else //文件上传用multipart/form-data,否则用www-form-urlencoded
|
||
{
|
||
$postMultipart = true;
|
||
$encodeArray[$k] = new \CURLFile(substr($v, 1));
|
||
}
|
||
|
||
}
|
||
unset ($k, $v);
|
||
curl_setopt($ch, CURLOPT_POST, true);
|
||
if ($postMultipart) {
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeArray);
|
||
} else {
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
|
||
}
|
||
}
|
||
|
||
if ($postMultipart) {
|
||
|
||
$headers = array('content-type: multipart/form-data;charset=' . $postCharset . ';boundary=' . $this->getMillisecond());
|
||
} else {
|
||
|
||
$headers = array('content-type: application/x-www-form-urlencoded;charset=' . $postCharset);
|
||
}
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||
|
||
$reponse = curl_exec($ch);
|
||
|
||
if (curl_errno($ch)) {
|
||
throw new Exception(curl_error($ch), 0);
|
||
} else {
|
||
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
if (200 !== $httpStatusCode) {
|
||
throw new Exception($reponse, $httpStatusCode);
|
||
}
|
||
}
|
||
curl_close($ch);
|
||
return $reponse;
|
||
}
|
||
} |