微信支付文档地址:微信支付-开发者文档
/**
* 微信支付
* 入参:
* $openid:用户openid
* $out_trade_no:商户订单号
* $total_fee:订单金额(元)
* $notify_url:支付回调地址
**/
public function wxPay($openid,$notify_url,$out_trade_no,$total_fee)
{
$config = Config::get('wechat');
$appid = $config['app_id']; //小程序appid
$merchantId = $config['mch_id']; // 商户号
$merchantSerialNumber = $config['cert_serial']; // 商户API证书序列号
$filepath = $config["APIv3_secret"]; //私钥在本地的位置
//生成请求报文的主体
$data = [
"appid" => $appid,// 用户appid
"mchid" => $merchantId,// 商户号
"description" => '微信支付',//标题商品描述
'out_trade_no' => $out_trade_no,//商户订单号
'notify_url' => $notify_url, //回调地址
"amount" => [
"total" => $total_fee*100,//订单金额(分)
"currency" => "CNY"
],
"payer" => [
"openid" => $openid //用户openid
]
];
$data = json_encode($data);
//生成签名数据主体
$timestamp = time();
$nonce = date('YmdHis', time()) . rand(1000, 9999);
$url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';
$url_parts = parse_url($url);
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
$message = 'POST' . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$data . "\n";
//生成签名值
$file = file_get_contents($filepath);//获取本地私钥
$mch_private_key = openssl_get_privatekey($file);
openssl_sign($message, $signature, $mch_private_key, "sha256WithRSAEncryption");
$sign = base64_encode($signature);
//对prepay_id再次签名的签名数据主体
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $merchantId, $nonce, $timestamp, $merchantSerialNumber, $sign);
$header = "Authorization: WECHATPAY2-SHA256-RSA2048 " . $token;//token前面一定要有空格
$res = $this->http_post($url, $header, $data);
$arr = json_decode($res, true);
$time = time();
$str = time() . round('1000', '9999');
$prepay = 'prepay_id=' . $arr['prepay_id'];
$message1 = $appid . "\n" .
$time . "\n" .
$str . "\n" .
$prepay . "\n";
openssl_sign($message1, $signature, $mch_private_key, "sha256WithRSAEncryption");
$sign1 = base64_encode($signature);
$data = array();
$data['timeStamp'] = $time;
$data['nonce'] = $str;
$data['prepay_id'] = $arr['prepay_id'];
$data['sign'] = $sign1;
return ['status' => 1, 'msg' => '操作成功', 'data' => $data];
}
微信回调文档地址:微信支付-开发者文档
//支付回调
public function notify()
{
try {
$mchkey= '';//商户平台设置的api v3 密码
//获得内容
$post = file_get_contents("php://input");
//转数组
$arr_post = json_decode($post,true);
//解密
$ciphertext = (new AesUtil($mchkey))->decryptToString($arr_post['resource']['associated_data'],$arr_post['resource']['nonce'],$arr_post['resource']['ciphertext']);
$res = json_decode($ciphertext, true);
if ($res['trade_state'] == 'SUCCESS') {
//成功操作
$data['out_trade_no'] = $res['out_trade_no'];
$data['transaction_id'] = $res['transaction_id'];
$data['openid'] = $res['payer']['openid'];
$data['total_fee'] = $res['amount']['payer_total']/100;
$data['success_time'] = strtotime($res['success_time']);
test_log('微信支付回调成功:'.$str);
return ['status' => 1, 'msg' => '操作成功', 'data' => $data];
} else {
test_log('微信支付回调失败1:'.$str);
return ['status' => 0, 'msg' => '操作失败'];
}
}catch(\Exception $e){
test_log('微信支付回调失败2:'.$e->getMessage());
return ['status'=> 0, 'msg'=> '操作失败-'. $e->getMessage()];
}
}
aesKey = $aesKey;
}
/**
* Decrypt AEAD_AES_256_GCM ciphertext
*
* @param string $associatedData AES GCM additional authentication data
* @param string $nonceStr AES GCM nonce
* @param string $ciphertext AES GCM cipher text
*
* @return string|bool Decrypted string on success or FALSE on failure
* @throws \SodiumException
*/
public function decryptToString($associatedData, $nonceStr, $ciphertext)
{
$ciphertext = \base64_decode($ciphertext);
if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
return false;
}
// ext-sodium (default installed on >= PHP 7.2)
if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
\sodium_crypto_aead_aes256gcm_is_available()) {
return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
}
// ext-libsodium (need install libsodium-php 1.x via pecl)
if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
\Sodium\crypto_aead_aes256gcm_is_available()) {
return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
}
// openssl (PHP >= 7.1 support AEAD)
if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
$ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
$authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
return \openssl_decrypt($ctext, 'aes-256-gcm', $this->aesKey, \OPENSSL_RAW_DATA, $nonceStr,
$authTag, $associatedData);
}
throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
}
}