159 lines
6.8 KiB
PHP
159 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace web\api;
|
|
|
|
class weixin {
|
|
public $tokenid;
|
|
public $token;
|
|
|
|
function __construct($tokenid) {
|
|
global $db;
|
|
$this->token = null;
|
|
$ret = gettokthd($db, $tokenid);
|
|
if (is_string($ret))
|
|
return $this->err($ret);
|
|
$this->tokenid = $tokenid;
|
|
$this->token = $ret;
|
|
}
|
|
function err($ret, $log = '') {
|
|
savelogfile('WXPAY', $ret . $log);
|
|
return $ret;
|
|
}
|
|
public function call($url, $post = null, $isbinary = false) {
|
|
if (!$this->token)
|
|
return 'token不存在';
|
|
if (strpos($url, '{accesstoken}') !== false) {
|
|
$ret = $this->getaccesstoken();
|
|
if (is_string($ret))
|
|
return $ret;
|
|
$url = str_replace('{accesstoken}', $ret['accesstoken'], $url);
|
|
}
|
|
if (strpos($url, '{appid}') !== false)
|
|
$url = str_replace('{appid}', $this->token['appid'], $url);
|
|
if (strpos($url, '{appsecret}') !== false)
|
|
$url = str_replace('{appsecret}', $this->token['appsecret'], $url);
|
|
|
|
$http = new \ciy\http();
|
|
$http->set_headeronce('Content-Type', 'application/json');
|
|
$http->set_headeronce('Accept', 'application/json');
|
|
if (is_array($post))
|
|
$post = json_encode($post, JSON_UNESCAPED_UNICODE);
|
|
$http->request($url, $post);
|
|
$statcode = $http->get_statcode();
|
|
if ($statcode != 200 && $statcode != 204)
|
|
return $this->err('微信服务器无法连接,错误码:' . $statcode);
|
|
$result = $http->get_data();
|
|
if ($isbinary) {
|
|
if (@$result[0] != '{')
|
|
return array('bin' => $result);
|
|
}
|
|
$json = json_decode($result, true);
|
|
if ($json === null)
|
|
return $this->err('微信服务器返回数据失败', $result);
|
|
if (isset($json['errcode']) && $json['errcode'] != 0)
|
|
return $this->err('微信服务器返回错误:' . @$json['errmsg']);
|
|
return $json;
|
|
}
|
|
public function refund($param) { //退款
|
|
$result = $this->certcall('https://api.mch.weixin.qq.com', '/v3/refund/domestic/refunds', $param);
|
|
if (is_string($result))
|
|
return $result;
|
|
return $result;
|
|
}
|
|
public function transfer($param) { //提现
|
|
$param['appid'] = $this->token['appid'];
|
|
$result = $this->certcall('https://api.mch.weixin.qq.com', '/v3/fund-app/mch-transfer/transfer-bills', $param);
|
|
if (is_string($result))
|
|
return $result;
|
|
$result['mchid'] = $this->token['mchid'];
|
|
$result['appid'] = $this->token['appid'];
|
|
return $result;
|
|
}
|
|
public function pay($param) { //支付
|
|
$param['appid'] = $this->token['appid'];
|
|
$param['mchid'] = $this->token['mchid'];
|
|
$result = $this->certcall('https://api.mch.weixin.qq.com', '/v3/pay/transactions/jsapi', $param);
|
|
if (is_string($result))
|
|
return $result;
|
|
|
|
$timestamp = time() . '';
|
|
$nonce = uniqid() . uniqid();
|
|
$pkey = openssl_pkey_get_private(file_get_contents($this->token['pem_path']));
|
|
$message = $this->token['appid'] . "\n" . $timestamp . "\n" . $nonce . "\nprepay_id=" . $result['prepay_id'] . "\n";
|
|
|
|
openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
|
|
$sign = base64_encode($raw_sign);
|
|
|
|
$ret['appId'] = $this->token['appid'];
|
|
$ret['timeStamp'] = $timestamp;
|
|
$ret['nonceStr'] = $nonce;
|
|
$ret['package'] = 'prepay_id=' . $result['prepay_id'];
|
|
$ret['signType'] = 'RSA';
|
|
$ret['paySign'] = $sign;
|
|
return $ret;
|
|
}
|
|
private function certcall($domain, $url, $post) {
|
|
if (!file_exists($this->token['pem_path']))
|
|
return $this->err('证书文件不存在', $this->token['pem_path']);
|
|
$timestamp = time() . '';
|
|
$nonce = uniqid() . uniqid();
|
|
$post = json_encode($post, JSON_UNESCAPED_UNICODE);
|
|
$message = "POST\n" . $url . "\n" . $timestamp . "\n" . $nonce . "\n" . $post . "\n";
|
|
$pkey = openssl_pkey_get_private(file_get_contents($this->token['pem_path']));
|
|
openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
|
|
$sign = base64_encode($raw_sign);
|
|
$token = 'mchid="' . $this->token['mchid'] . '",nonce_str="' . $nonce . '",timestamp="' . $timestamp . '",serial_no="' . $this->token['pem_no'] . '",signature="' . $sign . '"';
|
|
$http = new \ciy\http();
|
|
$http->set_headeronce('Content-Type', 'application/json');
|
|
$http->set_headeronce('Accept', 'application/json');
|
|
$http->set_headeronce('Authorization', 'WECHATPAY2-SHA256-RSA2048 ' . $token);
|
|
$http->request($domain . $url, $post);
|
|
$statcode = $http->get_statcode();
|
|
if ($statcode == 200 || $statcode == 204) {
|
|
$result = $http->get_data();
|
|
$json = json_decode($result, true);
|
|
if ($json === null)
|
|
return array('code' => 1);
|
|
if (isset($json['message']))
|
|
return $this->err('微信服务器返回错误:' . $json['message']);
|
|
$json['code'] = 1;
|
|
return $json;
|
|
} else {
|
|
$res['errmsg'] = 1;
|
|
$result = $http->get_data();
|
|
$json = json_decode($result, true);
|
|
if ($json === null)
|
|
return $this->err('微信服务器无法连接pay', $result);
|
|
if (isset($json['message']))
|
|
return $this->err('微信服务器返回错误:' . $json['message']);
|
|
return $this->err('微信服务器返回json:' . $result);
|
|
}
|
|
}
|
|
private function getaccesstoken() {
|
|
global $db;
|
|
if ($this->token['exptimes'] > time())
|
|
return array('accesstoken' => $this->token['accesstoken']);
|
|
$http = new \ciy\http();
|
|
$http->set_headeronce('Content-Type', 'application/json');
|
|
$http->set_headeronce('Accept', 'application/json');
|
|
$http->request('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->token['appid'] . '&secret=' . $this->token['appsecret']);
|
|
$result = $http->get_data();
|
|
$json = json_decode($result, true);
|
|
if ($json === null)
|
|
return $this->err('微信服务器无法连接token', $result);
|
|
if (toint(@$json['errcode']) != 0)
|
|
return $this->err($json['errmsg']);
|
|
$accesstoken = @$json['access_token'];
|
|
if (empty($accesstoken))
|
|
return $this->err('微信token授权失败', $result);
|
|
$exptimes = time() + toint($json['expires_in']);
|
|
$updata = array();
|
|
$updata['accesstoken'] = $accesstoken;
|
|
$updata['exptimes'] = $exptimes;
|
|
$ret = settokthd($db, $this->tokenid, $updata);
|
|
if (is_string($ret))
|
|
return $this->err($ret);
|
|
return array('accesstoken' => $accesstoken);
|
|
}
|
|
}
|