first();
} else {
$project = \App\Models\Project::with("wechatpayAccount")->find($project_id);
$wechatpayAccount = $project->wechatpayAccount;
}
self::$APPID = env("WEIXINPAY_APPID");
self::$APPSECRET = env("WEIXINPAY_APPSECRET");
self::$MCHID = $wechatpayAccount->mchid;
self::$KEY = $wechatpayAccount->key;
self::$SSLCERT_PATH = env("WEIXINPAY_CERT_PUBLIC_PATH") . $wechatpayAccount->mchid . "/apiclient_cert.pem";
self::$SSLKEY_PATH = env("WEIXINPAY_CERT_PUBLIC_PATH") . $wechatpayAccount->mchid . "/apiclient_key.pem";
}
}
class SDKRuntimeException extends Exception
{
public function errorMessage()
{
return $this->getMessage();
}
}
class CommonUtilPub
{
public $project_id;
public $merchant_id;
function __construct($project_id, $merchant_id = null)
{
$this->project_id = $project_id;
$this->merchant_id = $merchant_id;
}
function trimString($value)
{
$ret = null;
if (null != $value) {
$ret = $value;
if (strlen($ret) == 0) {
$ret = null;
}
}
return $ret;
}
/**
* 作用:产生随机字符串,不长于32位
*/
public function createNoncestr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
/**
* 作用:格式化参数,签名过程需要使用
*/
function formatBizQueryParaMap($paraMap, $urlencode)
{
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
//$buff .= strtolower($k) . "=" . $v . "&";
$buff .= $k . "=" . $v . "&";
}
$reqPar = "";
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}
/**
* 作用:生成签名
*/
public function getSign($Obj)
{
foreach ($Obj as $k => $v) {
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//echo '【string1】'.$String.'';
//签名步骤二:在string后加入KEY
$KEY = (new WxPayConfPub($this->project_id, $this->merchant_id))::$KEY;
$String = $String . "&key=" . $KEY;
//echo "【string2】".$String."";
//签名步骤三:MD5加密
$String = md5($String);
//echo "【string3】 ".$String."";
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
//echo "【result】 ".$result_."";
return $result_;
}
/**
* 作用:array转xml
*/
function arrayToXml($arr)
{
$xml = "
";
echo "错误原因查询";
curl_close($ch);
return false;
}
}
/**
* 作用:使用证书,以post方式提交xml到对应的接口url
*/
function postXmlSSLCurl($xml, $url, $second = 30)
{
$ch = curl_init();
$WxPayConfPub = new WxPayConfPub($this->project_id, $this->merchant_id);
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, $WxPayConfPub::$SSLCERT_PATH);
//默认格式为PEM,可以注释
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY, $WxPayConfPub::$SSLKEY_PATH);
//post提交方式
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$data = curl_exec($ch);
//返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
echo "curl出错,错误码:$error" . "
";
echo "错误原因查询";
curl_close($ch);
return false;
}
}
/**
* 作用:打印数组
*/
function printErr($wording = '', $err = '')
{
print_r('
');
echo $wording . "";
var_dump($err);
print_r('');
}
}
/**
* 请求型接口的基类
*/
class WxpayClientPub extends CommonUtilPub
{
var $parameters;//请求参数,类型为关联数组
public $response;//微信返回的响应
public $result;//返回参数,类型为关联数组
var $url;//接口链接
var $curl_timeout;//curl超时时间
/**
* 作用:设置请求参数
*/
function setParameter($parameter, $parameterValue)
{
$this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
}
/**
* 作用:设置标配的请求参数,生成签名,生成接口参数xml
*/
function createXml()
{
$WxPayConfPub = new WxPayConfPub($this->project_id, $this->merchant_id);
$this->parameters["appid"] = $WxPayConfPub::$APPID;//公众账号ID
$this->parameters["mch_id"] = $WxPayConfPub::$MCHID;//商户号
$this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
$this->parameters["sign"] = $this->getSign($this->parameters);//签名
return $this->arrayToXml($this->parameters);
}
/**
* 作用:post请求xml
*/
function postXml()
{
$xml = $this->createXml();
$this->response = $this->postXmlCurl($xml, $this->url, $this->curl_timeout);
return $this->response;
}
/**
* 作用:使用证书post请求xml
*/
function postXmlSSL()
{
$xml = $this->createXml();
$this->response = $this->postXmlSSLCurl($xml, $this->url, $this->curl_timeout);
return $this->response;
}
/**
* 作用:获取结果,默认不使用证书
*/
function getResult()
{
$this->postXml();
$this->result = $this->xmlToArray($this->response);
return $this->result;
}
}
/**
* 统一支付接口类
*/
class UnifiedOrderPub extends WxpayClientPub
{
public $project_id;
public $merchant_id;
function __construct($project_id, $merchant_id = null)
{
$this->project_id = $project_id;
$this->merchant_id = $merchant_id;
//设置接口链接
$this->url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//设置curl超时时间
$this->curl_timeout = WxPayConfPub::CURL_TIMEOUT;
parent::__construct($project_id, $merchant_id);
}
/**
* 生成接口参数xml
*/
function createXml()
{
$WxPayConfPub = new WxPayConfPub($this->project_id, $this->merchant_id);
try {
//检测必填参数
if ($this->parameters["out_trade_no"] == null) {
throw new SDKRuntimeException("缺少统一支付接口必填参数out_trade_no!" . "