class
Wxpay
{
public
static
function
getPayParam(
$sn
,
$money
,
$openid
)
{
$url
= 'https:
$notify_url
= url('/api/weixin/notify');
$data
= [];
$data
['appid'] = Action::config(CONFIG_WXXCX, 'app_id');
$data
['mchid'] = Action::config(CONFIG_WXXCX, 'mchid');
$data
['description'] = 'xxx';
$data
['out_trade_no'] =
$sn
;
$data
['time_expire'] =
date
('Y-m-d') . 'T' .
date
('H:i:s', (time() + 1800)) . '+08:00';
$data
['notify_url'] =
$notify_url
;
$data
['amount'] = ['total' =>
$money
* 100, 'currency' => 'CNY'];
$data
['payer'] = ['openid' =>
$openid
];
$re
= self::wxCurl(
$url
,
$data
, 'POST');
if
(!isset(
$re
['prepay_id'])) {
api_fail('参数获取失败');
}
$result
= [];
$result
['appId'] = Action::config(CONFIG_WXXCX, 'app_id');
$result
['timeStamp'] = (string)time();
$result
['nonceStr'] = uniqid();
$result
['package'] = 'prepay_id=' .
$re
['prepay_id'];
$result
['signType'] = 'RSA';
$result
['paySign'] = self::getPaySign(
$result
);
return
$result
;
}
public
static
function
select(
$sn
,
$return
= false)
{
$mchid
= Action::config(CONFIG_WXXCX, 'mchid');
$url
= 'https:
$re
= self::wxCurl(
$url
, [], 'GET');
if
(
$return
) {
return
$re
;
}
if
(isset(
$re
['trade_state']) &&
$re
['trade_state'] == 'SUCCESS') {
return
true;
}
return
false;
}
public
static
function
close(
$sn
)
{
$mchid
= Action::config(CONFIG_WXXCX, 'mchid');
$url
= 'https:
$re
= self::wxCurl(
$url
, ['mchid'=>
$mchid
], 'POST');
return
true;
}
public
static
function
refund(
$order_sn
,
$refund_sn
,
$total
,
$refund
,
$msg
='退款')
{
$url
='https:
$data
=[];
$data
['notify_url']=url('ag/weixin/notify_refund');
$data
['out_trade_no']=
$order_sn
;
$data
['out_refund_no']=
$refund_sn
;
$data
['reason']=
$msg
;
$data
['amount']=['refund'=>
$refund
*100,'total'=>
$total
*100,'currency'=>'CNY'];
$re
= self::wxCurl(
$url
,
$data
, 'POST');
return
$re
;
}
public
static
function
wxCurl(
$url
,
$data
= [],
$method
= 'GET')
{
$Authorization
= self::getReSign(
$url
,
$data
,
$method
);
$header
= [
'Content-Type: application/json',
'Accept: application/json',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.63',
'Authorization: ' .
$Authorization
];
$redata
=
$data
? json_encode(
$data
) : '';
$res
= reCurl(
$url
,
$redata
,
$header
);
return
$res
? json_decode(
$res
, true) : [];
}
public
static
function
getReSign(
$url
,
$data
,
$method
= 'GET')
{
$url_parts
=
parse_url
(
$url
);
$canonical_url
= (
$url_parts
['path'] . (!
empty
(
$url_parts
['query']) ?
"?${url_parts['query']}"
:
""
));
$http_method
=
$method
;
$timestamp
= time();
$nonce
= uniqid();
$body
=
$data
? json_encode(
$data
) : '';
$mchid
= Action::config(CONFIG_WXXCX, 'mchid');
$serial_no
= Action::config(CONFIG_WXXCX, 'serial_no');
$private_key
= self::getPrivateKey(BASE_PATH . 'cert/apiclient_key.pem');
$message
=
$http_method
.
"\n"
.
$canonical_url
.
"\n"
.
$timestamp
.
"\n"
.
$nonce
.
"\n"
.
$body
.
"\n"
;
openssl_sign(
$message
,
$raw_sign
,
$private_key
, 'sha256WithRSAEncryption');
$sign
=
base64_encode
(
$raw_sign
);
$token
= sprintf('mchid=
"%s"
,nonce_str=
"%s"
,timestamp=
"%d"
,serial_no=
"%s"
,signature=
"%s"
',
$mchid
,
$nonce
,
$timestamp
,
$serial_no
,
$sign
);
return
'WECHATPAY2-SHA256-RSA2048 ' .
$token
;
}
public
static
function
getPaySign(
$result
)
{
$private_key
= self::getPrivateKey(BASE_PATH . 'cert/apiclient_key.pem');
$message
=
$result
['appId'] .
"\n"
.
$result
['timeStamp'] .
"\n"
.
$result
['nonceStr'] .
"\n"
.
$result
['package'] .
"\n"
;
openssl_sign(
$message
,
$raw_sign
,
$private_key
, 'sha256WithRSAEncryption');
$sign
=
base64_encode
(
$raw_sign
);
return
$sign
;
}
public
static
function
checkSign()
{
$header
= Context::get('header');
$serial_no
=
$header
['wechatpay-serial'] ?? '';
$timeStamp
=
$header
['wechatpay-timestamp'] ?? '';
$nonce
=
$header
['wechatpay-nonce'] ?? '';
$body
= Context::get('raw');
$wx_sign
=
$header
['wechatpay-signature'] ?? '';
$wx_serial_no
= Action::config(CONFIG_WXXCX, 'wx_serial_no');
if
(!
$serial_no
||
$wx_serial_no
!=
$serial_no
) {
\sff\Log::write('签名过期');
return
false;
}
$message
=
$timeStamp
.
"\n"
.
$nonce
.
"\n"
.
$body
.
"\n"
;
$wx_sign
=
base64_decode
(
$wx_sign
);
$public_key
= self::getPublicKey(BASE_PATH . 'cert/wx_public_cert.pem');
$res
= openssl_verify(
$message
,
$wx_sign
,
$public_key
, OPENSSL_ALGO_SHA256);
if
(
$res
== 1) {
return
true;
}
\sff\Log::write('验签失败');
return
false;
}
public
static
function
getPrivateKey(
$filepath
)
{
return
openssl_get_privatekey(
file_get_contents
(
$filepath
));
}
public
static
function
getPublicKey(
$filepath
)
{
return
openssl_pkey_get_public(
file_get_contents
(
$filepath
));
}
public
static
function
getEncrypt(
$str
)
{
$public_key_path
= BASE_PATH . 'cert/wx_public_cert.pem';
$public_key
=
file_get_contents
(
$public_key_path
);
$encrypted
= '';
if
(openssl_public_encrypt(
$str
,
$encrypted
,
$public_key
, OPENSSL_PKCS1_OAEP_PADDING)) {
$sign
=
base64_encode
(
$encrypted
);
}
else
{
throw
new
Exception('encrypt failed');
}
return
$sign
;
}
public
static
function
decryptToString(
$ciphertext
,
$associatedData
,
$nonceStr
)
{
$aesKey
= Action::config(CONFIG_WXXCX, 'mch_keyv3');
$str
=
base64_decode
(
$ciphertext
);
if
(
strlen
(
$str
) <= 16) {
return
'';
}
return
\sodium_crypto_aead_aes256gcm_decrypt(
$str
,
$associatedData
,
$nonceStr
,
$aesKey
);
}
public
static
function
downCert()
{
$url
= 'https:
$re
= self::wxCurl(
$url
, [], 'GET');
if
(!isset(
$re
['data'])) {
api_fail('获取证书失败');
}
$ciphertext
=
$re
['data'][0]['encrypt_certificate']['ciphertext'];
$associatedData
=
$re
['data'][0]['encrypt_certificate']['associated_data'];
$nonceStr
=
$re
['data'][0]['encrypt_certificate']['nonce'];
$data
= self::decryptToString(
$ciphertext
,
$associatedData
,
$nonceStr
);
if
(!
$data
) {
api_fail('获取证书解密失败');
}
file_put_contents
(BASE_PATH . '/cert/wx_public_cert.pem',
$data
);
return
$data
;
}
}
暂时没有评论,来抢沙发吧~