微信支付V3版本小程序支付 php签名,验签,数据解密代码分享
微信支付v3版 php解密解密代码
数据解密需要用到sodium扩展 大部分php版本需要安装
证书序列号可以在这里查看https://myssl.com/cert_decode.html
我用的php7.4版本
直接上代码:
//微信原生支付
class Wxpay
{
/*
* 支付(小程序支付)
* @param type $sn 订单编号
* @param type $money 金额
* @param type $openid 用户小程序openid
* @return type
*/
public static function getPayParam($sn, $money, $openid)
{
$url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';
$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'; //订单失效时间2018-06-08T10:34:56+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;
}
/**
* 查询订单
* @param type $sn
*/
public static function select($sn, $return = false)
{
$mchid = Action::config(CONFIG_WXXCX, 'mchid'); //商户号
$url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/' . $sn . '?mchid=' . $mchid;
$re = self::wxCurl($url, [], 'GET');
if ($return) {
return $re;
}
if (isset($re['trade_state']) && $re['trade_state'] == 'SUCCESS') {
return true;
}
return false;
}
/**
* 关闭订单
* @param type $sn
*/
public static function close($sn)
{
$mchid = Action::config(CONFIG_WXXCX, 'mchid'); //商户号
$url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/' . $sn . '/close';
$re = self::wxCurl($url, ['mchid'=>$mchid], 'POST');
return true;
}
/**
* 退款
* @param type $sn
*/
public static function refund($order_sn,$refund_sn,$total,$refund,$msg='退款')
{
$url='https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
$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'); //商户id
$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) {
sffLog::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;
}
sffLog::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)
{
//$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)) {
//base64编码
$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'); //商户apiv3密钥解密
$str = base64_decode($ciphertext);
if (strlen($str) <= 16) {
return '';
}
// ext-sodium (default installed on >= PHP 7.2)
return sodium_crypto_aead_aes256gcm_decrypt($str, $associatedData, $nonceStr, $aesKey);
}
//下载平台证书
public static function downCert()
{
$url = 'https://api.mch.weixin.qq.com/v3/certificates';
$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;
}
}登录后复制
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!
相关教程推荐
- H5页面跳转小程序的3种实现方式
- 微信小程序向左滑动删除功能的实现
- 微信小程序中密码输入框的设计代码
- 微信小程序开发之跑步微信小程序
- 微信小程序内常用的运算符有哪些
- 微信小程序开发常用功能汇总
- 总结分享微信小程序的开发步骤
- 小程序中import和include有什么区别
- 微信公众号的服务号和订阅号区别是什么
- 快速实现一个微信小程序的Button组件
- 微信小程序:一个json帮你完成分享朋友圈图片
- 微信小程序项目结构介绍
- 常见的小程序实现技术及其比较
- 微信小程序开发流程是怎样的?
- 自己如何开发小程序
- 微信小程序如何自定义底部导航菜单
- 定义了重复的system.web.extensions/scripting/scriptResourceHandler怎
- 微信小程序分包流程步骤
其他课程推荐
- linux下添加phpcurl扩展的方法
- php添加pcntl多线程扩展(Linux)
- 做php的应该很多懂linux吧,问个有关问题,本地开发好后,怎么只把最近一天修改过的文件同步到服务器
- imagegif函数linux下失败,windows下成功,为什么?解决思路
- linux下怎么安装php的扩展库
- 学习PHP,然后学习C,深入Linux的,如果想往底层发展,应该是如何的一个学习过程?
- Perl、PHP、Python、Ruby对于入门的Linux运维来说,哪个更易学?
- linux进程如图这两个进程是什么?占用资源挺多的
- linux下安装redis以及phpRedis扩展
- Cygwin下安装LinuxPHP环境和Swoole扩展并在PHPStorm中调试
- linuxphp5.3.x升级到php5.5.x
- 【Linux】LAMP架构之以模块方式让php和httpd搭档工作
- linux下vim实现php远程调试环境搭
- linux php fopen怎么打不开远程文件?
- Linux配置主机名
- Linux网络配置~修改IP地址
- Linuxvi/vim编辑器
- linux系统目录介绍
- 为什么要学linux
- Linux下MySQL出现#1036–Table‘‘isreadonly错误解决方法