目录
支付............................................................................................................................................................1
退款............................................................................................................................................................4
订单查询....................................................................................................................................................7
退款查询....................................................................................................................................................7
支付成功,进行回调................................................................................................................................8
退款成功,进行回调................................................................................................................................9
用到的方法..............................................................................................................................................10
基于 thinkphp5 框架
支付
/**
* 预支付请求接口(POST)
* @param string $openid openid
* @param string $body 商品简单描述
* @param string $order_sn 订单编号
* @param string $total_fee 金额
* @return json 的数据
*/
public function prepay()
{
tp_log(' 预 支 付 请 求 数 据 ===>'
.
json_encode($_POST),
'prepay',
request()->controller());
$goods_user
$_POST['order_no']))->find();
=
db('tf_goods_user')->where(array('order_no'
=>
$goods = db('tf_goods')->where(array('id' => $goods_user['goods_id']))->find();
//判断产品的数量
if (($goods['sales_initial'] - $goods['sales_actual']) <= 0) {
$return['status'] = 0;
$return['info'] = '此产品已售完';
exit(json_encode($return));
}
$order_no = $_POST['order_no']; //订单号
$is_sale = $_POST['is_sale'];
$openid = $_POST['openid'];
$goods_name = $_POST['goods_name'];
$pay_price = $_POST['price'];
$attach['is_sale'] = $_POST['is_sale'];
$attach['sale_id'] = $_POST['sale_id'];
$nonce_str = $this->nonce_str();//随机字符串
$order_no_ssh = $this->get_orderssh(); //商户订单号
//组装支付数据
$data = [
//商品名称组合
'appid' => config('pay.APPID'),
'mch_id' => config('pay.MCHID'),
'nonce_str' => $nonce_str,
'body' => $goods_name,
'attach' => json_encode($attach),
'out_trade_no' => $order_no_ssh,//$order_no,
'total_fee' => intval($pay_price * 100),
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
'notify_url' => config('pay.NOTIFY_URL'),
'trade_type' => 'JSAPI',
'openid' => $openid
];
//订单支付表创建订单支付数据
$p_o_data['createtime'] = time();
$p_o_data['order_no'] = $order_no;
$p_o_data['order_no_ssh'] = $order_no_ssh;
$p_o_data['ready'] = json_encode($data);
$p_o_return = db('tf_pay_order')->insert($p_o_data);
if(!$p_o_return){
//失败
$return['status'] = -1;
$return['info'] = $p_o_data;
exit(json_encode($return));
}
//订单号 商户订单号
// 获取签名
$sign = $this->makeSign($data);
$data['sign'] = $sign;
$xml = $this->toXml($data);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; //发起支付接口链接
//发起预支付请求
$prepay_return_reslut_xml = $this->http_request($url, $xml);
$xml_to_arr = $this->fromXml($prepay_return_reslut_xml);
$return_result = json_encode($xml_to_arr, true);
tp_log(' 预 支 付 请 求 返 回 数 据 array===>'
.$return_result
,
'prepay',
request()->controller());
//记录预支付返回信息
db('tf_goods_order')->where(array('order_no' => $order_no))
->update(array(
'go_pay' => $return_result,
'updatetime' => time(),
'updateuser' => $openid
));
if($xml_to_arr['return_code']
==
'SUCCESS' && $xml_to_arr['result_code']
==
'SUCCESS'){
//成功
$time = time();
//临时数组用于签名
$tmp = [
'appId' => config('pay.APPID'),
'nonceStr' => $nonce_str,
'package' => 'prepay_id='.$xml_to_arr['prepay_id'],
'signType' => 'MD5',
'timeStamp' => "$time",
];
$data['timeStamp'] = "$time";//时间戳
$data['nonceStr'] = $nonce_str;//随机字符串
$data['signType'] = 'MD5';//签名算法,暂支持 MD5
$data['package'] = 'prepay_id='.$xml_to_arr['prepay_id'];//统一下单接口返回的
prepay_id 参数值,提交格式如:prepay_id=*
$data['paySign'] = $this->makeSign($tmp);//签名,具体签名方案参见微信公众号
支付帮助文档;$data['out_trade_no'] = $out_trade_no;
$return['status'] = 1;
$return['info'] = $data;
}else{
//失败
$return['status'] = -1;
$return['info'] = $xml_to_arr;
}
exit(json_encode($return));
}
//curl 请求
public function http_request($url, $data = null, $headers = array())
{
$curl = curl_init();
if (count($headers) >= 1) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
退款
/**
* 申请退款 API
* @param $transaction_id
* @param double $total_fee 账单总金额
* @param double $refund_fee 退款金额
* @return bool
* @throws BaseException
*/
public function refund()
{
$transaction_id = '4200000712202007274705432240';
$total_fee = '0.01';
$refund_fee = '0.01';
// 当前时间
$time = time();
// 生成随机字符串
$nonceStr = md5($time . $transaction_id . $total_fee . $refund_fee);
// API 参数
$params = [
'appid' => config('pay.APPID'),
'mch_id' => config('pay.MCHID'),
'nonce_str' => $nonceStr,
'transaction_id' => $transaction_id,
'out_refund_no' => $time,
'total_fee' => $total_fee * 100,
'refund_fee' => $refund_fee * 100,
'notify_url' => config('pay.NOTIFY_URL_REFUND'),//退款回调地址
];
// 生成签名
$params['sign'] = $this->makeSign($params);
tp_log('退款请求数据===>' . json_encode($params), 'refund', request()->controller());
// 请求 API
$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
$result = $this->post($url, $this->toXml($params), true, $this->getCertPem());
$prepay = $this->fromXml($result);
// 请求失败
if (empty($result)) {
throw new BaseException(['msg' => '微信退款 api 请求失败']);
}
// 格式化返回结果
$prepay = $this->fromXml($result);
tp_log('退款返回数据===>' . json_encode($prepay), 'refund', request()->controller());
// 请求失败
if ($prepay['return_code'] === 'FAIL') {
throw new BaseException(['msg' => 'return_msg: ' . $prepay['return_msg']]);
}
if ($prepay['result_code'] === 'FAIL') {
throw new BaseException(['msg' => 'err_code_des: ' . $prepay['err_code_des']]);
}
return true;
}
/**
* 模拟 POST 请求
* @param $url
* @param array $data
* @param bool $useCert
* @param array $sslCert
//
//
//
//
//
//
* @return mixed
*/
public function post($url, $data = [], $useCert = false, $sslCert = [])
{
$header = [
'Content-type: application/json;'
];
$curl = curl_init();
//
//
//
//
//
//如果有配置代理这里就设置代理
if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"
&& WxPayConfig::CURL_PROXY_PORT != 0){
curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
if ($useCert == true) {
// 设置证书:cert 与 key 分别属于两个.pem 文件
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLCERT, $sslCert['certPem']);
curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLKEY, $sslCert['keyPem']);
}
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
订单查询
/**
* 订单查询
* @param $out_trade_no
* @return mixed
* @throws BaseException
*/
public function orderquery()
{
$transaction_id = '4200000712202007274705432240';//微信订单号
// 当前时间
$time = time();
// 生成随机字符串
$nonce_str = md5($time . mt_rand(00000,99999));
//API 参数
$params = [
'appid'
'mch_id'
'transaction_id' => $transaction_id,
'nonce_str'
=> config('pay.APPID'),
=> config('pay.MCHID'),
=> $nonce_str,
//公众号 ID
//商户号
//商户订单号
// 随机字符串
];
//生成签名
$params['sign'] = $this->makeSign($params);
//请求 API
$url = 'https://api.mch.weixin.qq.com/pay/orderquery';
$result = $this->post($url, $this->toXml($params));
$prepay = $this->fromXml($result);
// 请求失败
if ($prepay['return_code'] === 'FAIL') {
throw new BaseException(['msg' => $prepay['return_msg'], 'code' => 0]);
}
if ($prepay['result_code'] === 'FAIL') {
throw new BaseException(['msg' => $prepay['err_code_des'], 'code' => 0]);
}
return $prepay;
}
退款查询
/**
* 退款查询
* @param $out_trade_no
* @return mixed
* @throws BaseException
*/
public function refundquery()
{
$transaction_id = '4200000712202007274705432240';//微信订单号
// 当前时间
$time = time();
// 生成随机字符串
$nonce_str = md5($time . mt_rand(00000,99999));
//API 参数
$params = [
'appid'
'mch_id'
'transaction_id' => $transaction_id,
'nonce_str'
=> config('pay.APPID'),
=> config('pay.MCHID'),
=> $nonce_str,
//公众号 ID
//商户号
//商户订单号
// 随机字符串
];
//生成签名
$params['sign'] = $this->makeSign($params);
//请求 API
$url = 'https://api.mch.weixin.qq.com/pay/refundquery';
$result = $this->post($url, $this->toXml($params));
$prepay = $this->fromXml($result);
dump($prepay);die;
// 请求失败
if ($prepay['return_code'] === 'FAIL') {
throw new BaseException(['msg' => $prepay['return_msg'], 'code' => 0]);
}
if ($prepay['result_code'] === 'FAIL') {
throw new BaseException(['msg' => $prepay['err_code_des'], 'code' => 0]);
}
return $prepay;
}
支付成功,进行回调
public function index()
{
$data = file_get_contents('php://input');
$data = $this->FromXml($data);
tp_log('支付回调数据===>' . json_encode($data), 'index', request()->controller());
// 保存微信服务器返回的签名 sign
$data_sign = $data['sign'];
// sign 不参与签名算法
unset($data['sign']);
$sign = $this->makeSign($data);//回调验证签名
$str_success
=
'