<?php /** * Created by PhpStorm. * User: Administrator * Date: 2021/9/13 * Time: 16:26 */ namespace app\index\controller; use think\Controller; use think\Request; /** * 微信支付V3 * Class Pay * @package app\index\controller */ class Pay extends Controller { protected $payApi = [ 'app' => 'https://api.mch.weixin.qq.com/v3/pay/transactions/app',//APP支付 'h5' => 'https://api.mch.weixin.qq.com/v3/pay/transactions/h5',//H5支付 ];//支付接口列表 protected $queryApi = 'https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id}';//查询订单接口 protected $refundApi = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';//退单接口 protected $refundNotify = '******';//退单回调自定义 public function _initialize() { } /** * 配置 */ public function config(){ return [ 'appid' => '******', 'mchid' => '******',//商户号 'serial_no' => '******',//证书序列号 'description' => '******',//应用名称 'notify' => '******',//支付回调 ]; } /** * 设置支付url * @param string $type 支付平台 * @return mixed */ public function getPayUrl($type = 'app'){ return $this->payApi[$type]; } /** * H5支付 * @param $total int 支付金额 * @return mixed */ public function h5Pay($total){ //请求参数(报文主体) $config = $this->config(); $body = [ 'appid' => $config['appid'], 'mchid' => $config['mchid'], 'description' => $config['description'], 'out_trade_no' => $this->getOrderNo(), 'notify_url' => $config['notify'], 'amount' => [ 'total' => $total, 'currency' => 'CNY' ], 'scene_info' => [ 'payer_client_ip' => Request::instance()->ip(), 'h5_info' => [ 'type' => 'Wap', ], ], ]; $headers = $this->sign('POST',$this->getPayUrl('h5'),json_encode($body)); return $this->curl_post($this->getPayUrl('h5'),json_encode($body),$headers); } /** * APP支付 * @param $total int 支付金额 * @return mixed */ public function appPay($total){ //请求参数(报文主体) $config = $this->config(); $body = [ 'appid' => $config['appid'], 'mchid' => $config['mchid'], 'description' => $config['description'], 'out_trade_no' => $this->getOrderNo(), 'notify_url' => $config['notify'], 'amount' => [ 'total' => $total, 'currency' => 'CNY' ], ]; $headers = $this->sign('POST',$this->getPayUrl(),json_encode($body)); return $this->curl_post($this->getPayUrl(),json_encode($body),$headers); } /** * 预下单 */ public function preOrder(){ $res = $this->h5Pay(1); print_r($res);die; } /** * 支付回调 */ public function notify(){ } /** * 退款 * @param string $transaction_id 平台订单号 * @return mixed */ public function refund($transaction_id = ''){ $body = [ 'transaction_id' => $transaction_id,//平台订单号 'out_refund_no' => $this->getOrderNo(),//系统退款单号 'reason' => '退款',//退款原因 'notify_url' => '',//退款回调 'amount' => [ 'refund' => 1,//退款金额 'total' => 1,//原订单金额 'currency' => 'CNY', ], ]; $headers = $this->sign('POST',$this->refundApi,json_encode($body)); return $this->curl_post($this->refundApi,json_encode($body),$headers); } /** * 退款回调 */ public function refundNotify(){ } /** * 签名 * @param string $http_method 请求方式GET|POST * @param string $url url * @param string $body 报文主体 * @return array */ public function sign($http_method = 'POST',$url = '',$body = ''){ $mch_private_key = $this->getMchKey();//私钥 $timestamp = time();//时间戳 $nonce = $this->getRandomStr(32);//随机串 $url_parts = parse_url($url); $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : "")); //构造签名串 $message = $http_method."\n". $canonical_url."\n". $timestamp."\n". $nonce."\n". $body."\n";//报文主体 //计算签名值 openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption'); $sign = base64_encode($raw_sign); //设置HTTP头 $config = $this->config(); $token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $config['mchid'], $nonce, $timestamp, $config['serial_no'], $sign); $headers = [ 'Accept: application/json', 'User-Agent: */*', 'Content-Type: application/json; charset=utf-8', 'Authorization: '.$token, ]; return $headers; } //私钥 public function getMchKey(){ //path->私钥文件存放路径 return openssl_get_privatekey(file_get_contents('path')); } //post请求 public function curl_post($url , $data,$headers=array()) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //设置header头 curl_setopt($ch, CURLOPT_HTTPHEADER,$headers); // POST数据 curl_setopt($ch, CURLOPT_POST, 1); // 把post的变量加上 curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $output = curl_exec($ch); curl_close($ch); return $output; } //get请求 public function curl_get($url,$headers=array()) { $info = curl_init(); curl_setopt($info,CURLOPT_RETURNTRANSFER,true); curl_setopt($info,CURLOPT_HEADER,0); curl_setopt($info,CURLOPT_NOBODY,0); curl_setopt($info,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($info,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($info,CURLOPT_SSL_VERIFYHOST,false); //设置header头 curl_setopt($info, CURLOPT_HTTPHEADER,$headers); curl_setopt($info,CURLOPT_URL,$url); $output = curl_exec($info); curl_close($info); return $output; } /** * 获得随机字符串 * @param $len integer 需要的长度 * @param $special bool 是否需要特殊符号 * @return string 返回随机字符串 */ public function getRandomStr($len, $special=false){ $chars = array( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ); if($special){ $chars = array_merge($chars, array( "!", "@", "#", "$", "?", "|", "{", "/", ":", ";", "%", "^", "&", "*", "(", ")", "-", "_", "[", "]", "}", "<", ">", "~", "+", "=", ",", "." )); } $charsLen = count($chars) - 1; shuffle($chars); //打乱数组顺序 $str = ''; for($i=0; $i<$len; $i++){ $str .= $chars[mt_rand(0, $charsLen)]; //随机取出一位 } return $str; } /** * 生成订单号 */ public function getOrderNo(){ return date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); } //H5测试支付 // public function pay(){ // $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/h5'; // $body = [ // 'appid' => '******', // 'mchid' => '******', // 'description' => '******', // 'out_trade_no' => date('YmdHis').rand(1000,9999), // 'notify_url' => "******", // 'amount' => [ // 'total' => 100, // 'currency' => 'CNY' // ], // 'scene_info' => [ // 'payer_client_ip' => Request::instance()->ip(), // 'h5_info' => [ // 'type' => 'Wap', // ], // ], // ]; // $headers = $this->sign('POST',$url,json_encode($body)); // $res = $this->curl_post($url,$body,$headers); // print_r($res); // } }
简单的写了个支付类,没有接通业务,其余的请自行补充