<?php namespace crmeb\services; use think\Request; class JiaLieService { private static $Url = "https://qrcode.jlpay.com/api/pay/"; private static $zsUrl = "https://qrcode.jlpay.com/api/pay/"; private static $dgurl = "https://qrcode-dev.jlpay.com/api/pay/"; private static $initialize = null; private static $org_code =null; private static $mch_id =null; private static $prikey =null; private static $pubkey =null; private static $dubeg =null; private static $errorMsg = ""; const DEFAULT_ERROR_MSG = '操作失败,请稍候再试!'; const MICROPAY = "micropay"; //付款码支付 const QRCODEPAY = "qrcodepay"; //扫码支付 const REFUND = "refund"; //退款接口 const CANCEL = "cancel"; //撤销接口 const APPPAY = "apppay"; //APP支付接口 const OFFICIALPAY = "officialpay";//微信公众号、小程序支付接口 const WAPH5PAY = "waph5pay"; // 支付宝服务窗、小程序支付接口 const QUERY = "chnquery"; //订单查询接口 const UNIONJSPAY = "unionjspay"; //银联行业码支付接口 const AUTHBIND= "authbind"; //绑定支付目录接口 const GETOPENID = "getopenid";//授权码获取openId或userId接口 const MICROPAYPREAUTH = "micropaypreauth";//付款码预授权 const QRCODEPAYPREAUTH = "qrcodepaypreauth";//扫码预授权 const PREAUTHCOMPLETE= "preauthcomplete"; //预授权完成 const PREAUTHREVIKE = "preauthrevoke"; //预授权撤销 const PREAUTHCLOSE = "preauthclose";//预授权关单 const PREAUTHQUREY = "preauthquery";//预授权查询 /** * 设置错误信息 * @param string $errorMsg * @return bool */ protected static function setErrorInfo($errorMsg = self::DEFAULT_ERROR_MSG, $rollback = false) { if ($rollback) self::rollbackTrans(); self::$errorMsg = $errorMsg; return false; } /** * 获取错误信息 * @param string $defaultMsg * @return string */ public static function getErrorInfo($defaultMsg = self::DEFAULT_ERROR_MSG) { return !empty(self::$errorMsg) ? self::$errorMsg : $defaultMsg; } private function __construct() { // TODO 初始化配置 $system = SystemConfigService::more(['jl_org_code', 'jl_mch_id', 'mer_prikey', 'jl_pubkey','jl_dubeg']); self::$org_code = $system['jl_org_code'] ?? ''; self::$mch_id = $system['jl_mch_id'] ?? ''; self::$prikey = $system['mer_prikey'] ?? ''; self::$pubkey = $system['jl_pubkey'] ?? ''; self::$dubeg = $system['jl_dubeg'] ?? ''; if($system['jl_dubeg']==1) { self::$Url = self::$dgurl; } else { self::$Url = self::$zsUrl; } } /** * 初始化静态类 * * @return Test */ public static function initialize(): JiaLieService { if (!self::$initialize instanceof self) { return new self(); } return self::$initialize; } private static function do_rsaSign($data, $private_key) { $search = [ "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", "\n", "\r", "\r\n" ]; $private_key = str_replace($search, "", $private_key); $private_key = $search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1]; $res = openssl_get_privatekey($private_key); if ($res) { openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA256); openssl_free_key($res); } else { self::setErrorInfo("私钥格式有误"); } @file_put_contents("xxx.txt",$sign); $sign = base64_encode($sign); return $sign; } /** * RSA验签 * @param $data 待签名数据 * @param $public_key 公钥字符串 * @param $sign 要校对的的签名结果 * return 验证结果 */ public static function do_rsaCheck($data, $public_key, $sign) { $search = [ "-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----", "\n", "\r", "\r\n" ]; $public_key = str_replace($search, "", $public_key); $public_key = $search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1]; $res = openssl_get_publickey($public_key); if ($res) { $result = (bool) openssl_verify($data, base64_decode($sign), $res,OPENSSL_ALGO_SHA256); file_put_contents("callback.txt", "\n异步验签原字符串\n", FILE_APPEND); file_put_contents("callback.txt",$data , FILE_APPEND); openssl_free_key($res); } else { self::setErrorInfo('公钥格式有误'); } return $result; } public static function rsaSign($params) { $dataStr = self::getJsonStr($params); return self::do_rsaSign($dataStr, self::$prikey); } public static function verify($params) { if (!isset($params['sign'])) { throw new Exception("没有sign签名参数"); } $sign = $params['sign']; unset($params['sign']); $dataStr = self::getJsonStr($params); return self::do_rsaCheck($dataStr, self::$pubkey, $sign); } public static function getJsonStr($params) { if (!is_array($params)) { return $params; } if (count($params) <= 0) { throw new Exception("检查参数"); } ksort($params); return json_encode($params,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); } public static function getKeyValueStr($params) { if (!is_array($params)) { return $params; } if (count($params) <= 0) { throw new Exception("检查参数"); } $dataStr = ""; ksort($params); foreach ($params as $key => $value) { if ($key == "sign") { continue; } if ($value === "" || $value === null) { continue; } $dataStr .= $key . "=" . $value; $dataStr .= "&"; } return rtrim($dataStr, "&"); } public static function checkTradeType($authCode) { if (empty($authCode)) { return ""; } $prefix = substr($authCode, 0, 2); $aliPayCode = array("25", "26", "27", "28", "29", "30"); $wxPayCode = array("10", "11", "12", "13", "14", "15"); $unionPayCode = array("62"); if (in_array($prefix, $aliPayCode)) { return "alipay"; } else if (in_array($prefix, $wxPayCode)) { return "wxpay"; } else if (in_array($prefix, $unionPayCode)) { return "unionpay"; } return ""; } public static function dataRecodes($title, $data) { $handler = fopen('logs/result.txt', 'a+'); $content = "================" . $title . "===================\n"; if (is_string($data) === true) { $content .= $data . "\n"; } if (is_array($data) === true) { foreach ($data as $k => $v) { $content .= "key:【" . $k . "】,value: 【" . var_export($v, true) . "】\n"; } } $flag = fwrite($handler, $content); fclose($handler); return $flag; } /** * 调取支付 * @param string $URL * @param array $Params * @return bool|string */ public static function paymentOrder($URL=self::MICROPAY,$Params=[]) { $headers = array("Content-Type:application/json"); $config = [ 'org_code' => self::$org_code, 'mch_id' => self::$mch_id, 'version' => "1.0.0", 'charset' => "UTF-8", 'sign_type' => "RSA", 'pay_type' => 'wxpay', 'notify_url'=> sys_config('site_url')."/api/jialie/notify", ]; $requestParams = array_merge($config, $Params); $requestParams['sign'] = self::rsaSign($requestParams); $http = new HttpClient(); $http->setDebug(true); self::dataRecodes('付款码支付request报文 ', $requestParams); $rs = $http->post(self::$Url.$URL,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers); //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers); self::dataRecodes('付款码支付response报文 ', self::$Url.$URL.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); self::dataRecodes('付款码支付response报文 ', $rs); return $rs; } public static function paymentquery($URL=self::QUERY,$Params) { $headers = array("Content-Type:application/json"); $config = [ 'org_code' => self::$org_code, 'mch_id' => self::$mch_id, 'version' => "1.0.0", 'charset' => "UTF-8", 'sign_type' => "RSA", ]; $requestParams = array_merge($config, $Params); $requestParams['sign'] = self::rsaSign($requestParams); $http = new HttpClient(); //$http->setDebug(true); //self::dataRecodes('订单查询request报文 ', $requestParams); $rs = $http->post(self::$Url.$URL,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers); //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers); //self::dataRecodes('订单查询response报文 ', self::$Url.$URL.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); //self::dataRecodes('订单查询response报文 ', $rs); return $rs; } public static function payOrderRefund($orderNo, array $opt) { if (!isset($opt['pay_price'])) exception('缺少pay_price'); $totalFee = floatval(bcmul($opt['pay_price'], 100, 0)); $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null; $refundReason = isset($opt['desc']) ? $opt['desc'] : ''; $headers = array("Content-Type:application/json"); $config = [ 'org_code' => self::$org_code, 'mch_id' => self::$mch_id, 'charset' => "UTF-8", 'sign_type' => "RSA", ]; $Params['nonce_str'] = uniqid(); $Params['out_trade_no'] = 'ref'.uniqid(); $Params['ori_out_trade_no'] = $orderNo; $Params['total_fee'] = intval($refundFee); $Params['mch_create_ip'] = app('request')->ip(); $Params['remark'] = $refundReason; $requestParams = array_merge($config, $Params); $requestParams['sign'] = self::rsaSign($requestParams); $http = new HttpClient(); $http->setDebug(true); self::dataRecodes('订单退款request报文 ', $requestParams); $rs = $http->post(self::$Url.self::REFUND,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers); //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers); self::dataRecodes('订单退款request报文 ', self::$Url.self::REFUND.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); self::dataRecodes('订单退款request报文 ', $rs); return $rs; } }