privateKey = $privateKey; $this->publicKey = $publicKey; $this->keyFormat = 1; } protected static $self = null; public static function instance($privateKey, $publicKey) { if (self::$self == null) { self::$self = new self($privateKey, $publicKey); } return self::$self; } /** * 获取签名 * @param $params 参数 * @return string */ public function getSign($params) { ksort($params); $data = ""; foreach ($params as $key => $value) { $data .= $value; } $sign = strtoupper(md5($data . $this->privateKey)); return $sign; } /** * 验证签名 * @param $params 参数 * @return bool */ public function checkSign($params) { ksort($params); $psign = ""; $data = ""; foreach ($params as $key => $value) { if ($key == "sign") { $psign = $value; } else { $data .= $value; } } $sign = strtoupper(md5($data . $this->publicKey)); if ($psign == $sign) { return true; } else { return false; } } public function encrypt($data) { ksort($data); $data = json_encode($data); $this->_makesure_provider($this->privateKey); $encrypted = ''; if ($this->isPrivate) { foreach (str_split($data, 117) as $chunk) { $r = openssl_private_encrypt($chunk, $encryptData, $this->keyProvider, OPENSSL_PKCS1_PADDING); $encrypted .= $encryptData; } } else { foreach (str_split($data, 117) as $chunk) { $r = openssl_public_encrypt($chunk, $encryptData, $this->keyProvider, OPENSSL_PKCS1_PADDING); $encrypted .= $encryptData; } } return $r ? $data = base64_encode($encrypted) : null; } public function decrypt($data) { $this->_makesure_provider($this->publicKey); $data = base64_decode($data); $crypto = ''; foreach (str_split($data, 128) as $chunk) { if ($this->isPrivate) { $r = openssl_private_decrypt($chunk, $decrypted, $this->keyProvider, OPENSSL_PKCS1_PADDING); } else { $r = openssl_public_decrypt($chunk, $decrypted, $this->keyProvider, OPENSSL_PKCS1_PADDING); } $crypto .= $decrypted; } return $crypto; } private function _makesure_provider($key) { $this->isPrivate = strlen($key) > 500; $key = chunk_split($key, 64, "\r\n");//转换为pem格式的公钥 if ($this->isPrivate) { $key = "-----BEGIN PRIVATE KEY-----\r\n" . $key . "-----END PRIVATE KEY-----"; } else { $key = "-----BEGIN PUBLIC KEY-----\r\n" . $key . "-----END PUBLIC KEY-----"; } $this->keyProvider = $this->isPrivate ? openssl_pkey_get_private($key) : openssl_pkey_get_public($key); } /** * 米花调用API接口 * @param $postData 发送到API的数据 * @param $data 加密前的明文参数 * @param $payInfo 支付信息 * @param $goodsInfo 商品信息 * @param $orderInfo 订单信息 * @param int $loopIndex 循环调用API的次数 * @return mixed|\Psr\Http\Message\ResponseInterface * @throws Exception */ public function payMihuaApi($postData, $data, $payInfo, $goodsInfo, $orderInfo, $loopIndex = 1) { $payUrl = ApiConstants::MIHUA_PAY_URL; $mihuaApiStartTime = microtime(true); try { $client = new Http([ 'connect_timeout' => 10, 'timeout' => 30, 'http_errors' => true, //抛出异常 true是 false否 'verify' => false, //不验证ssl证书 ]); $result = $client->post($payUrl, ['form_params' => $postData]); $mihuaApiEndTime = microtime(true); $apiRunTime = round($mihuaApiEndTime - $mihuaApiStartTime, 3); if ($result->getStatusCode() != '200') { LogService::error(sprintf('mihuapay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,loop_index:%s,errmessage:%s' , $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'], $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'], $apiRunTime, $loopIndex, json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE))); LogService::error(sprintf('米花平台订单创建失败!订单内容明文: %s 订单内容密文: %s 米花平台返回内容: %s', json_encode(var_export($data, true), JSON_UNESCAPED_UNICODE), json_encode(var_export($postData, true), JSON_UNESCAPED_UNICODE), json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE) )); throw new Exception('订单创建失败,请重新下单!'); } else { $result = json_decode($result->getBody()->getContents(), true); if ($result['code'] != '000000') { LogService::error(sprintf('mihuapay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,loop_index:%s,errmessage:%s' , $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'], $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'], $apiRunTime, $loopIndex, json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE))); LogService::error(sprintf('米花平台订单创建失败!订单内容明文: %s 订单内容密文: %s 米花平台返回内容: %s', json_encode(var_export($data, true), JSON_UNESCAPED_UNICODE), json_encode(var_export($postData, true), JSON_UNESCAPED_UNICODE), json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE) )); throw new Exception('订单创建失败,请重新下单!'); } } LogService::info(sprintf('mihuapay_create_order_success!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,loop_index:%s' , $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'], $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'], $apiRunTime, $loopIndex)); return $result; } catch (GuzzleException $exception) { $mihuaApiEndTime = microtime(true); $apiRunTime = round($mihuaApiEndTime - $mihuaApiStartTime, 3); LogService::error(sprintf('mihuapay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,loop_index:%s,errmessage:%s' , $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'], $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'], $apiRunTime, $loopIndex, $exception->getMessage())); LogService::error(sprintf('米花平台订单创建失败!订单内容明文: %s 订单内容密文:%s', json_encode(var_export($data, true), JSON_UNESCAPED_UNICODE), json_encode(var_export($postData, true), JSON_UNESCAPED_UNICODE))); LogService::error($exception->getMessage()); LogService::error($exception->getTraceAsString()); if ($loopIndex <= ApiConstants::LOOP_EXEC_API_COUNT) { $loopIndex++; return $this->payMihuaApi($postData, $data, $payInfo, $goodsInfo, $orderInfo, $loopIndex); } throw new Exception('订单创建失败,请重新下单!'); } } }